OriginChainDB

Schema field reference

Look up the fields used to define tables, indexes, relationships and validation.

Use this page to look up schema settings; start with the table name, ID and fields.

New to schema files? Follow the walkthrough.

Look up the schema part you needOnly add optional rules your table requires; the accepted manifest fields are listed below.
  1. Check the table identityLook up namespace, table and primary_key.
  2. Check a column definitionFind its supported type and field options.
  3. Look up an optional ruleUse the index, relation or constraint section when needed.
  4. Register and inspect errorsCorrect the named definition before adding records.

Name the table

FieldRequiredMeaning
namespaceYesGroup name, such as shop. Use letter-prefixed snake_case.
tableYesTable name, such as orders. Queries use shop.orders.
primary_keyYesArray of column names that identify one record.
versionNoDefaults to 1; increment as required by the schema-change workflow.

SQL can address composite keys. The direct /rows/:schema/:pk read accepts only one key column.

Define columns

Repeat [[columns]] for each field.

FieldMeaning
nameColumn name and the JSON key used in row writes.
tyData type, chosen from the tables below.
requiredDefaults to false. Set true when the value must be supplied.

Basic types

TypeUse for
strNames, IDs and other text.
i64Whole numbers that may be negative.
u64Non-negative whole numbers.
f64Approximate numeric values.
boolTrue/false values.
bytesEncoded binary values.

Extended column types

TypeValue or setting
timestampEpoch milliseconds; supported input forms also include timestamp text.
dateEpoch days; supported input forms also include date text.
intervalDuration in milliseconds, including negative values.
uuidValid UUID string.
decimalExact decimal text, such as "19.99"; optional precision and scale rules.
enumString selected from declared variants.
textText content.
jsonJSON object or array.
listArray; an optional element type checks each item.
inetIPv4 or IPv6 string.
pointLatitude/longitude object or a longitude/latitude pair.
vectorVector metadata with [columns.params] and vector_dim. Write search values through the vector API.

Picking the right type for common data

  • Use str for ordinary identifiers and uuid when UUID validation is useful.
  • Use decimal strings or integer minor units for money. Avoid passing exact amounts through floating-point values.
  • Include units in field names, such as price_cents or duration_ms.
  • Check SQL return formats before converting dates or large numbers in your application.

Add an index

An index gives the query planner another way to find matching rows. Start with fields used by important filters and check the actual plan with EXPLAIN.

FieldMeaning
nameIndex name used in plans and administration.
columnsOrdered list of indexed columns.

For [customer_id, placed_ms], a left-prefix match can use customer_id. Do not assume the same index helps a filter on placed_ms alone. Extra indexes also add write work.

Index examples
[[indexes]]
name    = "by_status"
columns = ["status"]                  # single-column

[[indexes]]
name    = "by_customer_and_time"
columns = ["customer_id", "placed_ms"]  # composite, in declared order

Define a graph relation

A relation names a connection between rows. Row writes maintain its derived graph links.

FieldMeaning
nameRelationship name used when following the link.
from_colLocal column containing the destination ID.
bidirectionalDefaults to true; also maintains a reverse link.
target.namespace, target.table, target.pkDestination table and primary-key column.
Relation examples
[[relations]]
name          = "supplied_by"         # the verb you'll walk in code
from_col      = "supplier_id"         # the FK column on THIS table
bidirectional = true                  # default; reverse edge written atomically

[relations.target]
namespace = "shop"                    # target table's namespace
table     = "suppliers"               # target table's name
pk        = "id"                      # target table's primary-key column

# Self-relations work - direction tags resolve the collision:

[[relations]]
name          = "follows"
from_col      = "followee_id"
bidirectional = true

[relations.target]
namespace = "social"
table     = "users"
pk        = "id"

A relation does not require the destination row to exist. Add a foreign key when that rule is needed. See graph setup for key and traversal limits.

Require a matching row

A foreign key rejects a reference to a missing record.

FieldMeaning
nameOptional error-reporting name; defaults to the source column plus _fk.
from_colLocal referencing column.
target_schemaDestination namespace.table.
target_colDestination primary-key or unique-indexed column.
on_deleteno_action, restrict, set_null, cascade or set_default.
on_updateno_action, restrict or set_null; update cascades and defaults are not supported.
Foreign-key example
[[foreign_keys]]
name          = "fk_customer"         # optional - defaults to "<from_col>_fk"
from_col      = "customer_id"         # column on THIS table
target_schema = "shop.customers"      # "namespace.table" of the target
target_col    = "id"                  # PK or unique-indexed column on target
on_delete     = "no_action"           # refuse deletion while referenced

no_action and restrict refuse a delete while references remain. set_null requires a nullable source column. cascade deletes referencing rows recursively; a conflicting restriction or the cascade row budget rejects the whole delete. set_default substitutes the column default, or NULL when no default exists, and validates that replacement against the foreign key.

These propagation actions apply to deletes. cascade and set_default remain unsupported for on_update. Check cross-shard restrictions before linking separately placed tables.

Validate values with CHECK

A check uses name and expression to reject values that violate a rule, such as a negative quantity.

Expression grammar

OperationExample
Comparisonqty > 0 using =, !=, <, <=, > or >=.
Combine conditionsprice > 0 AND price < 1000000; also OR and NOT.
Test missing valuesdescription IS NOT NULL.
Allow a setstatus IN ('pending', 'paid').

