diff --git a/moor_ffi/.gitignore b/moor_ffi/.gitignore deleted file mode 100644 index 5c859d0f..00000000 --- a/moor_ffi/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -.DS_Store -.dart_tool/ - -.packages -.pub/ - -build/ - -pubspec.lock - -# todo determine whether metadata should be added to gitignore (the file says it shouldn't, but does this break)? -.metadata -coverage/** \ No newline at end of file diff --git a/moor_ffi/CHANGELOG.md b/moor_ffi/CHANGELOG.md deleted file mode 100644 index bac64178..00000000 --- a/moor_ffi/CHANGELOG.md +++ /dev/null @@ -1,58 +0,0 @@ -## 0.8.0 - -This package is now deprecated, but will continue to work for Flutter users. - -Moor users should use the new `package:moor/ffi.dart` library. -To migrate, -- replace imports - - of `package:moor_ffi/moor_ffi.dart` with `package:moor/ffi.dart` - - of `package:moor_ffi/open_helper.dart` with `package:sqlite3/open.dart` -- when using Flutter, add a dependency on `sqlite3_flutter_libs` - -Users of this package that don't use moor should use the new [sqlite3](https://pub.dev/packages/sqlite3) -package instead. - -## 0.7.0 - -- Throw an error when using an unsupported datatype as argument -- Return null from `REGEXP` when either argument is null (used to report an error) - -## 0.6.0 - -- Added `moor_contains` sql function to support case-sensitive contains -- Workaround for `dlopen` issues on some Android devices. - -## 0.5.0 - -- Provide mathematical functions in sql (`pow`, `power`, `sin`, `cos`, `tan`, `asin`, `atan`, `acos`, `sqrt`) -- On Android, use sqlite 3.31.1 -- added an `extendedResultCode` to `SqliteException` - -## 0.4.0 - -- Use precompiled libraries for faster build times - -## 0.3.2 - -- Fix a bug where empty blobs would read as `null` instead of an empty list - -## 0.3.1 - -- Implement `overrideForAll` and `overrideFor` - thanks, [@negator](https://github.com/negator) - -## 0.3.0 - -- Better setup for compiling sqlite3 on Android - - Compilation options to increase runtime performance, enable `fts5` and `json1` - - We no longer download sqlite sources on the first run, they now ship with the plugin - -## 0.2.0 - -- Remove the `background` flag from the moor apis provided by this package. Use the moor isolate api - instead. -- Remove builtin support for background execution from the low-level `Database` api -- Support Dart 2.6, drop support for older versions - -## 0.0.1 - -- Initial release. Contains standalone bindings and a moor implementation. \ No newline at end of file diff --git a/moor_ffi/LICENSE b/moor_ffi/LICENSE deleted file mode 100644 index c75eb6c8..00000000 --- a/moor_ffi/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -MIT License - -Copyright (c) 2019 Simon Binder - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -This project also bundles sqlite, which is in the Public Domain. -See https://www.sqlite.org/copyright.html \ No newline at end of file diff --git a/moor_ffi/README.md b/moor_ffi/README.md deleted file mode 100644 index 41ab3218..00000000 --- a/moor_ffi/README.md +++ /dev/null @@ -1,111 +0,0 @@ -This package has been deprecated! Consider migrating to new sqlite packages depending on your setup: - -- You use moor to build Flutter apps: Remove `moor_ffi` from your dependencies and add `sqlite3_flutter_libs` - instead. Also, replace the following imports: - - change `package:moor_ffi/moor_ffi.dart` to `package:moor/ffi.dart` - - change `package:moor_ffi/open_helper.dart` to `package:sqlite3/open.dart` -- You use moor, but without Flutter: Just drop the `moor_ffi` dependency and use the new - `package:moor/ffi.dart` library. You need to make sure that a dynamic sqlite3 library is - available at runtime. -- You don't use moor, but you do use Flutter: Depend on `sqlite3` and `sqlite3_flutter_libs`. The - `sqlite3` package contains the new Dart apis to use sqlite3. -- You don't use the main moor package or Flutter: Just depend on the `sqlite3` package and make sure that a - dynamic sqlite3 library is available at runtime - -# moor_ffi - -Dart bindings to sqlite by using `dart:ffi`. This library contains utils to make -integration with [moor](https://pub.dev/packages/moor) easier, but it can also be used -as a standalone package. It also doesn't depend on Flutter, so it can be used on Dart VM -applications as well. - -## Supported platforms -You can make this library work on any platform that lets you obtain a `DynamicLibrary` -in which sqlite's symbols are available (see below). - -Out of the box, this library supports all platforms where `sqlite3` is installed: -- iOS: Yes -- macOS: Yes -- Linux: Available on most distros -- Windows: Additional setup is required -- Android: Yes when used with Flutter, this library includes the necessary native libraries on Android - -### On other platforms -Using this library on platforms that are not supported out of the box is fairly -straightforward. For instance, if you release your own `sqlite3.so` next to your application, -you could use -```dart -import 'dart:ffi'; -import 'dart:io'; -import 'package:moor_ffi/database.dart'; -import 'package:moor_ffi/open_helper.dart'; - -void main() { - open.overrideFor(OperatingSystem.linux, _openOnLinux); - - final db = Database.memory(); - db.close(); -} - -DynamicLibrary _openOnLinux() { - final script = File(Platform.script.toFilePath()); - final libraryNextToScript = File('${script.path}/sqlite3.so'); - return DynamicLibrary.open(libraryNextToScript.path); -} -``` -Just be sure to first override the behavior and then open the database. Further, -if you want to use the isolate api, you can only use a static method or a top-level -function to open the library. For Windows, a similar setup with a `sqlite3.dll` library -should work. - -### Supported datatypes -This library supports `null`, `int`, `double`, `String` and `Uint8List` to bind args. -Returned columns from select statements will have the same types. - -## Using without moor -```dart -import 'package:moor_ffi/database.dart'; - -void main() { - final database = Database.memory(); - // run some database operations. See the example for details - database.close(); -} -``` - -Be sure to __always__ call `Database.close` to avoid memory leaks! - -## Using with moor -If you're migrating an existing project using `moor_flutter`, see the -[documentation](https://moor.simonbinder.eu/docs/other-engines/vm/#migrating-from-moor-flutter-to-moor-ffi). - -Add both `moor` and `moor_ffi` to your pubspec: -```yaml -dependencies: - moor: ^2.0.0 - moor_ffi: ^0.2.0 -dev_dependencies: - moor_generator: ^2.0.0 -``` - -You can then use a `VmDatabase` as an executor: -```dart -@UseMoor(...) -class MyDatabase extends _$MyDatabase { - - MyDatabase(): super(VmDatabase(File('app.db'))); -} -``` -If you need to find an appropriate directory for the database file, you can use the `LazyDatabase` wrapper -from moor. It can be used to create the inner `VmDatabase` asynchronously: -```dart -import 'package:path_provider/path_provider.dart'; -import 'package:path/path.dart' as p; - -// use this instead of VmDatabase(...) -LazyDatabase(() async { - final dbFolder = await getApplicationDocumentsDirectory(); - final file = File(p.join(dbFolder.path, 'app.db')); - return VmDatabase(file); -}); -``` \ No newline at end of file diff --git a/moor_ffi/analysis_options.yaml b/moor_ffi/analysis_options.yaml deleted file mode 120000 index c9e0d9fb..00000000 --- a/moor_ffi/analysis_options.yaml +++ /dev/null @@ -1 +0,0 @@ -../analysis_options.yaml \ No newline at end of file diff --git a/moor_ffi/android/.gitignore b/moor_ffi/android/.gitignore deleted file mode 100644 index f49f1198..00000000 --- a/moor_ffi/android/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -*.iml -.gradle -/local.properties -/.idea/workspace.xml -/.idea/libraries -.DS_Store -/build -/captures - -.externalNativeBuild/ -cpp/sqlite* \ No newline at end of file diff --git a/moor_ffi/android/build.gradle b/moor_ffi/android/build.gradle deleted file mode 100644 index dae04261..00000000 --- a/moor_ffi/android/build.gradle +++ /dev/null @@ -1,42 +0,0 @@ -buildscript { - repositories { - google() - jcenter() - } - - dependencies { - classpath 'com.android.tools.build:gradle:3.5.3' - } -} - -group 'eu.simonbinder.moor_ffi' -version '1.0' - -rootProject.allprojects { - repositories { - google() - jcenter() - - maven { - url 'https://dl.bintray.com/sbinder/sqlite3-native-library/' - } - } -} - -apply plugin: 'com.android.library' - -android { - compileSdkVersion 28 - - defaultConfig { - minSdkVersion 16 - } - - lintOptions { - disable 'InvalidPackage' - } -} - -dependencies { - implementation 'eu.simonbinder:sqlite3-native-library:3.32.3' -} \ No newline at end of file diff --git a/moor_ffi/android/gradle.properties b/moor_ffi/android/gradle.properties deleted file mode 100644 index 2bd6f4fd..00000000 --- a/moor_ffi/android/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -org.gradle.jvmargs=-Xmx1536M - diff --git a/moor_ffi/android/gradle/wrapper/gradle-wrapper.properties b/moor_ffi/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 01a286e9..00000000 --- a/moor_ffi/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip diff --git a/moor_ffi/android/settings.gradle b/moor_ffi/android/settings.gradle deleted file mode 100644 index 2e83ea9c..00000000 --- a/moor_ffi/android/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'moor_ffi' diff --git a/moor_ffi/android/src/main/AndroidManifest.xml b/moor_ffi/android/src/main/AndroidManifest.xml deleted file mode 100644 index 2ac4a3a3..00000000 --- a/moor_ffi/android/src/main/AndroidManifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - \ No newline at end of file diff --git a/moor_ffi/android/src/main/java/eu/simonbinder/moor_ffi/MoorFfiPlugin.java b/moor_ffi/android/src/main/java/eu/simonbinder/moor_ffi/MoorFfiPlugin.java deleted file mode 100644 index e9dee623..00000000 --- a/moor_ffi/android/src/main/java/eu/simonbinder/moor_ffi/MoorFfiPlugin.java +++ /dev/null @@ -1,17 +0,0 @@ -package eu.simonbinder.moor_ffi; - -import io.flutter.embedding.engine.plugins.FlutterPlugin; - -public class MoorFfiPlugin implements FlutterPlugin { - - @Override - public void onAttachedToEngine(FlutterPluginBinding binding) { - // Do nothing, we only need the native libraries. - } - - @Override - public void onDetachedFromEngine(FlutterPluginBinding binding) { - // Again, nothing to do here. - } - -} \ No newline at end of file diff --git a/moor_ffi/example/main.dart b/moor_ffi/example/main.dart deleted file mode 100644 index cfe224a9..00000000 --- a/moor_ffi/example/main.dart +++ /dev/null @@ -1,27 +0,0 @@ -import 'package:moor_ffi/database.dart'; - -const _createTable = r''' -CREATE TABLE frameworks ( - id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - name VARCHAR NOT NULL -); -'''; - -void main() { - final db = Database.memory(); - db.execute(_createTable); - - final insertStmt = db.prepare('INSERT INTO frameworks(name) VALUES (?)'); - insertStmt.execute(['Flutter']); - insertStmt.execute(['AngularDart']); - insertStmt.close(); - - final selectStmt = db.prepare('SELECT * FROM frameworks ORDER BY name'); - final result = selectStmt.select(); - for (final row in result) { - print('${row['id']}: ${row['name']}'); - } - - selectStmt.close(); - db.close(); -} diff --git a/moor_ffi/ios/.gitignore b/moor_ffi/ios/.gitignore deleted file mode 100644 index aa479fd3..00000000 --- a/moor_ffi/ios/.gitignore +++ /dev/null @@ -1,37 +0,0 @@ -.idea/ -.vagrant/ -.sconsign.dblite -.svn/ - -.DS_Store -*.swp -profile - -DerivedData/ -build/ -GeneratedPluginRegistrant.h -GeneratedPluginRegistrant.m - -.generated/ - -*.pbxuser -*.mode1v3 -*.mode2v3 -*.perspectivev3 - -!default.pbxuser -!default.mode1v3 -!default.mode2v3 -!default.perspectivev3 - -xcuserdata - -*.moved-aside - -*.pyc -*sync/ -Icon? -.tags* - -/Flutter/Generated.xcconfig -/Flutter/flutter_export_environment.sh \ No newline at end of file diff --git a/moor_ffi/ios/Assets/.gitkeep b/moor_ffi/ios/Assets/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/moor_ffi/ios/Classes/MoorFfiPlugin.h b/moor_ffi/ios/Classes/MoorFfiPlugin.h deleted file mode 100644 index a47cb500..00000000 --- a/moor_ffi/ios/Classes/MoorFfiPlugin.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface MoorFfiPlugin : NSObject -@end diff --git a/moor_ffi/ios/Classes/MoorFfiPlugin.m b/moor_ffi/ios/Classes/MoorFfiPlugin.m deleted file mode 100644 index 9745116d..00000000 --- a/moor_ffi/ios/Classes/MoorFfiPlugin.m +++ /dev/null @@ -1,8 +0,0 @@ -#import "MoorFfiPlugin.h" -#import - -@implementation MoorFfiPlugin -+ (void)registerWithRegistrar:(NSObject*)registrar { - [SwiftMoorFfiPlugin registerWithRegistrar:registrar]; -} -@end diff --git a/moor_ffi/ios/Classes/SwiftMoorFfiPlugin.swift b/moor_ffi/ios/Classes/SwiftMoorFfiPlugin.swift deleted file mode 100644 index dac1b09f..00000000 --- a/moor_ffi/ios/Classes/SwiftMoorFfiPlugin.swift +++ /dev/null @@ -1,14 +0,0 @@ -import Flutter -import UIKit - -public class SwiftMoorFfiPlugin: NSObject, FlutterPlugin { - public static func register(with registrar: FlutterPluginRegistrar) { - let channel = FlutterMethodChannel(name: "moor_ffi", binaryMessenger: registrar.messenger()) - let instance = SwiftMoorFfiPlugin() - registrar.addMethodCallDelegate(instance, channel: channel) - } - - public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - result("iOS " + UIDevice.current.systemVersion) - } -} diff --git a/moor_ffi/ios/moor_ffi.podspec b/moor_ffi/ios/moor_ffi.podspec deleted file mode 100644 index 80c66141..00000000 --- a/moor_ffi/ios/moor_ffi.podspec +++ /dev/null @@ -1,23 +0,0 @@ -# -# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html -# -Pod::Spec.new do |s| - s.name = 'moor_ffi' - s.version = '0.0.1' - s.summary = 'A new flutter plugin project.' - s.description = <<-DESC -A new flutter plugin project. - DESC - s.homepage = 'http://example.com' - s.license = { :file => '../LICENSE' } - s.author = { 'Your Company' => 'email@example.com' } - s.source = { :path => '.' } - #s.source_files = 'Classes/**/*' - #s.public_header_files = 'Classes/**/*.h' - s.dependency 'Flutter' - - # when we run on Dart 2.6, we should use this library and also use DynamicLibrary.executable() - # s.dependency 'sqlite3' - - s.ios.deployment_target = '8.0' -end \ No newline at end of file diff --git a/moor_ffi/lib/database.dart b/moor_ffi/lib/database.dart deleted file mode 100644 index cac315aa..00000000 --- a/moor_ffi/lib/database.dart +++ /dev/null @@ -1,11 +0,0 @@ -/// 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'; - -export 'src/api/result.dart'; -export 'src/bindings/types.dart' hide Database, Statement; -export 'src/impl/database.dart' - show SqliteException, Database, PreparedStatement; diff --git a/moor_ffi/lib/moor_ffi.dart b/moor_ffi/lib/moor_ffi.dart deleted file mode 100644 index 94fe2573..00000000 --- a/moor_ffi/lib/moor_ffi.dart +++ /dev/null @@ -1,8 +0,0 @@ -@Deprecated('Use package:moor/ffi.dart instead') -import 'dart:io'; - -import 'package:moor/backends.dart'; -import 'package:moor/moor.dart'; -import 'package:moor_ffi/database.dart'; - -part 'src/vm_database.dart'; diff --git a/moor_ffi/lib/open_helper.dart b/moor_ffi/lib/open_helper.dart deleted file mode 100644 index 8eab2032..00000000 --- a/moor_ffi/lib/open_helper.dart +++ /dev/null @@ -1,8 +0,0 @@ -/// 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'; - -export 'src/load_library.dart'; diff --git a/moor_ffi/lib/src/api/result.dart b/moor_ffi/lib/src/api/result.dart deleted file mode 100644 index d26aced3..00000000 --- a/moor_ffi/lib/src/api/result.dart +++ /dev/null @@ -1,64 +0,0 @@ -import 'dart:collection'; - -import 'package:collection/collection.dart'; - -/// Stores the result of a select statement. -class Result extends Iterable { - final List columnNames; - // a result set can have multiple columns with the same name, but that's rare - // and users usually use a name as index. So we cache that for O(1) lookups - Map _calculatedIndexes; - final List> rows; - - Result(this.columnNames, this.rows) { - _calculatedIndexes = { - for (var column in columnNames) column: columnNames.lastIndexOf(column), - }; - } - - @override - Iterator get iterator => _ResultIterator(this); -} - -/// Stores a single row in the result of a select statement. -class Row extends MapMixin - with UnmodifiableMapMixin { - final Result _result; - final int _rowIndex; - - Row._(this._result, this._rowIndex); - - /// Returns the value stored in the [i]-th column in this row (zero-indexed). - dynamic columnAt(int i) { - return _result.rows[_rowIndex][i]; - } - - @override - dynamic operator [](Object key) { - if (key is! String) return null; - - final index = _result._calculatedIndexes[key]; - if (index == null) return null; - - return columnAt(index); - } - - @override - Iterable get keys => _result.columnNames; -} - -class _ResultIterator extends Iterator { - final Result result; - int index = -1; - - _ResultIterator(this.result); - - @override - Row get current => Row._(result, index); - - @override - bool moveNext() { - index++; - return index < result.rows.length; - } -} diff --git a/moor_ffi/lib/src/bindings/bindings.dart b/moor_ffi/lib/src/bindings/bindings.dart deleted file mode 100644 index 05c4ad58..00000000 --- a/moor_ffi/lib/src/bindings/bindings.dart +++ /dev/null @@ -1,266 +0,0 @@ -// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:ffi'; - -import 'package:moor_ffi/open_helper.dart'; - -import '../ffi/blob.dart'; - -import 'signatures.dart'; -import 'types.dart'; - -// ignore_for_file: comment_references, non_constant_identifier_names - -class _SQLiteBindings { - DynamicLibrary sqlite; - - int Function(Pointer filename, Pointer> databaseOut, - int flags, Pointer vfs) sqlite3_open_v2; - - int Function(Pointer database) sqlite3_close_v2; - void Function(Pointer ptr) sqlite3_free; - - int Function( - Pointer database, - Pointer query, - int nbytes, - Pointer> statementOut, - Pointer> tail) sqlite3_prepare_v2; - - int Function( - Pointer database, - Pointer query, - Pointer callback, - Pointer cbFirstArg, - Pointer> errorMsgOut, - ) sqlite3_exec; - - int Function(Pointer statement) sqlite3_step; - - int Function(Pointer statement) sqlite3_reset; - - int Function(Pointer statement) sqlite3_finalize; - - int Function(Pointer statement) sqlite3_column_count; - - Pointer Function(Pointer statement, int columnIndex) - sqlite3_column_name; - - int Function(Pointer statement, int columnIndex) - sqlite3_column_type; - - double Function(Pointer statement, int columnIndex) - sqlite3_column_double; - int Function(Pointer statement, int columnIndex) - sqlite3_column_int64; - Pointer Function(Pointer statement, int columnIndex) - sqlite3_column_text; - Pointer Function(Pointer statement, int columnIndex) - sqlite3_column_blob; - - /// Returns the amount of bytes to read when using [sqlite3_column_blob]. - int Function(Pointer statement, int columnIndex) - sqlite3_column_bytes; - - int Function(Pointer db) sqlite3_changes; - int Function(Pointer db) sqlite3_last_insert_rowid; - - int Function(Pointer db) sqlite3_extended_errcode; - Pointer Function(int code) sqlite3_errstr; - Pointer Function(Pointer database) sqlite3_errmsg; - int Function(Pointer database, int onOff) - sqlite3_extended_result_codes; - - int Function(Pointer statement, int columnIndex, double value) - sqlite3_bind_double; - int Function(Pointer statement, int columnIndex, int value) - sqlite3_bind_int64; - int Function( - Pointer statement, - int columnIndex, - Pointer value, - int minusOne, - Pointer disposeCb) sqlite3_bind_text; - int Function( - Pointer statement, - int columnIndex, - Pointer value, - int length, - Pointer disposeCb) sqlite3_bind_blob; - int Function(Pointer statement, int columnIndex) sqlite3_bind_null; - sqlite3_bind_parameter_count_dart sqlite3_bind_parameter_count; - - int Function( - Pointer db, - Pointer zFunctionName, - int argCount, - int eTextRep, - Pointer arg, - Pointer> handler, - Pointer> step, - Pointer> finalizer, - Pointer> destroyArg, - ) sqlite3_create_function_v2; - - Pointer Function(Pointer value) sqlite3_value_blob; - Pointer Function(Pointer value) sqlite3_value_text; - double Function(Pointer value) sqlite3_value_double; - int Function(Pointer value) sqlite3_value_int64; - int Function(Pointer value) sqlite3_value_bytes; - int Function(Pointer value) sqlite3_value_type; - - void Function(Pointer ctx) sqlite3_result_null; - void Function(Pointer ctx, int value) sqlite3_result_int64; - void Function(Pointer ctx, double value) - sqlite3_result_double; - void Function(Pointer ctx, Pointer msg, int length) - sqlite3_result_error; - - _SQLiteBindings() { - sqlite = open.openSqlite(); - - sqlite3_bind_double = sqlite - .lookup>( - 'sqlite3_bind_double') - .asFunction(); - sqlite3_bind_int64 = sqlite - .lookup>('sqlite3_bind_int64') - .asFunction(); - sqlite3_bind_text = sqlite - .lookup>('sqlite3_bind_text') - .asFunction(); - sqlite3_bind_blob = sqlite - .lookup>('sqlite3_bind_blob') - .asFunction(); - sqlite3_bind_null = sqlite - .lookup>('sqlite3_bind_null') - .asFunction(); - sqlite3_bind_parameter_count = sqlite.lookupFunction< - sqlite3_bind_parameter_count_native, - sqlite3_bind_parameter_count_dart>('sqlite3_bind_parameter_count'); - sqlite3_open_v2 = sqlite - .lookup>('sqlite3_open_v2') - .asFunction(); - sqlite3_close_v2 = sqlite - .lookup>('sqlite3_close_v2') - .asFunction(); - sqlite3_free = sqlite - .lookup>('sqlite3_free') - .asFunction(); - sqlite3_prepare_v2 = sqlite - .lookup>( - 'sqlite3_prepare_v2') - .asFunction(); - sqlite3_exec = sqlite - .lookup>('sqlite3_exec') - .asFunction(); - sqlite3_step = sqlite - .lookup>('sqlite3_step') - .asFunction(); - sqlite3_reset = sqlite - .lookup>('sqlite3_reset') - .asFunction(); - sqlite3_changes = sqlite - .lookup>('sqlite3_changes') - .asFunction(); - sqlite3_last_insert_rowid = sqlite - .lookup>( - 'sqlite3_last_insert_rowid') - .asFunction(); - sqlite3_finalize = sqlite - .lookup>('sqlite3_finalize') - .asFunction(); - sqlite3_extended_errcode = sqlite - .lookup>( - 'sqlite3_extended_errcode') - .asFunction(); - sqlite3_errstr = sqlite - .lookup>('sqlite3_errstr') - .asFunction(); - sqlite3_errmsg = sqlite - .lookup>('sqlite3_errmsg') - .asFunction(); - sqlite3_extended_result_codes = sqlite - .lookup>( - 'sqlite3_extended_result_codes') - .asFunction(); - sqlite3_column_count = sqlite - .lookup>( - 'sqlite3_column_count') - .asFunction(); - sqlite3_column_name = sqlite - .lookup>( - 'sqlite3_column_name') - .asFunction(); - sqlite3_column_type = sqlite - .lookup>( - 'sqlite3_column_type') - .asFunction(); - sqlite3_column_double = sqlite - .lookup>( - 'sqlite3_column_double') - .asFunction(); - sqlite3_column_int64 = sqlite - .lookup>( - 'sqlite3_column_int64') - .asFunction(); - sqlite3_column_text = sqlite - .lookup>( - 'sqlite3_column_text') - .asFunction(); - sqlite3_column_blob = sqlite - .lookup>( - 'sqlite3_column_blob') - .asFunction(); - sqlite3_column_bytes = sqlite - .lookup>( - 'sqlite3_column_bytes') - .asFunction(); - sqlite3_create_function_v2 = sqlite - .lookup>( - 'sqlite3_create_function_v2') - .asFunction(); - sqlite3_value_blob = sqlite - .lookup>('sqlite3_value_blob') - .asFunction(); - sqlite3_value_text = sqlite - .lookup>('sqlite3_value_text') - .asFunction(); - sqlite3_value_double = sqlite - .lookup>( - 'sqlite3_value_double') - .asFunction(); - sqlite3_value_int64 = sqlite - .lookup>( - 'sqlite3_value_int64') - .asFunction(); - sqlite3_value_bytes = sqlite - .lookup>( - 'sqlite3_value_bytes') - .asFunction(); - sqlite3_value_type = sqlite - .lookup>('sqlite3_value_type') - .asFunction(); - sqlite3_result_null = sqlite - .lookup>( - 'sqlite3_result_null') - .asFunction(); - sqlite3_result_int64 = sqlite - .lookup>( - 'sqlite3_result_int64') - .asFunction(); - sqlite3_result_double = sqlite - .lookup>( - 'sqlite3_result_double') - .asFunction(); - sqlite3_result_error = sqlite - .lookup>( - 'sqlite3_result_error') - .asFunction(); - } -} - -_SQLiteBindings _cachedBindings; -_SQLiteBindings get bindings => _cachedBindings ??= _SQLiteBindings(); diff --git a/moor_ffi/lib/src/bindings/constants.dart b/moor_ffi/lib/src/bindings/constants.dart deleted file mode 100644 index ae13e88c..00000000 --- a/moor_ffi/lib/src/bindings/constants.dart +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -// ignore_for_file: constant_identifier_names - -/// Result Codes -/// -/// Many SQLite functions return an integer result code from the set shown -/// here in order to indicates success or failure. -/// -/// New error codes may be added in future versions of SQLite. -/// -/// See also: SQLITE_IOERR_READ | extended result codes, -/// sqlite3_vtab_on_conflict() SQLITE_ROLLBACK | result codes. -class Errors { - /// Successful result - static const int SQLITE_OK = 0; - - /// Generic error - static const int SQLITE_ERROR = 1; - - /// Internal logic error in SQLite - static const int SQLITE_INTERNAL = 2; - - /// Access permission denied - static const int SQLITE_PERM = 3; - - /// Callback routine requested an abort - static const int SQLITE_ABORT = 4; - - /// The database file is locked - static const int SQLITE_BUSY = 5; - - /// A table in the database is locked - static const int SQLITE_LOCKED = 6; - - /// A malloc() failed - static const int SQLITE_NOMEM = 7; - - /// Attempt to write a readonly database - static const int SQLITE_READONLY = 8; - - /// Operation terminated by sqlite3_interrupt() - static const int SQLITE_INTERRUPT = 9; - - /// Some kind of disk I/O error occurred - static const int SQLITE_IOERR = 10; - - /// The database disk image is malformed - static const int SQLITE_CORRUPT = 11; - - /// Unknown opcode in sqlite3_file_control() - static const int SQLITE_NOTFOUND = 12; - - /// Insertion failed because database is full - static const int SQLITE_FULL = 13; - - /// Unable to open the database file - static const int SQLITE_CANTOPEN = 14; - - /// Database lock protocol error - static const int SQLITE_PROTOCOL = 15; - - /// Internal use only - static const int SQLITE_EMPTY = 16; - - /// The database schema changed - static const int SQLITE_SCHEMA = 17; - - /// String or BLOB exceeds size limit - static const int SQLITE_TOOBIG = 18; - - /// Abort due to constraint violation - static const int SQLITE_CONSTRAINT = 19; - - /// Data type mismatch - static const int SQLITE_MISMATCH = 20; - - /// Library used incorrectly - static const int SQLITE_MISUSE = 21; - - /// Uses OS features not supported on host - static const int SQLITE_NOLFS = 22; - - /// Authorization denied - static const int SQLITE_AUTH = 23; - - /// Not used - static const int SQLITE_FORMAT = 24; - - /// 2nd parameter to sqlite3_bind out of range - static const int SQLITE_RANGE = 25; - - /// File opened that is not a database file - static const int SQLITE_NOTADB = 26; - - /// Notifications from sqlite3_log() - static const int SQLITE_NOTICE = 27; - - /// Warnings from sqlite3_log() - static const int SQLITE_WARNING = 28; - - /// sqlite3_step() has another row ready - static const int SQLITE_ROW = 100; - - /// sqlite3_step() has finished executing - static const int SQLITE_DONE = 101; -} - -/// Flags For File Open Operations -/// -/// These bit values are intended for use in the -/// 3rd parameter to the [sqlite3_open_v2()] interface and -/// in the 4th parameter to the `sqlite3_vfs.xOpen` method. -class Flags { - /// Ok for sqlite3_open_v2() - static const int SQLITE_OPEN_READONLY = 0x00000001; - - /// Ok for sqlite3_open_v2() - static const int SQLITE_OPEN_READWRITE = 0x00000002; - - /// Ok for sqlite3_open_v2() - static const int SQLITE_OPEN_CREATE = 0x00000004; - - /// VFS only - static const int SQLITE_OPEN_DELETEONCLOSE = 0x00000008; - - /// VFS only - static const int SQLITE_OPEN_EXCLUSIVE = 0x00000010; - - /// VFS only - static const int SQLITE_OPEN_AUTOPROXY = 0x00000020; - - /// Ok for sqlite3_open_v2() - static const int SQLITE_OPEN_URI = 0x00000040; - - /// Ok for sqlite3_open_v2() - static const int SQLITE_OPEN_MEMORY = 0x00000080; - - /// VFS only - static const int SQLITE_OPEN_MAIN_DB = 0x00000100; - - /// VFS only - static const int SQLITE_OPEN_TEMP_DB = 0x00000200; - - /// VFS only - static const int SQLITE_OPEN_TRANSIENT_DB = 0x00000400; - - /// VFS only - static const int SQLITE_OPEN_MAIN_JOURNAL = 0x00000800; - - /// VFS only - static const int SQLITE_OPEN_TEMP_JOURNAL = 0x00001000; - - /// VFS only - static const int SQLITE_OPEN_SUBJOURNAL = 0x00002000; - - /// VFS only - static const int SQLITE_OPEN_MASTER_JOURNAL = 0x00004000; - - /// Ok for sqlite3_open_v2() - static const int SQLITE_OPEN_NOMUTEX = 0x00008000; - - /// Ok for sqlite3_open_v2() - static const int SQLITE_OPEN_FULLMUTEX = 0x00010000; - - /// Ok for sqlite3_open_v2() - static const int SQLITE_OPEN_SHAREDCACHE = 0x00020000; - - /// Ok for sqlite3_open_v2() - static const int SQLITE_OPEN_PRIVATECACHE = 0x00040000; - - /// VFS only - static const int SQLITE_OPEN_WAL = 0x00080000; -} - -class TextEncodings { - static const int SQLITE_UTF8 = 1; -} - -class FunctionFlags { - static const int SQLITE_DETERMINISTIC = 0x000000800; - static const int SQLITE_DIRECTONLY = 0x000080000; -} - -class Types { - static const int SQLITE_INTEGER = 1; - static const int SQLITE_FLOAT = 2; - static const int SQLITE_TEXT = 3; - static const int SQLITE_BLOB = 4; - static const int SQLITE_NULL = 5; -} diff --git a/moor_ffi/lib/src/bindings/signatures.dart b/moor_ffi/lib/src/bindings/signatures.dart deleted file mode 100644 index 678f4c79..00000000 --- a/moor_ffi/lib/src/bindings/signatures.dart +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:ffi'; - -import '../ffi/blob.dart'; - -import 'types.dart'; - -typedef sqlite3_open_v2_native_t = Int32 Function(Pointer filename, - Pointer> ppDb, Int32 flags, Pointer vfs); - -typedef sqlite3_close_v2_native_t = Int32 Function(Pointer database); - -typedef sqlite3_free_native = Void Function(Pointer pointer); - -typedef sqlite3_prepare_v2_native_t = Int32 Function( - Pointer database, - Pointer query, - Int32 nbytes, - Pointer> statementOut, - Pointer> tail); - -typedef sqlite3_exec_native = Int32 Function( - Pointer database, - Pointer query, - Pointer callback, - Pointer firstCbArg, - Pointer> errorOut); - -typedef sqlite3_step_native_t = Int32 Function(Pointer statement); - -typedef sqlite3_reset_native_t = Int32 Function(Pointer statement); - -typedef sqlite3_finalize_native_t = Int32 Function( - Pointer statement); - -typedef sqlite3_extended_errcode_native_t = Int32 Function( - Pointer database); - -typedef sqlite3_errstr_native_t = Pointer Function(Int32 error); - -typedef sqlite3_errmsg_native_t = Pointer Function( - Pointer database); - -typedef sqlite3_extended_result_codes_t = Int32 Function( - Pointer database, Int32 onOff); - -typedef sqlite3_column_count_native_t = Int32 Function( - Pointer statement); - -typedef sqlite3_column_name_native_t = Pointer Function( - Pointer statement, Int32 columnIndex); - -typedef sqlite3_column_type_native_t = Int32 Function( - Pointer statement, Int32 columnIndex); - -typedef sqlite3_column_double_native_t = Double Function( - Pointer statement, Int32 columnIndex); - -typedef sqlite3_column_int64_native_t = Int64 Function( - Pointer statement, Int32 columnIndex); - -typedef sqlite3_column_text_native_t = Pointer Function( - Pointer statement, Int32 columnIndex); - -typedef sqlite3_column_blob_native_t = Pointer Function( - Pointer statement, Int32 columnIndex); - -typedef sqlite3_column_bytes_native_t = Int32 Function( - Pointer statement, Int32 columnIndex); - -typedef sqlite3_changes_native = Int32 Function(Pointer database); -typedef sqlite3_last_insert_rowid_native = Int64 Function( - Pointer database); - -typedef sqlite3_bind_double_native = Int32 Function( - Pointer statement, Int32 columnIndex, Double value); -typedef sqlite3_bind_int64_native = Int32 Function( - Pointer statement, Int32 columnIndex, Int64 value); -typedef sqlite3_bind_text_native = Int32 Function( - Pointer statement, - Int32 columnIndex, - Pointer value, - Int32 length, - Pointer callback); -typedef sqlite3_bind_blob_native = Int32 Function( - Pointer statement, - Int32 columnIndex, - Pointer value, - Int32 length, - Pointer callback); -typedef sqlite3_bind_null_native = Int32 Function( - Pointer statement, Int32 columnIndex); -typedef sqlite3_bind_parameter_count_dart = int Function( - Pointer stmt); -typedef sqlite3_bind_parameter_count_native = Int32 Function( - Pointer statement); - -typedef sqlite3_function_handler = Void Function( - Pointer context, - Int32 argCount, - Pointer> args); - -typedef sqlite3_function_finalizer = Void Function( - Pointer context); - -typedef sqlite3_finalizer = Void Function(Pointer ptr); - -typedef sqlite3_create_function_v2_native = Int32 Function( - Pointer db, - Pointer zFunctionName, - Int32 nArg, - Int32 eTextRep, - Pointer pApp, - Pointer> xFunc, - Pointer> xStep, - Pointer> xDestroy, - Pointer> finalizePApp, -); - -typedef sqlite3_value_blob_native = Pointer Function( - Pointer value); -typedef sqlite3_value_double_native = Double Function( - Pointer value); -typedef sqlite3_value_int64_native = Int64 Function(Pointer value); -typedef sqlite3_value_text_native = Pointer Function( - Pointer value); -typedef sqlite3_value_bytes_native = Int32 Function(Pointer value); -typedef sqlite3_value_type_native = Int32 Function(Pointer value); - -typedef sqlite3_result_null_native = Void Function( - Pointer context); -typedef sqlite3_result_double_native = Void Function( - Pointer context, Double value); -typedef sqlite3_result_int64_native = Void Function( - Pointer context, Int64 value); -typedef sqlite3_result_error_native = Void Function( - Pointer context, Pointer char, Int32 len); diff --git a/moor_ffi/lib/src/bindings/types.dart b/moor_ffi/lib/src/bindings/types.dart deleted file mode 100644 index f92728c8..00000000 --- a/moor_ffi/lib/src/bindings/types.dart +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:convert'; -import 'dart:ffi'; - -import 'package:moor/moor.dart'; - -import '../ffi/blob.dart'; -import '../ffi/utils.dart'; -import 'bindings.dart'; -import 'constants.dart'; - -// ignore_for_file: comment_references - -/// Database Connection Handle -/// -/// Each open SQLite database is represented by a pointer to an instance of -/// the opaque structure named "sqlite3". It is useful to think of an sqlite3 -/// pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and -/// [sqlite3_open_v2()] interfaces are its constructors, and [sqlite3_close()] -/// is its destructor. There are many other interfaces (such as -/// [sqlite3_prepare_v2()], [sqlite3_create_function()], and -/// [sqlite3_busy_timeout()] to name but three) that are methods on an -class Database extends Struct {} - -/// SQL Statement Object -/// -/// An instance of this object represents a single SQL statement. -/// This object is variously known as a "prepared statement" or a -/// "compiled SQL statement" or simply as a "statement". -/// -/// The life of a statement object goes something like this: -/// -///
    -///
  1. Create the object using [sqlite3_prepare_v2()] or a related -/// function. -///
  2. Bind values to [host parameters] using the sqlite3_bind_*() -/// interfaces. -///
  3. Run the SQL by calling [sqlite3_step()] one or more times. -///
  4. Reset the statement using [sqlite3_reset()] then go back -/// to step 2. Do this zero or more times. -///
  5. Destroy the object using [sqlite3_finalize()]. -///
