Modifiers

The .forge field modifiers — + auto-generate, & unique, ^ indexed, and ? nullable — with placement and type rules.

Modifiers are sigils on a field's type. Three are prefix modifiers (+, &, ^) placed before the type name; one is the nullable modifier (?) placed after.

SymbolNamePositionMeaningValid on
+auto-generateprefixFill on create (uuid/timestamp today; integer is a marker)u32, u64, uuid, timestamp only
&uniqueprefixValue must be unique (enforced)any type
^indexedprefixBuild an index for fast lookupsany type
?nullablepostfix (or prefix)Value may be absentany type

+ — auto-generate#

+ marks a field ForgeDB fills for you. On create (db.create_<model>, and the REST POST /api/<model> that routes through it), an omitted or nil +uuid gets a fresh Uuid::new_v4() and an omitted or zero +timestamp gets the current time, so callers never supply them. Valid only on u32, u64, uuid, and timestamp:

id: +uuid            // fresh UUID on create when omitted/nil
seq: +u64            // primary-key marker — NOT yet auto-incremented (see below)
created_at: +timestamp   // current time on create when omitted/zero

`+` is type-restricted

+ on any other type — e.g. name: +string — is a fatal parse error. Only the four generatable types above are allowed.

Integer `+` is a marker, not yet auto-incremented

+u32/+u64 currently only mark the primary-key / auto field — the generator does not yet synthesize a value for them, so a create must still supply the integer id. Auto-increment for integer keys (a monotonic, restart-safe, reuse-free counter) is planned; it is deliberately not shipped as a subtly-wrong version that could reuse a deleted id. +uuid and +timestamp are fully synthesized today. See issue #187.

& — unique#

& marks a column whose values must be unique across all rows. Uniqueness is enforced: on insert/update the generated code probes the field's index and rejects a duplicate (HTTP 409). Applies to any type.

email: &string @email
slug: &string

& builds an index too, so a unique field is also fast to look up.

^ — indexed#

^ builds a secondary index on the field for fast find_by_* lookups and for index-served REST filters. Applies to any indexable type (not json).

slug: ^string
views: ^u64
status: ^OrderStatus

Combine & and ^ freely; since & already indexes, ^& mainly documents intent. See indexes & projections for hash-vs-ordered index behavior.

Combining prefix modifiers#

Any combination of +, &, ^ is allowed, in any order, all before the type — subject to the rule that + is valid only on u32/u64/uuid/timestamp:

id: +&^uuid               // auto-gen + unique + indexed (auto-gen needs an eligible type)
email: ^&string @email    // indexed + unique

? — nullable#

? makes a field optional (may be absent / NULL). It is a postfix modifier, placed after the type, and this is the idiomatic form. A prefix form also parses:

bio: string?         // nullable string (idiomatic)
age: i32?            // nullable int
avatar: ?string      // prefix form — also parses
published_at: timestamp?

? composes with the prefix modifiers:

external_id: +uuid?  // auto-generate and nullable

On a relation, prefix ? declares an optional foreign key (editor: ?User). See relations.

Nullable storage keeps absent distinct from zero

A nullable fixed-width field carries a 1-byte presence tag, so None and a stored 0 (or Value::Null, or an empty string) round-trip as different values.

Search documentation

Find pages across the ForgeDB docs