Repository navigation
fix: keep the online index candidate inside the identifier limit - #679
Conversation
[Medium impact] The change affects online index replacements across table and materialized-view indexes. Add the missing Findings
SummaryThis PR keeps temporary online index names within PostgreSQL’s 63-byte limit.
Reviews (1) · Last reviewed commit: "fix: keep the online index candidate ins..." · Reviewed by Greptile |
| CONSTRAINT entries_pkey PRIMARY KEY (id) | ||
| ); | ||
|
|
||
| CREATE INDEX iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii ON entries (b); |
There was a problem hiding this comment.
The new fixture is missing diff.sql. TestDiffFromFiles visits this directory and reads that file unconditionally, so its new subtest fails on PostgreSQL 18 before comparing either schema. Add the expected non-online migration as diff.sql; the online output in plan.sql serves a different test.
Appending _pgschema_new to a 63-byte index name produced a 76-byte candidate that PostgreSQL truncated back to the canonical name. CREATE INDEX CONCURRENTLY IF NOT EXISTS then skipped the build, the wait returned at once, and the final DROP/ALTER pair failed with 42P01. The candidate now shortens the canonical part when the suffix does not fit and takes the tail from a SHA-256 of the full name, so it is at most 63 bytes, differs from the canonical name, and stays distinct for names that share a long prefix. Names that fit are unchanged (lookup -> lookup_pgschema_new). Closes pgplex#670
2a30262 to
16b7d85
Compare
|
That file is on the branch already. Against the embedded PostgreSQL 18.3.0: All 19 |
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues were identified for the change that keeps temporary online-replacement index names within PostgreSQL’s 63-byte limit.
No open issues 🎉
What changed in this PR
Fixes #670 by keeping temporary online-replacement index names within PostgreSQL’s 63-byte identifier limit, preventing truncation from colliding with the original index.
Changes:
- Adds a shared naming helper that preserves short names and shortens long names using a hash suffix and UTF-8-safe truncation.
- Updates both online index replacement paths to use the helper.
- Adds unit coverage and a regression fixture for a 63-byte index name.
| File | Description |
|---|---|
testdata/diff/online/issue_670_long_index_name/plan.txt |
Expected readable online replacement plan. |
testdata/diff/online/issue_670_long_index_name/plan.sql |
Expected SQL using the shortened candidate name. |
testdata/diff/online/issue_670_long_index_name/plan.json |
Expected structured plan and transaction groups. |
testdata/diff/online/issue_670_long_index_name/old.sql |
Original maximum-length index on column a. |
testdata/diff/online/issue_670_long_index_name/new.sql |
Desired index on column b. |
testdata/diff/online/issue_670_long_index_name/diff.sql |
Expected baseline index replacement DDL. |
internal/plan/rewrite.go |
Adds bounded candidate naming to both replacement paths. |
internal/plan/rewrite_test.go |
Tests naming limits, UTF-8 validity, and rewrite usage. |
Review effort: Balanced
tianzhou
left a comment
There was a problem hiding this comment.
LGTM. Thanks for the contribution.
A 63-byte index name cannot be replaced through the online rewrite:
name + "_pgschema_new"is 76 bytes, PostgreSQL truncates it back to the canonical name,CREATE INDEX CONCURRENTLY IF NOT EXISTSskips the build, the wait returns at once, and the finalDROP/ALTERpair fails with 42P01.onlineIndexTempNamekeeps the current name when the suffix fits (solookupis stilllookup_pgschema_newand no existing fixture moves) and otherwise shortens the canonical part and takes the tail from a SHA-256 of the full name: at most 63 bytes, never equal to the canonical name, distinct for names sharing a long prefix, and cut on a UTF-8 boundary so a multi-byte name cannot produce invalid UTF-8 for the server.Both call sites use it (index replacement from the new IR index, and the
IndexDiffpath). The newtestdata/diff/online/issue_670_long_index_namecase is the issue's fixture with a 63-byte name;plan.sqlwas generated with-generateand re-checked with the integration suite in compare mode.go build ./...,go vet ./internal/plan/andgo test ./...pass.Closes #670