Data

Compare relations

We can compare relations. Since the restrict operation returns a relation, we can compare two filtered results.

S[STATUS=20]
SNOSNAMESTATUSCITY
S1Smith20London
S4Clark20London
S[CITY="London"]
SNOSNAMESTATUSCITY
S1Smith20London
S4Clark20London

The equality comparison, using = will return true for this case.

S[STATUS=20] = S[CITY="London"]
true

We can also test whether one relation is a subset of another, using <=. This symbol is meant to resemble the subset symbol, (which you can use instead, if your keyboard can create it).

S[STATUS=20] <= S[CITY="London"]
true
S[STATUS=20] <= S
true
S[STATUS=20] <= S[STATUS=30]
false

There is also a superset operator: >= (or ). And there are pure subset and pure superset operators (i.e. excluding the cases when both are equal): < and > (or and )

Heading

We can use the heading function to get the set of attributes for a relation.

heading(S)
attrtype
CITYstr
SNAMEstr
SNOstr
STATUSint

And because this returns a relation we can do further operations on it. For example, to find the common attributes in S and SP:

heading(S) & heading(SP)
attrtype
SNOstr
Using heading with no parameter will return the heading for the current scope, i.e. each local variable plus globals (which includes persisted relvars for the current schema).

heading()
attrtype
Constraint{name:str,rule:str}
P{PNO:str,PNAME:str,COLOR:str,WEIGHT:int,CITY:str}
S{SNO:str,SNAME:str,STATUS:int,CITY:str}
SP{SNO:str,PNO:str,QTY:int}
error{message:str}

Cardinality

We can count how many tuples are in a relation using count().

count(S[STATUS=20])
2

We can check if a relation has no tuples using empty().

empty(dee)
false
empty(dum)
true

Degree

We can count how many attributes are in a relation using count and heading.

count(heading(S))
4

Quantification

We can add a boolean attribute to a relation (or use an existing one). Then we can use the all or exists (or or if your keyboard can create them) operators to check if all or any tuples have the attribute set true.

exists(S{*, test:=(STATUS=20)}, test)
true
all(S{test:=(STATUS=20)})
false
all(S{test:=(STATUS<100)})
true

exists and all should be more efficient than counting filtered matches since they can short-circuit and finish early without necessarily checking all the tuples.