-
Notifications
You must be signed in to change notification settings - Fork 29
fix: defer FK constraints when referenced tables don't exist yet #156
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
Show all changes
11 commits
Select commit
Hold shift + click to select a range
4b0dd2e
fix: defer FK constraints when referenced tables don't exist yet
p-c-h-b 5366345
Address review feedback and update test fixtures
p-c-h-b 15e48f2
Update plan.json fixture for deferred FK constraint
p-c-h-b 6972e55
Update plan.txt to show deferred FK constraint
p-c-h-b 64744f9
Fix test fixture ordering
p-c-h-b f0ffd5f
test: Update employee expected output for deferred policy creation
p-c-h-b f0c6d2a
test: Enhance table_to_table test with circular FK dependency
p-c-h-b 46bc3c9
Sorry about that! Address PR #156 reviewer feedback
p-c-h-b 7d68c25
Fix non-deterministic table ordering in topological sort
p-c-h-b 9326023
Address PR #156 reviewer feedback on policy ordering
p-c-h-b 43b72e5
Update internal/diff/table.go
tianzhou 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 |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| # PR #156 Feedback Transcript | ||
|
|
||
| ## Pull Request: Fix non-deterministic table ordering in topological sort | ||
|
|
||
| ### Timeline of Comments and Feedback | ||
|
|
||
| --- | ||
|
|
||
| #### **p-c-h-b** | November 8, 2025, 03:00 | ||
| **Initial PR Description:** | ||
|
|
||
| Outlined the fix for FK constraint ordering issues when referenced tables don't exist yet. The contributor explained that "FK-heavy tables could be reordered alphabetically" causing creation failures, and proposed deterministic cycle breaking with deferred constraints applied via ALTER TABLE. | ||
|
|
||
| --- | ||
|
|
||
| #### **Copilot AI** | November 8, 2025, 03:00 | ||
| **Automated Review:** | ||
|
|
||
| Generated pull request overview noting: | ||
| - Refactored topological sort to handle cycles using insertion order as tiebreaker | ||
| - Added deferred constraint mechanism | ||
| - Deferred RLS policy creation | ||
|
|
||
| --- | ||
|
|
||
| #### **p-c-h-b** | November 8, 2025, 22:15 | ||
| **Author Response to Copilot:** | ||
|
|
||
| - Added validation for empty constraint names in generateDeferredConstraintsSQL | ||
| - Fixed the comment to accurately reflect insertion order instead of alphabetical order | ||
|
|
||
| --- | ||
|
|
||
| #### **tianzhou** | November 8, 2025, 03:43 | ||
| **Reviewer Feedback #1:** | ||
|
|
||
| Requested two actions: | ||
| 1. Enhance the table_to_table test case to validate the fix | ||
| 2. Remove test artifact files (`*_actual.sql`, `*_expected.sql`) | ||
|
|
||
| --- | ||
|
|
||
| #### **p-c-h-b** | November 8, 2025, 22:28 | ||
| **Author Response:** | ||
|
|
||
| Addressed feedback by enhancing dependency test with circular FK dependencies between departments and users tables to validate constraint deferral. | ||
|
|
||
| --- | ||
|
|
||
| #### **tianzhou** | November 9, 2025, 02:55 | ||
| **Reviewer Question:** | ||
|
|
||
| "have you forgot to push the update?" | ||
|
|
||
| --- | ||
|
|
||
| #### **p-c-h-b** | November 9, 2025, 09:37 | ||
| **Author Update:** | ||
|
|
||
| Pushed corrections: | ||
| - Removed test artifacts | ||
| - Fixed employee_status_log constraint to stay inline (one-way dependency) | ||
| - Updated shouldDeferConstraint() logic to check existing tables from old schema | ||
|
|
||
| --- | ||
|
|
||
| #### **tianzhou** | November 10, 2025, 02:55 | ||
| **Reviewer Feedback #2 (Latest):** | ||
|
|
||
| Identified remaining issues: | ||
|
|
||
| 1. **Policy Ordering Problem**: In `testdata/dump/employee/pgschema.sql`, RLS policies should be positioned alongside their corresponding `ALTER TABLE...ENABLE ROW LEVEL SECURITY` statements rather than separated. Currently policies appear much later after functions and procedures. | ||
|
|
||
| 2. **File Exclusion**: Directed the contributor to "exclude this from the PR" regarding the `cmd/dump/employee_expected.sql` file - it shouldn't be committed. | ||
|
|
||
| Noted overall progress with "Almost there," indicating the submission is nearly complete pending these structural adjustments. | ||
|
|
||
| --- | ||
|
|
||
| #### **tianzhou** | November 10, 2025, 15:45 | ||
| **Reviewer Feedback #3:** | ||
|
|
||
| - Reported that emitting `CREATE POLICY` immediately after enabling RLS causes migrations to fail when policies reference helper functions defined later in the diff. | ||
| - Requested restoring deferred policy creation until after all new functions/procedures exist. | ||
|
|
||
| --- | ||
|
|
||
| #### **p-c-h-b** | November 10, 2025, 18:02 | ||
| **Author Update:** | ||
|
|
||
| - Added selective policy deferral: policies stay co-located with their tables unless they reference helper functions introduced in the same migration, in which case they're executed after the corresponding functions/procedures are created. | ||
| - Updated the employee dump fixture to match the dependency-safe ordering. | ||
|
|
||
| --- | ||
|
|
||
| ## Summary of Key Issues Addressed | ||
|
|
||
| ### Round 1 (Nov 8): | ||
| - Enhanced test coverage for circular FK dependencies | ||
| - Removed test artifact files | ||
|
|
||
| ### Round 2 (Nov 9): | ||
| - Fixed constraint deferral logic | ||
| - Cleaned up test artifacts | ||
|
|
||
| ### Round 3 (Nov 10 - Current): | ||
| - **Policy Ordering**: Policies must be co-located with RLS enable statements | ||
| - **Test Artifacts**: Remove `cmd/dump/employee_expected.sql` | ||
| - **Policy Deferral**: Ensure CREATE POLICY statements execute only after dependent functions/procedures when helper functions are newly added | ||
|
|
||
| --- | ||
|
|
||
| ## Current Status | ||
|
|
||
| **Status**: Feedback addressed in latest commits | ||
| - ✅ Removed test artifact file (`cmd/dump/employee_expected.sql`) | ||
| - ✅ RLS enable statements remain co-located with their tables, with policies only deferred when they depend on helper functions added in the same migration | ||
| - ✅ Updated test fixture (`testdata/dump/employee/pgschema.sql`) | ||
| - ✅ All tests passing | ||
| - ✅ Restored dependency-safe policy creation without sacrificing readability |
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
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,61 @@ | ||
| package diff | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| "github.com/pgschema/pgschema/ir" | ||
| ) | ||
|
|
||
| func TestPolicyReferencesNewFunction_Unqualified(t *testing.T) { | ||
| functions := []*ir.Function{ | ||
| {Schema: "public", Name: "tenant_filter"}, | ||
| } | ||
| lookup := buildFunctionLookup(functions) | ||
|
|
||
| policy := &ir.RLSPolicy{ | ||
| Schema: "public", | ||
| Table: "users", | ||
| Name: "tenant_policy", | ||
| Using: "tenant_filter(tenant_id)", | ||
| } | ||
|
|
||
| if !policyReferencesNewFunction(policy, lookup) { | ||
| t.Fatalf("expected policy to reference newly added function") | ||
| } | ||
| } | ||
|
|
||
| func TestPolicyReferencesNewFunction_Qualified(t *testing.T) { | ||
| functions := []*ir.Function{ | ||
| {Schema: "auth", Name: "tenant_filter"}, | ||
| } | ||
| lookup := buildFunctionLookup(functions) | ||
|
|
||
| policy := &ir.RLSPolicy{ | ||
| Schema: "public", | ||
| Table: "users", | ||
| Name: "tenant_policy", | ||
| Using: "auth.tenant_filter(tenant_id)", | ||
| } | ||
|
|
||
| if !policyReferencesNewFunction(policy, lookup) { | ||
| t.Fatalf("expected policy to match schema-qualified helper function") | ||
| } | ||
| } | ||
|
|
||
| func TestPolicyReferencesNewFunction_BuiltInIgnored(t *testing.T) { | ||
| functions := []*ir.Function{ | ||
| {Schema: "public", Name: "tenant_filter"}, | ||
| } | ||
| lookup := buildFunctionLookup(functions) | ||
|
|
||
| policy := &ir.RLSPolicy{ | ||
| Schema: "public", | ||
| Table: "audit", | ||
| Name: "audit_policy", | ||
| Using: "user_name = CURRENT_USER", | ||
| } | ||
|
|
||
| if policyReferencesNewFunction(policy, lookup) { | ||
| t.Fatalf("expected policy referencing only built-in functions to remain inline") | ||
| } | ||
| } |
Oops, something went wrong.
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 regex pattern allows
$as part of identifier characters, but PostgreSQL identifiers cannot contain$in the middle. The pattern[a-z0-9_$.]*will incorrectly match things likefoo$bar(. PostgreSQL only allows$in quoted identifiers or at the start of dollar-quoted strings.Consider using
[a-z_][a-z0-9_]*(?:\.[a-z_][a-z0-9_]*)*to match schema-qualified identifiers correctly, or handle qualified names explicitly.