Does SurrealDB check an ASSERT against records that already exist?
ASSERT added to a field of an existing table
Warning: the statement succeeds, then writes fail, access changes, or the table is held up.
What happens
Observed on SurrealDB 3.0.2: with user:1 holding email = 'not-an-email', DEFINE FIELD email ... ASSERT string::is_email($value) succeeds, and UPDATE user:1 SET n = 1 then fails with "field must conform to: string::is_email($value)".
Why it is dangerous on a populated table
SurrealDB checks a schema change against new writes, not the records already stored, so an empty table hides it: on a populated one every old record is a write waiting to fail, and whole-table work runs for the length of the table in one transaction.
Fires on
ALTER FIELD email ON TABLE user ASSERT string::is_email($value);The safe pattern
Correct the records that break the rule in the same migration, before the ASSERT, or write the ASSERT so the values already stored pass it.
UPDATE user SET email = NONE WHERE !string::is_email(email);
ALTER FIELD email ON TABLE user ASSERT $value = NONE OR string::is_email($value);Fixtures
The rule ships with these files and the test suite runs them on every change: the first set must fire, the second must stay silent.
Fires (2)
ALTER FIELD email ON TABLE user ASSERT string::is_email($value);DEFINE FIELD OVERWRITE email ON TABLE user TYPE string ASSERT string::len($value) > 3;Stays silent (2)
UPDATE user SET email = NONE WHERE !string::is_email(email);
ALTER FIELD email ON TABLE user ASSERT $value = NONE OR string::is_email($value);DEFINE TABLE user SCHEMAFULL;
DEFINE FIELD email ON TABLE user TYPE string ASSERT string::is_email($value);How to check locally
SurrealDB support is in beta: this rule runs locally in the free CLI over .surql migrations, static only, and not in the hosted service yet. No install, nothing leaves your machine:
npx bolvrk check migration.surql --engine=surrealdb