A typeguard DEFAULT or VALUE clause is a generated-column expression, evaluated per row against the document. A column DEFAULT is a constant expression, const-folded once.
CREATE TYPEGUARD validates its clauses against the column-DEFAULT gate. A cross-field expression parses there, so declaration succeeds. CONVERT COLLECTION then copies it onto a strict-schema column, where the column-DEFAULT evaluator const-folds it and raises UnevaluableDefault on every insert.
Reproduction
CREATE COLLECTION t (id TEXT PRIMARY KEY, status TEXT, lowered TEXT);
CREATE TYPEGUARD ON t (lowered STRING VALUE LOWER(status));
CONVERT COLLECTION t TO document_strict (id TEXT, status TEXT, lowered TEXT);
INSERT INTO t (id, status) VALUES ('k1', 'ACTIVE');
The insert fails. The declaration reported no error.
Expected
Either the guard evaluates per row after conversion, keeping the semantics it had before, or CONVERT refuses to carry a guard whose expression references another column and says so.
Notes
Catching this at CONVERT needs nodedb-sql to expose whether a classified DEFAULT references a column. A second classifier must not be written for it.
There is a related semantic narrowing at the same site, documented in code: a guard VALUE expr always overwrites, while a strict-schema column DEFAULT fills only when the column is omitted. Strict schema has one materialization slot, so the conversion cannot preserve both meanings.
A typeguard
DEFAULTorVALUEclause is a generated-column expression, evaluated per row against the document. A columnDEFAULTis a constant expression, const-folded once.CREATE TYPEGUARDvalidates its clauses against the column-DEFAULT gate. A cross-field expression parses there, so declaration succeeds.CONVERT COLLECTIONthen copies it onto a strict-schema column, where the column-DEFAULT evaluator const-folds it and raisesUnevaluableDefaulton every insert.Reproduction
The insert fails. The declaration reported no error.
Expected
Either the guard evaluates per row after conversion, keeping the semantics it had before, or
CONVERTrefuses to carry a guard whose expression references another column and says so.Notes
Catching this at
CONVERTneedsnodedb-sqlto expose whether a classified DEFAULT references a column. A second classifier must not be written for it.There is a related semantic narrowing at the same site, documented in code: a guard
VALUE expralways overwrites, while a strict-schema columnDEFAULTfills only when the column is omitted. Strict schema has one materialization slot, so the conversion cannot preserve both meanings.