diff --git a/extras/integration_tests/tests/lib/database/database.dart b/extras/integration_tests/tests/lib/database/database.dart index c4590641..089890fe 100644 --- a/extras/integration_tests/tests/lib/database/database.dart +++ b/extras/integration_tests/tests/lib/database/database.dart @@ -98,7 +98,7 @@ class Database extends _$Database { await m.createTable(friendships); } }, - beforeOpen: (_, details) async { + beforeOpen: (details) async { if (details.wasCreated) { await into(users) .insertAll([People.dash, People.duke, People.gopher]); @@ -108,7 +108,7 @@ class Database extends _$Database { } Future deleteUser(User user, {bool fail = false}) { - return transaction((_) async { + return transaction(() async { final id = user.id; await (delete(friendships) ..where((f) => or(f.firstUser.equals(id), f.secondUser.equals(id)))) diff --git a/extras/integration_tests/tests/lib/suite/transactions.dart b/extras/integration_tests/tests/lib/suite/transactions.dart index 9b0e41ad..05b6f3b9 100644 --- a/extras/integration_tests/tests/lib/suite/transactions.dart +++ b/extras/integration_tests/tests/lib/suite/transactions.dart @@ -9,7 +9,7 @@ void transactionTests(TestExecutor executor) { final db = Database(executor.createExecutor()); // ignore: invalid_use_of_protected_member, invalid_use_of_visible_for_testing_member - await db.transaction((_) async { + await db.transaction(() async { final florianId = await db.writeUser(People.florian); final dash = await db.getUserById(People.dashId); @@ -32,7 +32,7 @@ void transactionTests(TestExecutor executor) { try { // ignore: invalid_use_of_protected_member, invalid_use_of_visible_for_testing_member - await db.transaction((_) async { + await db.transaction(() async { final florianId = await db.writeUser(People.florian); final dash = await db.getUserById(People.dashId); diff --git a/moor/CHANGELOG.md b/moor/CHANGELOG.md index 3bee3386..d0ab5e19 100644 --- a/moor/CHANGELOG.md +++ b/moor/CHANGELOG.md @@ -1,3 +1,36 @@ +## 2.0.0 +This is the first major update after the initial release and moor and we have a lot to cover. +... Finally, we also removed a variety of deprecated features. See the breaking changes +section to learn what components are affected and what alternatives are available. + +TODO: Properly describe these additions when they're finalized: + +- Queries and imports in `.moor` files +- Analyzer plugin for Dart Code +- `ffi` libraries + +### Breaking changes +- __THIS LIKELY AFFECTS YOUR APP:__ Removed the `transaction` parameter for callbacks + in transactions and `beforeOpen` callbacks. So, instead of writing + ```dart + transaction((t) async { + await t.update(table)...; + }); + ``` + simply write + ```dart + transaction(() async { + await update(table)...; + }); + ``` + Similarly, instead of using `onOpen: (db, details) async {...}`, use + `onOpen: (details) async {...}`. You don't have to worry about calling methods on + your database instead of a transaction objects. They will be delegated automatically. + + On a similar note, we also removed the `operateOn` parameter from compiled queries. + +- Removed `MigrationStrategy.onFinished`. Use `beforeOpen` instead. + ## 1.7.2 - Fixed a race condition that caused the database to be opened multiple times on slower devices. This problem was introduced in `1.7.0` and was causing problems during migrations. diff --git a/moor/example/example.dart b/moor/example/example.dart index 062a0f8e..84889677 100644 --- a/moor/example/example.dart +++ b/moor/example/example.dart @@ -59,10 +59,9 @@ class Database extends _$Database { @override MigrationStrategy get migration { return MigrationStrategy( - beforeOpen: (engine, details) async { + beforeOpen: (details) async { // populate data - await engine - .into(categories) + await into(categories) .insert(const CategoriesCompanion(description: Value('Sweets'))); }, ); diff --git a/moor/example/example.g.dart b/moor/example/example.g.dart index 68b79aec..68eec0dd 100644 --- a/moor/example/example.g.dart +++ b/moor/example/example.g.dart @@ -847,19 +847,15 @@ abstract class _$Database extends GeneratedDatabase { ); } - Selectable _totalWeightQuery( - {@Deprecated('No longer needed with Moor 1.6 - see the changelog for details') - QueryEngine operateOn}) { + Selectable _totalWeightQuery() { return (operateOn ?? this).customSelectQuery( ' SELECT r.title, SUM(ir.amount) AS total_weight\n FROM recipes r\n INNER JOIN recipe_ingredients ir ON ir.recipe = r.id\n GROUP BY r.id\n ', variables: [], readsFrom: {recipes, ingredientInRecipes}).map(_rowToTotalWeightResult); } - Future> _totalWeight( - {@Deprecated('No longer needed with Moor 1.6 - see the changelog for details') - QueryEngine operateOn}) { - return _totalWeightQuery(operateOn: operateOn).get(); + Future> _totalWeight() { + return _totalWeightQuery().get(); } Stream> _watchTotalWeight() { diff --git a/moor/example_web/lib/database/database.dart b/moor/example_web/lib/database/database.dart index 69eda725..ba259f5c 100644 --- a/moor/example_web/lib/database/database.dart +++ b/moor/example_web/lib/database/database.dart @@ -28,7 +28,7 @@ class Database extends _$Database { MigrationStrategy get migration { return MigrationStrategy( onCreate: (m) async => await m.createAllTables(), - beforeOpen: (engine, details) async { + beforeOpen: (details) async { if (details.wasCreated) { // populate default data await createTodoEntry( diff --git a/moor/lib/src/runtime/database.dart b/moor/lib/src/runtime/database.dart index 0abeb098..3c246668 100644 --- a/moor/lib/src/runtime/database.dart +++ b/moor/lib/src/runtime/database.dart @@ -280,10 +280,10 @@ mixin QueryEngine on DatabaseConnectionUser { /// inside a transaction returns the parent transaction. @protected @visibleForTesting - Future transaction(Future Function(QueryEngine transaction) action) async { + Future transaction(Future Function() action) async { final resolved = _resolvedEngine; if (resolved is Transaction) { - return action(resolved); + return action(); } final executor = resolved.executor; @@ -294,7 +294,7 @@ mixin QueryEngine on DatabaseConnectionUser { return _runEngineZoned(transaction, () async { var success = false; try { - await action(transaction); + await action(); success = true; } catch (e) { await transactionExecutor.rollback(); @@ -376,13 +376,11 @@ abstract class GeneratedDatabase extends DatabaseConnectionUser Future beforeOpenCallback( QueryExecutor executor, OpeningDetails details) async { final migration = _resolvedMigration; - if (migration.onFinished != null) { - await migration.onFinished(); - } + if (migration.beforeOpen != null) { final engine = BeforeOpenEngine(this, executor); await _runEngineZoned(engine, () { - return migration.beforeOpen(engine, details); + return migration.beforeOpen(details); }); } } diff --git a/moor/lib/src/runtime/migration.dart b/moor/lib/src/runtime/migration.dart index d1ad8224..40ca77aa 100644 --- a/moor/lib/src/runtime/migration.dart +++ b/moor/lib/src/runtime/migration.dart @@ -16,8 +16,7 @@ typedef Future OnMigrationFinished(); /// Signature of a function that's called before a database is marked opened by /// moor, but after migrations took place. This is a suitable callback to to /// populate initial data or issue `PRAGMA` statements that you want to use. -typedef OnBeforeOpen = Future Function( - QueryEngine db, OpeningDetails details); +typedef OnBeforeOpen = Future Function(OpeningDetails details); Future _defaultOnCreate(Migrator m) => m.createAllTables(); Future _defaultOnUpdate(Migrator m, int from, int to) async => @@ -33,14 +32,6 @@ class MigrationStrategy { /// happened at a lower [GeneratedDatabase.schemaVersion]. final OnUpgrade onUpgrade; - /// Executes after the database is ready and all migrations ran, but before - /// any other queries will be executed, making this method suitable to - /// populate data. - @Deprecated( - 'This callback is broken and only exists for backwards compatibility. ' - 'Use beforeOpen instead') - final OnMigrationFinished onFinished; - /// Executes after the database is ready to be used (ie. it has been opened /// and all migrations ran), but before any other queries will be sent. This /// makes it a suitable place to populate data after the database has been @@ -51,8 +42,6 @@ class MigrationStrategy { this.onCreate = _defaultOnCreate, this.onUpgrade = _defaultOnUpdate, this.beforeOpen, - @Deprecated('This callback is broken. Use beforeOpen instead') - this.onFinished, }); } diff --git a/moor/test/data/tables/custom_tables.g.dart b/moor/test/data/tables/custom_tables.g.dart index 69bb85c8..83b12f08 100644 --- a/moor/test/data/tables/custom_tables.g.dart +++ b/moor/test/data/tables/custom_tables.g.dart @@ -819,10 +819,7 @@ abstract class _$CustomTablesDb extends GeneratedDatabase { ); } - Selectable readConfig( - String var1, - {@Deprecated('No longer needed with Moor 1.6 - see the changelog for details') - QueryEngine operateOn}) { + Selectable readConfig(String var1) { return (operateOn ?? this).customSelectQuery( 'readConfig: SELECT * FROM config WHERE config_key = ?;', variables: [ @@ -833,11 +830,7 @@ abstract class _$CustomTablesDb extends GeneratedDatabase { }).map(_rowToConfigData); } - Future writeConfig( - String key, - String value, - {@Deprecated('No longer needed with Moor 1.6 - see the changelog for details') - QueryEngine operateOn}) { + Future writeConfig(String key, String value) { return (operateOn ?? this).customInsert( 'REPLACE INTO config VALUES (:key, :value)', variables: [ diff --git a/moor/test/data/tables/todos.g.dart b/moor/test/data/tables/todos.g.dart index d0bcdf53..9d853efc 100644 --- a/moor/test/data/tables/todos.g.dart +++ b/moor/test/data/tables/todos.g.dart @@ -1312,9 +1312,7 @@ abstract class _$TodoDb extends GeneratedDatabase { ); } - Selectable allTodosWithCategoryQuery( - {@Deprecated('No longer needed with Moor 1.6 - see the changelog for details') - QueryEngine operateOn}) { + Selectable allTodosWithCategoryQuery() { return (operateOn ?? this).customSelectQuery( 'SELECT t.*, c.id as catId, c."desc" as catDesc FROM todos t INNER JOIN categories c ON c.id = t.category', variables: [], @@ -1324,20 +1322,15 @@ abstract class _$TodoDb extends GeneratedDatabase { }).map(_rowToAllTodosWithCategoryResult); } - Future> allTodosWithCategory( - {@Deprecated('No longer needed with Moor 1.6 - see the changelog for details') - QueryEngine operateOn}) { - return allTodosWithCategoryQuery(operateOn: operateOn).get(); + Future> allTodosWithCategory() { + return allTodosWithCategoryQuery().get(); } Stream> watchAllTodosWithCategory() { return allTodosWithCategoryQuery().watch(); } - Future deleteTodoById( - int var1, - {@Deprecated('No longer needed with Moor 1.6 - see the changelog for details') - QueryEngine operateOn}) { + Future deleteTodoById(int var1) { return (operateOn ?? this).customUpdate( 'DELETE FROM todos WHERE id = ?', variables: [ @@ -1357,12 +1350,7 @@ abstract class _$TodoDb extends GeneratedDatabase { ); } - Selectable withInQuery( - String var1, - String var2, - List var3, - {@Deprecated('No longer needed with Moor 1.6 - see the changelog for details') - QueryEngine operateOn}) { + Selectable withInQuery(String var1, String var2, List var3) { var $highestIndex = 3; final expandedvar3 = $expandVar($highestIndex, var3.length); $highestIndex += var3.length; @@ -1378,13 +1366,8 @@ abstract class _$TodoDb extends GeneratedDatabase { }).map(_rowToTodoEntry); } - Future> withIn( - String var1, - String var2, - List var3, - {@Deprecated('No longer needed with Moor 1.6 - see the changelog for details') - QueryEngine operateOn}) { - return withInQuery(var1, var2, var3, operateOn: operateOn).get(); + Future> withIn(String var1, String var2, List var3) { + return withInQuery(var1, var2, var3).get(); } Stream> watchWithIn( @@ -1392,10 +1375,7 @@ abstract class _$TodoDb extends GeneratedDatabase { return withInQuery(var1, var2, var3).watch(); } - Selectable searchQuery( - int id, - {@Deprecated('No longer needed with Moor 1.6 - see the changelog for details') - QueryEngine operateOn}) { + Selectable searchQuery(int id) { return (operateOn ?? this).customSelectQuery( 'SELECT * FROM todos WHERE CASE WHEN -1 = :id THEN 1 ELSE id = :id END', variables: [ @@ -1406,11 +1386,8 @@ abstract class _$TodoDb extends GeneratedDatabase { }).map(_rowToTodoEntry); } - Future> search( - int id, - {@Deprecated('No longer needed with Moor 1.6 - see the changelog for details') - QueryEngine operateOn}) { - return searchQuery(id, operateOn: operateOn).get(); + Future> search(int id) { + return searchQuery(id).get(); } Stream> watchSearch(int id) { @@ -1424,19 +1401,15 @@ abstract class _$TodoDb extends GeneratedDatabase { ); } - Selectable findCustomQuery( - {@Deprecated('No longer needed with Moor 1.6 - see the changelog for details') - QueryEngine operateOn}) { + Selectable findCustomQuery() { return (operateOn ?? this).customSelectQuery( 'SELECT custom FROM table_without_p_k WHERE some_float < 10', variables: [], readsFrom: {tableWithoutPK}).map(_rowToFindCustomResult); } - Future> findCustom( - {@Deprecated('No longer needed with Moor 1.6 - see the changelog for details') - QueryEngine operateOn}) { - return findCustomQuery(operateOn: operateOn).get(); + Future> findCustom() { + return findCustomQuery().get(); } Stream> watchFindCustom() { @@ -1498,10 +1471,7 @@ mixin _$SomeDaoMixin on DatabaseAccessor { ); } - Selectable todosForUserQuery( - int user, - {@Deprecated('No longer needed with Moor 1.6 - see the changelog for details') - QueryEngine operateOn}) { + Selectable todosForUserQuery(int user) { return (operateOn ?? this).customSelectQuery( 'SELECT t.* FROM todos t INNER JOIN shared_todos st ON st.todo = t.id INNER JOIN users u ON u.id = st.user WHERE u.id = :user', variables: [ @@ -1514,11 +1484,8 @@ mixin _$SomeDaoMixin on DatabaseAccessor { }).map(_rowToTodoEntry); } - Future> todosForUser( - int user, - {@Deprecated('No longer needed with Moor 1.6 - see the changelog for details') - QueryEngine operateOn}) { - return todosForUserQuery(user, operateOn: operateOn).get(); + Future> todosForUser(int user) { + return todosForUserQuery(user).get(); } Stream> watchTodosForUser(int user) { diff --git a/moor/test/database_test.dart b/moor/test/database_test.dart index 0ebbdfb2..bdb256fc 100644 --- a/moor/test/database_test.dart +++ b/moor/test/database_test.dart @@ -15,8 +15,9 @@ class _FakeDb extends GeneratedDatabase { onUpgrade: (m, from, to) async { await m.issueCustomQuery('updated from $from to $to'); }, - beforeOpen: (db, details) async { - await db.customSelect( + beforeOpen: (details) async { + // this fake select query is verified via mocks + await customSelect( 'opened: ${details.versionBefore} to ${details.versionNow}'); }, ); diff --git a/moor/test/transactions_test.dart b/moor/test/transactions_test.dart index 2403cd5b..db15bb64 100644 --- a/moor/test/transactions_test.dart +++ b/moor/test/transactions_test.dart @@ -33,16 +33,16 @@ void main() { test("transactions don't allow creating streams", () { expect(() async { - await db.transaction((t) async { - t.select(db.users).watch(); + await db.transaction(() async { + db.select(db.users).watch(); }); }, throwsStateError); }); test('nested transactions use the outer transaction', () async { - await db.transaction((t) async { - await t.transaction((t2) async { - expect(t2, equals(t)); + await db.transaction(() async { + await db.transaction(() async { + // todo how can we test that these are really equal? }); // the outer callback has not completed yet, so shouldn't send @@ -55,7 +55,7 @@ void main() { test('code in callback uses transaction', () async { // notice how we call .select on the database, but it should be called on // transaction executor. - await db.transaction((_) async { + await db.transaction(() async { await db.select(db.users).get(); }); @@ -65,7 +65,7 @@ void main() { test('transactions rollback after errors', () async { final exception = Exception('oh no'); - final future = db.transaction((_) async { + final future = db.transaction(() async { throw exception; }); @@ -79,8 +79,8 @@ void main() { when(executor.transactions.runUpdate(any, any)) .thenAnswer((_) => Future.value(2)); - await db.transaction((t) async { - await t + await db.transaction(() async { + await db .update(db.users) .write(const UsersCompanion(name: Value('Updated name'))); @@ -95,7 +95,7 @@ void main() { }); test('the database is opened before starting a transaction', () async { - await db.transaction((t) async { + await db.transaction(() async { verify(executor.doWhenOpened(any)); }); }); diff --git a/moor_flutter/example/lib/database/database.dart b/moor_flutter/example/lib/database/database.dart index e48b539d..e8db92ea 100644 --- a/moor_flutter/example/lib/database/database.dart +++ b/moor_flutter/example/lib/database/database.dart @@ -63,7 +63,7 @@ class Database extends _$Database { await m.addColumn(todos, todos.targetDate); } }, - beforeOpen: (db, details) async { + beforeOpen: (details) async { if (details.wasCreated) { // create default categories and entries final workId = await into(categories) @@ -154,7 +154,7 @@ class Database extends _$Database { } Future deleteCategory(Category category) { - return transaction((t) async { + return transaction(() async { await _resetCategory(category.id); await delete(categories).delete(category); }); diff --git a/moor_generator/lib/src/writer/queries/query_writer.dart b/moor_generator/lib/src/writer/queries/query_writer.dart index 0a43f914..03f079ca 100644 --- a/moor_generator/lib/src/writer/queries/query_writer.dart +++ b/moor_generator/lib/src/writer/queries/query_writer.dart @@ -9,9 +9,6 @@ import 'package:moor_generator/src/writer/writer.dart'; import 'package:recase/recase.dart'; import 'package:sqlparser/sqlparser.dart'; -const queryEngineWarningDesc = - 'No longer needed with Moor 1.6 - see the changelog for details'; - const highestAssignedIndexVar = '\$highestIndex'; /// Writes the handling code for a query. The code emitted will be a method that @@ -157,9 +154,9 @@ class QueryWriter { } _buffer.write('Stream> $methodName('); - _writeParameters(dontOverrideEngine: true); + _writeParameters(); _buffer..write(') {\n')..write('return ${_nameOfCreationMethod()}('); - _writeUseParameters(dontUseEngine: true); + _writeUseParameters(); _buffer.write(').watch();\n}\n'); } @@ -187,7 +184,7 @@ class QueryWriter { _buffer..write(',);\n}\n'); } - void _writeParameters({bool dontOverrideEngine = false}) { + void _writeParameters() { final paramList = query.variables.map((v) { var dartType = dartTypeNames[v.type]; if (v.isArray) { @@ -197,25 +194,13 @@ class QueryWriter { }).join(', '); _buffer.write(paramList); - - // write named optional parameter to configure the query engine used to - // execute the statement, - if (!dontOverrideEngine) { - if (query.variables.isNotEmpty) _buffer.write(', '); - _buffer.write('{@Deprecated(${asDartLiteral(queryEngineWarningDesc)}) ' - 'QueryEngine operateOn}'); - } } /// Writes code that uses the parameters as declared by [_writeParameters], /// assuming that for each parameter, a variable with the same name exists /// in the current scope. - void _writeUseParameters({bool dontUseEngine = false}) { + void _writeUseParameters() { _buffer.write(query.variables.map((v) => v.dartParameterName).join(', ')); - if (!dontUseEngine) { - if (query.variables.isNotEmpty) _buffer.write(', '); - _buffer.write('operateOn: operateOn'); - } } // Some notes on parameters and generating query code: