fix: emit PARTITION OF for partition children on create path (#496)#498
Conversation
Partition children were rendered as standalone CREATE TABLE with inlined columns, dropping the PARTITION OF ... FOR VALUES attachment clause. The parent ended up with zero attached partitions and could not route inserts. Add PartitionOf/PartitionBound metadata to the IR Table struct, populate it from pg_inherits during inspection, and emit the correct PARTITION OF syntax in generateTableSQL. Also add partition parent→child edges to the topological sort so parents are always created before their children. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Fixes the create-path behavior for partitioned tables by teaching the IR/diff engine about partition parent/child attachments so partition children are created with PARTITION OF ... FOR VALUES ... (or DEFAULT) instead of detached standalone tables. This addresses #496 where from-scratch applies produced non-functional partitioned parents with zero attached partitions.
Changes:
- Extend
ir.Tablewith partition-child metadata (PartitionOf,PartitionOfSchema,PartitionBound) and populate it frompg_inherits+pg_get_expr(relpartbound). - Update table DDL generation to emit
CREATE TABLE ... PARTITION OF ... <bound>;for partition children. - Add partition parent → child dependencies to table topological sorting to ensure parents are created before their partitions, and add a new diff fixture for the reported scenario.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
ir/ir.go |
Adds partition-child metadata fields to ir.Table. |
ir/inspector.go |
Populates partition-child metadata during inspection while building partition mappings. |
internal/diff/table.go |
Emits PARTITION OF DDL for partition children on the create path. |
internal/diff/topological.go |
Ensures partition parents sort before children (dependency edge). |
cmd/plan/plan.go |
Normalizes partition parent schema during temp→target schema rewrite. |
testdata/diff/create_table/issue_496_partition_of_create_path/* |
New diff test fixture for LIST partition create-path attachment. |
testdata/diff/create_table/issue_495_partition_constraint_convergence/plan.json |
Expected-plan hash update. |
testdata/diff/online/issue_418_partitioned_parent_index/plan.json |
Expected-plan hash update. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Greptile SummaryThis PR fixes a correctness bug where partition child tables were incorrectly emitted as standalone
Confidence Score: 4/5Safe to merge for the common case; the fix correctly handles the create-from-scratch partition path for all standard LIST/RANGE/HASH bound types. The core fix is well-structured and the new test covers the important end-to-end flow including idempotency. One gap stands out: cmd/plan/plan.go — the Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant User as UserSQL
participant EmbPG as EmbeddedPostgres
participant Inspector as Inspector
participant Plan as PlanCmd
participant Diff as TableDiff
participant Topo as TopologicalSort
participant TargetDB as TargetDB
User->>EmbPG: Apply SQL files
EmbPG-->>Inspector: Schema inspected
Inspector->>Inspector: buildPartitionMapping sets PartitionOf, PartitionBound on child
Inspector-->>Plan: Desired IR with partition metadata
Plan->>Plan: normalizeSchemaNames replaces temp schema in PartitionOfSchema
Note over Plan: PartitionBound not normalized here
Plan->>Topo: topologicallySortTables
Topo->>Topo: Add parent to child edge for partition dep
Topo-->>Plan: Sorted parent before child
Plan->>Diff: generateTableSQL for child table
Diff->>Diff: PartitionOf and PartitionBound both set, early return
Diff-->>Plan: CREATE TABLE child PARTITION OF parent FOR VALUES
Plan->>TargetDB: Execute DDL in order
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant User as UserSQL
participant EmbPG as EmbeddedPostgres
participant Inspector as Inspector
participant Plan as PlanCmd
participant Diff as TableDiff
participant Topo as TopologicalSort
participant TargetDB as TargetDB
User->>EmbPG: Apply SQL files
EmbPG-->>Inspector: Schema inspected
Inspector->>Inspector: buildPartitionMapping sets PartitionOf, PartitionBound on child
Inspector-->>Plan: Desired IR with partition metadata
Plan->>Plan: normalizeSchemaNames replaces temp schema in PartitionOfSchema
Note over Plan: PartitionBound not normalized here
Plan->>Topo: topologicallySortTables
Topo->>Topo: Add parent to child edge for partition dep
Topo-->>Plan: Sorted parent before child
Plan->>Diff: generateTableSQL for child table
Diff->>Diff: PartitionOf and PartitionBound both set, early return
Diff-->>Plan: CREATE TABLE child PARTITION OF parent FOR VALUES
Plan->>TargetDB: Execute DDL in order
Reviews (1): Last reviewed commit: "fix: emit PARTITION OF for partition chi..." | Re-trigger Greptile |
- Normalize PartitionBound expression in normalizeSchemaNames to prevent temp-schema type casts from leaking into DDL (Copilot/Greptile P1) - Fall back to child's schema when PartitionOfSchema is empty in generateTableSQL to avoid invalid ".<parent>" reference (Copilot) - Hoist getOrCreateSchema outside loop in buildPartitionMapping (Copilot) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…496) Address review feedback on PR #498: - Broaden conparentid filter from FK-only to ALL constraint types (AND c.conparentid = 0) so inherited partition constraint copies are excluded from IR while child-specific constraints are preserved - Include child-specific constraints inline in PARTITION OF statement, with proper FK deferral support - Add timezone offset normalization in dump test comparison for cross-platform pg_get_expr consistency - Update dump test expected outputs (issue_409, issue_472) to use PARTITION OF syntax - Update issue_495 plan.json fingerprint hash Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update tzOffsetRe to match offsets like +05:30 and +05:45, not just whole-hour offsets like -08. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
pg_get_expr returns timestamps in the server's local timezone, causing partition bounds and fingerprint hashes to differ across platforms. Setting timezone=UTC ensures consistent output on all machines. - Update Sakila dump expected output for PARTITION OF rendering - Update issue_418 plan hash to match UTC-based fingerprint Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Emit CREATE UNLOGGED TABLE for partition children when the table is marked as unlogged, matching the regular create path behavior. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
Fixes #496. Partition children were rendered as standalone
CREATE TABLEwith inlined columns, dropping thePARTITION OF ... FOR VALUESattachment clause. The parent ended up with zero attached partitions and could not route inserts.PartitionOf,PartitionOfSchema,PartitionBoundfields toir.Tablepg_inherits/pg_get_expr(relpartbound)during catalog inspectiongenerateTableSQL()emitsCREATE TABLE IF NOT EXISTS <child> PARTITION OF <parent> <bound>;when the table is a partition childPartitionOfSchemain the temp→target schema replacement passTest plan
issue_496_partition_of_create_path— LIST partitioning with 3 children (2 value-based + DEFAULT), from-scratch createissue_495convergence,issue_418partitioned parent index)🤖 Generated with Claude Code