42 Cardinality Constraint Patterns

Exactly one requirements

  • a person must have exactly one primary residence
  • a project must have exactly one responsible officer

entity Person
{
    Address primaryResidence;
}

At least one requirements

  • a company must have at least one director
  • a contract must have at least one signatory

entity Company
{
    Person director+;
}

At most one

A person may have at most one active passport.


entity Person
{
    Passport passport?;
}

Optional-but-constrained fields

Sometimes a field is optional, but if present, it must satisfy further constraints. Example: A building project may have an environmental clearance, but if it does, it must be valid.


entity Project
{
    EnvironmentalClearance clearance?;

    constraints
    {
        // ∀C:EnvironmentalClearance ∀V:Boolean
        //     (this.clearance(C) ∧ C.valid(V)) → V
        clearance.valid;
    }
}

Collections that must be non-empty when another condition holds

Example: A project with “commercial = true” must have at least one safety audit.


entity Project
{
    Boolean commercial;
    Audit audit*;

    constraints
    {
        // if commercial, then there is at least 1 audit
        // Shorthand for commercial → audit.Σexists;
        // ∀C:Boolean (this.commercial(C) → ∃A:Audit this.audit(A))
        commercial → audit:+;
    }
}

Cardinality constraints on joins

A builder must hold exactly one valid licence at the time of a project.


entity BuilderLicence
{
    ...
    Boolean valid;
}

entity Builder
{
    BuilderLicence licence*;

    constraints
    {
        // exactly one valid licence
        // This is shorthand for licence.[valid].Σcount = 1
        // |{ L:BuilderLicence | ∃V:Boolean this.licence(L) ∧ L.valid(V) ∧ V }| = 1
        licence.[valid]:1;
    }
}