diff --git a/moor/CHANGELOG.md b/moor/CHANGELOG.md index af7d06a8..2aa4b26e 100644 --- a/moor/CHANGELOG.md +++ b/moor/CHANGELOG.md @@ -7,6 +7,7 @@ - Added extensions for `isNull` and `isNotNull` - Support creating a `VmDatabase` from a raw sqlite3 `Database` via `VmDatabase.opened` - New `named_parameters` build option to generate named parameters for named variables in moor files +- Added `Migrator.renameTable` to rename tables ## 3.4.0 diff --git a/moor/lib/src/runtime/query_builder/migration.dart b/moor/lib/src/runtime/query_builder/migration.dart index ab49f3d7..2ebea39e 100644 --- a/moor/lib/src/runtime/query_builder/migration.dart +++ b/moor/lib/src/runtime/query_builder/migration.dart @@ -367,6 +367,19 @@ class Migrator { return _issueCustomQuery(context.sql); } + /// Changes the [table] name from [oldName] to the current + /// [TableInfo.actualTableName]. + /// + /// After renaming a table in moor or Dart and re-running the generator, you + /// can use [renameTable] in a migration step to rename the table in existing + /// databases. + Future renameTable(TableInfo table, String oldName) async { + final context = _createContext(); + context.buffer.write('ALTER TABLE ${escapeIfNeeded(oldName)} ' + 'RENAME TO ${escapeIfNeeded(table.actualTableName)};'); + return _issueCustomQuery(context.sql); + } + /// Executes the custom query. @Deprecated('Use customStatement in the database class') Future issueCustomQuery(String sql, [List? args]) { diff --git a/moor/test/integration_tests/migrations_integration_test.dart b/moor/test/integration_tests/migrations_integration_test.dart index 97e0cb2a..9b2a1dca 100644 --- a/moor/test/integration_tests/migrations_integration_test.dart +++ b/moor/test/integration_tests/migrations_integration_test.dart @@ -104,6 +104,36 @@ void main() { expect(item.category, isNull); }); + test('rename tables', () async { + // Create todos table with old name + final executor = VmDatabase.memory(setup: (db) { + db.execute(''' + CREATE TABLE todos_old_name ( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + title TEXT NOT NULL, + content TEXT NOT NULL, + target_date INTEGER NOT NULL, + category INTEGER NULL + ); + '''); + + db.execute('INSERT INTO todos_old_name (title, content, target_date) ' + "VALUES ('title', 'content', 0)"); + }); + + final db = TodoDb(executor); + db.migration = MigrationStrategy( + onCreate: (m) async { + await m.renameTable(db.todosTable, 'todos_old_name'); + }, + ); + + // basic check to ensure we can query the table by its new name and that + // we have all the necessary data. + final entry = await db.select(db.todosTable).getSingle(); + expect(entry.title, 'title'); + }); + test('add columns with default value', () async { final executor = VmDatabase.memory(setup: (db) { // Create todos table without content column