Other Data Types
Any
The type Any
covers all possible values, and can be used as a wildcard to match any type.
Type Relation: Any(x)
Any(x)
will be true
for any x
.
Example
// read query
def R = (1, 3) ; (1, "foo")
ic any_ic {subset(R, (Int, Any) )}
def output = R
Boolean
The Rel language is based on two-valued logic (opens in a new tab) where the constants true
and false
are relations and not data values.
The relation true
is represented by an empty tuple ()
, which is a relation of arity 0 and cardinality 1.
The relation false
is the empty relation {}
, which has arity 0 and cardinality 0.
Rel does include, however, a separate Boolean
data type that is useful for importing data that explicitly
depends on Boolean
values β in particular, JSON data. See the example below.
Construction
There are two constructors, one for each Boolean
value: boolean_true
and boolean_false
:
// read query
def output = {boolean_false; boolean_true}
Type Relation: Boolean(x)
Boolean(x)
tests whether x
has the data type Boolean
.
// read query
def R = {(1, boolean_true); (2, true); (3, boolean_false); (4, false)}
def output(x, y) = R(x, y) and Boolean(y)
Noteworthy Operations
Examples
In the following example, the JSON true
and false
values are mapped to the Rel data type Boolean
:
// read query
def joe = parse_json["""
{ "address": null, "name" : "JJ" , "person" : true , "company" : false }
"""]
ic { Boolean(joe:person) }
ic { boolean_and[joe:person, boolean_not[joe:company]] = boolean_true }
ic { joe:person = boolean_true }
def output = joe
Here is an example showing how and
, or
, and not
operations over the data types are written:
// read query
def a = boolean_true
def b = boolean_false
def output:not_and = boolean_not[boolean_and[a, b]]
def output:or = boolean_or[a, b]
Note that boolean_and
, boolean_or
, and boolean_not
are distinctly different from the Rel key words and
, or
, and not
.
The former operate only on boolean data, whereas the latter are part of logic expressions like conjunction, disjunction, and negation.
FilePos
Construction
FilePos
types are created when importing CSV files.
They are used as keys when joining columns from the same row.
Currently, a user canβt directly create this data type themselves.
Type Relation: FilePos(x)
FilePos(x)
tests whether x
has the data type FilePos
:
// read query
def config:data="""
a,b,c
1,2,3
4,5,6
"""
def csv = load_csv[config]
def output(p) = csv(_, p, _)
def csv_ic {
subset(csv, (RelName, FilePos, String))
}
Examples
// read query
def config:data="""
a,b,c
1,2,3
4,5,6
"""
def output = ::std::display::table[load_csv[config]]
See CSV Import for more details.
Missing
Generally, missing or null data are simply represented in Rel by not having these facts in a relation.
Missing
is a singleton type, containing only one value, missing
.
It is used for data that require an explicit representation of null data. For instance, JSON data require an explicit representation for missing data (see example below). Data representation that is not fully normalized, such as Third Normal Form (opens in a new tab) (3NF), also requires an explicit representation of missing data.
For data that are stored in the fully normalized Graph Normal Form (GNF), missing data points are represented by not stating the missing fact in the relation. GNF is the recommended way to model data and makes best use of the RKGS query optimizer.
Construction
A Missing
data value is created by writing missing
:
// read query
def output = missing
Type Relation: Missing(x)
Missing(x)
tests whether x
has the data type Missing
:
// read query
def R = {("+1", 'π'); ("+10", missing); ("+100", 'π―')}
def output(x, y) = R(x, y) and not Missing(y)
Examples
Parsing JSON data that contain explicit null data:
// read query
def json = parse_json[""" { "address": null, "name" : "JJ" } """]
ic missing_ic { Missing(json:address) }
def output = json
Next: Keywords and Symbols