Skip to content

Fix schema-drift false positive on SERIAL/AUTOINCREMENT columns#84

Open
robertjbass wants to merge 1 commit into
erans:mainfrom
Layerbase-LLC:fix/schema-drift-serial-false-positive
Open

Fix schema-drift false positive on SERIAL/AUTOINCREMENT columns#84
robertjbass wants to merge 1 commit into
erans:mainfrom
Layerbase-LLC:fix/schema-drift-serial-false-positive

Conversation

@robertjbass

Copy link
Copy Markdown

Problem

The startup schema-drift check added in v0.0.22 refuses to open any existing database that has a SERIAL/BIGSERIAL/IDENTITY column:

Error: Failed to create database handler: Schema drift detected:
Table 'x' has schema drift:
  Type mismatches:
    - id expected SQLite type 'INTEGER PRIMARY KEY AUTOINCREMENT' but found 'INTEGER'

Cause: when a SERIAL column is created, pgsqlite stores the constraint-bearing string INTEGER PRIMARY KEY AUTOINCREMENT as the column's sqlite_type in __pgsqlite_schema, but the drift check reads the live column type via PRAGMA table_info, which only reports the bare declared type token (INTEGER). normalize_sqlite_type strips size specs but not constraint keywords, so the two sides can never compare equal and every database containing a SERIAL column fails to open on its next start.

We hit this in production: a database created normally refused to boot on its first restart, with the exact error above.

Fix

Strip trailing column constraints (PRIMARY KEY, AUTOINCREMENT, NOT NULL, UNIQUE, DEFAULT, CHECK, REFERENCES, COLLATE, CONSTRAINT, GENERATED) from the declared type before normalizing. Truncation happens on token boundaries, so multi-word base types (DOUBLE PRECISION, CHARACTER VARYING, NUMERIC(10, 2)) are preserved. The drift check only ever compared column types, not constraints, so no real drift signal is lost - genuine type mismatches (e.g. metadata TEXT vs actual INTEGER) are still detected, and there is an existing test asserting that.

Testing

  • New regression test test_no_drift_serial_autoincrement_column reproduces the SERIAL case end to end (metadata row as written by the SERIAL translation path, real table with id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL) and asserts no drift is reported.
  • cargo test --test schema_drift_test: 9/9 pass (all pre-existing drift-detection behaviors unchanged).

The startup schema-drift check compared the metadata sqlite_type stored in
__pgsqlite_schema against the type reported by PRAGMA table_info. For a
SERIAL/BIGSERIAL/IDENTITY column pgsqlite records the constraint-bearing
string "INTEGER PRIMARY KEY AUTOINCREMENT", but PRAGMA table_info only
returns the bare declared type token "INTEGER". normalize_sqlite_type did
not strip the constraint suffix, so the two never compared equal and any
existing database with a SERIAL column refused to open with a spurious
"expected SQLite type 'INTEGER PRIMARY KEY AUTOINCREMENT' but found
'INTEGER'" drift error.

Strip trailing column constraints (PRIMARY KEY, AUTOINCREMENT, NOT NULL,
etc.) before comparing types. The drift check only compares column type,
not constraints, so dropping the suffix is safe and still catches real
type drift. Add a regression test that reproduces the SERIAL case.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant