Skip to content

fix: resolve index generation bugs (Issue #21 + DropIndex reversibility) - #24

Merged
Phathdt merged 2 commits into
mainfrom
fix/issue-21-index-generation-and-dropindex-bug
Sep 20, 2026
Merged

Phathdt merged 2 commits into
mainfrom
fix/issue-21-index-generation-and-dropindex-bug

Conversation

@Phathdt

@Phathdt Phathdt commented Sep 17, 2026

Copy link
Copy Markdown
Owner

Summary

This PR fixes three critical bugs affecting index generation and migration reversibility.

Bugs Fixed

🔴 Issue #21: @@index not generated in migrations

Root cause: Differ only created CreateTable operation for new tables, without separate CreateIndex operations.

Fix: Generate CreateIndex operations for each index when creating new tables.

Impact: Indexes are now correctly included in migrations for new tables.


🔴 Bug #2: Migration builder loses indexes from history

Root cause: applyCreateIndex modified table.Indexes but didn't save table back to map (Go value semantics issue).

Fix: Add b.tables[stmt.Table] = table after modifying indexes.

Impact: Schema loaded from migration history now preserves indexes correctly.


🔴 Bug #3: DropIndex with unnamed indexes generates invalid SQL

Root cause: DropIndex operation only stored Name (empty for auto-generated indexes), resulting in DROP INDEX ; (invalid SQL).

Fixes:

  • Add Index field to DropIndex struct to store full index definition
  • Populate Index object when creating DropIndex operations
  • Auto-generate index name from columns when Name is empty
  • Generate CREATE INDEX for reverse DropIndex operations

Impact: DROP INDEX now generates valid SQL and fully reversible Down migrations.


Changes

  • internal/diff/differ.go: Generate CreateIndex ops for new tables, populate Index in DropIndex
  • internal/diff/operation.go: Add Index field to DropIndex struct
  • internal/migration/builder.go: Save modified table back to map after applying index
  • internal/prisma/converter.go: Extract index name from @@index attributes
  • internal/sql/postgres/generator.go: Auto-generate index names, implement reversible DROP INDEX
  • internal/sql/postgres/generator_reverse_test.go: Update test expectations for reversible DropIndex

Tests Added

  • ✅ internal/diff/differ_dropindex_test.go: Unit tests for DropIndex with unnamed/named indexes
  • ✅ internal/sql/postgres/generator_dropindex_test.go: Unit tests for DROP INDEX SQL generation and reverse
  • ✅ internal/prisma/converter_test.go: Test for index name extraction
  • ✅ internal/diff/differ_test.go: Tests for new tables with indexes

Verification

  • ✅ All unit tests pass
  • ✅ E2E manual testing confirms indexes generated correctly
  • ✅ Down migrations fully reversible
  • ✅ Zero regressions

Example

Before (Bug):

-- +goose Up
CREATE TABLE users (...);
-- Missing CREATE INDEX!

-- +goose Down
DROP INDEX ;  -- Invalid SQL!

After (Fixed):

-- +goose Up
CREATE TABLE users (...);
CREATE INDEX idx_users_email ON users (email);

-- +goose Down
CREATE INDEX idx_users_email ON users (email);
DROP TABLE users;

Closes #21

This commit fixes three critical bugs affecting index generation and migration reversibility:

**Issue #21: @@index not generated in migrations**
- Root cause: Differ only created CreateTable operation for new tables, without separate CreateIndex operations
- Fix: Generate CreateIndex operations for each index when creating new tables (differ.go:148-155)
- Impact: Indexes are now correctly included in migrations for new tables

**Bug #2: Migration builder loses indexes from history**
- Root cause: applyCreateIndex modified table.Indexes but didn't save table back to map (Go value semantics)
- Fix: Add b.tables[stmt.Table] = table after modifying indexes (builder.go:212)
- Impact: Schema loaded from migration history now preserves indexes correctly

**Bug #3: DropIndex with unnamed indexes generates invalid SQL**
- Root cause: DropIndex operation only stored Name (empty for auto-generated indexes)
- Fix: Add Index field to DropIndex struct to store full index definition (operation.go:230)
- Fix: Populate Index object when creating DropIndex operations (differ.go:404)
- Fix: Auto-generate index name from columns when Name is empty (generator.go:268-274)
- Fix: Generate CREATE INDEX for reverse DropIndex operations (generator.go:384-405)
- Impact: DROP INDEX now generates valid SQL and fully reversible Down migrations

**Changes:**
- internal/diff/differ.go: Generate CreateIndex ops for new tables, populate Index in DropIndex
- internal/diff/operation.go: Add Index field to DropIndex struct
- internal/migration/builder.go: Save modified table back to map after applying index
- internal/prisma/converter.go: Extract index name from @@index attributes
- internal/sql/postgres/generator.go: Auto-generate index names, implement reversible DROP INDEX
- internal/sql/postgres/generator_reverse_test.go: Update test expectations for reversible DropIndex

**Tests added:**
- internal/diff/differ_dropindex_test.go: Unit tests for DropIndex with unnamed/named indexes
- internal/sql/postgres/generator_dropindex_test.go: Unit tests for DROP INDEX SQL generation and reverse
- internal/prisma/converter_test.go: Test for index name extraction
- internal/diff/differ_test.go: Tests for new tables with indexes

**Verification:**
- All unit tests pass
- E2E manual testing confirms indexes generated correctly
- Down migrations fully reversible

Fixes #21

Co-authored-by: Claude (Anthropic)
Signed-off-by: Phathdt <phathdt189@gmail.com>
@Phathdt Phathdt added the bug Something isn't working label Sep 17, 2026
@Phathdt
Phathdt merged commit d83ab33 into main Sep 20, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

@@index not generated in migrations

1 participant