Skip to content

fix: keep the conditions after LIKE in CHECK constraints (#648) - #650

Closed
tomodian wants to merge 1 commit into
pgplex:mainfrom
tomodian:fix/check-like-trailing-conditions
Closed

tomodian wants to merge 1 commit into
pgplex:mainfrom
tomodian:fix/check-like-trailing-conditions

Conversation

@tomodian

Copy link
Copy Markdown

Summary

Fixes #648.

applyLegacyCheckNormalizations turned col ~~ 'pat'::text into col LIKE 'pat' by splitting the clause on " ~~ " and cutting the right-hand side at its first ::. If anything followed the pattern, it was dropped, e.g. ) AND (b IS NOT NULL). Both sides of a diff go through the same normalisation, so plan couldn't see the loss. dump and apply to an empty schema then wrote the weaker constraint.

The fix rewrites each ~~ '<literal>'::text|varchar operand in place and leaves the rest of the expression as it is. After the rewrite, one redundant pair of outer parentheses is stripped, so a simple CHECK (col LIKE 'x') normalises exactly as before. The existing dump fixtures (e.g. bytebase) don't change.

Tests

  • ir/normalize_test.go: a LIKE on its own, a LIKE followed by AND, two LIKEs, and a pattern with an escaped quote.
  • testdata/diff/create_table/issue_648_check_like_keeps_trailing_conditions: the old schema has CHECK (id IS NULL OR id LIKE 'p-%') and the new one adds AND partner_id IS NOT NULL. Without the fix the plan is empty; with it the constraint is dropped and re-added.

Ran locally: go test ./ir/ ./internal/diff/ ./cmd/dump/, plus TestPlanAndApply filtered to the new case.

Copilot AI balanced review requested due to automatic review settings October 15, 2026 05:34
@greptile-apps

greptile-apps Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 4/5

[Medium impact] Fixes CHECK constraint normalization for LIKE patterns.

Fix the quoted-pattern replacement before merging; it can change the rules enforced by generated constraints.

Findings

  1. P1 Quoted CHECK patterns change ▶

Summary

This PR rewrites LIKE expressions in place so CHECK constraints keep their trailing conditions.

  • LIKE checks keep the conditions that follow their patterns.

Reviews (1) · Last reviewed commit: "fix: keep the conditions after LIKE in C..." · Reviewed by Greptile

Comment thread ir/normalize.go
Comment on lines +1456 to +1457
clause = likeLiteralRe.ReplaceAllString(clause, " LIKE $1")
clause = strings.ReplaceAll(clause, " ~~ ", " LIKE ")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Quoted CHECK patterns change

The global replacement changes ~~ inside quoted text, not just LIKE operators. For example, CHECK (name LIKE 'a ~~ b') arrives as name ~~ 'a ~~ b'::text and now becomes name LIKE 'a LIKE b'. The old split left this expression unchanged because it contained two occurrences. Dumps and generated constraints therefore check a different value.

Rewrite only operators outside strings and quoted identifiers, and add a regression test for this pattern.

Knowledge Base Used: Schema normalization and identity

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The blanket replacement can modify quoted pattern contents and silently change constraint semantics.

1 open finding
What changed in this PR

Fixes #648 by preserving conditions after LIKE patterns when normalizing PostgreSQL CHECK constraints.

Changes:

  • Replaces truncating normalization with in-place rewriting.
  • Adds unit tests for compound conditions and escaped quotes.
  • Adds migration fixtures showing detection of a strengthened constraint.
File Description
ir/​normalize.go Rewrites LIKE operands without truncating trailing conditions.
ir/​normalize_test.go Adds LIKE normalization regression tests.
testdata/​diff/​create_table/​issue_648_check_like_keeps_trailing_conditions/​old.sql Defines the original constraint.
testdata/​diff/​create_table/​issue_648_check_like_keeps_trailing_conditions/​new.sql Adds the required partner condition.
testdata/​diff/​create_table/​issue_648_check_like_keeps_trailing_conditions/​diff.sql Records expected constraint replacement.
testdata/​diff/​create_table/​issue_648_check_like_keeps_trailing_conditions/​plan.json Records structured migration steps.
testdata/​diff/​create_table/​issue_648_check_like_keeps_trailing_conditions/​plan.sql Records executable migration SQL.
testdata/​diff/​create_table/​issue_648_check_like_keeps_trailing_conditions/​plan.txt Records human-readable migration output.

🧠 Review effort: Balanced


💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread ir/normalize.go
}
return fmt.Sprintf("%s LIKE %s", columnName, pattern)
clause = likeLiteralRe.ReplaceAllString(clause, " LIKE $1")
clause = strings.ReplaceAll(clause, " ~~ ", " LIKE ")
@tianzhou tianzhou closed this Oct 15, 2026
@tianzhou

Copy link
Copy Markdown
Contributor

Close in favor of #649

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.

CHECK constraint with LIKE loses the conditions after the pattern

3 participants