Skip to content

planner/lint: classify column and table renames as app-breaking - #19

Merged
Kiran01bm merged 3 commits into
mainfrom
kiran01bm/lint-rename
Aug 11, 2026
Merged

planner/lint: classify column and table renames as app-breaking#19
Kiran01bm merged 3 commits into
mainfrom
kiran01bm/lint-rename

Conversation

@Kiran01bm

Copy link
Copy Markdown
Collaborator

Summary

A direct RENAME COLUMN / RENAME TO previously classified as metadata-only and lint passed it clean — mechanically true for PostgreSQL, but a rename cannot land atomically across running application instances: code still referencing the old name breaks the instant it commits. This PR gives renames their own typed classification so lint and plan consumers can steer to a safe sequence.

What

  • New planner reason app-breaking-rename for column and table renames; the route stays native — the engine still executes the rename when asked.
  • New lint warning code app-breaking-rename, derived from the classifier (single-rulebook: the linter adds severity and presentation, never a second opinion). No suggestion array — the safe sequence involves application work the engine cannot construct SQL for.
  • Index renames stay metadata-only: SQL never references an index by name.
  • Regression test pinning the declarative differ's behavior: a rename-shaped edit (old column gone, new column present) stays drop + add — never an inferred rename — with the drop destructive-gated (invariant RF-4).
  • Reason/code rows added to the plan-report and lint-report contracts; LLD renames bullet extended.

Why

The safe path for a column rename is expand/contract — add the new column, dual-write and backfill, switch reads, then drop the old column as its own reviewed change. For a table rename, the rename must be coordinated with the application deploy that adopts the new name. Machine consumers (CI, orchestrator adapters) branch on the typed code; humans get the remedy in the report docs.

Severity is warning, not error: this repo's lint contract defines error as "the engine would refuse", and the engine executes renames (per the LLD: simple, unambiguous non-PK renames are allowed). Spirit flags column renames as an error but passes table renames because its unsafe linter is scoped to data loss — data loss is this repo's separate destructive code, so the app-compatibility warning applies to both rename kinds here.

Before / after

Before:  RENAME COLUMN / RENAME TO  -> native / metadata-only   (lint: clean)
After:   RENAME COLUMN / RENAME TO  -> native / app-breaking-rename
                                        (lint: warning app-breaking-rename)
         ALTER INDEX ... RENAME TO  -> native / metadata-only   (unchanged)

PostgreSQL executes RENAME COLUMN as a metadata-only catalog flip, but
the rename cannot land atomically across running application instances:
code still referencing the old name breaks the instant it commits. The
planner now carries a dedicated app-breaking-rename reason (route stays
native) and lint surfaces it as a warning recommending expand/contract:
add, dual-write/backfill, switch reads, drop separately. The declarative
differ already refuses to guess renames; a regression test pins the
drop+add shape.
A table rename has the same pod-atomicity hazard as a column rename:
running code queries the old table name and breaks the instant the
flip commits. Spirit's unsafe linter passes table renames because they
lose no data — data loss is our separate destructive code, so the
app-compatibility warning applies here too. Index renames stay
metadata-only: SQL never references an index by name.
@Kiran01bm
Kiran01bm changed the base branch from kiran01bm/p2-5-linter to main August 11, 2026 02:58
@Kiran01bm
Kiran01bm marked this pull request as ready for review August 11, 2026 21:53
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

* origin/main:
  testutil: gate Ministack harness behind build tag, demote CI job to signal
  vision: claim only what standalone use enforces today
  ci: make docs-only detection honor its exclusion patterns
  docs: reword README from research notes to decided outcomes
  ci: run the test matrix against one long-lived database
  Tighten the diffplan library seam per PR #20 API review
  Export the declarative diff→plan pipeline as pkg/diffplan
  Add pkg/executor native CREATE INDEX CONCURRENTLY with fail-closed recovery
  Add pkg/suggest: advisory safer-form rewrites with typed caveats
  Clarify safer rewrites are safer forms, not semantic equivalents
  testutil: control-plane error contract and rotation-seam tests
  testutil: AWS-boundary test tier via Ministack RDS/Aurora
  vision: standalone CLI use is a supported front door
@Kiran01bm
Kiran01bm merged commit 9e9dd61 into main Aug 11, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants