-
Notifications
You must be signed in to change notification settings - Fork 30
fix: trigger when IS NOT DISTINCT FROM #42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ import ( | |
| "context" | ||
| "database/sql" | ||
| "fmt" | ||
| "regexp" | ||
| "sort" | ||
| "strconv" | ||
| "strings" | ||
|
|
@@ -1555,6 +1556,39 @@ func (i *Inspector) normalizeTriggerCondition(rawCondition string) string { | |
| } | ||
| } | ||
|
|
||
| // Use pg_query to normalize the expression for consistent formatting | ||
| // This handles complex expressions, case normalization, etc. | ||
| normalizedCondition := normalizeExpressionWithPgQuery(condition) | ||
| if normalizedCondition != "" { | ||
| condition = normalizedCondition | ||
| } | ||
|
|
||
| // Post-process to handle PostgreSQL's "NOT x IS DISTINCT FROM y" → "x IS NOT DISTINCT FROM y" | ||
| condition = i.normalizeNotDistinctFromPattern(condition) | ||
|
|
||
| return condition | ||
| } | ||
|
|
||
| // normalizeNotDistinctFromPattern converts "NOT x IS DISTINCT FROM y" to "x IS NOT DISTINCT FROM y" | ||
| // This handles the specific case where pg_query.Deparse converts PostgreSQL's internal | ||
| // "NOT (x IS DISTINCT FROM y)" representation to "NOT x IS DISTINCT FROM y" | ||
| func (i *Inspector) normalizeNotDistinctFromPattern(condition string) string { | ||
| // Use regex to match: "NOT <expr> IS DISTINCT FROM <expr>" | ||
| // and convert to: "<expr> IS NOT DISTINCT FROM <expr>" | ||
|
|
||
| // Pattern explanation: | ||
| // ^NOT\s+ - starts with "NOT" followed by whitespace | ||
| // (.+?) - non-greedy capture of left expression | ||
| // \s+IS\s+DISTINCT\s+FROM\s+ - " IS DISTINCT FROM " with flexible whitespace | ||
| // (.+)$ - capture the right expression to end of string | ||
| re := regexp.MustCompile(`^NOT\s+(.+?)\s+IS\s+DISTINCT\s+FROM\s+(.+)$`) | ||
|
||
|
|
||
| if matches := re.FindStringSubmatch(condition); matches != nil { | ||
| left := strings.TrimSpace(matches[1]) | ||
| right := strings.TrimSpace(matches[2]) | ||
| return fmt.Sprintf("%s IS NOT DISTINCT FROM %s", left, right) | ||
| } | ||
|
|
||
| return condition | ||
| } | ||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
testdata/diff/create_trigger/add_trigger_when_distinct/diff.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| CREATE OR REPLACE TRIGGER products_description_trigger | ||
| BEFORE UPDATE ON products | ||
| FOR EACH ROW | ||
| WHEN (NEW.description IS DISTINCT FROM OLD.description) | ||
| EXECUTE FUNCTION log_description_change(); | ||
|
|
||
| CREATE OR REPLACE TRIGGER products_status_trigger | ||
| BEFORE UPDATE ON products | ||
| FOR EACH ROW | ||
| WHEN (NEW.status IS NOT DISTINCT FROM OLD.status) | ||
| EXECUTE FUNCTION skip_status_change(); |
34 changes: 34 additions & 0 deletions
34
testdata/diff/create_trigger/add_trigger_when_distinct/new.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| CREATE TABLE public.products ( | ||
| id serial PRIMARY KEY, | ||
| name text NOT NULL, | ||
| description text, | ||
| status text, | ||
| updated_at timestamp DEFAULT CURRENT_TIMESTAMP | ||
| ); | ||
|
|
||
| CREATE OR REPLACE FUNCTION public.log_description_change() | ||
| RETURNS trigger AS $$ | ||
| BEGIN | ||
| NEW.updated_at = CURRENT_TIMESTAMP; | ||
| RETURN NEW; | ||
| END; | ||
| $$ LANGUAGE plpgsql; | ||
|
|
||
| CREATE OR REPLACE FUNCTION public.skip_status_change() | ||
| RETURNS trigger AS $$ | ||
| BEGIN | ||
| RETURN NEW; | ||
| END; | ||
| $$ LANGUAGE plpgsql; | ||
|
|
||
| CREATE TRIGGER products_description_trigger | ||
| BEFORE UPDATE ON public.products | ||
| FOR EACH ROW | ||
| WHEN (NEW.description IS DISTINCT FROM OLD.description) | ||
| EXECUTE FUNCTION public.log_description_change(); | ||
|
|
||
| CREATE TRIGGER products_status_trigger | ||
| BEFORE UPDATE ON public.products | ||
| FOR EACH ROW | ||
| WHEN (NEW.status IS NOT DISTINCT FROM OLD.status) | ||
| EXECUTE FUNCTION public.skip_status_change(); |
22 changes: 22 additions & 0 deletions
22
testdata/diff/create_trigger/add_trigger_when_distinct/old.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| CREATE TABLE public.products ( | ||
| id serial PRIMARY KEY, | ||
| name text NOT NULL, | ||
| description text, | ||
| status text, | ||
| updated_at timestamp DEFAULT CURRENT_TIMESTAMP | ||
| ); | ||
|
|
||
| CREATE OR REPLACE FUNCTION public.log_description_change() | ||
| RETURNS trigger AS $$ | ||
| BEGIN | ||
| NEW.updated_at = CURRENT_TIMESTAMP; | ||
| RETURN NEW; | ||
| END; | ||
| $$ LANGUAGE plpgsql; | ||
|
|
||
| CREATE OR REPLACE FUNCTION public.skip_status_change() | ||
| RETURNS trigger AS $$ | ||
| BEGIN | ||
| RETURN NEW; | ||
| END; | ||
| $$ LANGUAGE plpgsql; |
26 changes: 26 additions & 0 deletions
26
testdata/diff/create_trigger/add_trigger_when_distinct/plan.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| { | ||
| "version": "1.0.0", | ||
| "pgschema_version": "1.1.1", | ||
| "created_at": "1970-01-01T00:00:00Z", | ||
| "source_fingerprint": { | ||
| "hash": "98db11096a7a86d2175ff6821924a2b64dddbf240681f23079c0d912d3ea22b5" | ||
| }, | ||
| "groups": [ | ||
| { | ||
| "steps": [ | ||
| { | ||
| "sql": "CREATE OR REPLACE TRIGGER products_description_trigger\n BEFORE UPDATE ON products\n FOR EACH ROW\n WHEN (NEW.description IS DISTINCT FROM OLD.description)\n EXECUTE FUNCTION log_description_change();", | ||
| "type": "table.trigger", | ||
| "operation": "create", | ||
| "path": "public.products.products_description_trigger" | ||
| }, | ||
| { | ||
| "sql": "CREATE OR REPLACE TRIGGER products_status_trigger\n BEFORE UPDATE ON products\n FOR EACH ROW\n WHEN (NEW.status IS NOT DISTINCT FROM OLD.status)\n EXECUTE FUNCTION skip_status_change();", | ||
| "type": "table.trigger", | ||
| "operation": "create", | ||
| "path": "public.products.products_status_trigger" | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } |
11 changes: 11 additions & 0 deletions
11
testdata/diff/create_trigger/add_trigger_when_distinct/plan.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| CREATE OR REPLACE TRIGGER products_description_trigger | ||
| BEFORE UPDATE ON products | ||
| FOR EACH ROW | ||
| WHEN (NEW.description IS DISTINCT FROM OLD.description) | ||
| EXECUTE FUNCTION log_description_change(); | ||
|
|
||
| CREATE OR REPLACE TRIGGER products_status_trigger | ||
| BEFORE UPDATE ON products | ||
| FOR EACH ROW | ||
| WHEN (NEW.status IS NOT DISTINCT FROM OLD.status) | ||
| EXECUTE FUNCTION skip_status_change(); |
24 changes: 24 additions & 0 deletions
24
testdata/diff/create_trigger/add_trigger_when_distinct/plan.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| Plan: 1 to modify. | ||
|
|
||
| Summary by type: | ||
| tables: 1 to modify | ||
|
|
||
| Tables: | ||
| ~ products | ||
| + products_description_trigger (trigger) | ||
| + products_status_trigger (trigger) | ||
|
|
||
| DDL to be executed: | ||
| -------------------------------------------------- | ||
|
|
||
| CREATE OR REPLACE TRIGGER products_description_trigger | ||
| BEFORE UPDATE ON products | ||
| FOR EACH ROW | ||
| WHEN (NEW.description IS DISTINCT FROM OLD.description) | ||
| EXECUTE FUNCTION log_description_change(); | ||
|
|
||
| CREATE OR REPLACE TRIGGER products_status_trigger | ||
| BEFORE UPDATE ON products | ||
| FOR EACH ROW | ||
| WHEN (NEW.status IS NOT DISTINCT FROM OLD.status) | ||
| EXECUTE FUNCTION skip_status_change(); |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function
normalizeExpressionWithPgQueryis called but not defined in this file or imported. This will cause a compilation error.