Skip to content

fix(migrate-ts): regex CHECK on a varchar/text column no longer reads as drift on Postgres - #463

Merged
dmealing merged 4 commits into
mainfrom
fm/mo-pg-check-normalize
Oct 26, 2026
Merged

dmealing merged 4 commits into
mainfrom
fm/mo-pg-check-normalize

Conversation

@dmealing

@dmealing dmealing commented Oct 26, 2026 •

Copy link
Copy Markdown
Member

What Changed

  • meta verify --db on Postgres no longer reports a regex CHECK on a text/varchar/bpchar column as dropped-and-added. Postgres stores "key" ~ '…' as ((key)::text ~ '…'::text); the comparison already folded the literal's ::text but not the column's. normalizeCheckExpr and checkExprEquals now take an optional set of text-family column names and drop (col)::text before ~, ~*, !~ and !~*. citext and every other column type keep the cast, because it changes the operator there.
  • The Postgres introspector records udt_name on a new optional ColumnDescriptor.udtName. diffTableChecks builds the text-family column set from it and passes it to the comparison.
  • Adds a CHANGELOG.md entry, unit tests for normalization and offline diff, and a Postgres integration test (pg-regex-check-cast.test.ts, skipped unless MIGRATE_TS_PG_URL is set).

Risk Assessment

Low. A (col)::text cast folds away before a regex operator only when the introspected Postgres column is text, varchar or bpchar. Every other caller keeps strict comparison.

Testing

  • Live validation: 5 of 6 scenarios driven live against Postgres (the sixth, comparator default-absent behaviour, is covered by unit tests only).
Scenario Result Live
varchar(64) column with regex CHECK built by authored DDL: no check drift (the reported pair); fails on base pass live
text and char(8) columns with regex CHECK: no drift pass live
citext column, uncast check: PG keeps citext's own operator, no drift pass live
citext column, explicit ::text-cast check vs uncast authored check reads as drift (citext negative) pass live
varchar column with a changed regex pattern still reads as drift pass live
comparator default-absent column set keeps the cast; non-regex casts survive unit tests only no
  • scripts/ci-local.sh --only ts-fast --only ts-unit --strict-toolchains on the PR head: exit 0 (build and typecheck, TypeScript conformance, unit suites, mutation gate all green).

Pipeline

Validated by no-mistakes in one run (CI is local; no forge checks run).

  • Review: raised that eliding ::text for every column hides a change on citext; fixed by gating the rule on text-family column types, with a citext negative test.
  • Test: the test agent timed out on a model timeout and left scratch directories that broke the codegen-ts typecheck; the scratch was removed and the local CI above was re-run green. The test step was then approved over the earlier failed-command finding (recorded as an override with no reason supplied), on the strength of that green re-run.
  • Document, lint and push passed.

@dmealing
dmealing merged commit 781d0bc into main Oct 26, 2026
1 check passed
@dmealing
dmealing deleted the fm/mo-pg-check-normalize branch October 26, 2026 02:42
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