Skip to content

fix: preserve INCLUDE columns on CREATE INDEX (#385)#390

Merged
tianzhou merged 1 commit intomainfrom
fix/issue-385-index-include-columns
Apr 7, 2026
Merged

fix: preserve INCLUDE columns on CREATE INDEX (#385)#390
tianzhou merged 1 commit intomainfrom
fix/issue-385-index-include-columns

Conversation

@tianzhou
Copy link
Copy Markdown
Contributor

@tianzhou tianzhou commented Apr 7, 2026

Summary

  • Index INCLUDE columns were being merged into regular indexed columns because the inspector used indnatts (total columns) instead of indnkeyatts (key columns only)
  • Added IncludeColumns field to Index IR struct and updated the SQL query to separately extract include columns from positions indnkeyatts+1 through indnatts
  • Updated diff generation to emit INCLUDE (...) clause and structural equality comparison

Fixes #385

Test plan

  • Added INCLUDE index test case to existing testdata/diff/create_index/add_index/
  • Run: PGSCHEMA_TEST_FILTER="create_index/" go test -v ./cmd -run TestPlanAndApply
  • All 150+ diff tests pass with no regressions

🤖 Generated with Claude Code

The index inspector was using indnatts (total columns) for both key and
include columns, causing INCLUDE columns to be merged into regular indexed
columns. Now uses indnkeyatts to extract only key columns, and separately
extracts include columns from positions indnkeyatts+1 through indnatts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 7, 2026 09:49
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Apr 7, 2026

Greptile Summary

This PR fixes a bug where index INCLUDE columns were being merged into the regular key-column list because the inspector iterated up to indnatts (total columns) rather than indnkeyatts (key columns only). The fix adds an IncludeColumns []string field to the Index IR struct, updates the SQL query to extract the two sets separately, emits the INCLUDE (...) clause in the correct PostgreSQL syntax position, and extends indexesStructurallyEqual to compare the new field.

Confidence Score: 5/5

Safe to merge — the fix is correct and well-tested with no blocking issues.

All findings are P2 (unused NumKeyColumns field in sqlc-generated code, consistent with the pre-existing unused NumColumns). The core bug fix correctly uses indnkeyatts vs indnatts to separate key and INCLUDE columns, the generated SQL clause ordering is valid PostgreSQL syntax (INCLUDE before NULLS NOT DISTINCT and WHERE), and the structural-equality comparison handles the ordered nature of INCLUDE columns correctly.

No files require special attention.

Important Files Changed

Filename Overview
ir/queries/queries.sql Correctly splits key columns (1..indnkeyatts) from INCLUDE columns (indnkeyatts+1..indnatts); adds num_key_columns which is unused in Go code
ir/queries/queries.sql.go sqlc-generated: adds NumKeyColumns and IncludeColumns with scan order matching SELECT list; NumKeyColumns unused
ir/ir.go Adds IncludeColumns []string to Index struct with omitempty json tag
ir/inspector.go Assigns indexRow.IncludeColumns to Index struct; column-building loop unchanged since it iterates ColumnDefinitions only
internal/diff/index.go Emits INCLUDE (...) after key-column list, before NULLS NOT DISTINCT and WHERE — correct PostgreSQL syntax order
internal/diff/table.go Extends indexesStructurallyEqual with ordered positional comparison of IncludeColumns
testdata/diff/create_index/add_index/new.sql Adds INCLUDE index test fixture
testdata/diff/create_index/add_index/diff.sql Expected diff output includes correct INCLUDE clause
testdata/diff/create_index/add_index/plan.json Plan JSON updated with new index entry
testdata/diff/create_index/add_index/plan.sql Plan SQL updated with INCLUDE index
testdata/diff/create_index/add_index/plan.txt Plan text output updated

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[pg_index row] --> B{indnkeyatts vs indnatts}
    B -->|generate_series 1..indnkeyatts| C[column_definitions
column_directions
column_opclasses]
    B -->|generate_series indnkeyatts+1..indnatts| D[include_columns]
    C --> E[Index.Columns]
    D --> F[Index.IncludeColumns]
    E --> G[generateIndexSQLWithName]
    F --> G
    G --> H["CREATE INDEX ... (key_cols)\nINCLUDE (include_cols)\n[NULLS NOT DISTINCT] [WHERE ...];"]
    E --> I[indexesStructurallyEqual]
    F --> I
    I -->|equal| J[no-op]
    I -->|differs| K[DROP + CREATE]
Loading

Reviews (1): Last reviewed commit: "fix: preserve INCLUDE columns on CREATE ..." | Re-trigger Greptile

Comment on lines +1782 to 1783
NumKeyColumns int16 `db:"num_key_columns" json:"num_key_columns"`
NumColumns int16 `db:"num_columns" json:"num_columns"`
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Unused NumKeyColumns field

NumKeyColumns is scanned from the database but never read anywhere in inspector.go — column counts are already derived implicitly from the lengths of ColumnDefinitions and IncludeColumns. The pre-existing NumColumns field had the same issue before this PR. Both fields could be removed from the query, struct, and scan to reduce noise, but they're harmless as-is.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acknowledged — both NumKeyColumns and NumColumns are unused in Go code (column counts come from array lengths). This is a pre-existing pattern; removing them would be unrelated cleanup. Keeping them harmless and consistent with the SQL query structure.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes schema inspection and diff/DDL generation so Postgres index INCLUDE columns are preserved (instead of being incorrectly merged into key columns), addressing issue #385.

Changes:

  • Update index inspection query to treat indnkeyatts as the key-column count and separately extract INCLUDE columns from indnkeyatts+1..indnatts.
  • Extend the IR index model with IncludeColumns, and update diff structural equality + SQL generation to emit INCLUDE (...).
  • Add/update a regression test case under testdata/diff/create_index/add_index/ to cover CREATE INDEX with INCLUDE.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.

Show a summary per file
File Description
ir/queries/queries.sql Fixes index column extraction by separating key vs INCLUDE columns using indnkeyatts / indnatts.
ir/queries/queries.sql.go Regenerates/updates sqlc output to include new query fields and scanning for INCLUDE columns.
ir/ir.go Adds IncludeColumns to the Index IR struct for non-key stored columns.
ir/inspector.go Populates Index.IncludeColumns from query results during inspection.
internal/diff/index.go Emits INCLUDE (...) clause in generated CREATE INDEX SQL when applicable.
internal/diff/table.go Includes IncludeColumns in indexesStructurallyEqual to detect structural changes correctly.
testdata/diff/create_index/add_index/new.sql Adds a desired-state index containing INCLUDE (name) for regression coverage.
testdata/diff/create_index/add_index/plan.txt Updates expected plan summary/DDL to include the INCLUDE index.
testdata/diff/create_index/add_index/plan.sql Updates expected plan SQL output for INCLUDE clause.
testdata/diff/create_index/add_index/plan.json Updates expected plan JSON step for the INCLUDE index.
testdata/diff/create_index/add_index/diff.sql Updates expected diff SQL to include INCLUDE (...).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@tianzhou tianzhou merged commit b85861a into main Apr 7, 2026
6 checks passed
@tianzhou tianzhou deleted the fix/issue-385-index-include-columns branch April 8, 2026 02:07
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.

Schema dump does not preserve INCLUDE columns on CREATE INDEX

2 participants