<schema>
Declarative database schema. Lowers to SQL DDL at compile time; the schema-differ compares declared shape to live DB shape and emits migrations. SQL- mirror canonical, with additive shared-core vocabulary that lowers to CHECK constraints.
Syntax
<schema>
tableName {
columnName: sqlType [native-sql-constraints] [shared-core-validators]
...
}
...
</schema>
Each table is a brace block; each column is a typed declaration with optional constraints. Two constraint vocabularies coexist on a column: native SQL constraints (canonical) and shared-core validators (additive). Both are legal; mixing is legal.
Worked example
A users table with both vocabularies in play.
<schema>
users {
id: integer primary key
email: text not null unique
name: text req length(>=2)
age: integer min(18) max(120)
role: text default('user') oneOf([user, admin])
}
posts {
id: integer primary key
user_id: integer not null references(users.id)
title: text req length(>=1) length(<=200)
body: text req
published: integer default(0)
}
</schema>
The compiler reads the schema, compares to the live DB
(via SQLite
PRAGMA table_info()
or equivalent), and emits migration SQL for the diff.
Dev mode applies the migrations on reload; production
runs them as a versioned step.
Semantics
-
SQL-mirror canonical (§39.5.9).
Native SQL constraints
(
not null,unique,primary key,references(table.col),default(literal)) are the source-level canonical form. They map 1:1 to emitted DDL. -
Shared-core additive (§39.5.7).
The universal-core validator vocabulary
(
req,length,pattern,min,max,gt,lt,gte,lte,eq,neq,oneOf,notIn) is admitted on schema columns and lowers to SQL CHECK / NOT NULL constraints per §39.5.8. The same word fires the same constraint in three loci: state-validator, refinement-type, and schema-column. -
Lowering rules (§39.5.8).
reqlowers toNOT NULL;length(>=N)lowers toCHECK (length(col) >= N);pattern(re)lowers driver-dependent (Postgres ~, SQLite/MySQL REGEXP);oneOf([a, b, c])lowers toCHECK (col IN (a, b, c)). -
SQL passthrough is inviolable. SQL
strings sent to the database from
?{}blocks are unchanged in shape. The shared-core vocabulary touches scrml source only; the wire form stays standard SQL. -
Compile-time cross-check. The
schema is the source of truth for column types and
names used by
?{}blocks. The compiler validates queries against the schema at compile time; unknown columns / type mismatches fire E-SQL-* errors before runtime. -
Migration diff. The schema-differ at
compiler/src/schema-differ.js(~273 LOC) compares desired (<schema>AST) against actual (PRAGMA table_info()output) and emits migration SQL.
Errors this feature can fire
- E-SQL-006 — deprecated SQL form in schema
- E-SQL-008 — bracket-matched ?{ scanner caught unmatched brace
- E-STRUCTURAL-ELEMENT-MISPLACED — <schema> in unsupported context
Edge cases
-
Mixed vocabularies on one column.
Legal:
email: text not null req length(>=3) pattern(/^.+@.+$/).not null+reqtogether is redundant but not erroneous — both lower to NOT NULL semantics. -
Driver-dependent lowering. Pattern
constraints emit different DDL by driver. Postgres
uses
~; SQLite/MySQL useREGEXP. Thedb=attribute on <program> tells the schema-differ which dialect to emit. - Schema lives at file or program scope. A <schema> element is structural; it does not live inside reactive scopes or per-page bodies. Multiple <schema> blocks across files are merged at compile time.
- Migration safety. The schema-differ emits forward migrations; destructive operations (DROP COLUMN, DROP TABLE) require explicit opt-in. Default behavior is additive-only.
Related features
- ?{ ... } — SQL context. Queries cross-checked against the schema at compile time.
- scrml:data stdlib module — runtime validator builders for untrusted-payload parsing at boundaries the schema doesn't cover.
- refinement types (§53) — same shared-core vocabulary on type annotations. Compile-time + runtime boundary check; complementary layer to the schema's DBMS- enforced constraints.
- validators on state cells (§55) — same vocabulary again, this time wired to the auto-synthesized validity surface for forms.
Availability
| Surface | Since | Notes |
|---|---|---|
| <schema> element | v0.2 | Pre-D3 SQL-mirror canonical form |
| Shared-core validators on schema columns | D3 (2026-05-04) | SPEC §39.5.7 + §39.5.8 lowering rules |
| Migration diff | v0.2 | compiler/src/schema-differ.js ~273 LOC |
| Multi-database lowering | SPEC §44 | Driver-dependent DDL via <program db=> |
Specification
This page summarizes SPEC §39 (Schema and Migrations), with cross-refs to §44 (multi-database adaptation) and §53 (refinement types) for the cross-locus vocabulary unification. The normative text lives at compiler/SPEC.md in the scrmlTS repository.