Skip to content

[SQLite-kit]: make index drop/recreate idempotent for libSQL/Turso push#5607

Open
MorganTitcher wants to merge 2 commits intodrizzle-team:mainfrom
MorganTitcher:cursor/-bc-c1cb5864-b4cb-4b3e-a076-1cc761dc7c01-eb2e
Open

[SQLite-kit]: make index drop/recreate idempotent for libSQL/Turso push#5607
MorganTitcher wants to merge 2 commits intodrizzle-team:mainfrom
MorganTitcher:cursor/-bc-c1cb5864-b4cb-4b3e-a076-1cc761dc7c01-eb2e

Conversation

@MorganTitcher
Copy link
Copy Markdown

@MorganTitcher MorganTitcher commented Apr 6, 2026

Summary

Fixes drizzle-kit push / db:push failures on libSQL/Turso when multiple LibSQLModifyColumn operations are executed in a single batch.

Previously, repeated DROP INDEX statements could fail with:

  • no such index (index already removed earlier in the batch)
  • duplicate index errors on re-creation

This occurs because LibSQLModifyColumn emits unconditional index teardown and recreation, which is not safe when multiple table/column modifications are processed together.

Changes

Idempotent index handling in LibSQLModifyColumn

Update index teardown and recreation to be safe under batching:

  • DROP INDEXDROP INDEX IF EXISTS
  • CREATE INDEXCREATE INDEX IF NOT EXISTS
  • CREATE UNIQUE INDEXCREATE UNIQUE INDEX IF NOT EXISTS

This ensures that:

  • repeated teardown does not fail if an index was already dropped
  • repeated creation does not fail if an index already exists

SQLite drop_index convertor

Update SqliteDropIndexConvertor to emit:

  • DROP INDEX IF EXISTS

for explicit drop_index statements on SQLite/libSQL/Turso.

Tests

All drizzle-kit tests pass:

cd drizzle-kit && pnpm test

Rationale

The current drop/recreate strategy is correct in principle, but not safe under batched execution where the same index may be touched multiple times.

Making index operations idempotent:

  • preserves existing behavior
  • eliminates ordering sensitivity within a batch
  • avoids introducing additional dependency tracking complexity

Notes / Follow-ups

A more targeted approach (only dropping/recreating indexes affected by a given column change) could reduce redundant operations, but would require deeper schema/index dependency analysis and is out of scope for this fix.

Reproduction

See #5564 for a minimal reproduction case involving:

  • multiple tables
  • indexed columns
  • set not null conversions in a single push

Checklist

  • Bug fix includes regression test
  • Tests updated and passing
  • No breaking changes
  • Behavior is backward-compatible (strictly more robust)

Fixes #5564

cursoragent and others added 2 commits April 6, 2026 21:40
Use DROP INDEX IF EXISTS when LibSQLModifyColumn tears down indexes, and
CREATE INDEX IF NOT EXISTS when recreating them so batchWithPragma survives
multiple column modifications in one push. Use DROP INDEX IF EXISTS in
SqliteDropIndexConvertor for explicit drop_index on sqlite/turso.

Fixes duplicate DROP INDEX failures (no such index) reported in drizzle-team#5564.

Co-authored-by: Morgan Titcher <MorganTitcher@users.noreply.github.com>
…team#5564

Align snapshots with IF EXISTS drops and IF NOT EXISTS index recreation.
Add regression test for two set_notnull statements across indexed tables.

Co-authored-by: Morgan Titcher <MorganTitcher@users.noreply.github.com>
@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.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

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.

[BUG]: [SQLite/Turso] LibSQLModifyColumn generates duplicate DROP INDEX (without IF EXISTS) causing "no such index" on db:push

2 participants