-/// -/// Refer to documentation on individual methods above for additional -/// information. -class Statement extends Struct {} - -/// The context in which an SQL function executes is stored in this object. -/// A pointer to this object is always the first paramater to -/// application-defined SQL functions. -/// -/// See also: -/// - https://www.sqlite.org/c3ref/context.html -class FunctionContext extends Struct {} - -/// A value object in sqlite, which can represent all values that can be stored -/// in a database table. -class SqliteValue extends Struct {} - -/// Extension to extract value from a [SqliteValue]. -extension SqliteValuePointer on Pointer { - /// Extracts the raw value from the object. - /// - /// Depending on the type of this value as set in sqlite, [value] returns - /// - a [String] - /// - a [Uint8List] - /// - a [int] - /// - a [double] - /// - `null` - /// - /// For texts and bytes, the value will be copied. - dynamic get value { - final api = bindings; - - final type = api.sqlite3_value_type(this); - switch (type) { - case Types.SQLITE_INTEGER: - return api.sqlite3_value_int64(this); - case Types.SQLITE_FLOAT: - return api.sqlite3_value_double(this); - case Types.SQLITE_TEXT: - final length = api.sqlite3_value_bytes(this); - return api.sqlite3_value_text(this).readAsStringWithLength(length); - case Types.SQLITE_BLOB: - final length = api.sqlite3_value_bytes(this); - if (length == 0) { - // sqlite3_value_bytes returns a null pointer for non-null blobs with - // a length of 0. Note that we can distinguish this from a proper null - // by checking the type (which isn't SQLITE_NULL) - return Uint8List(0); - } - return api.sqlite3_value_blob(this).readBytes(length); - case Types.SQLITE_NULL: - default: - return null; - } - } -} - -extension SqliteFunctionContextPointer on Pointer { - void resultNull() { - bindings.sqlite3_result_null(this); - } - - void resultInt(int value) { - bindings.sqlite3_result_int64(this, value); - } - - void resultDouble(double value) { - bindings.sqlite3_result_double(this, value); - } - - void resultNum(num value) { - if (value is int) { - resultInt(value); - return; - } else if (value is double) { - resultDouble(value); - return; - } - - throw AssertionError(); - } - - void resultBool(bool value) { - resultInt(value ? 1 : 0); - } - - void resultError(String message) { - final encoded = Uint8List.fromList(utf8.encode(message)); - final ptr = CBlob.allocate(encoded); - - bindings.sqlite3_result_error(this, ptr, encoded.length); - - // Note that sqlite3_result_error makes a private copy of error message - // before returning. Hence, we can deallocate the message here. - ptr.free(); - } -} diff --git a/moor_ffi/lib/src/ffi/blob.dart b/moor_ffi/lib/src/ffi/blob.dart deleted file mode 100644 index 69540073..00000000 --- a/moor_ffi/lib/src/ffi/blob.dart +++ /dev/null @@ -1,66 +0,0 @@ -import 'dart:convert'; -import 'dart:ffi'; - -import 'dart:typed_data'; - -import 'package:moor_ffi/src/ffi/utils.dart'; -import 'package:ffi/ffi.dart' as ffi; - -/// Pointer to arbitrary blobs in C. -class CBlob extends Struct { - static Pointer allocate(Uint8List blob, {int paddingAtEnd = 0}) { - final str = ffi.allocate(count: blob.length + paddingAtEnd); - - final asList = str.asTypedList(blob.length + paddingAtEnd); - asList.setAll(0, blob); - - if (paddingAtEnd != 0) { - asList.fillRange(blob.length, blob.length + paddingAtEnd, 0); - } - - return str.cast(); - } - - /// Allocates a 0-terminated string, encoded as utf8 and read from the - /// [string]. - static Pointer allocateString(String string) { - final encoded = utf8.encode(string); - final data = Uint8List(encoded.length + 1) // already filled with zeroes - ..setAll(0, encoded); - return CBlob.allocate(data); - } -} - -extension CBlobPointer on Pointer { - /// Reads a 0-terminated string, decoded with utf8. - /// - /// Warning: This method is very, very slow. If there is any way to know the - /// length of the string to read, [readAsStringWithLength] will be orders of - /// magnitude faster. - String readString() { - if (isNullPointer) return null; - - var len = 0; - final asUintPointer = cast(); - while (asUintPointer[++len] != 0) {} - - final units = readBytes(len); - return utf8.decode(units); - } - - /// More efficient version of [readString] that doesn't have to find a nil- - /// terminator. [length] is the amount of bytes to read. The string will be - /// decoded via [utf8]. - String readAsStringWithLength(int length) { - return utf8.decode(readBytes(length)); - } - - /// Reads [length] bytes from this address. - Uint8List readBytes(int length) { - assert(length >= 0); - if (isNullPointer) return null; - - final data = cast().asTypedList(length); - return Uint8List.fromList(data); - } -} diff --git a/moor_ffi/lib/src/ffi/utils.dart b/moor_ffi/lib/src/ffi/utils.dart deleted file mode 100644 index 40811214..00000000 --- a/moor_ffi/lib/src/ffi/utils.dart +++ /dev/null @@ -1,19 +0,0 @@ -import 'dart:ffi'; - -import 'package:ffi/ffi.dart' as ffi; - -extension FreePointerExtension on Pointer { - bool get isNullPointer => this == nullptr; - - void free() { - ffi.free(this); - } -} - -/// Loads a null-pointer with a specified type. -/// -/// The [nullptr] getter from `dart:ffi` can be slow due to being a -/// `Pointer` on which the VM has to perform runtime type checks. See also -/// https://github.com/dart-lang/sdk/issues/39488 -@pragma('vm:prefer-inline') -Pointer nullPtr() => nullptr.cast(); diff --git a/moor_ffi/lib/src/impl/database.dart b/moor_ffi/lib/src/impl/database.dart deleted file mode 100644 index 480d3963..00000000 --- a/moor_ffi/lib/src/impl/database.dart +++ /dev/null @@ -1,270 +0,0 @@ -import 'dart:convert'; -import 'dart:ffi'; -import 'dart:io'; -import 'dart:math'; -import 'dart:typed_data'; - -import 'package:ffi/ffi.dart'; -import 'package:meta/meta.dart'; -import 'package:moor_ffi/database.dart'; -import 'package:moor_ffi/src/api/result.dart'; -import 'package:moor_ffi/src/bindings/constants.dart'; -import 'package:moor_ffi/src/bindings/signatures.dart'; -import 'package:moor_ffi/src/bindings/types.dart' as types; -import 'package:moor_ffi/src/bindings/bindings.dart'; -import 'package:moor_ffi/src/ffi/blob.dart'; -import 'package:moor_ffi/src/ffi/utils.dart'; - -part 'errors.dart'; -part 'moor_functions.dart'; -part 'prepared_statement.dart'; - -const _openingFlags = Flags.SQLITE_OPEN_READWRITE | Flags.SQLITE_OPEN_CREATE; -const _readOnlyOpeningFlags = Flags.SQLITE_OPEN_READONLY; - -/// A opened sqlite database. -class Database { - final Pointer _db; - final List _preparedStmt = []; - final List> _furtherAllocations = []; - - bool _isClosed = false; - - Database._(this._db); - - /// Opens the [file] as a sqlite3 database. The file will be created if it - /// doesn't exist. - factory Database.openFile(File file) => Database.open(file.absolute.path); - - /// Opens an in-memory sqlite3 database. - factory Database.memory() => Database.open(':memory:'); - - /// Opens an sqlite3 database from a filename. - /// - /// Unless [readOnly] is set to true, database is opened in read/write mode. - factory Database.open(String fileName, {bool readOnly = false}) { - final dbOut = allocate>(); - final pathC = CBlob.allocateString(fileName); - final openingFlags = - (readOnly ?? false) ? _readOnlyOpeningFlags : _openingFlags; - - final resultCode = - bindings.sqlite3_open_v2(pathC, dbOut, openingFlags, nullPtr()); - final dbPointer = dbOut.value; - - dbOut.free(); - pathC.free(); - - if (resultCode == Errors.SQLITE_OK) { - // Turn extended result code to on. - bindings.sqlite3_extended_result_codes(dbPointer, 1); - - return Database._(dbPointer); - } else { - bindings.sqlite3_close_v2(dbPointer); - throw SqliteException._fromErrorCode(dbPointer, resultCode); - } - } - - void _ensureOpen() { - if (_isClosed) { - throw Exception('This database has already been closed'); - } - } - - /// Closes this database connection and releases the resources it uses. If - /// an error occurs while closing the database, an exception will be thrown. - /// The allocated memory will be freed either way. - void close() { - if (_isClosed) return; - - // close all prepared statements first - _isClosed = true; - for (final stmt in _preparedStmt) { - stmt.close(); - } - - final code = bindings.sqlite3_close_v2(_db); - SqliteException exception; - if (code != Errors.SQLITE_OK) { - exception = SqliteException._fromErrorCode(_db, code); - } - _isClosed = true; - - for (final additional in _furtherAllocations) { - additional.free(); - } - - // we don't need to deallocate the _db pointer, sqlite takes care of that - - if (exception != null) { - throw exception; - } - } - - void _handleStmtFinalized(PreparedStatement stmt) { - if (!_isClosed) { - _preparedStmt.remove(stmt); - } - } - - /// Executes the [sql] statement and ignores the result. Will throw if an - /// error occurs while executing. - void execute(String sql) { - _ensureOpen(); - - final sqlPtr = CBlob.allocateString(sql); - final errorOut = allocate>(); - - final result = - bindings.sqlite3_exec(_db, sqlPtr, nullPtr(), nullPtr(), errorOut); - sqlPtr.free(); - - final errorPtr = errorOut.value; - errorOut.free(); - - String errorMsg; - if (!errorPtr.isNullPointer) { - errorMsg = errorPtr.readString(); - // the message was allocated from sqlite, we need to free it - bindings.sqlite3_free(errorPtr.cast()); - } - - if (result != Errors.SQLITE_OK) { - throw SqliteException(result, errorMsg); - } - } - - /// Prepares the [sql] statement. - PreparedStatement prepare(String sql) { - _ensureOpen(); - - final stmtOut = allocate>(); - final sqlPtr = CBlob.allocateString(sql); - - final resultCode = - bindings.sqlite3_prepare_v2(_db, sqlPtr, -1, stmtOut, nullPtr()); - sqlPtr.free(); - - final stmt = stmtOut.value; - stmtOut.free(); - - if (resultCode != Errors.SQLITE_OK) { - // we don't need to worry about freeing the statement. If preparing the - // statement was unsuccessful, stmtOut.load() will be null - throw SqliteException._fromErrorCode(_db, resultCode); - } - - final prepared = PreparedStatement._(stmt, this); - _preparedStmt.add(prepared); - - return prepared; - } - - /// Registers a custom sqlite function by its [name]. - /// - /// The function must take [argumentCount] arguments, and it may not take more - /// than 127 arguments. If it can take a variable amount of arguments, - /// [argumentCount] should be set to `-1`. - /// - /// When the output of the function depends solely on its input, - /// [isDeterministic] should be set. This allows sqlite's query planer to make - /// further optimizations. - /// When [directOnly] is set (defaults to true), the function can't be used - /// outside a query (e.g. in triggers, views, check constraints, index - /// expressions, etc.). Unless necessary, this should be enabled for security - /// purposes. See the discussion at the link for more details - /// The length of the utf8 encoding of [name] must not exceed 255 bytes. - /// - /// See also: - /// - https://sqlite.org/c3ref/create_function.html - @visibleForTesting - void createFunction( - String name, - int argumentCount, - Pointer> implementation, { - bool isDeterministic = false, - bool directOnly = true, - }) { - _ensureOpen(); - final encodedName = Uint8List.fromList(utf8.encode(name)); - // length of encoded name is limited to 255 bytes in utf8, excluding the 0 - // terminator - if (encodedName.length > 255) { - throw ArgumentError.value( - name, 'name', 'Must be at most 255 bytes when encoded as utf8'); - } - - // argument length should be between -1 and 127 - if (argumentCount < -1 || argumentCount > 127) { - throw ArgumentError.value( - argumentCount, 'argumentCount', 'Should be between -1 and 127'); - } - - final namePtr = CBlob.allocate(encodedName, paddingAtEnd: 1); - _furtherAllocations.add(namePtr.cast()); - - var textFlag = TextEncodings.SQLITE_UTF8; - - if (isDeterministic) textFlag |= FunctionFlags.SQLITE_DETERMINISTIC; - if (directOnly) textFlag |= FunctionFlags.SQLITE_DIRECTONLY; - - final result = bindings.sqlite3_create_function_v2( - _db, - namePtr.cast(), - argumentCount, - textFlag, - nullPtr(), // *pApp, we don't use that - implementation, - nullPtr(), // *xStep, null for regular functions - nullPtr(), // *xFinal, null for regular functions - nullPtr(), // finalizer for *pApp, - ); - - if (result != Errors.SQLITE_OK) { - throw SqliteException._fromErrorCode(_db, result); - } - } - - /// Enables non-standard functions that ship with `moor_ffi`. - /// - /// After calling [enableMoorFfiFunctions], the following functions can - /// be used in sql: `power`, `pow`, `sqrt`, `sin`, `cos`, `tan`, `asin`, - /// `acos`, `atan` and `regexp`. - /// - /// At the moment, these functions are only available in statements. In - /// particular, they're not available in triggers, check constraints, index - /// expressions. - /// - /// This should only be called once per database. - void enableMoorFfiFunctions() { - _registerOn(this); - } - - /// Get the application defined version of this database. - int userVersion() { - final stmt = prepare('PRAGMA user_version'); - final result = stmt.select(); - stmt.close(); - - return result.first.columnAt(0) as int; - } - - /// Update the application defined version of this database. - void setUserVersion(int version) { - execute('PRAGMA user_version = $version'); - } - - /// Returns the amount of rows affected by the last INSERT, UPDATE or DELETE - /// statement. - int getUpdatedRows() { - _ensureOpen(); - return bindings.sqlite3_changes(_db); - } - - /// Returns the row-id of the last inserted row. - int getLastInsertId() { - _ensureOpen(); - return bindings.sqlite3_last_insert_rowid(_db); - } -} diff --git a/moor_ffi/lib/src/impl/errors.dart b/moor_ffi/lib/src/impl/errors.dart deleted file mode 100644 index 6df65fe3..00000000 --- a/moor_ffi/lib/src/impl/errors.dart +++ /dev/null @@ -1,49 +0,0 @@ -part of 'database.dart'; - -class SqliteException implements Exception { - final String message; - final String explanation; - - /// SQLite extended result code. - /// - /// As defined in https://sqlite.org/rescode.html, it represent an error code, - /// providing some idea of the cause of the failure. - final int extendedResultCode; - - /// SQLite primary result code. - /// - /// As defined in https://sqlite.org/rescode.html, it represent an error code, - /// providing some idea of the cause of the failure. - int get resultCode => extendedResultCode & 0xFF; - - SqliteException(this.extendedResultCode, this.message, [this.explanation]); - - factory SqliteException._fromErrorCode(Pointer db, int code) { - // We don't need to free the pointer returned by sqlite3_errmsg: "Memory to - // hold the error message string is managed internally. The application does - // not need to worry about freeing the result." - // https://www.sqlite.org/c3ref/errcode.html - final dbMessage = bindings.sqlite3_errmsg(db).readString(); - - String explanation; - if (code != null) { - // Getting hold of more explanatory error code as SQLITE_IOERR error group - // has an extensive list of extended error codes - final extendedCode = bindings.sqlite3_extended_errcode(db); - final errStr = bindings.sqlite3_errstr(extendedCode).readString(); - - explanation = '$errStr (code $extendedCode)'; - } - - return SqliteException(code, dbMessage, explanation); - } - - @override - String toString() { - if (explanation == null) { - return 'SqliteException($extendedResultCode): $message'; - } else { - return 'SqliteException($extendedResultCode): $message, $explanation'; - } - } -} diff --git a/moor_ffi/lib/src/impl/moor_functions.dart b/moor_ffi/lib/src/impl/moor_functions.dart deleted file mode 100644 index e33ee9f8..00000000 --- a/moor_ffi/lib/src/impl/moor_functions.dart +++ /dev/null @@ -1,184 +0,0 @@ -part of 'database.dart'; - -void _powImpl(Pointer ctx, int argCount, - Pointer> args) { - // sqlite will ensure that this is only called with 2 arguments - final first = args[0].value; - final second = args[1].value; - - if (first == null || second == null || first is! num || second is! num) { - ctx.resultNull(); - return; - } - - final result = pow(first as num, second as num); - ctx.resultNum(result); -} - -/// Base implementation for a sqlite function that takes one numerical argument -/// and returns one numerical argument. -/// -/// If [argCount] is not `1` or the single argument is not of a numerical type, -/// [ctx] will complete to null. Otherwise, it will complete to the result of -/// [calculation] with the casted argument. -void _unaryNumFunction(Pointer ctx, int argCount, - Pointer> args, num Function(num) calculation) { - // sqlite will ensure that this is only called with one argument - final value = args[0].value; - if (value is num) { - ctx.resultNum(calculation(value)); - } else { - ctx.resultNull(); - } -} - -void _sinImpl(Pointer ctx, int argCount, - Pointer> args) { - _unaryNumFunction(ctx, argCount, args, sin); -} - -void _cosImpl(Pointer ctx, int argCount, - Pointer> args) { - _unaryNumFunction(ctx, argCount, args, cos); -} - -void _tanImpl(Pointer ctx, int argCount, - Pointer> args) { - _unaryNumFunction(ctx, argCount, args, tan); -} - -void _sqrtImpl(Pointer ctx, int argCount, - Pointer> args) { - _unaryNumFunction(ctx, argCount, args, sqrt); -} - -void _asinImpl(Pointer ctx, int argCount, - Pointer> args) { - _unaryNumFunction(ctx, argCount, args, asin); -} - -void _acosImpl(Pointer ctx, int argCount, - Pointer> args) { - _unaryNumFunction(ctx, argCount, args, acos); -} - -void _atanImpl(Pointer ctx, int argCount, - Pointer> args) { - _unaryNumFunction(ctx, argCount, args, atan); -} - -void _regexpImpl(Pointer ctx, int argCount, - Pointer> args) { - var multiLine = false; - var caseSensitive = true; - var unicode = false; - var dotAll = false; - - if (argCount < 2 || argCount > 3) { - ctx.resultError('Expected two or three arguments to regexp'); - return; - } - - final firstParam = args[0].value; - final secondParam = args[1].value; - - if (firstParam == null || secondParam == null) { - ctx.resultNull(); - return; - } - if (firstParam is! String || secondParam is! String) { - ctx.resultError('Expected two strings as parameters to regexp'); - return; - } - - 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].value; - 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 catch (e) { - ctx.resultError('Invalid regex: $e'); - return; - } - - ctx.resultBool(regex.hasMatch(secondParam as String)); -} - -void _containsImpl(Pointer ctx, int argCount, - Pointer> args) { - if (argCount < 2 || argCount > 3) { - ctx.resultError('Expected 2 or 3 arguments to moor_contains'); - return; - } - - final first = args[0].value; - final second = args[1].value; - - if (first is! String || second is! String) { - ctx.resultError('First two args must be strings'); - return; - } - - final caseSensitive = argCount == 3 && args[2].value == 1; - - final firstAsString = first as String; - final secondAsString = second as String; - - final result = caseSensitive - ? firstAsString.contains(secondAsString) - : firstAsString.toLowerCase().contains(secondAsString.toLowerCase()); - - ctx.resultInt(result ? 1 : 0); -} - -void _registerOn(Database db) { - final powImplPointer = - Pointer.fromFunction(_powImpl); - db.createFunction('power', 2, powImplPointer, isDeterministic: true); - db.createFunction('pow', 2, powImplPointer, isDeterministic: true); - - db.createFunction('sqrt', 1, Pointer.fromFunction(_sqrtImpl), - isDeterministic: true); - - db.createFunction('sin', 1, Pointer.fromFunction(_sinImpl), - isDeterministic: true); - db.createFunction('cos', 1, Pointer.fromFunction(_cosImpl), - isDeterministic: true); - db.createFunction('tan', 1, Pointer.fromFunction(_tanImpl), - isDeterministic: true); - db.createFunction('asin', 1, Pointer.fromFunction(_asinImpl), - isDeterministic: true); - db.createFunction('acos', 1, Pointer.fromFunction(_acosImpl), - isDeterministic: true); - db.createFunction('atan', 1, Pointer.fromFunction(_atanImpl), - isDeterministic: true); - - db.createFunction('regexp', 2, Pointer.fromFunction(_regexpImpl), - isDeterministic: true); - // Third argument can be used to set flags (like multiline, case sensitivity, - // etc.) - db.createFunction('regexp_moor_ffi', 3, Pointer.fromFunction(_regexpImpl)); - - final containsImplPointer = - Pointer.fromFunction(_containsImpl); - db.createFunction('moor_contains', 2, containsImplPointer, - isDeterministic: true); - db.createFunction('moor_contains', 3, containsImplPointer, - isDeterministic: true); -} diff --git a/moor_ffi/lib/src/impl/prepared_statement.dart b/moor_ffi/lib/src/impl/prepared_statement.dart deleted file mode 100644 index 54cdfedb..00000000 --- a/moor_ffi/lib/src/impl/prepared_statement.dart +++ /dev/null @@ -1,167 +0,0 @@ -part of 'database.dart'; - -/// A prepared statement that can be executed multiple times. -class PreparedStatement { - final Pointer _stmt; - final Database _db; - bool _closed = false; - - bool _bound = false; - final List _allocatedWhileBinding = []; - - PreparedStatement._(this._stmt, this._db); - - /// Closes this prepared statement and releases its resources. - void close() { - if (!_closed) { - _reset(); - bindings.sqlite3_finalize(_stmt); - _db._handleStmtFinalized(this); - } - _closed = true; - } - - /// Returns the amount of parameters in this prepared statement. - /// - /// See also: - /// - `sqlite3_bind_parameter_count`: https://www.sqlite.org/c3ref/bind_parameter_count.html - int get parameterCount => bindings.sqlite3_bind_parameter_count(_stmt); - - void _ensureNotFinalized() { - if (_closed) { - throw StateError('Tried to operate on a released prepared statement'); - } - } - - /// Executes this prepared statement as a select statement. The returned rows - /// will be returned. - Result select([List params]) { - assert( - (params?.length ?? 0) == parameterCount, - 'Expected $parameterCount params, but got ${params?.length ?? 0}.', - ); - - _ensureNotFinalized(); - _reset(); - _bindParams(params); - - final columnCount = bindings.sqlite3_column_count(_stmt); - // not using a Map for indexed because column names are not - // guaranteed to be unique - final names = List(columnCount); - final rows = >[]; - - for (var i = 0; i < columnCount; i++) { - // name pointer doesn't need to be disposed, that happens when we finalize - names[i] = bindings.sqlite3_column_name(_stmt, i).readString(); - } - - int resultCode; - while ((resultCode = _step()) == Errors.SQLITE_ROW) { - rows.add([for (var i = 0; i < columnCount; i++) _readValue(i)]); - } - - if (resultCode != Errors.SQLITE_OK && resultCode != Errors.SQLITE_DONE) { - throw SqliteException._fromErrorCode(_db._db, resultCode); - } - - return Result(names, rows); - } - - dynamic _readValue(int index) { - final type = bindings.sqlite3_column_type(_stmt, index); - switch (type) { - case Types.SQLITE_INTEGER: - return bindings.sqlite3_column_int64(_stmt, index); - case Types.SQLITE_FLOAT: - return bindings.sqlite3_column_double(_stmt, index); - case Types.SQLITE_TEXT: - final length = bindings.sqlite3_column_bytes(_stmt, index); - return bindings - .sqlite3_column_text(_stmt, index) - .readAsStringWithLength(length); - case Types.SQLITE_BLOB: - final length = bindings.sqlite3_column_bytes(_stmt, index); - if (length == 0) { - // sqlite3_column_blob returns a null pointer for non-null blobs with - // a length of 0. Note that we can distinguish this from a proper null - // by checking the type (which isn't SQLITE_NULL) - return Uint8List(0); - } - return bindings.sqlite3_column_blob(_stmt, index).readBytes(length); - case Types.SQLITE_NULL: - default: - return null; - } - } - - /// Executes this prepared statement. - void execute([List params]) { - _ensureNotFinalized(); - _reset(); - _bindParams(params); - - final result = _step(); - - if (result != Errors.SQLITE_OK && result != Errors.SQLITE_DONE) { - throw SqliteException._fromErrorCode(_db._db, result); - } - } - - void _reset() { - if (_bound) { - bindings.sqlite3_reset(_stmt); - _bound = false; - } - for (final pointer in _allocatedWhileBinding) { - pointer.free(); - } - _allocatedWhileBinding.clear(); - } - - void _bindParams(List params) { - if (params != null && params.isNotEmpty) { - // variables in sqlite are 1-indexed - for (var i = 1; i <= params.length; i++) { - final param = params[i - 1]; - - if (param == null) { - bindings.sqlite3_bind_null(_stmt, i); - } else if (param is int) { - bindings.sqlite3_bind_int64(_stmt, i, param); - } else if (param is num) { - bindings.sqlite3_bind_double(_stmt, i, param.toDouble()); - } else if (param is String) { - final ptr = CBlob.allocateString(param); - _allocatedWhileBinding.add(ptr); - - bindings.sqlite3_bind_text(_stmt, i, ptr, -1, nullPtr()); - } else if (param is Uint8List) { - if (param.isEmpty) { - // malloc(0) is implementation-defined and might return a null - // pointer, which is not what we want: Passing a null-pointer to - // sqlite3_bind_blob will always bind NULL. So, we just pass 0x1 and - // set a length of 0 - bindings.sqlite3_bind_blob( - _stmt, i, Pointer.fromAddress(1), param.length, nullPtr()); - } else { - final ptr = CBlob.allocate(param); - - bindings.sqlite3_bind_blob(_stmt, i, ptr, param.length, nullPtr()); - _allocatedWhileBinding.add(ptr); - } - } else { - throw ArgumentError.value( - param, - 'params[$i]', - 'Allowed parameters must either be null or an int, num, String or ' - 'Uint8List.', - ); - } - } - } - _bound = true; - } - - int _step() => bindings.sqlite3_step(_stmt); -} diff --git a/moor_ffi/lib/src/load_library.dart b/moor_ffi/lib/src/load_library.dart deleted file mode 100644 index b938b079..00000000 --- a/moor_ffi/lib/src/load_library.dart +++ /dev/null @@ -1,131 +0,0 @@ -import 'dart:ffi'; -import 'dart:io'; -import 'dart:math'; - -import 'package:meta/meta.dart'; - -/// Signature responsible for loading the dynamic sqlite3 library that moor will -/// use. -typedef OpenLibrary = DynamicLibrary Function(); - -enum OperatingSystem { - android, - linux, - iOS, - macOS, - windows, - fuchsia, -} - -/// The instance managing different approaches to load the [DynamicLibrary] for -/// sqlite when needed. See the documentation for [OpenDynamicLibrary] to learn -/// how the default opening behavior can be overridden. -final OpenDynamicLibrary open = OpenDynamicLibrary._(); - -DynamicLibrary _defaultOpen() { - if (Platform.isLinux || Platform.isAndroid) { - try { - return DynamicLibrary.open('libsqlite3.so'); - } catch (_) { - if (Platform.isAndroid) { - // On some (especially old) Android devices, we somehow can't dlopen - // libraries shipped with the apk. We need to find the full path of the - // library (/data/data//lib/libsqlite3.so) and open that one. - // For details, see https://github.com/simolus3/moor/issues/420 - final appIdAsBytes = File('/proc/self/cmdline').readAsBytesSync(); - - // app id ends with the first \0 character in here. - final endOfAppId = max(appIdAsBytes.indexOf(0), 0); - final appId = String.fromCharCodes(appIdAsBytes.sublist(0, endOfAppId)); - - return DynamicLibrary.open('/data/data/$appId/lib/libsqlite3.so'); - } - - rethrow; - } - } - if (Platform.isMacOS || Platform.isIOS) { - // todo: Consider including sqlite3 in the build and use DynamicLibrary. - // executable() - return DynamicLibrary.open('/usr/lib/libsqlite3.dylib'); - } - if (Platform.isWindows) { - return DynamicLibrary.open('sqlite3.dll'); - } - - throw UnsupportedError( - 'moor_ffi does not support ${Platform.operatingSystem} yet'); -} - -/// Manages functions that define how to load the [DynamicLibrary] for sqlite. -/// -/// The default behavior will use `DynamicLibrary.open('libsqlite3.so')` on -/// Linux and Android, `DynamicLibrary.open('libsqlite3.dylib')` on iOS and -/// macOS and `DynamicLibrary.open('sqlite3.dll')` on Windows. -/// -/// The default behavior can be overridden for a specific OS by using -/// [overrideFor]. To override the behavior on all platforms, use -/// [overrideForAll]. -class OpenDynamicLibrary { - final Map _overriddenPlatforms = {}; - OpenLibrary _overriddenForAll; - - OpenDynamicLibrary._(); - - /// Returns the current [OperatingSystem] as read from the [Platform] getters. - OperatingSystem get os { - if (Platform.isAndroid) return OperatingSystem.android; - if (Platform.isLinux) return OperatingSystem.linux; - if (Platform.isIOS) return OperatingSystem.iOS; - if (Platform.isMacOS) return OperatingSystem.macOS; - if (Platform.isWindows) return OperatingSystem.windows; - if (Platform.isFuchsia) return OperatingSystem.fuchsia; - return null; - } - - /// Opens the [DynamicLibrary] from which `moor_ffi` is going to - /// [DynamicLibrary.lookup] sqlite's methods that will be used. This method is - /// meant to be called by `moor_ffi` only. - DynamicLibrary openSqlite() { - if (_overriddenForAll != null) { - return _overriddenForAll(); - } - - final forPlatform = _overriddenPlatforms[os]; - if (forPlatform != null) { - return forPlatform(); - } - - return _defaultOpen(); - } - - /// Makes `moor_ffi` use the [open] function when running on the specified - /// [os]. This can be used to override the loading behavior on some platforms. - /// To override that behavior on all platforms, consider using - /// [overrideForAll]. - /// This method must be called before opening any database. - /// - /// When using the asynchronous API over isolates, [open] __must be__ a top- - /// level function or a static method. - void overrideFor(OperatingSystem os, OpenLibrary open) { - _overriddenPlatforms[os] = open; - } - - // ignore: use_setters_to_change_properties - /// Makes `moor_ffi` use the [OpenLibrary] function for all Dart platforms. - /// If this method has been called, it takes precedence over [overrideFor]. - /// This method must be called before opening any database. - /// - /// When using the asynchronous API over isolates, [open] __must be__ a top- - /// level function or a static method. - void overrideForAll(OpenLibrary open) { - _overriddenForAll = open; - } - - /// Clears all associated open helpers for all platforms. - @visibleForTesting - void reset() { - _overriddenForAll = null; - _overriddenPlatforms.clear(); - } -} diff --git a/moor_ffi/lib/src/vm_database.dart b/moor_ffi/lib/src/vm_database.dart deleted file mode 100644 index 63d40346..00000000 --- a/moor_ffi/lib/src/vm_database.dart +++ /dev/null @@ -1,122 +0,0 @@ -part of 'package:moor_ffi/moor_ffi.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 = Database.openFile(file); - } else { - _db = Database.memory(); - } - _db.enableMoorFfiFunctions(); - 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.close(); - } - - 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.close(); - } - } - - @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.getLastInsertId(); - } - - @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.close(); - - return Future.value(QueryResult(result.columnNames, result.rows)); - } - - @override - Future close() async { - _db.close(); - } -} - -class _VmVersionDelegate extends DynamicVersionDelegate { - final Database database; - - _VmVersionDelegate(this.database); - - @override - Future get schemaVersion => Future.value(database.userVersion()); - - @override - Future setSchemaVersion(int version) { - database.setUserVersion(version); - return Future.value(); - } -} diff --git a/moor_ffi/pubspec.yaml b/moor_ffi/pubspec.yaml deleted file mode 100644 index 8b59ae70..00000000 --- a/moor_ffi/pubspec.yaml +++ /dev/null @@ -1,23 +0,0 @@ -name: moor_ffi -description: "Provides sqlite bindings using dart:ffi, including a moor executor" -version: 0.8.0 -homepage: https://github.com/simolus3/moor/tree/develop/moor_ffi -issue_tracker: https://github.com/simolus3/moor/issues - -environment: - sdk: ">=2.6.0 <3.0.0" - flutter: any - -dependencies: - moor: ^3.0.0 - ffi: ^0.1.3 - collection: ^1.0.0 - meta: ^1.0.2 - # moor_ffi used to include sqlite on Flutter builds, so we depend on sqlite3_flutter_libs to continue this behavior. - # This makes moor_ffi a Flutter-only package - not what we want, but now it's deprecated anyways. Non-Flutter users - # should use the `sqlite3` package instead. - sqlite3_flutter_libs: ^0.2.0 - -dev_dependencies: - test: ^1.6.0 - path: ^1.6.0 diff --git a/moor_ffi/test/database/database_test.dart b/moor_ffi/test/database/database_test.dart deleted file mode 100644 index 1c8c4a6e..00000000 --- a/moor_ffi/test/database/database_test.dart +++ /dev/null @@ -1,95 +0,0 @@ -import 'dart:io'; - -import 'package:moor_ffi/database.dart'; -import 'package:path/path.dart'; -import 'package:test/test.dart'; - -void main() { - test("database can't be used after close", () { - final db = Database.memory(); - db.execute('SELECT 1'); - - db.close(); - - expect(() => db.execute('SELECT 1'), throwsA(anything)); - }); - - test('getUpdatedRows', () { - final db = Database.memory(); - - db - ..execute('CREATE TABLE foo (bar INT);') - ..execute('INSERT INTO foo VALUES (3);'); - - expect(db.getUpdatedRows(), 1); - }); - - test('closing multiple times works', () { - final db = Database.memory(); - db.execute('SELECT 1'); - - db.close(); - db.close(); // shouldn't throw or crash - }); - - test('throws exception on an invalid statement', () { - final db = Database.memory(); - db.execute('CREATE TABLE foo (bar INTEGER CHECK (bar > 10));'); - - expect( - () => db.execute('INSERT INTO foo VALUES (3);'), - throwsA(const TypeMatcher().having( - (e) => e.message, 'message', contains('CHECK constraint failed'))), - ); - - db.close(); - }); - - test('throws when preparing an invalid statement', () { - final db = Database.memory(); - - expect( - () => db.prepare('INSERT INTO foo VALUES (3);'), - throwsA(const TypeMatcher() - .having((e) => e.message, 'message', contains('no such table'))), - ); - - db.close(); - }); - - test('open read-only', () async { - final path = join('.dart_tool', 'moor_ffi', 'test', 'read_only.db'); - // Make sure the path exists - try { - await Directory(dirname(path)).create(recursive: true); - } catch (_) {} - // but not the db - try { - await File(path).delete(); - } catch (_) {} - - // Opening a non-existent database should fail - try { - Database.open(path, readOnly: true); - fail('should fail'); - } on SqliteException catch (_) {} - - // Open in read-write mode to create the database - var db = Database.open(path); - // Change the user version to test read-write access - db.setUserVersion(1); - db.close(); - - // Open in read-only - db = Database.open(path, readOnly: true); - // Change the user version to test read-only mode - try { - db.setUserVersion(2); - fail('should fail'); - } on SqliteException catch (_) {} - // Check that it has not changed - expect(db.userVersion(), 1); - - db.close(); - }); -} diff --git a/moor_ffi/test/database/insert_test.dart b/moor_ffi/test/database/insert_test.dart deleted file mode 100644 index 5b5fdafd..00000000 --- a/moor_ffi/test/database/insert_test.dart +++ /dev/null @@ -1,16 +0,0 @@ -import 'package:moor_ffi/database.dart'; -import 'package:test/test.dart'; - -void main() { - test('insert statements report their id', () { - final opened = Database.memory(); - opened.execute('CREATE TABLE tbl(a INTEGER PRIMARY KEY AUTOINCREMENT)'); - - for (var i = 0; i < 5; i++) { - opened.execute('INSERT INTO tbl DEFAULT VALUES'); - expect(opened.getLastInsertId(), i + 1); - } - - opened.close(); - }); -} diff --git a/moor_ffi/test/database/int_test.dart b/moor_ffi/test/database/int_test.dart deleted file mode 100644 index 5530fffa..00000000 --- a/moor_ffi/test/database/int_test.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:moor_ffi/database.dart'; -import 'package:test/test.dart'; - -void main() { - test('can bind and retreive 64 bit ints', () { - const value = 1 << 62; - - final opened = Database.memory(); - final stmt = opened.prepare('SELECT ?'); - - final result = stmt.select([value]); - expect(result, [ - {'?': value} - ]); - - opened.close(); - }); -} diff --git a/moor_ffi/test/database/moor_functions_test.dart b/moor_ffi/test/database/moor_functions_test.dart deleted file mode 100644 index c6c29962..00000000 --- a/moor_ffi/test/database/moor_functions_test.dart +++ /dev/null @@ -1,177 +0,0 @@ -import 'dart:math'; - -import 'package:moor_ffi/database.dart'; -import 'package:test/test.dart'; - -void main() { - Database db; - - setUp(() => db = Database.memory()..enableMoorFfiFunctions()); - tearDown(() => db.close()); - - dynamic selectSingle(String expression) { - final stmt = db.prepare('SELECT $expression AS r;'); - final rows = stmt.select(); - stmt.close(); - - 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.close(); - }); - }); - - 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_ffi/test/database/prepared_statements_test.dart b/moor_ffi/test/database/prepared_statements_test.dart deleted file mode 100644 index 2eed2bc6..00000000 --- a/moor_ffi/test/database/prepared_statements_test.dart +++ /dev/null @@ -1,147 +0,0 @@ -import 'dart:ffi'; -import 'dart:typed_data'; - -import 'package:moor_ffi/database.dart'; -import 'package:test/test.dart'; - -void main() { - test('prepared statements can be used multiple times', () { - final opened = Database.memory(); - opened.execute('CREATE TABLE tbl (a TEXT);'); - - final stmt = opened.prepare('INSERT INTO tbl(a) VALUES(?)'); - stmt.execute(['a']); - stmt.execute(['b']); - stmt.close(); - - final select = opened.prepare('SELECT * FROM tbl ORDER BY a'); - final result = select.select(); - - expect(result, hasLength(2)); - expect(result.map((row) => row['a']), ['a', 'b']); - - select.close(); - - opened.close(); - }); - - test('prepared statements cannot be used after close', () { - final opened = Database.memory(); - - final stmt = opened.prepare('SELECT ?'); - stmt.close(); - - expect(stmt.select, throwsA(anything)); - - opened.close(); - }); - - test('prepared statements cannot be used after db is closed', () { - final opened = Database.memory(); - final stmt = opened.prepare('SELECT 1'); - opened.close(); - - expect(stmt.select, throwsA(anything)); - }); - - Uint8List _insertBlob(Uint8List value) { - final opened = Database.memory(); - opened.execute('CREATE TABLE tbl (x BLOB);'); - - final insert = opened.prepare('INSERT INTO tbl VALUES (?)'); - insert.execute([value]); - insert.close(); - - final select = opened.prepare('SELECT * FROM tbl'); - final result = select.select().single; - - opened.close(); - return result['x'] as Uint8List; - } - - test('can bind empty blob in prepared statements', () { - expect(_insertBlob(Uint8List(0)), isEmpty); - }); - - test('can bind null blob in prepared statements', () { - expect(_insertBlob(null), isNull); - }); - - test('can bind and read non-empty blob', () { - const bytes = [1, 2, 3]; - expect(_insertBlob(Uint8List.fromList(bytes)), bytes); - }); - - test('throws when sql statement has an error', () { - final db = Database.memory(); - db.execute('CREATE TABLE foo (id INTEGER CHECK (id > 10));'); - - final stmt = db.prepare('INSERT INTO foo VALUES (9)'); - - expect( - stmt.execute, - throwsA(const TypeMatcher() - .having((e) => e.message, 'message', contains('foo'))), - ); - - db.close(); - }); - - test('throws an exception when iterating over result rows', () { - final db = Database.memory() - ..createFunction( - 'raise_if_two', - 1, - Pointer.fromFunction(_raiseIfTwo), - ); - - db.execute( - 'CREATE TABLE tbl (a INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT)'); - // insert with a = 1..3 - for (var i = 0; i < 3; i++) { - db.execute('INSERT INTO tbl DEFAULT VALUES'); - } - - final statement = db.prepare('SELECT raise_if_two(a) FROM tbl ORDER BY a'); - - expect( - statement.select, - throwsA(isA() - .having((e) => e.message, 'message', contains('was two'))), - ); - }); - - test('throws an exception when passing an invalid type as argument', () { - final db = Database.memory(); - final stmt = db.prepare('SELECT ?'); - - expect(() => stmt.execute([false]), throwsArgumentError); - db.close(); - }); - - group('asserts that the amount of parameters are correct', () { - final db = Database.memory(); - - test('when no parameters are set', () { - final stmt = db.prepare('SELECT ?'); - expect(stmt.select, throwsA(isA())); - }); - - test('when the wrong amount of parameters are set', () { - final stmt = db.prepare('SELECT ?, ?'); - expect(() => stmt.select([1]), throwsA(isA())); - }); - - tearDownAll(db.close); - }); -} - -void _raiseIfTwo(Pointer ctx, int argCount, - Pointer> args) { - final value = args[0].value; - if (value == 2) { - ctx.resultError('parameter was two'); - } else { - ctx.resultNull(); - } -} diff --git a/moor_ffi/test/database/select_test.dart b/moor_ffi/test/database/select_test.dart deleted file mode 100644 index 2567101d..00000000 --- a/moor_ffi/test/database/select_test.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'package:moor_ffi/database.dart'; -import 'package:test/test.dart'; - -void main() { - test('select statements return expected value', () { - final opened = Database.memory(); - - final prepared = opened.prepare('SELECT ?'); - - final result1 = prepared.select([1]); - expect(result1.columnNames, ['?']); - expect(result1.single.columnAt(0), 1); - - final result2 = prepared.select([2]); - expect(result2.columnNames, ['?']); - expect(result2.single.columnAt(0), 2); - - final result3 = prepared.select(['']); - expect(result3.columnNames, ['?']); - expect(result3.single.columnAt(0), ''); - - opened.close(); - }); -} diff --git a/moor_ffi/test/database/sqlite_exception_test.dart b/moor_ffi/test/database/sqlite_exception_test.dart deleted file mode 100644 index 5009a1d4..00000000 --- a/moor_ffi/test/database/sqlite_exception_test.dart +++ /dev/null @@ -1,125 +0,0 @@ -import 'dart:io'; - -import 'package:moor_ffi/database.dart'; -import 'package:moor_ffi/src/bindings/constants.dart'; -import 'package:path/path.dart'; -import 'package:test/test.dart'; - -void main() { - test('open read-only exception', () async { - final path = - join('.dart_tool', 'moor_ffi', 'test', 'read_only_exception.db'); - // Make sure the path exists - try { - await Directory(dirname(path)).create(recursive: true); - } catch (_) {} - // but not the db - try { - await File(path).delete(); - } catch (_) {} - - // Opening a non-existent database should fail - try { - Database.open(path, readOnly: true); - fail('should fail'); - } on SqliteException catch (e) { - expect(e.extendedResultCode, Errors.SQLITE_CANTOPEN); - expect(e.toString(), startsWith('SqliteException(14): ')); - } - }); - - test('statement exception', () async { - // Only testing some common errors... - final db = Database.memory(); - - // Basic syntax error - try { - db.execute('DUMMY'); - fail('should fail'); - } on SqliteException catch (e) { - expect(e.extendedResultCode, Errors.SQLITE_ERROR); - expect(e.resultCode, Errors.SQLITE_ERROR); - expect(e.toString(), startsWith('SqliteException(1): ')); - } - - // No table - try { - db.execute('SELECT * FROM missing_table'); - fail('should fail'); - } on SqliteException catch (e) { - expect(e.extendedResultCode, Errors.SQLITE_ERROR); - expect(e.resultCode, Errors.SQLITE_ERROR); - } - - // Constraint primary key - db.execute('CREATE TABLE Test (name TEXT PRIMARY KEY)'); - db.execute("INSERT INTO Test(name) VALUES('test1')"); - try { - db.execute("INSERT INTO Test(name) VALUES('test1')"); - fail('should fail'); - } on SqliteException catch (e) { - // SQLITE_CONSTRAINT_PRIMARYKEY (1555) - expect(e.extendedResultCode, 1555); - expect(e.resultCode, Errors.SQLITE_CONSTRAINT); - expect(e.toString(), startsWith('SqliteException(1555): ')); - } - - // Constraint using prepared statement - db.execute('CREATE TABLE Test2 (id PRIMARY KEY, name TEXT UNIQUE)'); - final prepared = db.prepare('INSERT INTO Test2(name) VALUES(?)'); - prepared.execute(['test2']); - try { - prepared.execute(['test2']); - fail('should fail'); - } on SqliteException catch (e) { - // SQLITE_CONSTRAINT_UNIQUE (2067) - expect(e.extendedResultCode, 2067); - expect(e.resultCode, Errors.SQLITE_CONSTRAINT); - } - db.close(); - }); - - test('busy exception', () async { - final path = join('.dart_tool', 'moor_ffi', 'test', 'busy.db'); - // Make sure the path exists - try { - await Directory(dirname(path)).create(recursive: true); - } catch (_) {} - // but not the db - try { - await File(path).delete(); - } catch (_) {} - - final db1 = Database.open(path); - final db2 = Database.open(path); - db1.execute('BEGIN EXCLUSIVE TRANSACTION'); - try { - db2.execute('BEGIN EXCLUSIVE TRANSACTION'); - fail('should fail'); - } on SqliteException catch (e) { - expect(e.extendedResultCode, Errors.SQLITE_BUSY); - expect(e.resultCode, Errors.SQLITE_BUSY); - } - db1.close(); - db2.close(); - }); - - test('invalid format', () async { - final path = join('.dart_tool', 'moor_ffi', 'test', 'invalid_format.db'); - // Make sure the path exists - try { - await Directory(dirname(path)).create(recursive: true); - } catch (_) {} - await File(path).writeAsString('not a database file'); - - final db = Database.open(path); - try { - db.setUserVersion(1); - fail('should fail'); - } on SqliteException catch (e) { - expect(e.extendedResultCode, Errors.SQLITE_NOTADB); - expect(e.resultCode, Errors.SQLITE_NOTADB); - } - db.close(); - }); -} diff --git a/moor_ffi/test/database/user_defined_functions_test.dart b/moor_ffi/test/database/user_defined_functions_test.dart deleted file mode 100644 index c1c594a4..00000000 --- a/moor_ffi/test/database/user_defined_functions_test.dart +++ /dev/null @@ -1,105 +0,0 @@ -import 'dart:ffi'; - -import 'package:moor/moor.dart'; -import 'package:moor_ffi/database.dart'; -import 'package:test/test.dart'; - -final _params = []; - -void _testFunImpl(Pointer ctx, int argCount, - Pointer> args) { - _params.clear(); - for (var i = 0; i < argCount; i++) { - _params.add(args[i].value); - } - - ctx.resultNull(); -} - -void _testNullImpl(Pointer ctx, int argCount, - Pointer> args) { - ctx.resultNull(); -} - -void _testIntImpl(Pointer ctx, int argCount, - Pointer> args) { - ctx.resultInt(420); -} - -void _testDoubleImpl(Pointer ctx, int argCount, - Pointer> args) { - ctx.resultDouble(133.7); -} - -void main() { - test('can read arguments of user defined functions', () { - final db = Database.memory(); - db.createFunction('test_fun', 6, Pointer.fromFunction(_testFunImpl)); - - db.execute( - r'''SELECT test_fun(1, 2.5, 'hello world', X'ff00ff', X'', NULL)'''); - db.close(); - - expect(_params, [ - 1, - 2.5, - 'hello world', - Uint8List.fromList([255, 0, 255]), - Uint8List(0), - null, - ]); - }); - - group('can return', () { - Database db; - - setUp(() => db = Database.memory()); - tearDown(() => db.close()); - - test('null', () { - db.createFunction('test_null', 0, Pointer.fromFunction(_testNullImpl)); - final stmt = db.prepare('SELECT test_null() AS result'); - - expect(stmt.select(), [ - {'result': null} - ]); - }); - - test('integers', () { - db.createFunction('test_int', 0, Pointer.fromFunction(_testIntImpl)); - final stmt = db.prepare('SELECT test_int() AS result'); - - expect(stmt.select(), [ - {'result': 420} - ]); - }); - - test('doubles', () { - db.createFunction( - 'test_double', 0, Pointer.fromFunction(_testDoubleImpl)); - final stmt = db.prepare('SELECT test_double() AS result'); - - expect(stmt.select(), [ - {'result': 133.7} - ]); - }); - }); - - test('throws when using a long function name', () { - final db = Database.memory(); - - expect( - () => db.createFunction('foo' * 100, 10, nullptr), throwsArgumentError); - - db.close(); - }); - - test('throws when using an invalid argument count', () { - final db = Database.memory(); - - expect(() => db.createFunction('foo', -2, nullptr), throwsArgumentError); - expect(() => db.createFunction('foo', 128, nullptr), throwsArgumentError); - - db.close(); - }); -} diff --git a/moor_ffi/test/database/user_version_test.dart b/moor_ffi/test/database/user_version_test.dart deleted file mode 100644 index 8e30618d..00000000 --- a/moor_ffi/test/database/user_version_test.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'dart:io'; - -import 'package:moor_ffi/database.dart'; -import 'package:test/test.dart'; -import 'package:path/path.dart' as p; - -void main() { - test('can set the user version on a database', () { - final file = File(p.join( - Directory.systemTemp.absolute.path, 'moor_ffi_test_user_version.db')); - final opened = Database.openFile(file); - - var version = opened.userVersion(); - expect(version, 0); - - opened.setUserVersion(3); - version = opened.userVersion(); - expect(version, 3); - - // ensure that the version is stored on file - opened.close(); - - final another = Database.openFile(file); - expect(another.userVersion(), 3); - another.close(); - - file.deleteSync(); - }); -} diff --git a/moor_ffi/test/ffi/blob_test.dart b/moor_ffi/test/ffi/blob_test.dart deleted file mode 100644 index 692698b5..00000000 --- a/moor_ffi/test/ffi/blob_test.dart +++ /dev/null @@ -1,22 +0,0 @@ -import 'package:moor/moor.dart'; -import 'package:moor_ffi/src/ffi/blob.dart'; -import 'package:moor_ffi/src/ffi/utils.dart'; -import 'package:test/test.dart'; - -void main() { - test('utf8 store and load test', () { - const content = 'Hasta MaƱana'; - final blob = CBlob.allocateString(content); - - expect(blob.readString(), content); - blob.free(); - }); - - test('blob load and store test', () { - final data = List.generate(256, (x) => x); - final blob = CBlob.allocate(Uint8List.fromList(data)); - - expect(blob.readBytes(256), data); - blob.free(); - }); -} diff --git a/moor_ffi/test/ffi/extended_error_codes_test.dart b/moor_ffi/test/ffi/extended_error_codes_test.dart deleted file mode 100644 index a2438a57..00000000 --- a/moor_ffi/test/ffi/extended_error_codes_test.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'package:moor_ffi/database.dart'; -import 'package:test/test.dart'; - -void main() { - Database database; - - setUp(() => database = Database.memory()); - - tearDown(() => database.close()); - - test('violating constraint throws exception with extended error code', () { - database.execute('CREATE TABLE tbl(a INTEGER NOT NULL)'); - - final statement = database.prepare('INSERT INTO tbl DEFAULT VALUES'); - - expect( - statement.execute, - throwsA( - isA().having( - (e) => e.explanation, 'explanation', endsWith(' (code 1299)')), - ), - ); - }); -} diff --git a/moor_ffi/test/load_library_test.dart b/moor_ffi/test/load_library_test.dart deleted file mode 100644 index a4827bf4..00000000 --- a/moor_ffi/test/load_library_test.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'package:test/test.dart'; -import 'package:moor_ffi/open_helper.dart'; - -void main() { - tearDown(open.reset); - - test('opening behavior can be overridden', () { - var called = false; - open.overrideFor(open.os, () { - called = true; - return null; - }); - - expect(open.openSqlite(), isNull); - expect(called, isTrue); - }); -}