orb » data modelling


A bit-field is a user-defined type consisting of up to 64 bits, each with symbolic meaning. A field may be assigned a bits type to this type to have each of its bits be a symbolic value.

Bit-field names are unique (case insensitive) among a data model's enumerations, other bit-fields, and structures. orb saves bit-field names as lower-case to avoid confusion.

Bit-fields are divided into items that describe each bit in a bit-field. A bit-field must have at least one item.

bit-field item

A single bit in a user-defined bit-field type. A bit-field item is paired with the bit index from zero to sixty-three, inclusive, standing for the first bit to the last bit, respectively.

Bit-field item names are unique (case insensitive) among the parent bit-field's other items. orb saves these names as lower-case to avoid confusion.

bit (field type)

A field type. It represents a bit set in an opaque 64-bit bit-field. Bits are validated as integers between 0 and 64 inclusive, with 0 meaning no bits, 1 being the first bit, and so on until the last bit. While they are validated as a single bit (or no bits), values are stored and retrieved as a bit-mask.

For applications with specific bit-field layouts, use the bits type.

bits (field type)

Like the bit type, but having each bit index be defined according to a named bit-field.

blob (field type)

A field type that's simply binary data of a given length. This is well-suited for binaries like images, binary file-formats, and so on.


In version control, a branch is a series of versions that are on the branch. The branch points to the latest version in its path of versions. A data model consists of an implicit main branch, sometimes called the trunk, when the first version is merged. Only committers to a data model are allowed to create new branches.

When a new branch is created, the next version will be on that branch, and the original branch continues to point to the prior version. Thus, changes may be made independently on the new and original branch.

Branches may be (and usually are) merged into one another at some point when development on a branch reaches its desired conclusion. A common development paradigm is to have features develop on a particular branch, which is merged into the trunk when the feature is stable.

date (field type)

Like the epoch type, but validating as an ISO 8601 date in the YYYY-MM-DD format, then translated into an epoch at time zero for the given date. This is stored as a 64-bit integer.


A structure operation to delete data already in the database. It is very similar to the update operator, except it does not accept a set of modifiers—only constraints.

email (field type)

A field type. This is just text (UTF-8) that's minimally validated as an e-mail address. This is not guaranteed to cover the full specification of e-mail addresses, but works in most cases.


An enumeration is a user-defined type consisting of fixed values, each with symbolic meaning. A field may be assigned an enum type to this for for each possible value be have symbolic meaning.

Enumeration names are unique (case insensitive) among a data model's other enumerations, bit-fields, and structures. orb saves names as lower-case to avoid confusion.

Enumerations are divided into items that describe each possible value. An enumeration must have at least one item.

enumeration item

A single value in a user-defined enumeration type.

Enumeration item names are unique (case insensitive) among the parent's other items. orb saves these names as lower-case to avoid confusion.

enum (field type)

Like the int type, but with values constrained to items in the named enumeration.

epoch (field type)

A field type. It represents seconds since (or until) 0 hours, 0 minutes, 0 seconds, January 1, 1970, Coordinated Universal Time (UTC). (This is also known as the UNIX epoch.) This is stored as a 64-bit integer.


A field is equivalent to a table column in SQL, an interface property in TypeScript, or a column in a spreadsheet. It describes how a piece of data is stored, its representation, and its relationship to other fields.

Each field has a unique name (case insensitive) among the parent structure's other fields. orb saves field names as lower-case to avoid confusion.

A field is identified with a type. The type may be one of bit, bits (also called a bitfield), date, epoch, int, real, blob, text, password, email, struct, or enum.

Zero or more flags may be associated with a field. These may be row identifier, which means that values are unique and used by the database as an identifier; can be null, meaning the database values may be null; unique if each value is unique; and not exported if the generated API never exports the value.


A structure operation to insert new data into the database. Inserts are either enabled for a structure or not.

int (field type)

A field type. Stored as a 64-bit signed integer.


One or more merges describe changes from one version to another. A merge consists of a user-given message that describes a logical change and a description of the change being documented. Merges are purely informational.

The set of merges between versions is suggested by orb to allow for separately describing the changes between versions. This facilitates better change auditing and history analysis.

password (field type)

A field type. This is always hashed (using bcrypt with randomly-generated salt) prior to being stored in the database. Queries and other operations are slower on password fields because they must be compared to hashed values programmatically, instead of in the database itself by simple text comparison.


A structure operation to extract data from the database. Queries return results in the data types dictated by structures and their fields. There are three main types of queries: a search, which returns a single data type; a list, which returns a set of data types; and an iterator, which returns one data type at a time in an iteration over the database.

