-
Notifications
You must be signed in to change notification settings - Fork 28
fix: track altering identities #282
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
Conversation
Greptile OverviewGreptile SummaryThis PR adds diff/plan support for identity-generation changes and serial↔non-serial transitions by:
Main issues to address before merge are around correctness/safety of the generated SQL: unquoted identifiers for sequences, dropping sequences based only on defaults (can drop still-in-use objects), and the identity rewrite’s Confidence Score: 2/5
|
| Filename | Overview |
|---|---|
| internal/diff/column.go | Adds sequence creation/drop based on nextval defaults and emits DROP/ADD IDENTITY when identity generation changes; contains unsafe/unquoted identifiers and potentially incorrect sequence dropping. |
| internal/plan/rewrite.go | Adds rewrite generator to sync identity sequence after ADD GENERATED; uses unescaped table name in SQL string literals and may generate invalid pg_get_serial_sequence args for schema-qualified tables. |
| testdata/diff/create_table/alter_identity/diff.sql | Adds expected diff output for serial/identity transitions; reflects unqualified names and missing quoting from implementation. |
| testdata/diff/create_table/alter_identity/new.sql | Adds desired schema fixture covering serial and identity columns. |
| testdata/diff/create_table/alter_identity/old.sql | Adds current schema fixture covering serial and identity columns. |
| testdata/diff/create_table/alter_identity/plan.json | Adds plan fixture including setval rewrites; includes pg_get_serial_sequence('table1', ...) calls that may not work with schema-qualified tables. |
| testdata/diff/create_table/alter_identity/plan.sql | Adds plan SQL fixture including setval rewrites; mirrors potential schema-qualification issue. |
| testdata/diff/create_table/alter_identity/plan.txt | Adds plan text fixture reflecting identity rewrite steps; mirrors potential schema-qualification issue. |
Sequence Diagram
sequenceDiagram
participant Planner as plan.generateRewrite
participant Diff as diff.ColumnDiff.generateColumnSQL
participant IR as ir.Column
participant Plan as plan.generateColumnIdentityRewrite
Planner->>Diff: DiffTypeTableColumn alter
Diff->>Diff: extractSequenceNameFromDefault(old/new)
alt serial default added
Diff->>Diff: CREATE SEQUENCE IF NOT EXISTS ... OWNED BY table.column
Diff->>Diff: ALTER COLUMN ... SET DEFAULT nextval(...)
else serial default removed
Diff->>Diff: DROP SEQUENCE ...
end
alt identity changed or removed
Diff->>Diff: ALTER COLUMN ... DROP IDENTITY
end
alt identity added or generation changed
Diff->>Diff: ALTER COLUMN ... ADD GENERATED {ALWAYS|BY DEFAULT} AS IDENTITY
end
Planner->>Planner: scan d.Statements for "ADD GENERATED"
Planner->>Plan: generateColumnIdentityRewrite
Plan->>Plan: ALTER TABLE ... ADD GENERATED ... AS IDENTITY
Plan->>Plan: SELECT setval(pg_get_serial_sequence(table, col), COALESCE(MAX(col),0)+1)
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.
8 files reviewed, 4 comments
Additional Comments (1)
The rewrite selection checks Prompt To Fix With AIThis is a comment left during a code review.
Path: internal/plan/rewrite.go
Line: 91:105
Comment:
**Over-broad rewrite match**
The rewrite selection checks `strings.Contains(stmt.SQL, "ADD GENERATED")` across `d.Statements`. If any statement in the diff group contains that substring, `generateColumnIdentityRewrite` returns a new `ADD GENERATED ...` step, which can duplicate the base diff statement(s) or rewrite the wrong statement when multiple columns are altered in the same group. The rewrite dispatch should target the specific statement being rewritten (or rewrite the plan step in-place) rather than adding a second `ADD GENERATED` unconditionally.
How can I resolve this? If you propose a fix, please make it concise. |
Greptile OverviewGreptile SummaryThis PR adds proper tracking and migration support for PostgreSQL identity column changes, addressing issue #279. Key changes:
The implementation correctly handles three scenarios demonstrated in the test case:
Confidence Score: 5/5
|
| Filename | Overview |
|---|---|
| internal/diff/column.go | Added identity column change tracking: drops old identity if generation type changes, adds new identity configuration. Skips DROP DEFAULT for nextval() defaults when converting from serial to identity. |
| internal/diff/diff.go | Modified sequence filtering logic to only skip serial-owned sequences when the owning column doesn't exist in the other schema state. Added columnExistsInTables helper function. Fixed whitespace formatting in privilege fields. |
| internal/diff/sequence.go | Added OWNED BY clause to sequence creation SQL to properly track sequence ownership. Fixed whitespace formatting in constants. |
| internal/plan/rewrite.go | Added generateColumnIdentityRewrite function to handle identity column additions by adding identity then syncing sequence value with existing data using setval(pg_get_serial_sequence(...)). Integrated into rewrite detection logic. |
Sequence Diagram
sequenceDiagram
participant User
participant Diff as diff.GenerateMigration
participant Column as ColumnDiff
participant Sequence as Sequence Logic
participant Rewrite as plan.generateRewrite
User->>Diff: Compare old.sql vs new.sql
Note over Diff: Scan for column changes<br/>(identity additions/changes)
Diff->>Column: Detect c1: int → serial
Note over Column: Old has no identity,<br/>new has no identity<br/>(serial uses default nextval)
Column->>Sequence: Check if c1 sequence exists in old
Sequence-->>Column: No (column didn't exist)
Sequence->>Diff: Create table1_c1_seq
Column->>Diff: SET DEFAULT nextval('table1_c1_seq'::regclass)
Diff->>Column: Detect c2: serial → identity ALWAYS
Note over Column: Check if nextval() default exists
Column->>Column: Skip DROP DEFAULT (has nextval)
Column->>Diff: ADD GENERATED ALWAYS AS IDENTITY
Column->>Sequence: Check if c2_seq should be dropped
Sequence->>Sequence: Column still exists in new state
Sequence-->>Diff: DROP SEQUENCE table1_c2_seq
Diff->>Column: Detect c3: identity ALWAYS → BY DEFAULT
Note over Column: Identity generation changed
Column->>Diff: DROP IDENTITY
Column->>Diff: ADD GENERATED BY DEFAULT AS IDENTITY
Diff->>Rewrite: Check for rewrite steps
Rewrite->>Rewrite: Detect ADD GENERATED in c2
Note over Rewrite: generateColumnIdentityRewrite(c2)
Rewrite->>Diff: Add setval step for c2
Rewrite->>Rewrite: Detect ADD GENERATED in c3
Note over Rewrite: generateColumnIdentityRewrite(c3)
Rewrite->>Diff: Add setval step for c3
Diff-->>User: Migration plan with synced sequences
tianzhou
left a comment
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.
LGTM. Thanks for the contribution
Fixes #279