A more comprehensive test corpus, with expected ASTs in JSON form, is planned for a future release. The grammar repository (grammar/) currently contains the grammar file (xDBML.g4) and this reference test corpus only.
§17.1 Version declaration
VALID -- bare version
xdbml: 0.1
Project p { targets: Oracle }VALID -- with experimental opt-in
xdbml: 0.1
experimental: [graph_path_expressions]
Project p { targets: Oracle }VALID -- DBML compatibility (no version declaration)
Table users {
id int [pk]
email varchar
}INVALID -- version declared after other constructs
Project p { }
xdbml: 0.1Expected error: "version declaration must precede all other constructs."
§17.2 Nested / hierarchical structures
VALID -- nested object
xdbml: 0.1
Entity customers {
id int [pk]
address object {
street varchar [not null]
city varchar [not null]
}
}VALID -- array of named objects
xdbml: 0.1
Entity orders {
id int [pk]
line_items array [
line_item object {
sku varchar
quantity int
}
]
}VALID -- heterogeneous tuple
xdbml: 0.1
Entity customers {
id int [pk]
addresses array [
[0] billing object {
street varchar
city varchar
}
[1] shipping object {
street varchar
city varchar
}
]
}VALID -- recursive named type
xdbml: 0.1
Type TreeNode {
value int
children array [child TreeNode]
}
Entity org_chart {
root_id int [pk]
tree TreeNode
}INVALID -- tuple positions not contiguous
xdbml: 0.1
Entity bad {
arr array [
[0] first object { x int }
[2] third object { x int }
]
}Expected error (semantic-analysis pass, not grammar): "tuple positions must be contiguous starting at 0."
§17.3 Polymorphism
VALID -- oneOf with discriminator
xdbml: 0.1
Entity payments {
method oneOf {
card object {
last4 varchar(4)
brand varchar
}
bank object { iban varchar }
} [discriminator: method_kind]
}VALID -- union (scalar type alternatives)
xdbml: 0.1
Entity records {
score union [int, decimal, null]
legacy_id union [string, int] [not null]
}VALID -- array element-type shorthand (folds to a union)
xdbml: 0.1
Entity records {
ids array [int, varchar] // shorthand for array [union [int, varchar]]
mixed array [int, varchar, null]
tagged array [union [int, varchar]] // explicit form, still valid
}VALID -- polymorphism inside an array
xdbml: 0.1
Entity event_log {
events array [
event oneOf {
user_event object {
type varchar
user_id objectId
action varchar
}
item_event object {
type varchar
item_id objectId
qty int
}
} [discriminator: type]
]
}§17.5 JSON-with-schema
VALID -- opaque JSON
xdbml: 0.1
Entity api_logs {
payload json
response variant
}VALID -- JSON with inline schema
xdbml: 0.1
Entity orders {
id int [pk]
payload json {
shipping_address object {
street varchar
city varchar
}
items array [
item object {
sku varchar
quantity int
}
]
}
}VALID -- BSON types
xdbml: 0.1
Container app [type: database] {
Collection users {
_id objectId [pk]
email varchar [unique]
balance Decimal128
last_login Date
avatar BinData
}
}§17.6 Path syntax
VALID -- path on index
xdbml: 0.1
Entity orders {
id int [pk]
line_items array [
line_item object {
sku varchar
quantity int
}
]
indexes {
line_items.sku // implicit array iteration (allowed in indexes)
line_items.[*].sku // explicit array iteration
line_items.[0].sku // positional
}
}VALID -- quoted segment for non-identifier name
xdbml: 0.1
Entity legacy {
data object {
"user.id" varchar
}
indexes {
data."user.id"
}
}VALID -- JSONPath alias (parses, normalizes to dot-prefixed)
xdbml: 0.1
Entity orders {
id int [pk]
items array [item object { sku varchar }]
indexes {
items[*].sku // JSONPath alias; normalizes to items.[*].sku
}
}INVALID -- implicit array iteration in Ref source path
xdbml: 0.1
Entity orders {
id int [pk]
line_items array [item object { sku varchar }]
}
Entity products {
sku varchar [pk]
}
Ref: orders.line_items.sku > products.skuExpected error (semantic-analysis pass): "Ref source path crosses array; explicit .[*] required."
VALID -- explicit .[*] in Ref
Ref: orders.line_items.[*].sku > products.sku§17.7 Container
VALID -- explicit container
xdbml: 0.1
Container core [type: schema] {
Entity users {
id int [pk]
name varchar
}
}VALID -- container synonyms
xdbml: 0.1
Database orders_store {
Collection orders {
_id objectId [pk]
}
}
Keyspace metrics {
Table page_views {
event_id varchar [pk]
}
}
Namespace events {
Record OrderPlaced {
event_id varchar [pk]
}
}VALID -- cross-container reference
xdbml: 0.1
Container core [type: schema] {
Entity customers {
id int [pk]
}
}
Container sales [type: schema] {
Entity orders {
id int [pk]
customer_id int [ref: > core.customers.id]
}
}
Ref: sales.orders.customer_id > core.customers.id§17.8 Named types
VALID -- named type referenced from multiple entities
xdbml: 0.1
Type Address {
street varchar
city varchar
}
Entity customers {
primary_address Address
alternate_address Address
}
Entity orders {
shipping_address Address
}INVALID -- named type shadows builtin
xdbml: 0.1
Type varchar { // shadows builtin
custom_field int
}Expected error (semantic-analysis pass): "named type 'varchar' shadows built-in type keyword; rename or remove."
§17.9 AI-readiness settings
VALID -- all four AI-readiness settings
xdbml: 0.1
Entity customers {
mrr_amount decimal(10,2) [
synonyms: ['monthly revenue', 'recurring revenue'],
business_term: 'https://glossary.acme.com/MRR',
tags: ['finance', 'kpi'],
granularity: month
]
}VALID -- custom property with x_ prefix
xdbml: 0.1
Entity customers [
x_governance_owner: 'finance-team@acme.com',
x_collibra_asset_id: 'urn:collibra:asset:abc-123'
] {
id int [pk]
name varchar
}§17.10 Cardinality
VALID -- compact form
xdbml: 0.1
Entity customers { id int [pk] }
Entity orders { id int [pk]; customer_id int }
Ref: orders.customer_id > customers.idVALID -- explicit source/target cardinality
Ref: orders.customer_id > customers.id [source: '1..*', target: '1..1']VALID -- four-key alternative form
Ref: pets.owner_id > people.id [
min_source: 0, max_source: '*',
min_target: 0, max_target: 1
]§17.11 Edge
VALID -- basic edge
xdbml: 0.1
Entity Person { id int [pk]; name varchar }
Edge KNOWS [source: Person, target: Person] {
since date [not null]
intimacy int [minimum: 0, maximum: 10]
}VALID -- edge with cardinality
Edge OWNS [source: Person, target: Pet,
source_cardinality: '0..*', target_cardinality: '0..1'] {
acquired_date date
}VALID -- undirected edge
Edge FRIENDS_WITH [source: Person, target: Person, undirected: true] {
since date
}VALID -- multiple edges between same entities
Edge LIKES [source: User, target: Post] { liked_at timestamp }
Edge SHARED [source: User, target: Post] { shared_at timestamp }
Edge BLOCKED [source: User, target: Post] { blocked_at timestamp }§17.12 View
VALID -- virtual view
xdbml: 0.1
View active_customers [materialized: false] {
source_query: '''
SELECT id, email, name
FROM customers
WHERE deleted_at IS NULL
'''
id int [pk]
email varchar
name varchar
}VALID -- materialized view with refresh settings
View monthly_revenue [materialized: true,
refresh_schedule: 'daily',
source_database: 'Oracle'] {
source_query: '''
SELECT TRUNC(placed_at, 'MM') AS month, SUM(total) AS revenue
FROM orders
GROUP BY TRUNC(placed_at, 'MM')
'''
month date [pk]
revenue decimal(15,2)
}VALID -- view inside container
xdbml: 0.1
Container analytics [type: schema] {
Entity orders {
id int [pk]
total decimal(10,2)
placed_at timestamp
}
View daily_totals [materialized: true] {
source_query: 'SELECT DATE(placed_at) day, SUM(total) total FROM orders GROUP BY DATE(placed_at)'
day date [pk]
total decimal(10,2)
}
}End-to-end: polyglot model
VALID -- full polyglot model with Oracle, MongoDB, Avro, Neo4j
xdbml: 0.1
Project polyglot { targets: [Oracle, MongoDB, Avro, Neo4j] }
Type Address {
street varchar [not null]
city varchar [not null]
country varchar
}
Type MonetaryAmount {
amount Decimal128 [not null]
currency string [not null, pattern: '^[A-Z]{3}$', minLength: 3, maxLength: 3]
}
Container core [type: schema, target: Oracle] {
Entity customers {
id int [pk]
email varchar [unique, not null, pattern: '^[^@]+@[^@]+$']
display_name varchar [not null]
primary_address Address
}
}
Container orders_store [type: database, target: MongoDB] {
Collection orders {
_id objectId [pk]
customer_id int32 [not null]
placed_at Date [granularity: second]
total MonetaryAmount
line_items array [
line_item object {
sku string [not null]
quantity int32 [not null, minimum: 1]
unit_price MonetaryAmount
}
]
payment_method oneOf {
card object {
last4 string [maxLength: 4]
brand string
}
bank object { iban string }
wallet object {
provider string
account string
}
} [discriminator: method_kind]
}
}
Container events [type: namespace, target: Avro] {
Record OrderPlaced {
event_id string [pk]
occurred long [granularity: millisecond, not null]
order_id string [not null]
customer_id int [not null]
total MonetaryAmount
}
}
Container social [type: database, target: Neo4j] {
Edge FOLLOWS [source: core.customers, target: core.customers,
source_cardinality: '0..*', target_cardinality: '0..*'] {
since date [not null]
is_close boolean [default: false]
}
}
Ref: orders_store.orders.customer_id > core.customers.id [source: '1..*', target: '1..1']
Ref: orders_store.orders.line_items.[*].sku > catalog.products.sku
Ref: events.OrderPlaced.order_id > orders_store.orders._id§14.7 Scalar Named Types (v0.2)
VALID -- scalar Named Type with validation settings
xdbml: 0.2
Type Email varchar [pattern: '^[^@]+@[^@]+$', tags: ['pii']]
Type CountryCode varchar [pattern: '^[A-Z]{2}$', minLength: 2, maxLength: 2]
Type Percentage decimal(5,2) [minimum: 0, maximum: 100]
Entity users {
id int [pk]
email Email
country CountryCode
}VALID -- scalar Named Type alongside object-shaped Type
xdbml: 0.2
Type Email varchar [pattern: '^[^@]+@[^@]+$']
Type Address {
street varchar [not null]
city varchar [not null]
}
Entity customers {
id int [pk]
email Email
primary_address Address
}VALID -- scalar Named Type referencing another Type
xdbml: 0.2
Type Email varchar [pattern: '^[^@]+@[^@]+$']
Type PII_Email Email [tags: ['pii', 'gdpr-subject']]
Entity customers {
id int [pk]
email PII_Email
}§26 Module system (v0.2)
VALID -- reuse * (import all) at file scope
xdbml: 0.2
Project app { targets: [PostgreSQL] }
reuse * from './catalog'
Container ordering [type: schema] {
Entity orders {
id int [pk]
customer_id int
}
}VALID -- selective import inside Container body
xdbml: 0.2
Project app { targets: [PostgreSQL] }
Container ordering [type: schema] {
reuse { entity core.products, entity core.categories } from './catalog'
Entity orders {
id int [pk]
customer_id int
}
Entity order_lines {
order_id int [ref: > ordering.orders.id]
product_id int [ref: > ordering.products.id]
quantity int
}
}VALID -- import with clone block
xdbml: 0.2
Project sales_data_product { targets: [Snowflake] }
Container facts [type: schema] {
reuse { entity core.dim_customer } from './conformed-dimensions' [cloned_at: '2026-06-06T14:30:00Z'] {
Entity dim_customer {
id int [pk]
email varchar [pattern: '^[^@]+@[^@]+$', tags: ['pii']]
}
}
Entity fact_sales {
customer_id int [ref: > facts.dim_customer.id]
amount decimal(10,2)
}
}VALID -- aliased import
xdbml: 0.2
Project app { targets: [PostgreSQL] }
Container app [type: schema] {
reuse { entity users as auth_users } from './auth'
reuse { entity users as billing_users } from './billing'
Entity sessions {
id int [pk]
auth_user_id int [ref: > app.auth_users.id]
billing_user_id int [ref: > app.billing_users.id]
}
}VALID -- field-level import at file scope, used as a field type
xdbml: 0.2
Project new_system { targets: [PostgreSQL] }
reuse { field ops.customer_legacy.legacy_email as contact_email } from './legacy-customer' [cloned_at: '2026-06-06T14:30:00Z'] {
contact_email varchar [pattern: '^[^@]+@[^@]+$', tags: ['pii']]
}
Container app [type: schema] {
Entity new_customer {
id int [pk]
contact_email contact_email
}
}VALID -- use (non-transitive) for private internal imports
xdbml: 0.2
use { type InternalAuditFields } from './internal-helpers'
Container ordering [type: schema] {
Entity orders {
id int [pk]
audit InternalAuditFields
customer_id int
}
}VALID -- multi-line and comma-separated equivalence
xdbml: 0.2
// Multi-line form
reuse {
entity products
entity categories
type Email
} from './catalog'
// Equivalent comma-separated single-line form
reuse { entity products, entity categories, type Email } from './catalog'VALID -- reference-only directive (no clone block, DBML-compatible)
xdbml: 0.2
Project order_system { targets: [PostgreSQL] }
Container ordering [type: schema] {
reuse { entity core.products } from './catalog'
Entity orders {
id int [pk]
customer_id int
}
}INVALID -- field import inside Container body
xdbml: 0.2
Container app [type: schema] {
reuse { field core.dim_customer.email } from './conformed-dimensions'
Entity new_customer {
id int [pk]
email email
}
}Expected semantic error: "field imports may only appear at file scope (§25.5)."
INVALID -- absolute path
xdbml: 0.2
reuse * from '/absolute/path/to/file.xdbml'Expected error: "import path must begin with './' or '../' (relative paths only in v0.2 phase 1)."
INVALID -- URL path (deferred to a later phase)
xdbml: 0.2
reuse * from 'https://example.com/schemas/users.xdbml'Expected error: "URL imports are reserved for a later phase; v0.2 phase 1 supports relative paths only."
INVALID -- v0.1 file using v0.2-only constructs
xdbml: 0.1
reuse { entity core.products } from './catalog'Expected error: "the module system (use/reuse directives) requires xdbml: 0.2 or later; this document declares xdbml: 0.1."
INVALID -- unrecognized element-type slot value
xdbml: 0.2
reuse { widget core.products } from './catalog'Expected error: "unrecognized element type 'widget'; expected one of: table, entity, collection, record, enum, tablepartial, note, schema, container, tablegroup, type, edge, view, diagramview, field."
INVALID -- importing Project
xdbml: 0.2
reuse { project some_project } from './other'Expected error: "Project declarations are not importable (§26.4)."
§10 Checks -- entity-level constraints (v0.2)
VALID -- multi-column check expression
xdbml: 0.2
Entity users {
id int [pk]
wealth decimal(15,2)
debt decimal(15,2)
checks {
`debt + wealth >= 0` [name: 'chk_positive_net_worth']
}
}VALID -- multiple checks with and without names
xdbml: 0.2
Entity reservations {
id int [pk]
start_date date
end_date date
checks {
`start_date <= end_date` [name: 'chk_valid_date_range']
`end_date - start_date <= 30` [name: 'chk_max_30_days']
`start_date >= CURRENT_DATE`
}
}VALID -- check with note
xdbml: 0.2
Entity orders {
id int [pk]
status varchar
shipped_at timestamp
checks {
`(status != 'shipped') OR (shipped_at IS NOT NULL)` [
name: 'chk_shipped_has_timestamp',
note: 'A shipped order must record the shipment timestamp.'
]
}
}VALID -- entity with both checks and indexes
xdbml: 0.2
Entity inventory {
id int [pk]
sku varchar
warehouse varchar
qty int
indexes {
(sku, warehouse) [unique]
}
checks {
`qty >= 0` [name: 'chk_non_negative_qty']
}
}INVALID -- check expression not backtick-wrapped
xdbml: 0.2
Entity users {
id int [pk]
wealth decimal(15,2)
checks {
wealth >= 0
}
}Expected error: "check expressions must be backtick-wrapped EXPRESSION_LITERAL values."
§11.9 Relationship settings -- inactive and color (v0.2)
VALID -- inactive flag on Ref
xdbml: 0.2
Entity posts {
id int [pk]
user_id int
}
Entity users {
id int [pk]
}
Ref: posts.user_id > users.id [inactive]VALID -- inactive + color + note
xdbml: 0.2
Entity audit_log {
id int [pk]
user_id int
}
Entity users {
id int [pk]
}
Ref: audit_log.user_id > users.id [
inactive,
color: '#999999',
note: 'Historical FK; superseded by audit_ref table'
]VALID -- color alone (active relationship with custom color)
xdbml: 0.2
Entity orders {
id int [pk]
customer_id int
}
Entity customers {
id int [pk]
}
Ref: orders.customer_id > customers.id [color: '#3f51b5']§16.2 TableGroup color (v0.2)
VALID -- TableGroup with color and note
xdbml: 0.2
Entity orders { id int [pk] }
Entity order_lines { id int [pk] }
Entity invoices { id int [pk] }
TableGroup ecommerce [color: '#3498DB', note: 'Commerce-side entities'] {
orders
order_lines
invoices
}VALID -- TableGroup with only color
xdbml: 0.2
Entity users { id int [pk] }
Entity sessions { id int [pk] }
TableGroup auth [color: '#FF5722'] {
users
sessions
}§25 Records -- expanded forms (v0.2)
VALID -- records inside entity (implicit column list, v0.1 syntax)
xdbml: 0.2
Entity users {
id int [pk]
name varchar
email varchar
records {
1, 'Alice', 'alice@example.com'
2, 'Bob', 'bob@example.com'
}
}VALID -- top-level records with explicit column list
xdbml: 0.2
Entity users {
id int [pk]
name varchar
email varchar
}
records users (id, name, email) {
1, 'Alice', 'alice@example.com'
2, 'Bob', 'bob@example.com'
}VALID -- top-level records with cross-container reference
xdbml: 0.2
Container core [type: schema] {
Entity users {
id int [pk]
email varchar
}
}
records core.users (id, email) {
1, 'alice@example.com'
2, 'bob@example.com'
}VALID -- value forms (string, number, boolean, null, date, enum, backtick)
xdbml: 0.2
Enum Status { active inactive pending }
Entity events {
id int [pk]
occurred_at timestamp
status Status
is_archived boolean
payload varchar
records {
1, '2026-06-10T14:30:00Z', Status.active, true, 'string value'
2, '2026-06-11T09:00:00Z', Status.pending, false, null
3, `gen_random_uuid()`, Status.inactive, null, '''multi
line string'''
}
}Test runner
A reference TypeScript test harness (planned at grammar/test-runner.ts) parses each example, captures the resulting AST, and compares it against expected ASTs in grammar/expected/*.json. Implementations in other languages can run the same corpus with language-appropriate harnesses.
$ npx @xdbml/test-runner grammar/test-cases.md
PASS §4.1.001 version declaration with experimental opt-in
PASS §4.1.002 DBML document parses without xdbml: directive
FAIL §10.6.005 expected error not raised: Ref source path crosses array
PASS §6.1.001 explicit container with type
...
PASS rate: 247/250 (98.8%)A conforming v0.2 implementation should achieve 100% pass rate on the published corpus, including v0.2 module system and scalar Named Type cases. A v0.1-only implementation should achieve 100% pass rate on the v0.1 subset and produce appropriate errors for v0.2 constructs.