In general, searches are for single results (usually on unique or rowid fields), listings are when an application needs to process multiple results at once, and iterators are for general display or aggregation.

A fourth type, count, simply returns the number of matching results.

Queries work by matching rows of data with zero or more query fields. Each field is matched by an operator: equal, the default, which tests for value equality; nequal, for value non-equality; ge, for greater than or equal (numeric or lexicographic); gt, for greater than (numeric or lexicographic); le, for less than or equal (numeric or lexicographic); lt, for less than (numeric or lexicographic); like, for textual pattern matching; and, for bit-wise AND; or, for bit-wise OR; streq, for direct string comparison; strneq, for direct string comparison; isnull, for whether a field is null; or notnull. for whether a field is not null; The streq and strneq fields are useful for passwords, which would otherwise be checked out-of-band. The like operator is only for text types, while the and and or are only for integers. If a field is null, comparisons always fail—use isnull and notnull.

real (field type)

A field type. Stored as a double-precision floating point number, validated as a decimal (or natural) number.


A certain kind of version that increments one or more of the major, minor, or patch components of the release identifier x.y.z-b.

Releases should follow the guidelines of semantic versioning, but this isn't enforced by orb. However, releases may only increase from previous releases, e.g., 0.1.3 to 0.2.1 or 0.6.4 to 1.0.0.


A role is the context of a running application. When roles are set for a data model, operations (and the export of data) are restricted to set roles. An application begins in a given role, then may transition to other roles.

By default, a data model has no roles. If any roles are user-defined, there are several implicit roles that come along for the ride: all, none, and default. An application begins in the default state, and is able to migrate to any other state from it. (It is a source state.) The none role, on the other hand, may not be migrated out of (it is a sink state), nor may any operations or data be defined for it. User-defined roles all fall under the all role, which may itself never be entered.

User-defined roles are hierarchical and fall under the all role. In general, an application begins in default and transitions into a user-defined role. It may then transition into sub-roles to narrow the scope of allowed operations: a sub-role expands which operations are allowed.

By default, all operations (queries, updates, deletes, and inserts) are available to any caller. When roles are enabled, the data model must white-list specific roles. Data, on the other hand, is exported by default—the data model may specifically deny exports to roles.

struct (field type)

Fields of this type aren't stored in the database and are only represented in the model's operations and programmatic data types. These represent nested types for reference fields, where referenced result is included as part of the data type.


A structure is equivalent to a table schema in SQL, an interface in TypeScript, or a sheet (or logical grouping of columns) in a spreadsheet workbook. The term is sometimes shortened to just struct (a structure is also equivalent to structs in C/C++).

Each structure has a unique name (case insensitive) among a data model's enumerations, bit-fields, and other structures. orb saves structure names as lower-case to avoid confusion.

Structures are divided into fields, just as SQL tables are divided into columns and TypeScript interfaces are divided into properties. A structure must have at least one field. Each structure may also contain an insert (operation) and zero or more queries, updates, or deletions.

text (field type)

A field type. (Usually the most common type.) Arbitrary-length text. Text must be encoded in UTF-8 (or plain ASCII). Other encodings may be accepted, but are not guaranteed to work properly. The NUL character (value of zero) is prohibited.


In version control, synonym for the main branch. The trunk branch is created when the first version is committed to a data model. It is always called main, although other branches may also be named main.


A structure operation to modify data already in the database. An update works over two sets: the constraint set, which dictates which data to change; and the modifier set, which consists of the changes. Both of these consist of zero or more fields, with the modifier being one or more.

The constraint set is similar to a query in admitting a field and an operator. The modifiers are applied to rows matching the constraints.

The modifier set dictates how the row should be changed. It consists of the fields that will be changed (the application provides the values to set) and a modifier. The modifier may be one of set, the default, which simply sets the value; concat, a string operator for concatenating to the existing value; dec, for decrementing by the given integer amount; inc, for incrementing by the given integer amount; strset, for directly setting the value. The last modifier is useful for password types, to directly set the hash instead of using the built-in hashing mechanism.


A well-formed data model specification connected to a series of merge statements defining changes from a prior version (or a generic message for the initial version). A version has zero or one parent (predecessor), with zero for the initial version, but may have multiple children. A version sits on a branch.

Only branch committers or owners may create new versions on a branch.

A version may have multiple children if branches are created on the version.

Versions are identified as x.y.z-b, where x.y.z. are the last release and b increments automatically with each subsequent version, resetting at the release. This triplet is composed of the major, minor, and patch numbers, with the build number following the hyphen. This conforms to the syntax of semantic versioning.