Skip to content

Relationships

Relationships define how entities connect to each other. They are declared inside an entity’s schema block using three types: has-many, has-one, and belongs-to.

entity "User" {
    schema {
        pk "id" type="int"
        field "name" type="string"
        has-many "Post" as="posts"
    }
}

entity "Post" {
    schema {
        pk "id" type="int"
        field "title" type="string"
        belongs-to "User" as="author" on="id"
    }
}

has-many

Defines a one‑to‑many relationship where the current entity is the parent (e.g., a User has many Posts).

has-many "Comment" as="comments" on-delete="cascade" optional=true
Attribute Type Required Default Description
name string Target entity name (child)
as string name Relationship name
on-delete string "cascade" Action when parent is deleted: "cascade", "restrict", "set null", "no action"
on-update string "no action" Action when parent’s primary key changes
optional bool false Whether the relationship can be empty (i.e., no child records)

Example:

A User has many Posts. The foreign key column in the post table will be named user_id.

entity "User" {
    schema {
        pk "id" type="int"
        has-many "Post" as="posts" on-delete="cascade"
    }
}

has-one

Defines a one‑to‑one relationship (e.g., a User has one Profile).

has-one "Profile" as="profile" on-delete="restrict"
Attribute Type Required Default Description
name string Target entity name
as string name Relationship name
on-delete string "cascade" Action when parent is deleted
on-update string "no action" Action when parent’s primary key changes
optional bool false Whether the relationship can be missing (i.e., no child record)

Example:

A User has one Profile. The foreign key column in the profile table will be user_id.

entity "User" {
    schema {
        pk "id" type="int"
        has-one "Profile" as="profile"
    }
}

belongs-to

Defines the inverse side of a relationship (child belongs to parent). Usually used with has-many or has-one.

belongs-to "User" as="author" on="id" optional=false
Attribute Type Required Default Description
name string Parent entity name
as string name Relationship name ({as}_id)
on string "id" Primary key column name in the parent table
optional bool false Whether the foreign key can be NULL

Important: The on attribute refers to the parent’s primary key column, not the foreign key in the child.

Example:

A Post belongs to a User. The parent User has a primary key column id.

entity "User" {
    schema {
        pk "id" type="int"   // primary key column name is "id"
    }
}

entity "Post" {
    schema {
        belongs-to "User" as="author"   // foreign key column becomes "author_id"
    }
}

If the parent’s primary key is named differently:

entity "User" {
    schema {
        pk "user_id" type="int"   // custom primary key name
    }
}

entity "Post" {
    schema {
        belongs-to "User" as="author" on="user_id"   // references User(user_id)
    }
}

Complete Example

application "BlogApp" version="0.1" {
    entity "User" {
        schema {
            pk "id" type="int"
            field "name" type="string"
            has-many "Post" as="posts" on-delete="cascade"
            has-one "Profile" as="profile"
        }
    }

    entity "Profile" {
        schema {
            pk "id" type="int"
            field "bio" type="string"
            belongs-to "User" as="user" optional=false
        }
    }

    entity "Post" {
        schema {
            pk "id" type="int"
            field "title" type="string"
            field "content" type="string"
            belongs-to "User" as="author" on="id"
            has-many "Comment" as="comments"
        }
    }

    entity "Comment" {
        schema {
            pk "id" type="int"
            field "body" type="string"
            belongs-to "Post" as="post" on="id"
        }
    }
    profile "dev" default=true {
        listen address="127.0.0.1" port=8080
    }
}

What Terranova Does With Relationships

  • Database schema – Creates foreign key columns in the child table based on the relationship definition.
  • Referential actions – The on-delete and on-update attributes influence how the API behaves (and may be passed to SQLite if supported).

See Also

  • Schemas – Fields and primary keys
  • Entities – Entity container
  • Queries – Using relationships in custom queries
  • Views – Displaying related data in templates