Enable legacy alter table in alterTable

This commit is contained in:
Simon Binder 2022-12-21 18:09:05 +01:00
parent 7be97d139e
commit 1d8fa16e2c
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
4 changed files with 31 additions and 16 deletions

View File

@ -8,6 +8,8 @@
generate a mapping to the new `DriftAny` type.
- Fix `UNIQUE` keys declared in drift files being written twice.
- Fix `customConstraints` not appearing in dumped database schema files.
- Work-around an issue causing complex migrations via `Migrator.alterTable` not to
work if a view referenced the altered table.
## 2.3.0-dev

View File

@ -146,6 +146,9 @@ class Migrator {
final foreignKeysEnabled =
(await _db.customSelect('PRAGMA foreign_keys').getSingle())
.read<bool>('foreign_keys');
final legacyAlterTable =
(await _db.customSelect('PRAGMA legacy_alter_table').getSingle())
.read<bool>('legacy_alter_table');
if (foreignKeysEnabled) {
await _db.customStatement('PRAGMA foreign_keys = OFF;');
@ -235,11 +238,24 @@ class Migrator {
// Step 6: Drop the old table
await _issueCustomQuery('DROP TABLE ${context.identifier(tableName)}');
// This step is not mentioned in the documentation, but: If we use `ALTER`
// on an inconsistent schema (and it is inconsistent right now because
// we've just dropped the original table), we need to enable the legacy
// option which skips the integrity check.
// See also: https://sqlite.org/forum/forumpost/0e2390093fbb8fd6
if (!legacyAlterTable) {
await _issueCustomQuery('pragma legacy_alter_table = 1;');
}
// Step 7: Rename the new table to the old name
await _issueCustomQuery(
'ALTER TABLE ${context.identifier(temporaryName)} '
'RENAME TO ${context.identifier(tableName)}');
if (!legacyAlterTable) {
await _issueCustomQuery('pragma legacy_alter_table = 0;');
}
// Step 8: Re-create associated indexes, triggers and views
for (final stmt in createAffected) {
await _issueCustomQuery(stmt);

View File

@ -15,7 +15,8 @@ void main() {
test('change column types', () async {
// Create todos table with category as text (it's an int? in Dart).
final executor = NativeDatabase.memory(setup: (db) {
db.execute('''
db
..execute('''
CREATE TABLE todos (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
@ -25,14 +26,12 @@ void main() {
status TEXT NULL,
UNIQUE(title, category)
);
''');
db.execute('CREATE INDEX my_index ON todos (content);');
db.execute('INSERT INTO todos (title, content, target_date, category) '
"VALUES ('title', 'content', 0, '12')");
db.execute('PRAGMA foreign_keys = ON');
''')
..execute('CREATE INDEX my_index ON todos (content);')
..execute('INSERT INTO todos (title, content, target_date, category) '
"VALUES ('title', 'content', 0, '12')")
..execute('CREATE VIEW todo_categories AS SELECT category FROM todos;')
..execute('PRAGMA foreign_keys = ON');
});
final db = TodoDb(executor);
@ -63,6 +62,11 @@ void main() {
final foreignKeysResult =
await db.customSelect('PRAGMA foreign_keys').getSingle();
expect(foreignKeysResult.read<bool>('foreign_keys'), isTrue);
// Similarly, the legacy_alter_table behavior should be disabled.
final legacyAlterTable =
await db.customSelect('PRAGMA legacy_alter_table').getSingle();
expect(legacyAlterTable.read<bool>('legacy_alter_table'), isFalse);
});
test('rename columns', () async {

View File

@ -63,18 +63,11 @@ class Database extends _$Database {
break;
case 8:
// Added a unique key to the users table
// TODO: Figure out why dropping the view is necessary (https://sqlite.org/forum/forumpost/de614349cb)
await m.drop(groupCount);
await m.alterTable(TableMigration(v8.Users(this)));
await m.recreateAllViews();
break;
case 9:
// Added a check to the users table
await m.drop(groupCount);
await m.alterTable(TableMigration(users));
await m.recreateAllViews();
break;
}
}