A NULL result fails the check. To allow a missing value, include it explicitly: qty IS NULL OR qty > 0.

CHECK examples
[[check_constraints]]
name       = "qty_positive"
expression = "qty > 0"

[[check_constraints]]
name       = "country_or_continent_set"
expression = "country IS NOT NULL OR continent IS NOT NULL"

[[check_constraints]]
name       = "status_in_set"
expression = "status IN ('pending', 'paid', 'cancelled')"

Extract a nested JSON value

Use [[extractions]] to derive a queryable column from a nested path at write time.

FieldMeaning
nameName of the derived column.
pathDotted source path, such as customer.address.country.
tyType of the extracted value.

Missing paths produce the type's zero value. Extractions do not create full-text or vector indexes.

Extraction examples
# Pull a derived column out of a nested JSON row at write time.
# The dotted path walks into the JSON; missing fields emit zero values.

[[extractions]]
name = "customer_country"
path = "customer.address.country"
ty   = "str"

[[extractions]]
name = "order_total_cents"
path = "totals.grand_cents"
ty   = "i64"

Set row expiry

TTL means time to live. Choose one way to determine when a row expires.

Two ways to declare it

SettingBehaviour
Column ttl = "30d"Gives the whole row a fixed lifetime from its write. Units: s, m, h, d, w.
[ttl] with column = "expires_at"Uses the row's timestamp or date value as its expiry.
TOML expiry examples
# Row expiry (TTL) - two ways to declare it. Use ONE.

# (A) Fixed lifetime: put `ttl` on any column and the WHOLE row expires
#     this long after it is written. Units: s / m / h / d / w.

[[columns]]
name     = "id"
ty       = "str"
required = true
ttl      = "30d"                 # every row lives 30 days from write

# (B) Per-row expiry: instead of (A), add a [ttl] block pointing at a
#     timestamp or date column. Each row expires at its own stored value.
#
#   [ttl]
#   column = "expires_at"        # a `timestamp` or `date` column
SQL expiry example
CREATE TABLE app.sessions (
  id       TEXT NOT NULL PRIMARY KEY,
  user_id  TEXT
) WITH (ttl = '30d');
  • TTL applies to the whole row, not a single field.
  • Existing rows are not assigned a new expiry until rewritten.
  • A missing per-row expiry does not expire the record.
  • Coordinate lifetimes across related tables; do not assume TTL cascades to all related records. Check configured foreign-key delete actions.

Describe a vector collection

[vector] describes how embeddings in the collection should be shaped. It does not generate them or index ordinary row writes.

FieldRequiredMeaning
dimYesPositive number of values in each vector.
distanceNocosine by default; also l2, dot, manhattan or l1.
embedderNoModel identity. A different supplied identity is rejected; an omitted identity is not blocked.
Vector metadata example
# Optional. One [vector] table per manifest.

[vector]
dim      = 768                        # REQUIRED. No default.
distance = "cosine"                   # the default. Five values accepted.
embedder = "your-768d-model"          # replace with the model used for these vectors

# A `vector` COLUMN carries the same width in its own params block.
# Declare both and the two dims must agree, or registration fails.

[[columns]]
name = "embedding"
ty   = "vector"

[columns.params]
vector_dim = 768

How distance resolves at runtime

An omitted request measure uses the declared distance. A conflicting non-default declaration returns 400. A cosine declaration does not reject another request measure in this contract, so enforce consistent settings in your application.

Use [vector], not [[vectors]]; use schema distance, not request metric. Unknown manifest fields can be ignored, so verify the stored definition after registration. IVF and quantization settings use separate endpoints.

Complete reference example

This example combines columns, indexes, relations, foreign keys and checks. Register its target tables before using it.

Combined orders schema
# A schema using every block at once.
namespace   = "shop"
table       = "orders"
primary_key = ["id"]

[[columns]]
name = "id"
ty   = "str"
required = true

[[columns]]
name = "customer_id"
ty   = "str"
required = true

[[columns]]
name = "product_id"
ty   = "str"
required = true

[[columns]]
name = "qty"
ty   = "i64"

[[columns]]
name = "total_cents"
ty   = "i64"

[[columns]]
name = "placed_ms"
ty   = "u64"

[[indexes]]
name    = "by_customer"
columns = ["customer_id"]

[[indexes]]
name    = "by_product_and_time"
columns = ["product_id", "placed_ms"]

[[relations]]
name          = "bought_product"
from_col      = "product_id"
bidirectional = true

[relations.target]
namespace = "shop"
table     = "products"
pk        = "id"

[[relations]]
name          = "by_customer"
from_col      = "customer_id"
bidirectional = true

[relations.target]
namespace = "shop"
table     = "customers"
pk        = "id"

[[foreign_keys]]
name          = "fk_customer"
from_col      = "customer_id"
target_schema = "shop.customers"
target_col    = "id"
on_delete     = "restrict"

[[check_constraints]]
name       = "qty_positive"
expression = "qty > 0"

[[check_constraints]]
name       = "total_positive"
expression = "total_cents > 0"

Create your first schema ยท Register and verify it

ยฉ 2026 Silicoyn Technologies Pvt Ltd

On this page