mirror of https://github.com/AMT-Cheif/drift.git
Move ffi bindings into new moor_ffi package
This commit is contained in:
parent
9e498fb575
commit
928c9832b5
|
@ -9,6 +9,10 @@ TODO: Properly describe these additions when they're finalized:
|
|||
- Analyzer plugin for Dart Code
|
||||
- `ffi` libraries
|
||||
|
||||
### Minor changes
|
||||
- a `Constant<String>` can now be written to SQL, it used to throw before. This is useful
|
||||
if you need default values for strings columns.
|
||||
|
||||
### Breaking changes
|
||||
- __THIS LIKELY AFFECTS YOUR APP:__ Removed the `transaction` parameter for callbacks
|
||||
in transactions and `beforeOpen` callbacks. So, instead of writing
|
||||
|
@ -28,7 +32,9 @@ TODO: Properly describe these additions when they're finalized:
|
|||
your database instead of a transaction objects. They will be delegated automatically.
|
||||
|
||||
On a similar note, we also removed the `operateOn` parameter from compiled queries.
|
||||
|
||||
- Compiled queries that return only a single column (e.g. `SELECT COUNT(*) FROM users`)
|
||||
will just return their value (in this case, an `int`) now. Moor no longer generates a
|
||||
new class in that case.
|
||||
- Removed `MigrationStrategy.onFinished`. Use `beforeOpen` instead.
|
||||
- Compiled sql queries starting with an underscore will now generate private match queries.
|
||||
Previously, the query `_allUsers` would generate a `watchAllUsers` method, that has been
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
/// A version of moor that runs on the Dart VM by integrating sqlite3 with
|
||||
/// ffi.
|
||||
@experimental
|
||||
library moor_vm;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
import 'backends.dart';
|
||||
import 'moor.dart';
|
||||
|
||||
import 'src/vm/api/database.dart';
|
||||
|
||||
part 'src/vm/vm_database.dart';
|
|
@ -1,105 +0,0 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:moor/moor.dart';
|
||||
import 'package:pedantic/pedantic.dart';
|
||||
import 'package:test_api/test_api.dart';
|
||||
import 'package:moor/moor_vm.dart';
|
||||
|
||||
import '../data/tables/todos.dart';
|
||||
|
||||
TodoDb db;
|
||||
|
||||
void main() {
|
||||
test('CRUD integration test', () async {
|
||||
db = TodoDb(VMDatabase.memory(logStatements: false));
|
||||
|
||||
// write some dummy data
|
||||
await insertCategory();
|
||||
await insertUser();
|
||||
await insertTodos();
|
||||
|
||||
await db.into(db.sharedTodos).insert(SharedTodo(todo: 2, user: 1));
|
||||
|
||||
// test select statements
|
||||
final forUser = (await db.someDao.todosForUser(1)).single;
|
||||
expect(forUser.title, 'Another entry');
|
||||
|
||||
// test delete statements
|
||||
await db.deleteTodoById(2);
|
||||
final queryAgain = await db.someDao.todosForUser(1);
|
||||
expect(queryAgain, isEmpty);
|
||||
|
||||
// test update statements
|
||||
await (db.update(db.todosTable)..where((t) => t.id.equals(1)))
|
||||
.write(const TodosTableCompanion(content: Value('Updated content')));
|
||||
final readUpdated = await db.select(db.todosTable).getSingle();
|
||||
expect(readUpdated.content, 'Updated content');
|
||||
});
|
||||
|
||||
test('Transactions test', () async {
|
||||
db = TodoDb(VMDatabase.memory(logStatements: false));
|
||||
|
||||
final completedOperations = StreamController<String>();
|
||||
|
||||
unawaited(db.transaction((_) async {
|
||||
await insertCategory();
|
||||
completedOperations.add('transaction');
|
||||
await pumpEventQueue();
|
||||
}));
|
||||
|
||||
unawaited(insertUser().then((_) {
|
||||
completedOperations.add('regular');
|
||||
}));
|
||||
|
||||
await expectLater(
|
||||
completedOperations.stream, emitsInOrder(['transaction', 'regular']));
|
||||
|
||||
// call .getSingle to verify both rows have been written
|
||||
await db.select(db.users).getSingle();
|
||||
await db.select(db.categories).getSingle();
|
||||
});
|
||||
}
|
||||
|
||||
Future insertCategory() async {
|
||||
final forInsert = const CategoriesCompanion(description: Value('Work'));
|
||||
final row = Category(id: 1, description: 'Work');
|
||||
|
||||
final id = await db.into(db.categories).insert(forInsert);
|
||||
expect(id, equals(1));
|
||||
|
||||
final loaded = await db.select(db.categories).getSingle();
|
||||
expect(loaded, equals(row));
|
||||
}
|
||||
|
||||
Future insertUser() async {
|
||||
final profilePic = Uint8List.fromList([1, 2, 3, 4, 5, 6]);
|
||||
final forInsert = UsersCompanion(
|
||||
name: const Value('Dashy McDashface'),
|
||||
isAwesome: const Value(true),
|
||||
profilePicture: Value(profilePic),
|
||||
);
|
||||
|
||||
final id = await db.into(db.users).insert(forInsert);
|
||||
expect(id, equals(1));
|
||||
|
||||
final user = await db.select(db.users).getSingle();
|
||||
expect(user.id, equals(1));
|
||||
expect(user.name, equals('Dashy McDashface'));
|
||||
expect(user.isAwesome, isTrue);
|
||||
expect(user.profilePicture, profilePic);
|
||||
}
|
||||
|
||||
Future insertTodos() async {
|
||||
await db.into(db.todosTable).insertAll([
|
||||
TodosTableCompanion(
|
||||
title: const Value('A first entry'),
|
||||
content: const Value('Some content I guess'),
|
||||
targetDate: Value(DateTime(2019)),
|
||||
),
|
||||
const TodosTableCompanion(
|
||||
title: Value('Another entry'),
|
||||
content: Value('this is a really creative test case'),
|
||||
category: Value(1), // "Work"
|
||||
),
|
||||
]);
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
.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
|
|
@ -0,0 +1,3 @@
|
|||
## 0.0.1
|
||||
|
||||
* TODO: Describe initial release.
|
|
@ -0,0 +1,24 @@
|
|||
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
|
|
@ -0,0 +1,14 @@
|
|||
# moor_ffi
|
||||
|
||||
Moor backend that uses the new `dart:ffi` apis.
|
||||
|
||||
## Supported platforms
|
||||
At the moment, this plugin supports Android natively. However, it's also going to run on all
|
||||
platforms that expose `sqlite3` as a shared native library (macOS and virtually all Linux
|
||||
distros).
|
||||
|
||||
## Notes
|
||||
|
||||
Using `flutter run` or `flutter build` when this library is imported is going to take very long for
|
||||
the first time. The reason is that we compile sqlite. Subsequent builds should take an acceptable
|
||||
time execute.
|
|
@ -0,0 +1,12 @@
|
|||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
|
||||
.externalNativeBuild/
|
||||
cpp/sqlite*
|
||||
sqlite_*.zip
|
|
@ -0,0 +1,67 @@
|
|||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.0'
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id "de.undercouch.download" version "4.0.0"
|
||||
}
|
||||
|
||||
group 'com.example.moor_ffi'
|
||||
version '1.0'
|
||||
|
||||
|
||||
rootProject.allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
cppFlags ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path "cpp/CMakeLists.txt"
|
||||
}
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
disable 'InvalidPackage'
|
||||
}
|
||||
}
|
||||
|
||||
task downloadSqlite(type: Download) {
|
||||
src 'https://sqlite.org/2019/sqlite-amalgamation-3290000.zip'
|
||||
dest 'sqlite_3290000.zip'
|
||||
overwrite false
|
||||
}
|
||||
|
||||
task extractSqlite(dependsOn: downloadSqlite, type: Copy) {
|
||||
from zipTree(downloadSqlite.dest).matching {
|
||||
include '*/sqlite3.c'
|
||||
eachFile { it.setPath(it.getName()) } // Don't use top-level folder in zip
|
||||
}
|
||||
into 'cpp'
|
||||
}
|
||||
|
||||
preBuild.dependsOn extractSqlite
|
|
@ -0,0 +1,4 @@
|
|||
cmake_minimum_required(VERSION 3.4.1)
|
||||
project(sqlite3)
|
||||
|
||||
add_library(sqlite3 SHARED sqlite3.c)
|
|
@ -0,0 +1,2 @@
|
|||
org.gradle.jvmargs=-Xmx1536M
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
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
|
|
@ -0,0 +1 @@
|
|||
rootProject.name = 'moor_ffi'
|
|
@ -0,0 +1,37 @@
|
|||
.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
|
|
@ -0,0 +1,4 @@
|
|||
#import <Flutter/Flutter.h>
|
||||
|
||||
@interface MoorFfiPlugin : NSObject<FlutterPlugin>
|
||||
@end
|
|
@ -0,0 +1,8 @@
|
|||
#import "MoorFfiPlugin.h"
|
||||
#import <moor_ffi/moor_ffi-Swift.h>
|
||||
|
||||
@implementation MoorFfiPlugin
|
||||
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
|
||||
[SwiftMoorFfiPlugin registerWithRegistrar:registrar];
|
||||
}
|
||||
@end
|
|
@ -0,0 +1,14 @@
|
|||
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)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#
|
||||
# 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'
|
||||
|
||||
s.ios.deployment_target = '8.0'
|
||||
end
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:moor/backends.dart';
|
||||
import 'package:moor/moor.dart';
|
||||
import 'package:moor_ffi/src/api/database.dart';
|
||||
|
||||
part 'src/vm_database.dart';
|
|
@ -4,11 +4,11 @@ import 'dart:io';
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:moor/src/vm/bindings/constants.dart';
|
||||
import 'package:moor/src/vm/bindings/types.dart' as types;
|
||||
import 'package:moor/src/vm/bindings/bindings.dart';
|
||||
import 'package:moor/src/vm/ffi/blob.dart';
|
||||
import 'package:moor/src/vm/ffi/utils.dart';
|
||||
import 'package:moor_ffi/src/bindings/constants.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 'prepared_statement.dart';
|
|
@ -3,7 +3,7 @@ import 'dart:ffi';
|
|||
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:moor/src/vm/ffi/utils.dart';
|
||||
import 'package:moor_ffi/src/ffi/utils.dart';
|
||||
|
||||
/// Pointer to arbitrary blobs in C.
|
||||
class CBlob extends Struct<CBlob> {
|
||||
|
@ -33,6 +33,7 @@ class CBlob extends Struct<CBlob> {
|
|||
final str = addressOf;
|
||||
if (isNullPointer(str)) return null;
|
||||
|
||||
// todo can we user Pointer.asExternalTypedData here?
|
||||
final blob = Uint8List(bytesToRead);
|
||||
for (var i = 0; i < bytesToRead; ++i) {
|
||||
blob[i] = str.elementAt(i).load<CBlob>().data;
|
|
@ -1,4 +1,4 @@
|
|||
part of 'package:moor/moor_vm.dart';
|
||||
part of 'package:moor_ffi/moor_ffi.dart';
|
||||
|
||||
/// A moor database that runs on the Dart VM.
|
||||
class VMDatabase extends DelegatedDatabase {
|
|
@ -0,0 +1,25 @@
|
|||
name: moor_ffi
|
||||
description: "Experimental moor implementation that uses dart:ffi"
|
||||
version: 2.0.0-dev
|
||||
author:
|
||||
homepage:
|
||||
|
||||
environment:
|
||||
sdk: ">=2.5.0-dev <2.6.0"
|
||||
|
||||
dependencies:
|
||||
moor: ^2.0.0
|
||||
# flutter:
|
||||
# sdk: flutter
|
||||
|
||||
dev_dependencies:
|
||||
test: ^1.6.0
|
||||
|
||||
#flutter:
|
||||
# plugin:
|
||||
# androidPackage: com.example.moor_ffi
|
||||
# pluginClass: MoorFfiPlugin
|
||||
|
||||
dependency_overrides:
|
||||
moor:
|
||||
path: ../moor
|
Loading…
Reference in New Issue