-
Notifications
You must be signed in to change notification settings - Fork 29
fix: EXCLUDE constraint incorrectly dumped as regular INDEX (#281) #289
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -877,10 +877,22 @@ func normalizeConstraint(constraint *Constraint) { | |||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| // Only normalize CHECK constraints - other constraint types are already consistent | ||||||||||||||||||||||||||||||||||||
| // Only normalize CHECK and EXCLUDE constraints - other constraint types are already consistent | ||||||||||||||||||||||||||||||||||||
| if constraint.Type == ConstraintTypeCheck && constraint.CheckClause != "" { | ||||||||||||||||||||||||||||||||||||
| constraint.CheckClause = normalizeCheckClause(constraint.CheckClause) | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| if constraint.Type == ConstraintTypeExclusion && constraint.ExclusionDefinition != "" { | ||||||||||||||||||||||||||||||||||||
| constraint.ExclusionDefinition = normalizeExclusionDefinition(constraint.ExclusionDefinition) | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| // normalizeExclusionDefinition normalizes EXCLUDE constraint definitions. | ||||||||||||||||||||||||||||||||||||
| // | ||||||||||||||||||||||||||||||||||||
| // pg_get_constraintdef() returns the full definition like: | ||||||||||||||||||||||||||||||||||||
| // "EXCLUDE USING gist (range_col WITH &&)" | ||||||||||||||||||||||||||||||||||||
| // We keep it as-is since both desired and current state come from pg_get_constraintdef(). | ||||||||||||||||||||||||||||||||||||
| func normalizeExclusionDefinition(definition string) string { | ||||||||||||||||||||||||||||||||||||
| return strings.TrimSpace(definition) | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+893
to
+895
|
||||||||||||||||||||||||||||||||||||
| // We keep it as-is since both desired and current state come from pg_get_constraintdef(). | |
| func normalizeExclusionDefinition(definition string) string { | |
| return strings.TrimSpace(definition) | |
| // We keep it as-is since both desired and current state come from pg_get_constraintdef(), | |
| // except for stripping a trailing " NOT VALID" suffix to match normalizeCheckClause behavior. | |
| func normalizeExclusionDefinition(definition string) string { | |
| normalized := strings.TrimSpace(definition) | |
| // Strip " NOT VALID" suffix if present (mimicking pg_dump behavior) | |
| // PostgreSQL's pg_get_constraintdef may include NOT VALID at the end, | |
| // but the validation state should be represented via the IsValid field. | |
| const notValidSuffix = " NOT VALID" | |
| if strings.HasSuffix(normalized, notValidSuffix) { | |
| normalized = strings.TrimSpace(strings.TrimSuffix(normalized, notValidSuffix)) | |
| } | |
| return normalized |
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.
Same as above — PostgreSQL does not support NOT VALID for EXCLUDE constraints, so pg_get_constraintdef() will never return a "NOT VALID" suffix for them. Stripping it would be dead code.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| ALTER TABLE test_table | ||
| ADD CONSTRAINT excl_no_overlap EXCLUDE USING gist (range_col WITH &&); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| CREATE TABLE IF NOT EXISTS test_table ( | ||
| id integer, | ||
| range_col int4range NOT NULL, | ||
| CONSTRAINT test_table_pkey PRIMARY KEY (id), | ||
| CONSTRAINT excl_no_overlap EXCLUDE USING gist (range_col WITH &&) | ||
| ); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| CREATE TABLE IF NOT EXISTS test_table ( | ||
| id integer, | ||
| range_col int4range NOT NULL, | ||
| CONSTRAINT test_table_pkey PRIMARY KEY (id) | ||
| ); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| { | ||
| "version": "1.0.0", | ||
| "pgschema_version": "1.7.0", | ||
| "created_at": "1970-01-01T00:00:00Z", | ||
| "source_fingerprint": { | ||
| "hash": "4fbb3d8c221ccc65b31f81678cb19ac44eccc901628273d00cc3e124a6ee6877" | ||
| }, | ||
| "groups": [ | ||
| { | ||
| "steps": [ | ||
| { | ||
| "sql": "ALTER TABLE test_table\nADD CONSTRAINT excl_no_overlap EXCLUDE USING gist (range_col WITH &&);", | ||
| "type": "table.constraint", | ||
| "operation": "create", | ||
| "path": "public.test_table.excl_no_overlap" | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| ALTER TABLE test_table | ||
| ADD CONSTRAINT excl_no_overlap EXCLUDE USING gist (range_col WITH &&); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| Plan: 1 to modify. | ||
|
|
||
| Summary by type: | ||
| tables: 1 to modify | ||
|
|
||
| Tables: | ||
| ~ test_table | ||
| + excl_no_overlap (constraint) | ||
|
|
||
| DDL to be executed: | ||
| -------------------------------------------------- | ||
|
|
||
| ALTER TABLE test_table | ||
| ADD CONSTRAINT excl_no_overlap EXCLUDE USING gist (range_col WITH &&); |
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 EXCLUDE constraint generation does not handle the NOT VALID state. While pg_get_constraintdef() returns the constraint definition, it does not include the validation state. Similar to CHECK constraints (lines 56-64), EXCLUDE constraints should append " NOT VALID" when constraint.IsValid is false to properly represent invalidated exclusion constraints.
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.
PostgreSQL does not support
NOT VALIDfor EXCLUDE constraints — only CHECK, FOREIGN KEY, and NOT NULL constraints support it (docs).pg_get_constraintdef()will never include "NOT VALID" for exclusion constraints, so this handling is unnecessary.