REL
REFERENCE
Data Types
Other

# Data Types: 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

// 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:

// query

def output = {boolean_false; boolean_true}

### Type Relation: Boolean(x)

Boolean(x) tests whether x has the data type Boolean.

// query

def R = {(1, boolean_true); (2, true); (3, boolean_false); (4, false)}

def output(x, y) = R(x, y) and Boolean(y)

### Examples

In the following example, the JSON true and false values are mapped to the Rel data type Boolean:

// 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:

// 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:

// query

def config:data="""
a,b,c
1,2,3
4,5,6
"""

def output(p) = csv(_, p, _)

def csv_ic {
subset(csv, (RelName, FilePos, String))
}

### Examples

// query

def config:data="""
a,b,c
1,2,3
4,5,6
"""

def output = 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 RKGMS query optimizer.

### Construction

A Missing data value is created by writing missing:

// query

def output = missing

### Type Relation: Missing(x)

Missing(x) tests whether x has the data type Missing:

// 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:

// query

def json = parse_json[""" { "address": null, "name" : "JJ" } """]
def output = json