Define query

Define queries are used to add new types, constraints, or functions to the schema.

Syntax

Define queries start with the define keyword following by definition statements.

define
  <definition_statements>

Definition statement can consist of any number of schema-related statements, simple or composite. Statements should be separated by semicolons. Schema statements in a define query cannot use variables or values, except for functions.

Behavior

A define query adds schema statements to an existing schema. These statements can add new types and functions, or they can add new interfaces and annotations to existing types. Define queries cannot change schema statements already existing in a schema.

Define queries are idempotent, meaning they can be applied multiple times without changing the result of the initial application.

An error is returned (on execution or on commit), and no changes are preserved, if:

  • A definition conflicts with an existing definition.

  • The query results in an invalid schema.

Statements

  • entity statements define new entity types. This statement should be provided for every new type of kind entity.

  • relation statements define new relation types. This statement should be provided for every new type of kind relation.

  • attribute statements define new attribute types. This statement should be provided for every new type of kind attribute.

  • relates statements define new role types for relations. It can be followed by the as keyword to define a specialization for two role types.

  • plays statements define new roleplayings between types and relation types. Only entity and relation types can play roles.

  • owns statements define new ownerships between types and attribute types. Only entity and relation types can own attributes.

  • value statements define new value types of attribute types. An attribute type can only have up to one value type. If another value is already defined for the subject type, an error is returned.

  • sub statements define new subtyping between two types. Those types should be of the same kind: entity, relation, or attribute. If another sub is already defined for the subject type, an error is returned.

  • @annotations define new annotations. If another annotation of the same type but with different arguments is already defined, an error is returned. Can be applied to:

    • Type labels for entities, relations, attributes.

    • interfaces: relates, plays, owns.

    • Attribute value types: value.

  • fun statements define new functions.

Examples

Defining types

Defining entity types
#!test[schema, commit]
define entity user;
Defining relation types
#!test[schema, fail_at=commit]
define relation parentship;
Defining attribute types
#!test[schema, fail_at=commit]
define attribute email;

Defining interfaces

Defining relation type’s relates
#!test[schema]
#{{
define relation parentship, relates unused-role;
#}}
#!test[schema]
define parentship relates parent, relates child;
Defining relation types with subtyping
#!test[schema, commit]
define relation fathership sub parentship;
Defining relates with role type specializing
#!test[schema]
define fathership relates father as parent;
Defining roleplaying for multiple roles
#!test[schema]
define user plays parentship:parent, plays parentship:child;
Defining attribute type’s value type
#!test[schema]
define attribute email @abstract; # cheat.
#!test[schema]
define email value string;
Defining type’s ownership
#!test[schema]
define user owns email;

Defining annotations

Defining type’s annotation without arguments
#!test[schema]
define parentship @abstract;
Defining attribute type’s annotation and value type’s annotation with arguments
#!test[schema]
define email @independent, value string @regex("^.*@\w+\.\w+$");
Defining type’s ownership’s annotation with arguments
#!test[schema]
define user owns email @card(0..2);
Defining annotations for relates
#!test[schema]
define parentship relates parent @abstract;
Defining annotations for specializing relates
#!test[schema]
define fathership relates father as parent @abstract;

Defining functions

#!test[schema, commit]
define
  fun karma_with_squared_value($user: user) -> karma, double:
    match
      $user has karma $karma;
      let $karma-squared = $karma * $karma;
    return first $karma, $karma-squared;