diff --git a/drizzle-kit/src/sqlgenerator.ts b/drizzle-kit/src/sqlgenerator.ts index 64d3c4063c..7678d6158e 100644 --- a/drizzle-kit/src/sqlgenerator.ts +++ b/drizzle-kit/src/sqlgenerator.ts @@ -2407,7 +2407,7 @@ export class LibSQLModifyColumn extends Convertor { for (const table of Object.values(json2.tables)) { for (const index of Object.values(table.indexes)) { const unsquashed = SQLiteSquasher.unsquashIdx(index); - sqlStatements.push(`DROP INDEX "${unsquashed.name}";`); + sqlStatements.push(`DROP INDEX IF EXISTS "${unsquashed.name}";`); indexes.push({ ...unsquashed, tableName: table.name }); } } @@ -3735,7 +3735,7 @@ export class SqliteDropIndexConvertor extends Convertor { convert(statement: JsonDropIndexStatement): string { const { name } = PgSquasher.unsquashIdx(statement.data); - return `DROP INDEX \`${name}\`;`; + return `DROP INDEX IF EXISTS \`${name}\`;`; } } diff --git a/drizzle-kit/tests/libsql-statements.test.ts b/drizzle-kit/tests/libsql-statements.test.ts index 636496c458..a9ae0f7fa8 100644 --- a/drizzle-kit/tests/libsql-statements.test.ts +++ b/drizzle-kit/tests/libsql-statements.test.ts @@ -917,7 +917,7 @@ test('set not null with index', async (t) => { expect(sqlStatements.length).toBe(3); expect(sqlStatements[0]).toBe( - `DROP INDEX "users_name_index";`, + `DROP INDEX IF EXISTS "users_name_index";`, ); expect(sqlStatements[1]).toBe( `ALTER TABLE \`users\` ALTER COLUMN "name" TO "name" text NOT NULL;`, @@ -972,10 +972,10 @@ test('drop not null with two indexes', async (t) => { expect(sqlStatements.length).toBe(5); expect(sqlStatements[0]).toBe( - `DROP INDEX "users_name_unique";`, + `DROP INDEX IF EXISTS "users_name_unique";`, ); expect(sqlStatements[1]).toBe( - `DROP INDEX "users_age_index";`, + `DROP INDEX IF EXISTS "users_age_index";`, ); expect(sqlStatements[2]).toBe( `ALTER TABLE \`users\` ALTER COLUMN "name" TO "name" text;`, @@ -987,3 +987,52 @@ test('drop not null with two indexes', async (t) => { `CREATE INDEX \`users_age_index\` ON \`users\` (\`age\`);`, ); }); + +test('set not null on two tables uses idempotent index drops', async (t) => { + const schema1 = { + users: sqliteTable('users', { + id: int('id').primaryKey({ autoIncrement: true }), + name: text('name'), + }, (table) => ({ + someIndex: index('users_name_index').on(table.name), + })), + projects: sqliteTable('projects', { + id: int('id').primaryKey({ autoIncrement: true }), + title: text('title'), + }, (table) => ({ + someIndex: index('projects_title_index').on(table.title), + })), + }; + + const schema2 = { + users: sqliteTable('users', { + id: int('id').primaryKey({ autoIncrement: true }), + name: text('name').notNull(), + }, (table) => ({ + someIndex: index('users_name_index').on(table.name), + })), + projects: sqliteTable('projects', { + id: int('id').primaryKey({ autoIncrement: true }), + title: text('title').notNull(), + }, (table) => ({ + someIndex: index('projects_title_index').on(table.title), + })), + }; + + const { statements, sqlStatements } = await diffTestSchemasLibSQL( + schema1, + schema2, + [], + ); + + expect(statements.length).toBe(2); + expect(statements.every((statement) => statement.type === 'alter_table_alter_column_set_notnull')).toBe(true); + + const usersDrops = sqlStatements.filter((statement) => statement === `DROP INDEX IF EXISTS "users_name_index";`); + const projectsDrops = sqlStatements.filter((statement) => statement === `DROP INDEX IF EXISTS "projects_title_index";`); + + expect(usersDrops.length).toBeGreaterThanOrEqual(1); + expect(projectsDrops.length).toBeGreaterThanOrEqual(1); + expect(sqlStatements.some((statement) => statement.startsWith(`DROP INDEX "users_name_index"`))).toBe(false); + expect(sqlStatements.some((statement) => statement.startsWith(`DROP INDEX "projects_title_index"`))).toBe(false); +}); diff --git a/drizzle-kit/tests/push/libsql.test.ts b/drizzle-kit/tests/push/libsql.test.ts index 2ae2e38110..460809d9e3 100644 --- a/drizzle-kit/tests/push/libsql.test.ts +++ b/drizzle-kit/tests/push/libsql.test.ts @@ -185,7 +185,7 @@ test('added, dropped index', async (t) => { expect(sqlStatements.length).toBe(2); expect(sqlStatements[0]).toBe( - `DROP INDEX \`customers_address_unique\`;`, + `DROP INDEX IF EXISTS \`customers_address_unique\`;`, ); expect(sqlStatements[1]).toBe( `CREATE UNIQUE INDEX \`customers_is_confirmed_unique\` ON \`customers\` (\`is_confirmed\`);`, @@ -963,7 +963,7 @@ test('set not null with index', async (t) => { expect(sqlStatements.length).toBe(3); expect(sqlStatements[0]).toBe( - `DROP INDEX "users_name_index";`, + `DROP INDEX IF EXISTS "users_name_index";`, ); expect(sqlStatements[1]).toBe( `ALTER TABLE \`users\` ALTER COLUMN "name" TO "name" text NOT NULL;`, @@ -1035,10 +1035,10 @@ test('drop not null with two indexes', async (t) => { expect(sqlStatements.length).toBe(5); expect(sqlStatements[0]).toBe( - `DROP INDEX "users_name_unique";`, + `DROP INDEX IF EXISTS "users_name_unique";`, ); expect(sqlStatements[1]).toBe( - `DROP INDEX "users_age_index";`, + `DROP INDEX IF EXISTS "users_age_index";`, ); expect(sqlStatements[2]).toBe( `ALTER TABLE \`users\` ALTER COLUMN "name" TO "name" text;`, diff --git a/drizzle-kit/tests/push/sqlite.test.ts b/drizzle-kit/tests/push/sqlite.test.ts index e2c85233a3..dd1d88fe3a 100644 --- a/drizzle-kit/tests/push/sqlite.test.ts +++ b/drizzle-kit/tests/push/sqlite.test.ts @@ -185,7 +185,7 @@ test('dropped, added unique index', async (t) => { expect(sqlStatements.length).toBe(2); expect(sqlStatements[0]).toBe( - `DROP INDEX \`customers_address_unique\`;`, + `DROP INDEX IF EXISTS \`customers_address_unique\`;`, ); expect(sqlStatements[1]).toBe( `CREATE UNIQUE INDEX \`customers_is_confirmed_unique\` ON \`customers\` (\`is_confirmed\`);`,