diff --git a/extras/benchmarks/lib/src/moor/database.dart b/extras/benchmarks/lib/src/moor/database.dart index 9638cfc0..966397a9 100644 --- a/extras/benchmarks/lib/src/moor/database.dart +++ b/extras/benchmarks/lib/src/moor/database.dart @@ -1,7 +1,7 @@ import 'dart:io'; +import 'package:moor/ffi.dart'; import 'package:moor/moor.dart'; -import 'package:moor_ffi/moor_ffi.dart'; import 'package:path/path.dart' as p; import 'package:uuid/uuid.dart'; diff --git a/extras/benchmarks/lib/src/moor/database.g.dart b/extras/benchmarks/lib/src/moor/database.g.dart index 30d59cca..60bd295f 100644 --- a/extras/benchmarks/lib/src/moor/database.g.dart +++ b/extras/benchmarks/lib/src/moor/database.g.dart @@ -21,6 +21,26 @@ class KeyValue extends DataClass implements Insertable { stringType.mapFromDatabaseResponse(data['${effectivePrefix}value']), ); } + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (!nullToAbsent || key != null) { + map['key'] = Variable(key); + } + if (!nullToAbsent || value != null) { + map['value'] = Variable(value); + } + return map; + } + + KeyValuesCompanion toCompanion(bool nullToAbsent) { + return KeyValuesCompanion( + key: key == null && nullToAbsent ? const Value.absent() : Value(key), + value: + value == null && nullToAbsent ? const Value.absent() : Value(value), + ); + } + factory KeyValue.fromJson(Map json, {ValueSerializer serializer}) { serializer ??= moorRuntimeOptions.defaultSerializer; @@ -38,15 +58,6 @@ class KeyValue extends DataClass implements Insertable { }; } - @override - KeyValuesCompanion createCompanion(bool nullToAbsent) { - return KeyValuesCompanion( - key: key == null && nullToAbsent ? const Value.absent() : Value(key), - value: - value == null && nullToAbsent ? const Value.absent() : Value(value), - ); - } - KeyValue copyWith({String key, String value}) => KeyValue( key: key ?? this.key, value: value ?? this.value, @@ -80,12 +91,43 @@ class KeyValuesCompanion extends UpdateCompanion { @required String value, }) : key = Value(key), value = Value(value); + static Insertable custom({ + Expression key, + Expression value, + }) { + return RawValuesInsertable({ + if (key != null) 'key': key, + if (value != null) 'value': value, + }); + } + KeyValuesCompanion copyWith({Value key, Value value}) { return KeyValuesCompanion( key: key ?? this.key, value: value ?? this.value, ); } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (key.present) { + map['key'] = Variable(key.value); + } + if (value.present) { + map['value'] = Variable(value.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('KeyValuesCompanion(') + ..write('key: $key, ') + ..write('value: $value') + ..write(')')) + .toString(); + } } class $KeyValuesTable extends KeyValues @@ -126,17 +168,19 @@ class $KeyValuesTable extends KeyValues @override final String actualTableName = 'key_values'; @override - VerificationContext validateIntegrity(KeyValuesCompanion d, + VerificationContext validateIntegrity(Insertable instance, {bool isInserting = false}) { final context = VerificationContext(); - if (d.key.present) { - context.handle(_keyMeta, key.isAcceptableValue(d.key.value, _keyMeta)); + final data = instance.toColumns(true); + if (data.containsKey('key')) { + context.handle( + _keyMeta, key.isAcceptableOrUnknown(data['key'], _keyMeta)); } else if (isInserting) { context.missing(_keyMeta); } - if (d.value.present) { + if (data.containsKey('value')) { context.handle( - _valueMeta, value.isAcceptableValue(d.value.value, _valueMeta)); + _valueMeta, value.isAcceptableOrUnknown(data['value'], _valueMeta)); } else if (isInserting) { context.missing(_valueMeta); } @@ -151,18 +195,6 @@ class $KeyValuesTable extends KeyValues return KeyValue.fromData(data, _db, prefix: effectivePrefix); } - @override - Map entityToSql(KeyValuesCompanion d) { - final map = {}; - if (d.key.present) { - map['key'] = Variable(d.key.value); - } - if (d.value.present) { - map['value'] = Variable(d.value.value); - } - return map; - } - @override $KeyValuesTable createAlias(String alias) { return $KeyValuesTable(_db, alias); diff --git a/extras/benchmarks/lib/src/sqlite/bind_string.dart b/extras/benchmarks/lib/src/sqlite/bind_string.dart index 814b0d5a..84870055 100644 --- a/extras/benchmarks/lib/src/sqlite/bind_string.dart +++ b/extras/benchmarks/lib/src/sqlite/bind_string.dart @@ -1,5 +1,5 @@ import 'package:benchmarks/benchmarks.dart'; -import 'package:moor_ffi/database.dart'; +import 'package:sqlite3/sqlite3.dart'; class SelectStringBenchmark extends BenchmarkBase { SelectStringBenchmark(ScoreEmitter emitter) @@ -10,7 +10,7 @@ class SelectStringBenchmark extends BenchmarkBase { @override void setup() { - database = Database.memory(); + database = sqlite3.openInMemory(); statement = database.prepare('SELECT ?;'); } @@ -29,7 +29,7 @@ class SelectStringBenchmark extends BenchmarkBase { @override void teardown() { - statement.close(); - database.close(); + statement.dispose(); + database.dispose(); } } diff --git a/extras/benchmarks/pubspec.yaml b/extras/benchmarks/pubspec.yaml index 514d636c..568209e3 100644 --- a/extras/benchmarks/pubspec.yaml +++ b/extras/benchmarks/pubspec.yaml @@ -3,7 +3,7 @@ description: Runs simple and complex benchmarks to measure performance of moor a dependencies: moor: - moor_ffi: + sqlite3: ^0.1.3 benchmark_harness: ^1.0.5 intl: ^0.16.0 uuid: ^2.0.0 @@ -16,8 +16,6 @@ dev_dependencies: dependency_overrides: moor: path: ../../moor - moor_ffi: - path: ../../moor_ffi moor_generator: path: ../../moor_generator sqlparser: diff --git a/extras/integration_tests/vm/test/save_and_restore_test.dart b/extras/integration_tests/vm/test/save_and_restore_test.dart index 224f3187..82b42b11 100644 --- a/extras/integration_tests/vm/test/save_and_restore_test.dart +++ b/extras/integration_tests/vm/test/save_and_restore_test.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:moor_ffi/moor_ffi.dart'; +import 'package:moor/ffi.dart'; import 'package:path/path.dart'; import 'package:test/test.dart'; import 'package:tests/database/database.dart'; diff --git a/extras/integration_tests/vm/test/vm_test.dart b/extras/integration_tests/vm/test/vm_test.dart index d935f6ad..f5ec5596 100644 --- a/extras/integration_tests/vm/test/vm_test.dart +++ b/extras/integration_tests/vm/test/vm_test.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:moor_ffi/moor_ffi.dart'; +import 'package:moor/ffi.dart'; import 'package:tests/tests.dart'; import 'package:path/path.dart' show join; diff --git a/moor/lib/ffi.dart b/moor/lib/ffi.dart new file mode 100644 index 00000000..3108a63b --- /dev/null +++ b/moor/lib/ffi.dart @@ -0,0 +1,4 @@ +/// Moor implementation using `package:sqlite3/`. +library moor.ffi; + +export 'src/ffi/vm_database.dart'; diff --git a/moor/lib/src/ffi/moor_ffi_functions.dart b/moor/lib/src/ffi/moor_ffi_functions.dart new file mode 100644 index 00000000..490644c9 --- /dev/null +++ b/moor/lib/src/ffi/moor_ffi_functions.dart @@ -0,0 +1,197 @@ +import 'dart:math'; + +import 'package:sqlite3/sqlite3.dart'; + +// ignore_for_file: avoid_returning_null, only_throw_errors + +/// Extension to register moor-specific sql functions. +extension EnableMoorFunctions on Database { + /// Enables moor-specific sql functions on this database. + void useMoorVersions() { + createFunction( + functionName: 'power', + deterministic: true, + argumentCount: const AllowedArgumentCount(2), + function: _pow, + ); + createFunction( + functionName: 'pow', + deterministic: true, + argumentCount: const AllowedArgumentCount(2), + function: _pow, + ); + + createFunction( + functionName: 'sqrt', + deterministic: true, + argumentCount: const AllowedArgumentCount(1), + function: _unaryNumFunction(sqrt), + ); + createFunction( + functionName: 'sin', + deterministic: true, + argumentCount: const AllowedArgumentCount(1), + function: _unaryNumFunction(sin), + ); + createFunction( + functionName: 'cos', + deterministic: true, + argumentCount: const AllowedArgumentCount(1), + function: _unaryNumFunction(cos), + ); + createFunction( + functionName: 'tan', + deterministic: true, + argumentCount: const AllowedArgumentCount(1), + function: _unaryNumFunction(tan), + ); + createFunction( + functionName: 'asin', + deterministic: true, + argumentCount: const AllowedArgumentCount(1), + function: _unaryNumFunction(asin), + ); + createFunction( + functionName: 'acos', + deterministic: true, + argumentCount: const AllowedArgumentCount(1), + function: _unaryNumFunction(acos), + ); + createFunction( + functionName: 'atan', + deterministic: true, + argumentCount: const AllowedArgumentCount(1), + function: _unaryNumFunction(atan), + ); + + createFunction( + functionName: 'regexp', + deterministic: true, + argumentCount: const AllowedArgumentCount(2), + function: _regexpImpl, + ); + // Third argument can be used to set flags (like multiline, case + // sensitivity, etc.) + createFunction( + functionName: 'regexp_moor_ffi', + deterministic: true, + argumentCount: const AllowedArgumentCount(3), + function: _regexpImpl, + ); + + createFunction( + functionName: 'moor_contains', + deterministic: true, + argumentCount: const AllowedArgumentCount(2), + function: _containsImpl, + ); + createFunction( + functionName: 'moor_contains', + deterministic: true, + argumentCount: const AllowedArgumentCount(3), + function: _containsImpl, + ); + } +} + +num _pow(List args) { + final first = args[0]; + final second = args[1]; + + if (first == null || second == null || first is! num || second is! num) { + return null; + } + + return pow(first as num, second as num); +} + +/// Base implementation for a sqlite function that takes one numerical argument +/// and returns one numerical argument. +/// +/// When not called with a number, returns will null. Otherwise, returns with +/// [calculation]. +num Function(List) _unaryNumFunction(num Function(num) calculation) { + return (List args) { + // sqlite will ensure that this is only called with one argument + final value = args[0]; + if (value is num) { + return calculation(value); + } else { + return null; + } + }; +} + +bool _regexpImpl(List args) { + var multiLine = false; + var caseSensitive = true; + var unicode = false; + var dotAll = false; + + final argCount = args.length; + if (argCount < 2 || argCount > 3) { + throw 'Expected two or three arguments to regexp'; + } + + final firstParam = args[0]; + final secondParam = args[1]; + + if (firstParam == null || secondParam == null) { + return null; + } + if (firstParam is! String || secondParam is! String) { + throw 'Expected two strings as parameters to regexp'; + } + + if (argCount == 3) { + // In the variant with three arguments, the last (int) arg can be used to + // enable regex flags. See the regexp() extension in moor for details. + final value = args[2]; + if (value is int) { + multiLine = (value & 1) == 1; + caseSensitive = (value & 2) != 2; + unicode = (value & 4) == 4; + dotAll = (value & 8) == 8; + } + } + + RegExp regex; + try { + regex = RegExp( + firstParam as String, + multiLine: multiLine, + caseSensitive: caseSensitive, + unicode: unicode, + dotAll: dotAll, + ); + } on FormatException { + throw 'Invalid regex'; + } + + return regex.hasMatch(secondParam as String); +} + +bool _containsImpl(List args) { + final argCount = args.length; + if (argCount < 2 || argCount > 3) { + throw 'Expected 2 or 3 arguments to moor_contains'; + } + + final first = args[0]; + final second = args[1]; + + if (first is! String || second is! String) { + throw 'First two args to contains must be strings'; + } + + final caseSensitive = argCount == 3 && args[2] == 1; + + final firstAsString = first as String; + final secondAsString = second as String; + + final result = caseSensitive + ? firstAsString.contains(secondAsString) + : firstAsString.toLowerCase().contains(secondAsString.toLowerCase()); + + return result; +} diff --git a/moor/lib/src/ffi/vm_database.dart b/moor/lib/src/ffi/vm_database.dart new file mode 100644 index 00000000..6ac609e4 --- /dev/null +++ b/moor/lib/src/ffi/vm_database.dart @@ -0,0 +1,127 @@ +import 'dart:io'; + +import 'package:moor/backends.dart'; +import 'package:sqlite3/sqlite3.dart'; + +import 'moor_ffi_functions.dart'; + +/// A moor database that runs on the Dart VM. +class VmDatabase extends DelegatedDatabase { + VmDatabase._(DatabaseDelegate delegate, bool logStatements) + : super(delegate, isSequential: true, logStatements: logStatements); + + /// Creates a database that will store its result in the [file], creating it + /// if it doesn't exist. + factory VmDatabase(File file, {bool logStatements = false}) { + return VmDatabase._(_VmDelegate(file), logStatements); + } + + /// Creates an in-memory database won't persist its changes on disk. + factory VmDatabase.memory({bool logStatements = false}) { + return VmDatabase._(_VmDelegate(null), logStatements); + } +} + +class _VmDelegate extends DatabaseDelegate { + Database _db; + + final File file; + + _VmDelegate(this.file); + + @override + final TransactionDelegate transactionDelegate = const NoTransactionDelegate(); + + @override + DbVersionDelegate versionDelegate; + + @override + Future get isOpen => Future.value(_db != null); + + @override + Future open(QueryExecutorUser user) async { + if (file != null) { + _db = sqlite3.open(file.path); + } else { + _db = sqlite3.openInMemory(); + } + _db.useMoorVersions(); + versionDelegate = _VmVersionDelegate(_db); + return Future.value(); + } + + @override + Future runBatched(BatchedStatements statements) async { + final prepared = [ + for (final stmt in statements.statements) _db.prepare(stmt), + ]; + + for (final application in statements.arguments) { + final stmt = prepared[application.statementIndex]; + + stmt.execute(application.arguments); + } + + for (final stmt in prepared) { + stmt.dispose(); + } + + return Future.value(); + } + + Future _runWithArgs(String statement, List args) async { + if (args.isEmpty) { + _db.execute(statement); + } else { + final stmt = _db.prepare(statement); + stmt.execute(args); + stmt.dispose(); + } + } + + @override + Future runCustom(String statement, List args) async { + await _runWithArgs(statement, args); + } + + @override + Future runInsert(String statement, List args) async { + await _runWithArgs(statement, args); + return _db.lastInsertRowId; + } + + @override + Future runUpdate(String statement, List args) async { + await _runWithArgs(statement, args); + return _db.getUpdatedRows(); + } + + @override + Future runSelect(String statement, List args) async { + final stmt = _db.prepare(statement); + final result = stmt.select(args); + stmt.dispose(); + + return Future.value(QueryResult.fromRows(result.toList())); + } + + @override + Future close() async { + _db.dispose(); + } +} + +class _VmVersionDelegate extends DynamicVersionDelegate { + final Database database; + + _VmVersionDelegate(this.database); + + @override + Future get schemaVersion => Future.value(database.userVersion); + + @override + Future setSchemaVersion(int version) { + database.userVersion = version; + return Future.value(); + } +} diff --git a/moor/pubspec.yaml b/moor/pubspec.yaml index 9d841c14..8158df88 100644 --- a/moor/pubspec.yaml +++ b/moor/pubspec.yaml @@ -14,12 +14,11 @@ dependencies: collection: ^1.0.0 synchronized: ^2.1.0 pedantic: ^1.0.0 + sqlite3: ^0.1.3 dev_dependencies: moor_generator: ^3.2.0 uuid: ^2.0.0 - moor_ffi: # Used to run integration tests - path: ../moor_ffi path: ^1.6.4 build_runner: '>=1.3.0 <2.0.0' test: ^1.9.0 diff --git a/moor/test/engines/connection_pool_integration_test.dart b/moor/test/engines/connection_pool_integration_test.dart index 44cdc608..ebf324a9 100644 --- a/moor/test/engines/connection_pool_integration_test.dart +++ b/moor/test/engines/connection_pool_integration_test.dart @@ -1,9 +1,10 @@ @TestOn('vm') import 'dart:io'; +import 'package:moor/ffi.dart'; import 'package:moor/isolate.dart'; import 'package:moor/moor.dart'; -import 'package:moor_ffi/moor_ffi.dart'; + import 'package:test/test.dart'; import 'package:path/path.dart' show join; diff --git a/moor/test/expressions/expressions_integration_test.dart b/moor/test/expressions/expressions_integration_test.dart index a9ef3979..f77e8bd3 100644 --- a/moor/test/expressions/expressions_integration_test.dart +++ b/moor/test/expressions/expressions_integration_test.dart @@ -1,7 +1,7 @@ -import 'package:moor/moor.dart'; @TestOn('vm') +import 'package:moor/ffi.dart'; +import 'package:moor/moor.dart'; import 'package:test/test.dart'; -import 'package:moor_ffi/moor_ffi.dart'; import '../data/tables/todos.dart'; diff --git a/moor/test/extensions/fts5_integration_test.dart b/moor/test/extensions/fts5_integration_test.dart index 156dbe64..3df3ff8b 100644 --- a/moor/test/extensions/fts5_integration_test.dart +++ b/moor/test/extensions/fts5_integration_test.dart @@ -1,6 +1,6 @@ @Tags(['integration']) @TestOn('vm') -import 'package:moor_ffi/moor_ffi.dart'; +import 'package:moor/ffi.dart'; import 'package:test/test.dart'; import '../data/tables/custom_tables.dart'; diff --git a/moor/test/extensions/json1_integration_test.dart b/moor/test/extensions/json1_integration_test.dart index 0292e9d2..d171c4f5 100644 --- a/moor/test/extensions/json1_integration_test.dart +++ b/moor/test/extensions/json1_integration_test.dart @@ -2,9 +2,9 @@ @TestOn('vm') import 'dart:convert'; +import 'package:moor/ffi.dart'; import 'package:moor/moor.dart'; import 'package:moor/extensions/json1.dart'; -import 'package:moor_ffi/moor_ffi.dart'; import 'package:test/test.dart'; import '../data/tables/todos.dart'; diff --git a/moor/test/extensions/moor_ffi_functions_test.dart b/moor/test/extensions/moor_ffi_functions_test.dart index 3d69649d..5b101cfa 100644 --- a/moor/test/extensions/moor_ffi_functions_test.dart +++ b/moor/test/extensions/moor_ffi_functions_test.dart @@ -1,7 +1,7 @@ @TestOn('vm') import 'package:moor/moor.dart'; import 'package:moor/extensions/moor_ffi.dart'; -import 'package:moor_ffi/moor_ffi.dart'; +import 'package:moor/ffi.dart'; import 'package:test/test.dart'; import '../data/tables/todos.dart'; diff --git a/moor/test/ffi/moor_functions_test.dart b/moor/test/ffi/moor_functions_test.dart new file mode 100644 index 00000000..b43192c9 --- /dev/null +++ b/moor/test/ffi/moor_functions_test.dart @@ -0,0 +1,178 @@ +import 'dart:math'; + +import 'package:moor/src/ffi/moor_ffi_functions.dart'; +import 'package:sqlite3/sqlite3.dart'; +import 'package:test/test.dart'; + +void main() { + Database db; + + setUp(() => db = sqlite3.openInMemory()..useMoorVersions()); + tearDown(() => db.dispose()); + + dynamic selectSingle(String expression) { + final stmt = db.prepare('SELECT $expression AS r;'); + final rows = stmt.select(); + stmt.dispose(); + + return rows.single['r']; + } + + group('pow', () { + dynamic _resultOfPow(String a, String b) { + return selectSingle('pow($a, $b)'); + } + + test('returns null when any argument is null', () { + expect(_resultOfPow('null', 'null'), isNull); + expect(_resultOfPow('3', 'null'), isNull); + expect(_resultOfPow('null', '3'), isNull); + }); + + test('returns correct results', () { + expect(_resultOfPow('10', '0'), 1); + expect(_resultOfPow('0', '10'), 0); + expect(_resultOfPow('0', '0'), 1); + expect(_resultOfPow('2', '5'), 32); + expect(_resultOfPow('3.5', '2'), 12.25); + expect(_resultOfPow('10', '-1'), 0.1); + }); + }); + + for (final scenario in _testCases) { + final function = scenario.sqlFunction; + + test(function, () { + final stmt = db.prepare('SELECT $function(?) AS r'); + + for (final input in scenario.inputs) { + final sqlResult = stmt.select([input]).single['r']; + final dartResult = scenario.dartEquivalent(input); + + // NaN in sqlite is null, account for that + if (dartResult.isNaN) { + expect( + sqlResult, + null, + reason: '$function($input) = $dartResult', + ); + } else { + expect( + sqlResult, + equals(dartResult), + reason: '$function($input) = $dartResult', + ); + } + } + + final resultWithNull = stmt.select([null]); + expect(resultWithNull.single['r'], isNull); + }); + } + + group('regexp', () { + test('cannot be called with more or fewer than 2 parameters', () { + expect(() => db.execute("SELECT regexp('foo')"), + throwsA(isA())); + + expect(() => db.execute("SELECT regexp('foo', 'bar', 'baz')"), + throwsA(isA())); + }); + + test('results in error when not passing a string', () { + final complainsAboutTypes = throwsA(isA().having( + (e) => e.message, + 'message', + contains('Expected two strings as parameters to regexp'), + )); + + expect(() => db.execute("SELECT 'foo' REGEXP 3"), complainsAboutTypes); + expect(() => db.execute("SELECT 3 REGEXP 'foo'"), complainsAboutTypes); + }); + + test('fails on invalid regex', () { + expect( + () => db.execute("SELECT 'foo' REGEXP '('"), + throwsA(isA() + .having((e) => e.message, 'message', contains('Invalid regex'))), + ); + }); + + test('returns true on a match', () { + final stmt = db.prepare("SELECT 'foo' REGEXP 'fo+' AS r"); + final result = stmt.select(); + expect(result.single['r'], 1); + }); + + test("returns false when the regex doesn't match", () { + final stmt = db.prepare("SELECT 'bar' REGEXP 'fo+' AS r"); + final result = stmt.select(); + expect(result.single['r'], 0); + }); + + test('supports flags', () { + final stmt = + db.prepare(r"SELECT regexp_moor_ffi('^bar', 'foo\nbar', 8) AS r;"); + final result = stmt.select(); + expect(result.single['r'], 0); + }); + + test('returns null when either argument is null', () { + final stmt = db.prepare('SELECT ? REGEXP ?'); + + expect(stmt.select(['foo', null]).single.columnAt(0), isNull); + expect(stmt.select([null, 'foo']).single.columnAt(0), isNull); + + stmt.dispose(); + }); + }); + + group('moor_contains', () { + test('checks for type errors', () { + expect(() => db.execute('SELECT moor_contains(12, 1);'), + throwsA(isA())); + }); + + test('case insensitive without parameter', () { + expect(selectSingle("moor_contains('foo', 'O')"), 1); + }); + + test('case insensitive with parameter', () { + expect(selectSingle("moor_contains('foo', 'O', 0)"), 1); + }); + + test('case sensitive', () { + expect(selectSingle("moor_contains('Hello', 'hell', 1)"), 0); + expect(selectSingle("moor_contains('hi', 'i', 1)"), 1); + }); + }); +} + +// utils to verify the sql functions behave exactly like the ones from the VM + +class _UnaryFunctionTestCase { + final String sqlFunction; + final num Function(num) dartEquivalent; + final List inputs; + + const _UnaryFunctionTestCase( + this.sqlFunction, this.dartEquivalent, this.inputs); +} + +const _unaryInputs = [ + pi, + 0, + pi / 2, + e, + 123, +]; + +const _testCases = <_UnaryFunctionTestCase>[ + _UnaryFunctionTestCase('sin', sin, _unaryInputs), + _UnaryFunctionTestCase('cos', cos, _unaryInputs), + _UnaryFunctionTestCase('tan', tan, _unaryInputs), + _UnaryFunctionTestCase('sqrt', sqrt, _unaryInputs), + _UnaryFunctionTestCase('asin', asin, _unaryInputs), + _UnaryFunctionTestCase('acos', acos, _unaryInputs), + _UnaryFunctionTestCase('atan', atan, _unaryInputs), +]; diff --git a/moor/test/integration_tests/insert_integration_test.dart b/moor/test/integration_tests/insert_integration_test.dart index b668ef34..beb4d835 100644 --- a/moor/test/integration_tests/insert_integration_test.dart +++ b/moor/test/integration_tests/insert_integration_test.dart @@ -1,5 +1,5 @@ import 'package:moor/moor.dart'; -import 'package:moor_ffi/moor_ffi.dart'; +import 'package:moor/ffi.dart'; @TestOn('vm') import 'package:test/test.dart'; diff --git a/moor/test/isolate_test.dart b/moor/test/isolate_test.dart index 4bd45fbc..67a13530 100644 --- a/moor/test/isolate_test.dart +++ b/moor/test/isolate_test.dart @@ -4,7 +4,7 @@ import 'dart:isolate'; import 'package:moor/isolate.dart'; import 'package:moor/moor.dart'; -import 'package:moor_ffi/moor_ffi.dart'; +import 'package:moor/ffi.dart'; import 'package:test/test.dart'; import 'data/tables/todos.dart'; diff --git a/moor_ffi/lib/database.dart b/moor_ffi/lib/database.dart index 95ee60af..cac315aa 100644 --- a/moor_ffi/lib/database.dart +++ b/moor_ffi/lib/database.dart @@ -1,5 +1,6 @@ /// Exports the low-level [Database] class to run operations on a sqlite /// database via `dart:ffi`. +@Deprecated('Consider migrating to package:sqlite3/sqlite3.dart') library database; import 'package:moor_ffi/src/bindings/types.dart'; diff --git a/moor_ffi/lib/moor_ffi.dart b/moor_ffi/lib/moor_ffi.dart index af2469b7..94fe2573 100644 --- a/moor_ffi/lib/moor_ffi.dart +++ b/moor_ffi/lib/moor_ffi.dart @@ -1,3 +1,4 @@ +@Deprecated('Use package:moor/ffi.dart instead') import 'dart:io'; import 'package:moor/backends.dart'; diff --git a/moor_ffi/lib/open_helper.dart b/moor_ffi/lib/open_helper.dart index ed421162..8eab2032 100644 --- a/moor_ffi/lib/open_helper.dart +++ b/moor_ffi/lib/open_helper.dart @@ -1,5 +1,6 @@ /// Utils to open a [DynamicLibrary] on platforms that aren't supported by /// `moor_ffi` by default. +@Deprecated('Consider migrating to package:sqlite3/open.dart') library open_helper; import 'dart:ffi'; diff --git a/sqlparser/pubspec.yaml b/sqlparser/pubspec.yaml index 47fc99c5..961d9933 100644 --- a/sqlparser/pubspec.yaml +++ b/sqlparser/pubspec.yaml @@ -18,4 +18,4 @@ dev_dependencies: test: ^1.9.4 path: ^1.6.0 ffi: ^0.1.3 - moor_ffi: ^0.6.0 \ No newline at end of file + sqlite3: ^0.1.3 \ No newline at end of file diff --git a/sqlparser/test/scanner/recognizes_all_tokens_test.dart b/sqlparser/test/scanner/recognizes_all_tokens_test.dart index 28825ac4..68fd24ff 100644 --- a/sqlparser/test/scanner/recognizes_all_tokens_test.dart +++ b/sqlparser/test/scanner/recognizes_all_tokens_test.dart @@ -2,7 +2,7 @@ import 'dart:convert'; import 'dart:ffi'; import 'package:test/test.dart'; -import 'package:moor_ffi/open_helper.dart'; +import 'package:sqlite3/open.dart'; import 'package:ffi/ffi.dart'; import 'package:sqlparser/src/reader/tokenizer/token.dart';