You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(sqlite-migrate): Support PK changes to schema (#7006)
#### Summary
Related to #6600, #6763 and #6759
This PR adds support for PK changes migration. Before we would just ignore them, so the following use cases were ignored:
1. Adding a new column as a primary key -> The column was added, but the table PKs were left unchanged
2. Removing a PK from an existing column -> Was ignored
3. Adding a PK to an existing column -> Was ignored
4. Changing the type of an existing PK column -> Was handled by a regular non PK column type change. We dropped the column, but we need to drop the table.
SQLite is quite limited in what can be done with PK changes. On any PK change we need to recreate the table, so either `drop + create` or `create new + copy old to new + drop old + rename new`.
I went with the former for simplicity.
<!--
can't migrate table "table_1" since adding the new PK column "new_pk_column" is not supported. Try dropping this table
65
-
can't migrate table "table_2" since changing the type of column "age" from "integer" to "text" is not supported. Try dropping this column for this table
66
-
can't migrate table "table_2" since changing the type of column "created_at" from "text" to "timestamp" is not supported. Try dropping this column for this table
67
-
68
-
To force a migration add "migrate_mode: forced" to your destination spec`,
64
+
can't migrate table "table_with_new_pk_column" since adding the new PK column "new_pk_column" is not supported. Try dropping this table
65
+
can't migrate table "table_with_pk_addition_existing_column" since making the existing column "id" a PK is not supported. Try dropping this table
66
+
can't migrate table "table_with_pk_removal" since removing an existing column "id" as a PK is not supported. Try dropping this table
67
+
can't migrate table "table_with_pk_type_change" since changing the type of the PK column "id" from "integer" to "text" is not supported. Try dropping this table
68
+
can't migrate table "table_with_non_pk_type_change" since changing the type of column "created_at" from "text" to "timestamp" is not supported. Try dropping this column for this table`,
69
69
},
70
70
{
71
71
name: "should succeed on migrate mode force",
@@ -75,15 +75,39 @@ To force a migration add "migrate_mode: forced" to your destination spec`,
err: fmt.Sprintf("can't migrate table %q since adding the new PK column %q is not supported. Try dropping this table", tableChange.table.Name, colChange.name),
163
-
info: fmt.Sprintf("table %q will be dropped and recreated", tableChange.table.Name),
200
+
info: fmt.Sprintf("table %q will be dropped and recreated due to adding %q as a PK", tableChange.table.Name, colChange.name),
201
+
})
202
+
// no need to report other errors as the user needs to drop the table altogether
203
+
break
204
+
}
205
+
ifcolChange.isPKAddToExistingColumn() {
206
+
messages=append(messages, migrationMessage{
207
+
err: fmt.Sprintf("can't migrate table %q since making the existing column %q a PK is not supported. Try dropping this table", tableChange.table.Name, colChange.name),
208
+
info: fmt.Sprintf("table %q will be dropped and recreated due to adding %q as a PK", tableChange.table.Name, colChange.name),
209
+
})
210
+
// no need to report other errors as the user needs to drop the table altogether
211
+
break
212
+
}
213
+
ifcolChange.isPKRemoveFromExistingColumn() {
214
+
messages=append(messages, migrationMessage{
215
+
err: fmt.Sprintf("can't migrate table %q since removing an existing column %q as a PK is not supported. Try dropping this table", tableChange.table.Name, colChange.name),
216
+
info: fmt.Sprintf("table %q will be dropped and recreated due to removing %q as a PK", tableChange.table.Name, colChange.name),
164
217
})
165
218
// no need to report other errors as the user needs to drop the table altogether
err: fmt.Sprintf("can't migrate table %q since changing the type of the PK column %q from %q to %q is not supported. Try dropping this table", tableChange.table.Name, colChange.name, colChange.oldType, colChange.newType),
224
+
info: fmt.Sprintf("table %q will be dropped and recreated due to the type change of the PK column %q", tableChange.table.Name, colChange.name),
225
+
})
226
+
// no need to report other errors as the user needs to drop the table altogether
227
+
break
228
+
}
229
+
ifcolChange.isNonPKTypeChange() {
169
230
messages=append(messages, migrationMessage{
170
231
err: fmt.Sprintf("can't migrate table %q since changing the type of column %q from %q to %q is not supported. Try dropping this column for this table", tableChange.table.Name, colChange.name, colChange.oldType, colChange.newType),
171
232
info: fmt.Sprintf("column %q of table %q will be dropped and recreated", colChange.name, tableChange.table.Name),
// If this is a new PK column we need to drop the table
212
-
ifcolChange.new&&colChange.newPk {
273
+
ifcolChange.isNewPKColumn() {
213
274
c.logger.Debug().Str("table", tableName).Str("column", colChange.name).Msg("New column is a primary key, dropping and adding table since in forced migrate mode")
// SQLite doesn't support PK additions on tables so we need to drop and add the table
282
+
ifcolChange.isPKAddToExistingColumn() {
283
+
c.logger.Debug().Str("table", table.Name).Str("column", colChange.name).Msg("Primary key added for existing column, dropping and adding table since in forced migrate mode")
284
+
err:=c.recreateTable(table)
223
285
iferr!=nil {
224
286
returnerr
225
287
}
288
+
break
289
+
}
290
+
// SQLite doesn't support PK removals on tables so we need to drop and add the table
291
+
ifcolChange.isPKRemoveFromExistingColumn() {
292
+
c.logger.Debug().Str("table", table.Name).Str("column", colChange.name).Msg("Primary key removed for existing column, dropping and adding table since in forced migrate mode")
293
+
err:=c.recreateTable(table)
294
+
iferr!=nil {
295
+
returnerr
296
+
}
297
+
break
298
+
}
299
+
// Since we can't recreate a PK column in SQLite we need to drop and add the table if a type changed for an existing PK column
300
+
ifcolChange.isPKTypeChange() {
301
+
c.logger.Debug().Str("table", table.Name).Str("column", colChange.name).Msg("Type changed for existing primary key column, dropping and adding table since in forced migrate mode")
302
+
err:=c.recreateTable(table)
303
+
iferr!=nil {
304
+
returnerr
305
+
}
306
+
break
226
307
}
227
308
// if this is an existing column with type change we need to drop and add it
c.logger.Debug().Str("table", table.Name).Str("column", colChange.name).Msg("Existing column type changed, dropping and adding column since in forced migrate mode")
0 commit comments