Skip to main content

Types

This page uses Wasm code blocks so you can run the examples directly in the browser.

Objects are classified into types making each object an instance of one or several types. The set of all instances of a type is called the extent of the type. The types are organized in a supertype/subtype hierarchy. If an object is an instance of a type, then it is also an instance of all the supertypes of that type; conversely, the extent of a type is a subset of all extents of the supertypes of that type.

System types

The following picture shows the type hierarchy for built-in system types:

System types

The most general type in named Object. All other types are below Object in the hierarchy. The arrows connecting two types in the diagram should be read is a.

Literal types

Literal objects are self-described system maintained objects that are implicitly created or deleted by the system when needed. Literals types such as numbers (type Number), strings (type Charstring), Booleans (type Boolean) or time stamps (Timeval) are below type Literal in the type hierarchy. The type Number can represent both integers (type Integer) and floating point numbers (type Real).

The function typesig(o) can be used to inspect the type signature of object o as a string specifying the type of o. The following expression exemplify type signatures of various kinds of literal objects:

typesig(123);
typesig(1.2);
typesig(-2.4e-21);
typesig(+inf);
typesig('Hello World');
typesig(|2023-09-21T09:45:44.086Z|);
typesig(true);
typesig(false);
typesig(null);

Collection types

Collections (type Collection) are objects containing collections of other objects as elements. As literals, collections are implicitly created and deleted by the system when needed. The following kinds of collections are supported:

  • Collections of type Bag contain unordered sets of objects where duplicates are allowed. A set query return a bag as result.

  • Type Json represent JSON collections that, more specifically:

    • Collections of type Vector contain ordered sequences of objects of any kind. A vector query returns an collection of type Vector as result.

    • Collections of type Record represents key/value pairs.

  • Collections of type Array represent tensors and contain numerical values organized as a cube of arbitrary dimensionality. An array query returns an object of type Array as result.

  • Type Stream represents a possibly infinite and growing sequence of objects, e.g. to represent continuous readings of sensor measurements. A stream query returns a stream as result.

Examples of collections:

bag(1,2,3);
[1,2,3];
[[1,2],[3,4]];
{"id":1,"name":"Kalle","age":32};
array([1,2,3]);
array([1.1,2.2,3.3]);

The type signatures of collections are often parameterized types with format "type of other type", for example:

typesig(bag(1,2,3));
typesig([1,2,3]);
typesig([[1,2],[3,4]]);
typesig({"id":1,"name":"Kalle","age":32});
typesig(array([1,2,3]));
typesig(array([1.1,2.2,3.3]));

Surrogate types

Each instance of a surrogate type has an associated object identifier (OID). The surrogate objects are explicitly created or deleted by the user or the system. Examples of surrogate objects are objects representing real-world entities such as sensors, system objects such as functions, or even objects representing other SA Engine peers.

The types Type, Function, Userobject and their subtypes are all surrogate types.

  • The type Userobject is a place holder for user defined types used for organizing data in the local database. All user defined types are subtypes of type Usertype.

  • The system type named Type represents the types themselves, such as their names, their supertypes, etc.

  • The system type Function represents functions and their properties.

User defined types

The create type statement creates a new user defined type.

For examples:

create type Person;
create type Student under Person;
create type Teacher under Person;

The result of a create type statement is a surrogate object representing the so created type.

Type names are not case sensitive and the type names are always internally upper-cased. For clarity all type names used in examples in this manual have the first letter capitalized. Type names must be unique in the database.

The new type will be a subtype of all the supertypes in the under clause.

If no supertypes are specified the new type becomes a subtype of the system type named Userobject.

After the type definitions above the type hierarchy around type Userobject will look like this:

Multiple inheritance is defined by specifying more than one supertype, for example:

create type TA under Student, Teacher;

Defining properties

Properties of a type are defined as functions. The simplest kind of functions are stored functions, which are tables stored in the local database. Let us add the properties name and income to type Person as stored functions:

create function name(Person p) -> Charstring
as stored;
create function income(Person p) -> Real
as stored;

Once types and functions are defined the database can be populated by creating new objects, for example:

create Person  (name,    income) instances
:venus ("Venus", 3500),
:serena ("Serena",3900)

The statement above creates two new objects of type Person and binds the session variables :venus and :serena to those objects. It thereby sets values of the stored functions name and income to the names and incomes of :venus and :serena, respectively.

When the database is populated we can make simple queries by calling the new stored property functions, for example:

name(:venus);
income(:serena)

Deleting types

The delete type statement deletes a type and all its subtypes.

Example:

   delete type Person;

If the deleted type has subtypes they will be deleted as well. In this case Student, Teacher, and TA and all theirs properties and objects are deleted.