57 Keys

A key declaration on an entity type names attributes that distinguish entities of that type within an extension. A key does not change the carrier of the entity type. Instead, it constrains every extension whose element type is that entity type.

For example, if Supplier declares key {id}, an extension of Supplier may not contain two distinct suppliers with equal id extensions:


entity Supplier
{
    Integer id;
    key {id};
}

entity ShipmentsSystem
{
    Supplier supplier*;
}

Keys are sets of attribute names

A key is a non-empty set of attribute names. Each name must resolve uniquely to a direct or inherited attribute of the entity type. Unknown and ambiguous names are static errors. Repeating an attribute name in one key is also a static error.


key {name, date};       // valid
key {missing};          // Error: unknown attribute
key {name, name};       // Error: repeated attribute

The order of names has no semantic significance: key {name, date} and key {date, name} denote the same candidate key. Paths and arbitrary expressions are not permitted. A calculated key component must first be given a name by declaring a derived attribute.


key {customer.id};          // Error: paths are not permitted
key {normalize(email)};     // Error: expressions are not permitted

→ String normalizedEmail = normalize(email);
key {normalizedEmail};      // valid

Equality on key attribute types

Predica defines = on every type: values of the same static type can always be compared for equality. This includes abstract types. Equality on an abstract carrier is not determined by its declared attributes; it preserves the identity of the concrete values which inhabit that carrier. Every attribute type can therefore be used in a key.

Equality is applied separately to the extension of each key attribute. Equality between the element types of different key attributes is not required.


abstract value AbstractValue
{
    String description;
}

entity Observation
{
    AbstractValue subject;

    key {subject};  // valid: equality is defined on AbstractValue
}

Attribute extensions are key components

An attribute contributes its complete extension to a key. It does not contribute an arbitrarily selected member of that extension. There is therefore no restriction on the cardinality constraint of a key attribute: exactly-one, optional, multivalued, bounded, and infinite-capable attributes may all be used.


entity Person
{
    String name;
    String email+;

    key {name, email};
}

Two Person values have equal key profiles exactly when their complete name extensions are equal and their complete email extensions are equal. More generally, for a key K on entity type E, the key profiles of x:E and y:E are equal iff:


∀a ∈ K, a(x) = a(y)

Extension equality is set equality. For an attribute a with element type T:


a(x) = a(y)  iff  ∀v:T (v ∈ a(x) ↔ v ∈ a(y))

An infinite extension is a mathematically valid key component. Whether its equality can be decided or indexed efficiently depends on its representation and is an implementation concern rather than a change to the key's denotation.

Base and derived key attributes

A key may name either a base or derived attribute, whether declared directly or inherited. A derived key component is compared using the extension produced by its definition.


entity Person
{
    String givenName;
    String familyName;
    → String normalizedName = normalizeName(givenName, familyName);

    key {normalizedName};
}

If a subtype refines an inherited derived calculation, the inherited definition remains in force and the refined calculation must produce the same extension. The meaning of an inherited key is therefore unchanged.

Keys on abstract entity types

Every abstract entity type must have at least one explicitly declared or inherited key. A root abstract entity must therefore declare a key. An abstract subtype may inherit a key and does not need to repeat it. A subtype cannot remove or replace an inherited key, although it may declare additional candidate keys. An abstract entity declaration with no effective key after inheritance is a static error.

An underived key attribute on an abstract entity is an outstanding attribute requirement. Every concrete subtype must implement it as a base or derived attribute. A derived key declared by an abstract entity already has an implementation and may also be inherited.


abstract entity Identified
{
    String identifier;

    key {identifier};
}

entity Customer isa Identified
{
    String identifier;
    String name;
}

entity Catalogue
{
    Integer id;
    Identified item*;

    key {id};
}

The inherited key permits Catalogue.item to distinguish and index values uniformly, including when its extension contains values of different concrete subtypes of Identified.

The inherited key provides operational identity within each Identified extension; it does not define equality on the carrier of Identified. Keys constrain which values may coexist in an extension and do not change the carrier or equality of the entity type.

Multiple candidate keys

An entity may declare multiple candidate keys. All candidate keys have equal logical status:


entity Book
{
    Integer id;
    Person author;
    String title;
    String description;

    key {id};
    key {author, title};
}

A database implementation may use the first candidate key as its primary physical index and the others as secondary indexes, but that choice does not alter their logical meaning.

Default key

If a concrete entity does not explicitly define or inherit a key, the system assumes one key consisting of all base attributes. This yields structural identity: two instances are identical exactly when all their base attribute extensions are equal.

Relationship entities such as ownership, enrolment, membership, and authorship commonly use this default:


entity Ownership
{
    Person owner;
    Vehicle vehicle;
}

An abstract entity does not receive the default all-base-attribute key because its attributes do not collectively identify its carrier values. It must instead have at least one explicit or inherited key.