From 7704c243e2489d511c31b20e6212b36f8872e4f2 Mon Sep 17 00:00:00 2001 From: Alexander Mateo Date: Wed, 21 Sep 2022 14:28:50 -0600 Subject: [PATCH 1/4] sqflite: ^2.1.0 --- .flutter-plugins | 3 +- pubspec.lock | 259 ++++++++++++++++++++++------------------------- pubspec.yaml | 2 +- 3 files changed, 126 insertions(+), 138 deletions(-) diff --git a/.flutter-plugins b/.flutter-plugins index 8b83c95..83cef15 100644 --- a/.flutter-plugins +++ b/.flutter-plugins @@ -1 +1,2 @@ -sqflite=/home/evan/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-1.0.0/ +# This is a generated file; do not edit or check into version control. +sqflite=/home/lex/snap/flutter/common/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-2.1.0/ diff --git a/pubspec.lock b/pubspec.lock index 19b29f8..5c1d789 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,76 +1,104 @@ # Generated by pub -# See https://www.dartlang.org/tools/pub/glossary#lockfile +# See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + url: "https://pub.dartlang.org" + source: hosted + version: "47.0.0" analyzer: dependency: transitive description: name: analyzer url: "https://pub.dartlang.org" source: hosted - version: "0.34.2" + version: "4.7.0" + archive: + dependency: transitive + description: + name: archive + url: "https://pub.dartlang.org" + source: hosted + version: "3.3.0" args: dependency: transitive description: name: args url: "https://pub.dartlang.org" source: hosted - version: "1.5.1" + version: "2.3.1" async: dependency: transitive description: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.9.0" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" - charcode: + version: "2.1.0" + characters: + dependency: transitive + description: + name: characters + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.1" + clock: dependency: transitive description: - name: charcode + name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.1.2" + version: "1.1.1" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.14.11" + version: "1.16.0" convert: dependency: transitive description: name: convert url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "3.0.2" + coverage: + dependency: transitive + description: + name: coverage + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.0" crypto: dependency: transitive description: name: crypto url: "https://pub.dartlang.org" source: hosted - version: "2.0.6" - csslib: + version: "3.0.2" + fake_async: dependency: transitive description: - name: csslib + name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "0.14.6" + version: "1.3.1" file: dependency: transitive description: name: file url: "https://pub.dartlang.org" source: hosted - version: "5.0.7" + version: "6.1.2" flutter: dependency: "direct main" description: flutter @@ -86,13 +114,13 @@ packages: description: flutter source: sdk version: "0.0.0" - front_end: + frontend_server_client: dependency: transitive description: - name: front_end + name: frontend_server_client url: "https://pub.dartlang.org" source: hosted - version: "0.1.9" + version: "2.1.3" fuchsia_remote_debug_protocol: dependency: transitive description: flutter @@ -104,98 +132,70 @@ packages: name: glob url: "https://pub.dartlang.org" source: hosted - version: "1.1.7" - html: - dependency: transitive - description: - name: html - url: "https://pub.dartlang.org" - source: hosted - version: "0.13.3+3" - http: - dependency: transitive - description: - name: http - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.0+1" + version: "2.1.0" http_multi_server: dependency: transitive description: name: http_multi_server url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "3.2.1" http_parser: dependency: transitive description: name: http_parser url: "https://pub.dartlang.org" source: hosted - version: "3.1.3" - intl: - dependency: transitive - description: - name: intl - url: "https://pub.dartlang.org" - source: hosted - version: "0.15.7" + version: "4.0.1" io: dependency: transitive description: name: io url: "https://pub.dartlang.org" source: hosted - version: "0.3.3" + version: "1.0.3" js: dependency: transitive description: name: js url: "https://pub.dartlang.org" source: hosted - version: "0.6.1+1" - json_rpc_2: - dependency: transitive - description: - name: json_rpc_2 - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.9" - kernel: - dependency: transitive - description: - name: kernel - url: "https://pub.dartlang.org" - source: hosted - version: "0.3.9" + version: "0.6.4" logging: dependency: transitive description: name: logging url: "https://pub.dartlang.org" source: hosted - version: "0.11.3+2" + version: "1.0.2" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.3+1" + version: "0.12.12" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.5" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" + version: "1.8.0" mime: dependency: transitive description: name: mime url: "https://pub.dartlang.org" source: hosted - version: "0.9.6+2" + version: "1.0.2" mockito: dependency: "direct dev" description: @@ -203,118 +203,83 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.0.2" - multi_server_socket: - dependency: transitive - description: - name: multi_server_socket - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.2" node_preamble: dependency: transitive description: name: node_preamble url: "https://pub.dartlang.org" source: hosted - version: "1.4.4" + version: "2.0.1" package_config: dependency: transitive description: name: package_config url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" - package_resolver: - dependency: transitive - description: - name: package_resolver - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.6" + version: "2.1.0" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.6.2" - pedantic: - dependency: transitive - description: - name: pedantic - url: "https://pub.dartlang.org" - source: hosted - version: "1.4.0" + version: "1.8.2" platform: dependency: transitive description: name: platform url: "https://pub.dartlang.org" source: hosted - version: "2.2.0" - plugin: - dependency: transitive - description: - name: plugin - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.0+3" + version: "3.1.0" pool: dependency: transitive description: name: pool url: "https://pub.dartlang.org" source: hosted - version: "1.4.0" + version: "1.5.1" process: dependency: transitive description: name: process url: "https://pub.dartlang.org" source: hosted - version: "3.0.9" + version: "4.2.4" pub_semver: dependency: transitive description: name: pub_semver url: "https://pub.dartlang.org" source: hosted - version: "1.4.2" - quiver: - dependency: transitive - description: - name: quiver - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" + version: "2.1.1" shelf: dependency: transitive description: name: shelf url: "https://pub.dartlang.org" source: hosted - version: "0.7.4" + version: "1.4.0" shelf_packages_handler: dependency: transitive description: name: shelf_packages_handler url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "3.0.1" shelf_static: dependency: transitive description: name: shelf_static url: "https://pub.dartlang.org" source: hosted - version: "0.2.8" + version: "1.1.1" shelf_web_socket: dependency: transitive description: name: shelf_web_socket url: "https://pub.dartlang.org" source: hosted - version: "0.2.2+4" + version: "1.0.2" sky_engine: dependency: transitive description: flutter @@ -326,132 +291,154 @@ packages: name: source_map_stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.1.5" + version: "2.1.0" source_maps: dependency: transitive description: name: source_maps url: "https://pub.dartlang.org" source: hosted - version: "0.10.8" + version: "0.10.10" source_span: dependency: transitive description: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.5.3" + version: "1.9.0" sqflite: dependency: "direct main" description: name: sqflite url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "2.1.0" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.0" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.9.3" + version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "1.6.8" + version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "1.1.1" + sync_http: + dependency: transitive + description: + name: sync_http + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.1" synchronized: dependency: transitive description: name: synchronized url: "https://pub.dartlang.org" source: hosted - version: "1.5.3+2" + version: "3.0.0+3" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.1" test: dependency: transitive description: name: test url: "https://pub.dartlang.org" source: hosted - version: "1.5.2" + version: "1.21.4" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.2" + version: "0.4.12" test_core: dependency: transitive description: name: test_core url: "https://pub.dartlang.org" source: hosted - version: "0.2.1" + version: "0.4.16" typed_data: dependency: transitive description: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" - utf: - dependency: transitive - description: - name: utf - url: "https://pub.dartlang.org" - source: hosted - version: "0.9.0+5" + version: "1.3.1" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" - vm_service_client: + version: "2.1.2" + vm_service: dependency: transitive description: - name: vm_service_client + name: vm_service url: "https://pub.dartlang.org" source: hosted - version: "0.2.6" + version: "9.0.0" watcher: dependency: transitive description: name: watcher url: "https://pub.dartlang.org" source: hosted - version: "0.9.7+10" + version: "1.0.1" web_socket_channel: dependency: transitive description: name: web_socket_channel url: "https://pub.dartlang.org" source: hosted - version: "1.0.9" + version: "2.2.0" + webdriver: + dependency: transitive + description: + name: webdriver + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" yaml: dependency: transitive description: name: yaml url: "https://pub.dartlang.org" source: hosted - version: "2.1.15" + version: "3.1.1" sdks: - dart: ">=2.1.0 <3.0.0" + dart: ">=2.18.0-0 <3.0.0" + flutter: ">=3.3.0-0" diff --git a/pubspec.yaml b/pubspec.yaml index bf0ddeb..da03ea4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -10,7 +10,7 @@ environment: dependencies: flutter: sdk: flutter - sqflite: ^1.0.0 + sqflite: ^2.1.0 dev_dependencies: flutter_test: From 98f15538776f3e9081acc37442f30e15bb0eb9c6 Mon Sep 17 00:00:00 2001 From: Alexander Mateo Date: Wed, 9 Aug 2023 13:13:39 -0600 Subject: [PATCH 2/4] sqflite: ^2.2.0 --- .flutter-plugins | 2 +- example.dart | 2 + lib/streamqflite.dart | 118 ++++++------ pubspec.lock | 353 ++++++++++++++++-------------------- pubspec.yaml | 8 +- test/streamqflite_test.dart | 158 ++++++++-------- 6 files changed, 305 insertions(+), 336 deletions(-) diff --git a/.flutter-plugins b/.flutter-plugins index 83cef15..5f8aaae 100644 --- a/.flutter-plugins +++ b/.flutter-plugins @@ -1,2 +1,2 @@ # This is a generated file; do not edit or check into version control. -sqflite=/home/lex/snap/flutter/common/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-2.1.0/ +sqflite=/home/lex/.pub-cache/hosted/pub.dev/sqflite-2.3.0/ diff --git a/example.dart b/example.dart index 8f13db3..ab935b5 100644 --- a/example.dart +++ b/example.dart @@ -1,3 +1,4 @@ +/* // Emits a single row, doesn't emit if the row dosen't exist. Stream singleQuery = streamDb.createQuery("MyTable", where: 'id = ?', whereArgs: [id]) .mapToOne((row) => MyEntry(row)); @@ -22,3 +23,4 @@ var flexibleQuery = streamDb.createQuery("MyTable", where: 'name LIKE ?', whereA // Do something with all the rows. return ...; }); +*/ diff --git a/lib/streamqflite.dart b/lib/streamqflite.dart index ffd5017..93cfecb 100644 --- a/lib/streamqflite.dart +++ b/lib/streamqflite.dart @@ -21,14 +21,14 @@ abstract class StreamDatabaseExecutor { /// Execute an SQL query with no return value. /// No notifications will be sent to queries if [sql] affects the data of the /// table. - Future execute(String sql, [List arguments]) => + Future execute(String sql, [List? arguments]) => _db.execute(sql, arguments); /// Execute an SQL query with no return value. /// A notification to queries for [tables] will be sent after the statement is /// executed. Future executeAndTrigger(Iterable tables, String sql, - [List arguments]) async { + [List? arguments]) async { await _db.execute(sql, arguments); _sendTableTrigger(tables); } @@ -39,7 +39,7 @@ abstract class StreamDatabaseExecutor { /// /// @return The inserted record id. Future rawInsert(Iterable tables, String sql, - [List arguments]) async { + [List? arguments]) async { var rowId = await _db.rawInsert(sql, arguments); if (rowId != -1) { _sendTableTrigger(tables); @@ -52,7 +52,7 @@ abstract class StreamDatabaseExecutor { /// A notification to queries for [table] will be sent after the statement is /// executed. Future insert(String table, Map values, - {String nullColumnHack, ConflictAlgorithm conflictAlgorithm}) async { + {String? nullColumnHack, ConflictAlgorithm? conflictAlgorithm}) async { var rowId = await _db.insert(table, values, conflictAlgorithm: conflictAlgorithm); if (rowId != -1) { @@ -65,7 +65,7 @@ abstract class StreamDatabaseExecutor { /// /// @return A list of rows that were found. Future>> rawQuery(String sql, - [List arguments]) => + [List? arguments]) => _db.rawQuery(sql, arguments); /// Helper to query a table. @@ -97,15 +97,15 @@ abstract class StreamDatabaseExecutor { /// @return The items found. /// Future>> query(String table, - {bool distinct, - List columns, - String where, - List whereArgs, - String groupBy, - String having, - String orderBy, - int limit, - int offset}) { + {bool? distinct, + List? columns, + String? where, + List? whereArgs, + String? groupBy, + String? having, + String? orderBy, + int? limit, + int? offset}) { return _db.query(table, distinct: distinct, columns: columns, @@ -124,7 +124,7 @@ abstract class StreamDatabaseExecutor { /// /// @return a list of rows that were found. Future rawUpdate(Iterable tables, String sql, - [List args]) async { + [List? args]) async { var rows = await _db.rawUpdate(sql, args); if (rows > 0) { _sendTableTrigger(tables); @@ -149,9 +149,9 @@ abstract class StreamDatabaseExecutor { /// A notification to queries for [table] will be sent after the statement is /// executed. Future update(String table, Map values, - {String where, - List whereArgs, - ConflictAlgorithm conflictAlgorithm}) async { + {String? where, + List? whereArgs, + ConflictAlgorithm? conflictAlgorithm}) async { var rows = await _db.update(table, values, where: where, whereArgs: whereArgs, @@ -169,7 +169,7 @@ abstract class StreamDatabaseExecutor { /// /// @return The number of changes made. Future rawDelete(Iterable tables, String sql, - [List args]) async { + [List? args]) async { var rows = await _db.rawDelete(sql, args); if (rows > 0) { _sendTableTrigger(tables); @@ -197,7 +197,7 @@ abstract class StreamDatabaseExecutor { /// otherwise. To remove all rows and get a count pass "1" as the /// whereClause. Future delete(String table, - {String where, List whereArgs}) async { + {String? where, List? whereArgs}) async { var rows = await _db.delete(table, where: where, whereArgs: whereArgs); if (rows > 0) { _sendTableTrigger([table]); @@ -221,10 +221,14 @@ class QueryStream extends Stream { QueryStream(Stream source) : _source = source; @override - StreamSubscription listen(void Function(LazyQuery event) onData, - {Function onError, void Function() onDone, bool cancelOnError}) { - return _source.listen(onData, - onError: onError, onDone: onDone, cancelOnError: cancelOnError); + StreamSubscription listen(void Function(LazyQuery event)? onData, + {Function? onError, void Function()? onDone, bool? cancelOnError}) { + return _source.listen( + onData, + onError: onError, + onDone: onDone, + cancelOnError: cancelOnError + ); } Stream mapToOne(T mapper(Map row)) { @@ -243,7 +247,7 @@ class QueryStream extends Stream { Stream> mapToList(T mapper(Map row)) { return _source.asyncMap((query) => query()).map((rows) { - var result = List(rows.length); + var result = List.filled(rows.length, T as T, growable: false);//List(rows.length); for (int i = 0; i < rows.length; i++) { result[i] = mapper(rows[i]); } @@ -279,7 +283,7 @@ class StreamDatabase extends StreamDatabaseExecutor { /// Calls in action must only be done using the transaction object /// using the database will trigger a dead-lock. Future transaction(Future action(StreamTransaction txn), - {bool exclusive}) async { + {bool? exclusive}) async { var notify = Set(); var result = await _db.transaction( (t) => action(StreamTransaction(t, notify)), @@ -318,15 +322,15 @@ class StreamDatabase extends StreamDatabaseExecutor { /// /// @see [query] QueryStream createQuery(String table, - {bool distinct, - List columns, - String where, - List whereArgs, - String groupBy, - String having, - String orderBy, - int limit, - int offset}) => + {bool? distinct, + List? columns, + String? where, + List? whereArgs, + String? groupBy, + String? having, + String? orderBy, + int? limit, + int? offset}) => _createQuery( [table], () => _db.query(table, @@ -378,7 +382,7 @@ class _StartWith extends StreamTransformerBase { class StreamBatch { final StreamDatabaseExecutor _executor; final Set _notify = Set(); - Batch _batch; + late Batch _batch; StreamBatch(StreamDatabaseExecutor executor) : _executor = executor { _batch = executor._db.batch(); @@ -395,7 +399,7 @@ class StreamBatch { /// be a DatabaseException) /// Future> commit( - {bool exclusive, bool noResult, bool continueOnError}) async { + {bool? exclusive, bool? noResult, bool? continueOnError}) async { final result = await _batch.commit( exclusive: exclusive, noResult: noResult, @@ -406,14 +410,14 @@ class StreamBatch { /// See [StreamDatabase.rawInsert] void rawInsert(Iterable tables, String sql, - [List arguments]) { + [List? arguments]) { _batch.rawInsert(sql, arguments); _notify.addAll(tables); } /// See [StreamDatabase.insert] void insert(String table, Map values, - {String nullColumnHack, ConflictAlgorithm conflictAlgorithm}) { + {String? nullColumnHack, ConflictAlgorithm? conflictAlgorithm}) { _batch.insert(table, values, nullColumnHack: nullColumnHack, conflictAlgorithm: conflictAlgorithm); _notify.add(table); @@ -421,16 +425,16 @@ class StreamBatch { /// See [StreamDatabase.rawUpdate] void rawUpdate(Iterable tables, String sql, - [List arguments]) { + [List? arguments]) { _batch.rawUpdate(sql, arguments); _notify.addAll(tables); } /// See [StreamDatabase.update] void update(String table, Map values, - {String where, - List whereArgs, - ConflictAlgorithm conflictAlgorithm}) { + {String? where, + List? whereArgs, + ConflictAlgorithm? conflictAlgorithm}) { _batch.update(table, values, where: where, whereArgs: whereArgs, @@ -440,40 +444,40 @@ class StreamBatch { /// See [StreamDatabase.rawDelete] void rawDelete(Iterable tables, String sql, - [List arguments]) { + [List? arguments]) { _batch.rawDelete(sql, arguments); _notify.addAll(tables); } /// See [StreamDatabase.delete] - void delete(String table, {String where, List whereArgs}) { + void delete(String table, {String? where, List? whereArgs}) { _batch.delete(table, where: where, whereArgs: whereArgs); _notify.add(table); } /// See [StreamDatabase.execute]; - void execute(String sql, [List arguments]) { + void execute(String sql, [List? arguments]) { _batch.execute(sql, arguments); } /// See [StreamDatabase.executeAndTrigger]; void executeAndTrigger(Iterable tables, String sql, - [List arguments]) { + [List? arguments]) { _batch.execute(sql, arguments); _notify.addAll(tables); } /// See [StreamDatabase.query]; void query(String table, - {bool distinct, - List columns, - String where, - List whereArgs, - String groupBy, - String having, - String orderBy, - int limit, - int offset}) { + {bool? distinct, + List? columns, + String? where, + List? whereArgs, + String? groupBy, + String? having, + String? orderBy, + int? limit, + int? offset}) { _batch.query(table, columns: columns, where: where, @@ -486,7 +490,7 @@ class StreamBatch { } /// See [StreamDatabase.query]; - void rawQuery(String sql, [List arguments]) { + void rawQuery(String sql, [List? arguments]) { _batch.rawQuery(sql, arguments); } } diff --git a/pubspec.lock b/pubspec.lock index 5c1d789..1c4cd8f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,100 +5,146 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - url: "https://pub.dartlang.org" + sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a + url: "https://pub.dev" source: hosted - version: "47.0.0" + version: "61.0.0" analyzer: dependency: transitive description: name: analyzer - url: "https://pub.dartlang.org" + sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562 + url: "https://pub.dev" source: hosted - version: "4.7.0" - archive: - dependency: transitive - description: - name: archive - url: "https://pub.dartlang.org" - source: hosted - version: "3.3.0" + version: "5.13.0" args: dependency: transitive description: name: args - url: "https://pub.dartlang.org" + sha256: b003c3098049a51720352d219b0bb5f219b60fbfb68e7a4748139a06a5676515 + url: "https://pub.dev" source: hosted version: "2.3.1" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" source: hosted - version: "2.9.0" + version: "2.11.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" + build: + dependency: transitive + description: + name: build + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: "598a2a682e2a7a90f08ba39c0aaa9374c5112340f0a2e275f61b59389543d166" + url: "https://pub.dev" + source: hosted + version: "8.6.1" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.3.0" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" source: hosted version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: "4ad01d6e56db961d29661561effde45e519939fdaeb46c351275b182eac70189" + url: "https://pub.dev" + source: hosted + version: "4.5.0" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.1" convert: dependency: transitive description: name: convert - url: "https://pub.dartlang.org" + sha256: "196284f26f69444b7f5c50692b55ec25da86d9e500451dc09333bf2e3ad69259" + url: "https://pub.dev" source: hosted version: "3.0.2" - coverage: - dependency: transitive - description: - name: coverage - url: "https://pub.dartlang.org" - source: hosted - version: "1.5.0" crypto: dependency: transitive description: name: crypto - url: "https://pub.dartlang.org" + sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + url: "https://pub.dev" source: hosted version: "3.0.2" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55" + url: "https://pub.dev" + source: hosted + version: "2.3.2" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" source: hosted version: "1.3.1" file: dependency: transitive description: name: file - url: "https://pub.dartlang.org" + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" + source: hosted + version: "6.1.4" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" source: hosted - version: "6.1.2" + version: "1.1.0" flutter: dependency: "direct main" description: flutter @@ -114,13 +160,6 @@ packages: description: flutter source: sdk version: "0.0.0" - frontend_server_client: - dependency: transitive - description: - name: frontend_server_client - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.3" fuchsia_remote_debug_protocol: dependency: transitive description: flutter @@ -130,315 +169,239 @@ packages: dependency: transitive description: name: glob - url: "https://pub.dartlang.org" + sha256: c51b4fdfee4d281f49b8c957f1add91b815473597f76bcf07377987f66a55729 + url: "https://pub.dev" source: hosted version: "2.1.0" - http_multi_server: - dependency: transitive - description: - name: http_multi_server - url: "https://pub.dartlang.org" - source: hosted - version: "3.2.1" - http_parser: - dependency: transitive - description: - name: http_parser - url: "https://pub.dartlang.org" - source: hosted - version: "4.0.1" - io: - dependency: transitive - description: - name: io - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.3" js: dependency: transitive description: name: js - url: "https://pub.dartlang.org" + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" source: hosted - version: "0.6.4" + version: "0.6.7" logging: dependency: transitive description: name: logging - url: "https://pub.dartlang.org" + sha256: "293ae2d49fd79d4c04944c3a26dfd313382d5f52e821ec57119230ae16031ad4" + url: "https://pub.dev" source: hosted version: "1.0.2" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + url: "https://pub.dev" source: hosted - version: "0.12.12" + version: "0.12.15" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" source: hosted - version: "0.1.5" + version: "0.2.0" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" source: hosted - version: "1.8.0" - mime: - dependency: transitive - description: - name: mime - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.2" + version: "1.9.1" mockito: dependency: "direct dev" description: name: mockito - url: "https://pub.dartlang.org" + sha256: "7d5b53bcd556c1bc7ffbe4e4d5a19c3e112b7e925e9e172dd7c6ad0630812616" + url: "https://pub.dev" source: hosted - version: "3.0.2" - node_preamble: - dependency: transitive - description: - name: node_preamble - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" + version: "5.4.2" package_config: dependency: transitive description: name: package_config - url: "https://pub.dartlang.org" + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" source: hosted version: "2.1.0" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" source: hosted - version: "1.8.2" + version: "1.8.3" platform: dependency: transitive description: name: platform - url: "https://pub.dartlang.org" + sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + url: "https://pub.dev" source: hosted version: "3.1.0" - pool: - dependency: transitive - description: - name: pool - url: "https://pub.dartlang.org" - source: hosted - version: "1.5.1" process: dependency: transitive description: name: process - url: "https://pub.dartlang.org" + sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + url: "https://pub.dev" source: hosted version: "4.2.4" pub_semver: dependency: transitive description: name: pub_semver - url: "https://pub.dartlang.org" + sha256: "816c1a640e952d213ddd223b3e7aafae08cd9f8e1f6864eed304cc13b0272b07" + url: "https://pub.dev" source: hosted version: "2.1.1" - shelf: - dependency: transitive - description: - name: shelf - url: "https://pub.dartlang.org" - source: hosted - version: "1.4.0" - shelf_packages_handler: - dependency: transitive - description: - name: shelf_packages_handler - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.1" - shelf_static: - dependency: transitive - description: - name: shelf_static - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.1" - shelf_web_socket: - dependency: transitive - description: - name: shelf_web_socket - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.2" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.99" - source_map_stack_trace: - dependency: transitive - description: - name: source_map_stack_trace - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - source_maps: + source_gen: dependency: transitive description: - name: source_maps - url: "https://pub.dartlang.org" + name: source_gen + sha256: fc0da689e5302edb6177fdd964efcb7f58912f43c28c2047a808f5bfff643d16 + url: "https://pub.dev" source: hosted - version: "0.10.10" + version: "1.4.0" source_span: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" sqflite: dependency: "direct main" description: name: sqflite - url: "https://pub.dartlang.org" + sha256: "591f1602816e9c31377d5f008c2d9ef7b8aca8941c3f89cc5fd9d84da0c38a9a" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.3.0" sqflite_common: dependency: transitive description: name: sqflite_common - url: "https://pub.dartlang.org" + sha256: "1b92f368f44b0dee2425bb861cfa17b6f6cf3961f762ff6f941d20b33355660a" + url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.5.0" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.2.0" sync_http: dependency: transitive description: name: sync_http - url: "https://pub.dartlang.org" + sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" + url: "https://pub.dev" source: hosted version: "0.3.1" synchronized: dependency: transitive description: name: synchronized - url: "https://pub.dartlang.org" + sha256: "7b530acd9cb7c71b0019a1e7fa22c4105e675557a4400b6a401c71c5e0ade1ac" + url: "https://pub.dev" source: hosted version: "3.0.0+3" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted version: "1.2.1" - test: - dependency: transitive - description: - name: test - url: "https://pub.dartlang.org" - source: hosted - version: "1.21.4" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + url: "https://pub.dev" source: hosted - version: "0.4.12" - test_core: - dependency: transitive - description: - name: test_core - url: "https://pub.dartlang.org" - source: hosted - version: "0.4.16" + version: "0.5.1" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + url: "https://pub.dev" source: hosted version: "1.3.1" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" vm_service: dependency: transitive description: name: vm_service - url: "https://pub.dartlang.org" + sha256: f6deed8ed625c52864792459709183da231ebf66ff0cf09e69b573227c377efe + url: "https://pub.dev" source: hosted - version: "9.0.0" + version: "11.3.0" watcher: dependency: transitive description: name: watcher - url: "https://pub.dartlang.org" + sha256: e42dfcc48f67618344da967b10f62de57e04bae01d9d3af4c2596f3712a88c99 + url: "https://pub.dev" source: hosted version: "1.0.1" - web_socket_channel: - dependency: transitive - description: - name: web_socket_channel - url: "https://pub.dartlang.org" - source: hosted - version: "2.2.0" webdriver: dependency: transitive description: name: webdriver - url: "https://pub.dartlang.org" + sha256: "3c923e918918feeb90c4c9fdf1fe39220fa4c0e8e2c0fffaded174498ef86c49" + url: "https://pub.dev" source: hosted - version: "3.0.0" - webkit_inspection_protocol: - dependency: transitive - description: - name: webkit_inspection_protocol - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" + version: "3.0.2" yaml: dependency: transitive description: name: yaml - url: "https://pub.dartlang.org" + sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" + url: "https://pub.dev" source: hosted version: "3.1.1" sdks: - dart: ">=2.18.0-0 <3.0.0" - flutter: ">=3.3.0-0" + dart: ">=3.0.0 <4.0.0" + flutter: ">=3.3.0" diff --git a/pubspec.yaml b/pubspec.yaml index da03ea4..c485a36 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,23 +1,23 @@ name: streamqflite description: reactive stream wrapper around sqflite inspired by sqlbrite -version: 1.0.0 +version: 2.2.0 author: Evan Tatarka homepage: https://github.com/evant/streamqflite environment: - sdk: ">=2.0.0-dev.61.0 <3.0.0" + sdk: '>=3.0.0 <4.0.0' dependencies: flutter: sdk: flutter - sqflite: ^2.1.0 + sqflite: ^2.3.0 dev_dependencies: flutter_test: sdk: flutter flutter_driver: sdk: flutter - mockito: ^3.0.1 + mockito: ^5.4.2 # For information on the generic Dart part of this file, see the # following page: https://www.dartlang.org/tools/pub/pubspec diff --git a/test/streamqflite_test.dart b/test/streamqflite_test.dart index d4ef187..a9f877e 100644 --- a/test/streamqflite_test.dart +++ b/test/streamqflite_test.dart @@ -7,17 +7,17 @@ import 'package:streamqflite/streamqflite.dart'; import "package:flutter_test/flutter_test.dart"; void main() { - Database db; - StreamDatabase streamDb; + Database? db; + StreamDatabase? streamDb; setUp(() { db = MockDatabase(); - streamDb = StreamDatabase(db); + streamDb = StreamDatabase(db!); }); group("createQuery", () { test("delegates to db query", () async { - final stream = streamDb.createQuery( + final stream = streamDb!.createQuery( "Table", distinct: true, columns: ["column"], @@ -30,7 +30,7 @@ void main() { offset: 1, ); (await stream.first)(); - verify(db.query( + verify(db!.query( "Table", distinct: true, columns: ["column"], @@ -45,138 +45,138 @@ void main() { }); test("triggers intial query", () async { - final stream = streamDb.createQuery("Table"); + final stream = streamDb!.createQuery("Table"); expect(stream, emitsInOrder([anything])); }); test("triggers query again on insert", () async { - when(db.insert("Table", {})) + when(db!.insert("Table", {})) .thenAnswer((_) => Future.value(0)); - final stream = streamDb.createQuery("Table"); - await streamDb.insert("Table", {}); + final stream = streamDb!.createQuery("Table"); + await streamDb!.insert("Table", {}); expect(stream, emitsInOrder([anything, anything])); }); test("triggers query again on rawInsert", () async { - when(db.insert("Table", {})) + when(db!.insert("Table", {})) .thenAnswer((_) => Future.value(0)); - final stream = streamDb.createQuery("Table"); - await streamDb.rawInsert(["Table"], ""); + final stream = streamDb!.createQuery("Table"); + await streamDb!.rawInsert(["Table"], ""); expect(stream, emitsInOrder([anything, anything])); }); test("triggers query again on delete", () async { - when(db.delete("Table")).thenAnswer((_) => Future.value(1)); - final stream = streamDb.createQuery("Table"); - await streamDb.delete("Table"); + when(db!.delete("Table")).thenAnswer((_) => Future.value(1)); + final stream = streamDb!.createQuery("Table"); + await streamDb!.delete("Table"); expect(stream, emitsInOrder([anything, anything])); }); test("triggers query again on rawDelete", () async { - when(db.rawDelete("")).thenAnswer((_) => Future.value(1)); - final stream = streamDb.createQuery("Table"); - await streamDb.rawDelete(["Table"], ""); + when(db!.rawDelete("")).thenAnswer((_) => Future.value(1)); + final stream = streamDb!.createQuery("Table"); + await streamDb!.rawDelete(["Table"], ""); expect(stream, emitsInOrder([anything, anything])); }); test("triggers query again on update", () async { - when(db.update("Table", {})) + when(db!.update("Table", {})) .thenAnswer((_) => Future.value(1)); - final stream = streamDb.createQuery("Table"); - await streamDb.update("Table", {}); + final stream = streamDb!.createQuery("Table"); + await streamDb!.update("Table", {}); expect(stream, emitsInOrder([anything, anything])); }); test("triggers query again on rawUpdate", () async { - when(db.rawUpdate("")).thenAnswer((_) => Future.value(1)); - final stream = streamDb.createQuery("Table"); - await streamDb.rawUpdate(["Table"], ""); + when(db!.rawUpdate("")).thenAnswer((_) => Future.value(1)); + final stream = streamDb!.createQuery("Table"); + await streamDb!.rawUpdate(["Table"], ""); expect(stream, emitsInOrder([anything, anything])); }); test("triggers query again on executeAndTrigger", () async { - when(db.execute("")).thenAnswer((_) => Future.value(0)); - final stream = streamDb.createQuery("Table"); - await streamDb.executeAndTrigger(["Table"], ""); + when(db!.execute("")).thenAnswer((_) => Future.value(0)); + final stream = streamDb!.createQuery("Table"); + await streamDb!.executeAndTrigger(["Table"], ""); expect(stream, emitsInOrder([anything, anything])); }); }); group("createRawQuery", () { test("delegates to db rawQuery", () async { - final stream = streamDb.createRawQuery( + final stream = streamDb!.createRawQuery( ["Table"], "sql", ["whereArg"], ); (await stream.first)(); - verify(db.rawQuery( + verify(db!.rawQuery( "sql", ["whereArg"], )); }); test("triggers intial query", () async { - final stream = streamDb.createRawQuery(["Table"], ""); + final stream = streamDb!.createRawQuery(["Table"], ""); expect(stream, emitsInOrder([anything])); }); test("triggers query again on insert", () async { - when(db.insert("Table", {})) + when(db!.insert("Table", {})) .thenAnswer((_) => Future.value(0)); - final stream = streamDb.createRawQuery(["Table"], ""); - await streamDb.insert("Table", {}); + final stream = streamDb!.createRawQuery(["Table"], ""); + await streamDb!.insert("Table", {}); expect(stream, emitsInOrder([anything, anything])); }); test("triggers query again on rawInsert", () async { - when(db.insert("Table", {})) + when(db!.insert("Table", {})) .thenAnswer((_) => Future.value(0)); - final stream = streamDb.createRawQuery(["Table"], ""); - await streamDb.rawInsert(["Table"], ""); + final stream = streamDb!.createRawQuery(["Table"], ""); + await streamDb!.rawInsert(["Table"], ""); expect(stream, emitsInOrder([anything, anything])); }); test("triggers query again on delete", () async { - when(db.delete("Table")).thenAnswer((_) => Future.value(1)); - final stream = streamDb.createRawQuery(["Table"], ""); - await streamDb.delete("Table"); + when(db!.delete("Table")).thenAnswer((_) => Future.value(1)); + final stream = streamDb!.createRawQuery(["Table"], ""); + await streamDb!.delete("Table"); expect(stream, emitsInOrder([anything, anything])); }); test("triggers query again on rawDelete", () async { - when(db.rawDelete("")).thenAnswer((_) => Future.value(1)); - final stream = streamDb.createRawQuery(["Table"], ""); - await streamDb.rawDelete(["Table"], ""); + when(db!.rawDelete("")).thenAnswer((_) => Future.value(1)); + final stream = streamDb!.createRawQuery(["Table"], ""); + await streamDb!.rawDelete(["Table"], ""); expect(stream, emitsInOrder([anything, anything])); }); test("triggers query again on update", () async { - when(db.update("Table", {})) + when(db!.update("Table", {})) .thenAnswer((_) => Future.value(1)); - final stream = streamDb.createRawQuery(["Table"], ""); - await streamDb.update("Table", {}); + final stream = streamDb!.createRawQuery(["Table"], ""); + await streamDb!.update("Table", {}); expect(stream, emitsInOrder([anything, anything])); }); test("triggers query again on rawUpdate", () async { - when(db.rawUpdate("")).thenAnswer((_) => Future.value(1)); - final stream = streamDb.createRawQuery(["Table"], ""); - await streamDb.rawUpdate(["Table"], ""); + when(db!.rawUpdate("")).thenAnswer((_) => Future.value(1)); + final stream = streamDb!.createRawQuery(["Table"], ""); + await streamDb!.rawUpdate(["Table"], ""); expect(stream, emitsInOrder([anything, anything])); }); test("triggers query again on executeAndTrigger", () async { - when(db.execute("")).thenAnswer((_) => Future.value(0)); - final stream = streamDb.createRawQuery(["Table"], ""); - await streamDb.executeAndTrigger(["Table"], ""); + when(db!.execute("")).thenAnswer((_) => Future.value(0)); + final stream = streamDb!.createRawQuery(["Table"], ""); + await streamDb!.executeAndTrigger(["Table"], ""); expect(stream, emitsInOrder([anything, anything])); }); }); group("query", () { test("delegates to db query", () async { - await streamDb.query( + await streamDb!.query( "Table", distinct: true, columns: ["column"], @@ -188,7 +188,7 @@ void main() { limit: 1, offset: 1, ); - verify(db.query( + verify(db!.query( "Table", distinct: true, columns: ["column"], @@ -205,11 +205,11 @@ void main() { group("rawQuery", () { test("delegates to db rawQuery", () async { - await streamDb.rawQuery( + await streamDb!.rawQuery( "sql", ["whereArg"], ); - verify(db.rawQuery( + verify(db!.rawQuery( "sql", ["whereArg"], )); @@ -218,23 +218,23 @@ void main() { group("insert", () { test("delegates to db insert", () async { - await streamDb.insert("Table", {}, + await streamDb!.insert("Table", {}, conflictAlgorithm: ConflictAlgorithm.fail); - verify(db.insert("Table", {}, + verify(db!.insert("Table", {}, conflictAlgorithm: ConflictAlgorithm.fail)); }); }); group("rawInsert", () { test("delegates to db rawInsert", () async { - await streamDb.rawInsert(["Table"], "sql", ["arg"]); - verify(db.rawInsert("sql", ["arg"])); + await streamDb!.rawInsert(["Table"], "sql", ["arg"]); + verify(db!.rawInsert("sql", ["arg"])); }); }); group("delete", () { test("delegates to db delete", () async { - when(db.delete( + when(db!.delete( // ignore: argument_type_not_assignable any, // ignore: argument_type_not_assignable @@ -242,28 +242,28 @@ void main() { // ignore: argument_type_not_assignable whereArgs: anyNamed("whereArgs"))) .thenAnswer((_) => Future.value(1)); - await streamDb.delete("Table", where: "where", whereArgs: ["whereArg"]); + await streamDb!.delete("Table", where: "where", whereArgs: ["whereArg"]); verify( - db.delete("Table", where: "where", whereArgs: ["whereArg"])); + db!.delete("Table", where: "where", whereArgs: ["whereArg"])); }); }); group("rawDelete", () { test("delegates to db rawDelete", () async { - when(db.rawDelete( + when(db!.rawDelete( // ignore: argument_type_not_assignable any, // ignore: argument_type_not_assignable any)) .thenAnswer((_) => Future.value(1)); - await streamDb.rawDelete(["Table"], "sql", ["arg"]); - verify(db.rawDelete("sql", ["arg"])); + await streamDb!.rawDelete(["Table"], "sql", ["arg"]); + verify(db!.rawDelete("sql", ["arg"])); }); }); group("update", () { test("delegates to db update", () async { - when(db.update( + when(db!.update( // ignore: argument_type_not_assignable any, // ignore: argument_type_not_assignable @@ -275,11 +275,11 @@ void main() { // ignore: argument_type_not_assignable conflictAlgorithm: anyNamed("conflictAlgorithm"))) .thenAnswer((_) => Future.value(1)); - await streamDb.update("Table", {}, + await streamDb!.update("Table", {}, where: "where", whereArgs: ["whereArg"], conflictAlgorithm: ConflictAlgorithm.fail); - verify(db.update("Table", {}, + verify(db!.update("Table", {}, where: "where", whereArgs: ["whereArg"], conflictAlgorithm: ConflictAlgorithm.fail)); @@ -288,21 +288,21 @@ void main() { group("rawUpdate", () { test("delegates to db rawUpdate", () async { - when(db.rawUpdate( + when(db!.rawUpdate( // ignore: argument_type_not_assignable any, // ignore: argument_type_not_assignable any)) .thenAnswer((_) => Future.value(1)); - await streamDb.rawUpdate(["Table"], "sql", ["arg"]); - verify(db.rawUpdate("sql", ["arg"])); + await streamDb!.rawUpdate(["Table"], "sql", ["arg"]); + verify(db!.rawUpdate("sql", ["arg"])); }); }); group("execute", () { test("delegates to db execute", () async { - await streamDb.execute("sql", ["arg"]); - verify(db.execute("sql", ["arg"])); + await streamDb!.execute("sql", ["arg"]); + verify(db!.execute("sql", ["arg"])); }); }); @@ -311,7 +311,7 @@ void main() { final transaction = MockTransaction(); when(transaction.insert("Table", {})) .thenAnswer((_) => Future.value(0)); - when(db.transaction( + when(db!.transaction( // ignore: argument_type_not_assignable any, // ignore: argument_type_not_assignable @@ -321,8 +321,8 @@ void main() { Future result = f(transaction) as Future; return result; }); - final stream = streamDb.createQuery("Table"); - await streamDb.transaction((transaction) { + final stream = streamDb!.createQuery("Table"); + await streamDb!.transaction((transaction) { return transaction.insert("Table", {}); }); expect(stream, emitsInOrder([anything, anything])); @@ -334,9 +334,9 @@ void main() { final batch = MockBatch(); when(batch.insert("Table", {})) .thenAnswer((_) => Future.value(0)); - when(db.batch()).thenAnswer((_) => batch); - final stream = streamDb.createQuery("Table"); - final streamBatch = streamDb.batch(); + when(db!.batch()).thenAnswer((_) => batch); + final stream = streamDb!.createQuery("Table"); + final streamBatch = streamDb!.batch(); streamBatch.insert("Table", {}); await streamBatch.commit(); From 8bdff53518b31917f46230d957905d1ec4a05816 Mon Sep 17 00:00:00 2001 From: Alexander Mateo Date: Wed, 9 Aug 2023 19:47:53 -0600 Subject: [PATCH 3/4] sqflite: ^2.2.2 --- lib/streamqflite.dart | 95 ++++---- lib/streamqflite2.dart | 498 +++++++++++++++++++++++++++++++++++++++++ pubspec.yaml | 2 +- 3 files changed, 545 insertions(+), 50 deletions(-) create mode 100644 lib/streamqflite2.dart diff --git a/lib/streamqflite.dart b/lib/streamqflite.dart index 93cfecb..ab3b577 100644 --- a/lib/streamqflite.dart +++ b/lib/streamqflite.dart @@ -54,7 +54,7 @@ abstract class StreamDatabaseExecutor { Future insert(String table, Map values, {String? nullColumnHack, ConflictAlgorithm? conflictAlgorithm}) async { var rowId = - await _db.insert(table, values, conflictAlgorithm: conflictAlgorithm); + await _db.insert(table, values, conflictAlgorithm: conflictAlgorithm); if (rowId != -1) { _sendTableTrigger([table]); } @@ -65,7 +65,7 @@ abstract class StreamDatabaseExecutor { /// /// @return A list of rows that were found. Future>> rawQuery(String sql, - [List? arguments]) => + [List? arguments]) => _db.rawQuery(sql, arguments); /// Helper to query a table. @@ -98,14 +98,14 @@ abstract class StreamDatabaseExecutor { /// Future>> query(String table, {bool? distinct, - List? columns, - String? where, - List? whereArgs, - String? groupBy, - String? having, - String? orderBy, - int? limit, - int? offset}) { + List? columns, + String? where, + List? whereArgs, + String? groupBy, + String? having, + String? orderBy, + int? limit, + int? offset}) { return _db.query(table, distinct: distinct, columns: columns, @@ -150,8 +150,8 @@ abstract class StreamDatabaseExecutor { /// executed. Future update(String table, Map values, {String? where, - List? whereArgs, - ConflictAlgorithm? conflictAlgorithm}) async { + List? whereArgs, + ConflictAlgorithm? conflictAlgorithm}) async { var rows = await _db.update(table, values, where: where, whereArgs: whereArgs, @@ -223,12 +223,8 @@ class QueryStream extends Stream { @override StreamSubscription listen(void Function(LazyQuery event)? onData, {Function? onError, void Function()? onDone, bool? cancelOnError}) { - return _source.listen( - onData, - onError: onError, - onDone: onDone, - cancelOnError: cancelOnError - ); + return _source.listen(onData, + onError: onError, onDone: onDone, cancelOnError: cancelOnError); } Stream mapToOne(T mapper(Map row)) { @@ -247,7 +243,8 @@ class QueryStream extends Stream { Stream> mapToList(T mapper(Map row)) { return _source.asyncMap((query) => query()).map((rows) { - var result = List.filled(rows.length, T as T, growable: false);//List(rows.length); + //var result = List(rows.length); + List result = []; for (int i = 0; i < rows.length; i++) { result[i] = mapper(rows[i]); } @@ -286,7 +283,7 @@ class StreamDatabase extends StreamDatabaseExecutor { {bool? exclusive}) async { var notify = Set(); var result = await _db.transaction( - (t) => action(StreamTransaction(t, notify)), + (t) => action(StreamTransaction(t, notify)), exclusive: exclusive); _sendTableTrigger(notify); return result; @@ -311,7 +308,7 @@ class StreamDatabase extends StreamDatabaseExecutor { /// /// @see [rawQuery] QueryStream createRawQuery(Iterable tables, String sql, - [List arguments = const []]) => + [List arguments = const []]) => _createQuery(tables, () => _db.rawQuery(sql, arguments)); /// Creates a [Stream] that will notify listeners with a [LazyQuery] for @@ -322,18 +319,18 @@ class StreamDatabase extends StreamDatabaseExecutor { /// /// @see [query] QueryStream createQuery(String table, - {bool? distinct, - List? columns, - String? where, - List? whereArgs, - String? groupBy, - String? having, - String? orderBy, - int? limit, - int? offset}) => + {bool? distinct, + List? columns, + String? where, + List? whereArgs, + String? groupBy, + String? having, + String? orderBy, + int? limit, + int? offset}) => _createQuery( [table], - () => _db.query(table, + () => _db.query(table, distinct: distinct, columns: columns, where: where, @@ -347,13 +344,13 @@ class StreamDatabase extends StreamDatabaseExecutor { QueryStream _createQuery(Iterable tables, LazyQuery query) { return QueryStream(triggers.stream .where((strings) { - for (var table in tables) { - if (strings.contains(table)) { - return true; - } - } - return false; - }) + for (var table in tables) { + if (strings.contains(table)) { + return true; + } + } + return false; + }) .map((strings) => query) .transform(_StartWith(query))); } @@ -433,8 +430,8 @@ class StreamBatch { /// See [StreamDatabase.update] void update(String table, Map values, {String? where, - List? whereArgs, - ConflictAlgorithm? conflictAlgorithm}) { + List? whereArgs, + ConflictAlgorithm? conflictAlgorithm}) { _batch.update(table, values, where: where, whereArgs: whereArgs, @@ -470,14 +467,14 @@ class StreamBatch { /// See [StreamDatabase.query]; void query(String table, {bool? distinct, - List? columns, - String? where, - List? whereArgs, - String? groupBy, - String? having, - String? orderBy, - int? limit, - int? offset}) { + List? columns, + String? where, + List? whereArgs, + String? groupBy, + String? having, + String? orderBy, + int? limit, + int? offset}) { _batch.query(table, columns: columns, where: where, @@ -493,4 +490,4 @@ class StreamBatch { void rawQuery(String sql, [List? arguments]) { _batch.rawQuery(sql, arguments); } -} +} \ No newline at end of file diff --git a/lib/streamqflite2.dart b/lib/streamqflite2.dart new file mode 100644 index 0000000..6bac6ea --- /dev/null +++ b/lib/streamqflite2.dart @@ -0,0 +1,498 @@ +/* +library sqlflight; + +import 'dart:async'; + +import 'package:sqflite/sqflite.dart'; + +/// Represents a query to be executed, invoking it will actually execute the +/// query and returns a [Future] of the result. +typedef Future>> LazyQuery(); + +/// +/// Common API for [StreamDatabase] and [StreamTransaction] to execute SQL commands +/// +abstract class StreamDatabaseExecutor { + final DatabaseExecutor _db; + + StreamDatabaseExecutor(DatabaseExecutor db) : _db = db; + + void _sendTableTrigger(Iterable tables); + + /// Execute an SQL query with no return value. + /// No notifications will be sent to queries if [sql] affects the data of the + /// table. + Future execute(String sql, [List? arguments]) => + _db.execute(sql, arguments); + + /// Execute an SQL query with no return value. + /// A notification to queries for [tables] will be sent after the statement is + /// executed. + Future executeAndTrigger(Iterable tables, String sql, + [List? arguments]) async { + await _db.execute(sql, arguments); + _sendTableTrigger(tables); + } + + /// Execute a raw SQL INSERT query + /// A notification to queries for [tables] will be sent after the statement is + /// executed. + /// + /// @return The inserted record id. + Future rawInsert(Iterable tables, String sql, + [List? arguments]) async { + var rowId = await _db.rawInsert(sql, arguments); + if (rowId != -1) { + _sendTableTrigger(tables); + } + return rowId; + } + + /// Insert a row into a table, where the keys of [values] correspond to + /// column names. + /// A notification to queries for [table] will be sent after the statement is + /// executed. + Future insert(String table, Map values, + {String? nullColumnHack, ConflictAlgorithm? conflictAlgorithm}) async { + var rowId = + await _db.insert(table, values, conflictAlgorithm: conflictAlgorithm); + if (rowId != -1) { + _sendTableTrigger([table]); + } + return rowId; + } + + /// Execute a raw SQL SELECT query. + /// + /// @return A list of rows that were found. + Future>> rawQuery(String sql, + [List? arguments]) => + _db.rawQuery(sql, arguments); + + /// Helper to query a table. + /// + /// @param distinct true if you want each row to be unique, false otherwise. + /// @param table The table names to compile the query against. + /// @param columns A list of which columns to return. Passing null will + /// + /// + /// return all columns, which is discouraged to prevent reading + /// data from storage that isn't going to be used. + /// @param where A filter declaring which rows to return, formatted as an SQL + /// WHERE clause (excluding the WHERE itself). Passing null will + /// return all rows for the given URL. + /// @param groupBy A filter declaring how to group rows, formatted as an SQL + /// GROUP BY clause (excluding the GROUP BY itself). Passing null + /// will cause the rows to not be grouped. + /// @param having A filter declare which row groups to include in the cursor, + /// if row grouping is being used, formatted as an SQL HAVING + /// clause (excluding the HAVING itself). Passing null will cause + /// all row groups to be included, and is required when row + /// grouping is not being used. + /// @param orderBy How to order the rows, formatted as an SQL ORDER BY clause + /// (excluding the ORDER BY itself). Passing null will use the + /// default sort order, which may be unordered. + /// @param limit Limits the number of rows returned by the query, + /// @param offset starting index, + /// + /// @return The items found. + /// + Future>> query(String table, + {bool? distinct, + List? columns, + String? where, + List? whereArgs, + String? groupBy, + String? having, + String? orderBy, + int? limit, + int? offset}) { + return _db.query(table, + distinct: distinct, + columns: columns, + where: where, + whereArgs: whereArgs, + groupBy: groupBy, + having: having, + orderBy: orderBy, + limit: limit, + offset: offset); + } + + /// Execute a raw SQL SELECT query. + /// A notification to queries for [tables] will be sent after the statement is + /// executed. + /// + /// @return a list of rows that were found. + Future rawUpdate(Iterable tables, String sql, + [List? args]) async { + var rows = await _db.rawUpdate(sql, args); + if (rows > 0) { + _sendTableTrigger(tables); + } + return rows; + } + + /// Convenience method for updating rows in the database. + /// + /// Update [table] with [values], a map from column names to new column + /// values. null is a valid value that will be translated to NULL. + /// + /// [where] is the optional WHERE clause to apply when updating. + /// Passing null will update all rows. + /// + /// You may include ?s in the where clause, which will be replaced by the + /// values from [whereArgs] + /// + /// [conflictAlgorithm] (optional) specifies algorithm to use in case of a + /// conflict. See [ConflictResolver] docs for more details. + /// + /// A notification to queries for [table] will be sent after the statement is + /// executed. + Future update(String table, Map values, + {String? where, + List? whereArgs, + ConflictAlgorithm? conflictAlgorithm}) async { + var rows = await _db.update(table, values, + where: where, + whereArgs: whereArgs, + conflictAlgorithm: conflictAlgorithm); + if (rows > 0) { + _sendTableTrigger([table]); + } + return rows; + } + + /// Executes a raw SQL DELETE query. + /// + /// A notification to queries for [tables] will be sent after the statement is + /// executed. + /// + /// @return The number of changes made. + Future rawDelete(Iterable tables, String sql, + [List? args]) async { + var rows = await _db.rawDelete(sql, args); + if (rows > 0) { + _sendTableTrigger(tables); + } + return rows; + } + + /// Convenience method for deleting rows in the database. + /// + /// Delete from [table] + /// + /// [where] is the optional WHERE clause to apply when updating. Passing null + /// will update all rows. + /// + /// You may include ?s in the where clause, which will be replaced by the + /// values from [whereArgs] + /// + /// [conflictAlgorithm] (optional) specifies algorithm to use in case of a + /// conflict. See [ConflictResolver] docs for more details + /// + /// A notification to queries for [table] will be sent after the statement is + /// executed. + /// + /// @return The number of rows affected if a whereClause is passed in, 0 + /// otherwise. To remove all rows and get a count pass "1" as the + /// whereClause. + Future delete(String table, + {String? where, List? whereArgs}) async { + var rows = await _db.delete(table, where: where, whereArgs: whereArgs); + if (rows > 0) { + _sendTableTrigger([table]); + } + return rows; + } + + /// Creates a batch, used for performing multiple operation + /// in a single atomic operation. + /// + /// a batch can be commited using [StreamBatch.commit] + /// + /// If the batch was created in a transaction, it will be commited + /// when the transaction is done + StreamBatch batch() => StreamBatch(this); +} + +class QueryStream extends Stream { + final Stream _source; + + QueryStream(Stream source) : _source = source; + + @override + StreamSubscription listen(void Function(LazyQuery event)? onData, + {Function? onError, void Function()? onDone, bool? cancelOnError}) { + return _source.listen( + onData, + onError: onError, + onDone: onDone, + cancelOnError: cancelOnError + ); + } + + Stream mapToOne(T mapper(Map row)) { + return _source + .asyncMap((query) => query()) + .where((rows) => rows.isNotEmpty) + .map((rows) => mapper(rows.first)); + } + + Stream mapToOneOrDefault( + T mapper(Map row), T defaultValue) { + return _source + .asyncMap((query) => query()) + .map((rows) => rows.isNotEmpty ? mapper(rows.first) : defaultValue); + } + + Stream> mapToList(T mapper(Map row)) { + return _source.asyncMap((query) => query()).map((rows) { + var result = List.filled(rows.length, T as T, growable: false);//List(rows.length); + for (int i = 0; i < rows.length; i++) { + result[i] = mapper(rows[i]); + } + return result; + }); + } +} + +class StreamTransaction extends StreamDatabaseExecutor { + final Set _notify; + + StreamTransaction(Transaction transaction, Set notify) + : _notify = notify, + super(transaction); + + @override + _sendTableTrigger(Iterable tables) { + _notify.addAll(tables); + } +} + +/// +/// StreamDatabase to send sql commands, created by wrapping a [Database]. +/// +class StreamDatabase extends StreamDatabaseExecutor { + final StreamController> triggers = StreamController.broadcast(); + final Database _db; + + StreamDatabase(Database db) + : _db = db, + super(db); + + /// Calls in action must only be done using the transaction object + /// using the database will trigger a dead-lock. + Future transaction(Future action(StreamTransaction txn), + {bool? exclusive}) async { + var notify = Set(); + var result = await _db.transaction( + (t) => action(StreamTransaction(t, notify)), + exclusive: exclusive); + _sendTableTrigger(notify); + return result; + } + + /// Tell if the database is open, returns false once close has been called. + bool get isOpen => _db.isOpen; + + @override + void _sendTableTrigger(Iterable tables) { + triggers.add(tables.toSet()); + } + + /// Close the database. Cannot be accessed anymore. + Future close() => _db.close(); + + /// Creates a [Stream] that will notify listeners with a [LazyQuery] for + /// execution. Listeners will always receive an immediate notification with + /// initial data as well as subsequent notifications when the supplied [tables] + /// data changes through [insert], [update], and [delete] calls. Close the + /// [Stream] when you no longer want updates to the query. + /// + /// @see [rawQuery] + QueryStream createRawQuery(Iterable tables, String sql, + [List arguments = const []]) => + _createQuery(tables, () => _db.rawQuery(sql, arguments)); + + /// Creates a [Stream] that will notify listeners with a [LazyQuery] for + /// execution. Listeners will always receive an immediate notification with + /// initial data as well as subsequent notifications when the supplied [tables] + /// data changes through [insert], [update], and [delete] calls. Close the + /// [Stream] when you no longer want updates to the query. + /// + /// @see [query] + QueryStream createQuery(String table, + {bool? distinct, + List? columns, + String? where, + List? whereArgs, + String? groupBy, + String? having, + String? orderBy, + int? limit, + int? offset}) => + _createQuery( + [table], + () => _db.query(table, + distinct: distinct, + columns: columns, + where: where, + whereArgs: whereArgs, + groupBy: groupBy, + having: having, + orderBy: orderBy, + limit: limit, + offset: offset)); + + QueryStream _createQuery(Iterable tables, LazyQuery query) { + return QueryStream(triggers.stream + .where((strings) { + for (var table in tables) { + if (strings.contains(table)) { + return true; + } + } + return false; + }) + .map((strings) => query) + .transform(_StartWith(query))); + } +} + +class _StartWith extends StreamTransformerBase { + final T value; + + _StartWith(this.value); + + @override + Stream bind(Stream stream) { + StreamController controller = StreamController(); + controller.add(value); + controller.addStream(stream).whenComplete(() => controller.close()); + return controller.stream; + } +} + +/// +/// A batch is used to perform multiple operation as a single atomic unit. +/// A Batch object can be acquired by calling [StreamDatabase.batch]. It provides +/// methods for adding operation. None of the operation will be +/// executed (or visible locally) until commit() is called. +/// +class StreamBatch { + final StreamDatabaseExecutor _executor; + final Set _notify = Set(); + late Batch _batch; + + StreamBatch(StreamDatabaseExecutor executor) : _executor = executor { + _batch = executor._db.batch(); + } + + /// Commits all of the operations in this batch as a single atomic unit + /// The result is a list of the result of each operation in the same order + /// if [noResult] is true, the result list is empty (i.e. the id inserted + /// the count of item changed is not returned. + /// + /// The batch is stopped if any operation failed + /// If [continueOnError] is true, all the operations in the batch are executed + /// and the failure are ignored (i.e. the result for the given operation will + /// be a DatabaseException) + /// + Future> commit( + {bool? exclusive, bool? noResult, bool? continueOnError}) async { + final result = await _batch.commit( + exclusive: exclusive, + noResult: noResult, + continueOnError: continueOnError); + _executor._sendTableTrigger(_notify); + return result; + } + + /// See [StreamDatabase.rawInsert] + void rawInsert(Iterable tables, String sql, + [List? arguments]) { + _batch.rawInsert(sql, arguments); + _notify.addAll(tables); + } + + /// See [StreamDatabase.insert] + void insert(String table, Map values, + {String? nullColumnHack, ConflictAlgorithm? conflictAlgorithm}) { + _batch.insert(table, values, + nullColumnHack: nullColumnHack, conflictAlgorithm: conflictAlgorithm); + _notify.add(table); + } + + /// See [StreamDatabase.rawUpdate] + void rawUpdate(Iterable tables, String sql, + [List? arguments]) { + _batch.rawUpdate(sql, arguments); + _notify.addAll(tables); + } + + /// See [StreamDatabase.update] + void update(String table, Map values, + {String? where, + List? whereArgs, + ConflictAlgorithm? conflictAlgorithm}) { + _batch.update(table, values, + where: where, + whereArgs: whereArgs, + conflictAlgorithm: conflictAlgorithm); + _notify.add(table); + } + + /// See [StreamDatabase.rawDelete] + void rawDelete(Iterable tables, String sql, + [List? arguments]) { + _batch.rawDelete(sql, arguments); + _notify.addAll(tables); + } + + /// See [StreamDatabase.delete] + void delete(String table, {String? where, List? whereArgs}) { + _batch.delete(table, where: where, whereArgs: whereArgs); + _notify.add(table); + } + + /// See [StreamDatabase.execute]; + void execute(String sql, [List? arguments]) { + _batch.execute(sql, arguments); + } + + /// See [StreamDatabase.executeAndTrigger]; + void executeAndTrigger(Iterable tables, String sql, + [List? arguments]) { + _batch.execute(sql, arguments); + _notify.addAll(tables); + } + + /// See [StreamDatabase.query]; + void query(String table, + {bool? distinct, + List? columns, + String? where, + List? whereArgs, + String? groupBy, + String? having, + String? orderBy, + int? limit, + int? offset}) { + _batch.query(table, + columns: columns, + where: where, + whereArgs: whereArgs, + groupBy: groupBy, + having: having, + orderBy: orderBy, + limit: limit, + offset: offset); + } + + /// See [StreamDatabase.query]; + void rawQuery(String sql, [List? arguments]) { + _batch.rawQuery(sql, arguments); + } +} +*/ diff --git a/pubspec.yaml b/pubspec.yaml index c485a36..6262206 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: streamqflite description: reactive stream wrapper around sqflite inspired by sqlbrite -version: 2.2.0 +version: 2.2.2 author: Evan Tatarka homepage: https://github.com/evant/streamqflite From 12628b1888bc790144331b9a0262afb7bf5efecf Mon Sep 17 00:00:00 2001 From: Alexander Mateo Date: Wed, 9 Aug 2023 19:59:32 -0600 Subject: [PATCH 4/4] sqflite: ^2.2.3 --- README.md | 2 +- lib/streamqflite.dart | 2 +- lib/streamqflite2.dart | 498 ----------------------------------------- pubspec.yaml | 2 +- 4 files changed, 3 insertions(+), 501 deletions(-) delete mode 100644 lib/streamqflite2.dart diff --git a/README.md b/README.md index 84da3ec..5af9f8f 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ In your flutter project, add the dependency to your `pubspec.yaml` ```yaml dependencies: ... - streamqflite: ^1.0.0 + streamqflite: ^2.2.3 ``` ## Usage diff --git a/lib/streamqflite.dart b/lib/streamqflite.dart index ab3b577..cbc4124 100644 --- a/lib/streamqflite.dart +++ b/lib/streamqflite.dart @@ -246,7 +246,7 @@ class QueryStream extends Stream { //var result = List(rows.length); List result = []; for (int i = 0; i < rows.length; i++) { - result[i] = mapper(rows[i]); + result.add(mapper(rows[i])); } return result; }); diff --git a/lib/streamqflite2.dart b/lib/streamqflite2.dart deleted file mode 100644 index 6bac6ea..0000000 --- a/lib/streamqflite2.dart +++ /dev/null @@ -1,498 +0,0 @@ -/* -library sqlflight; - -import 'dart:async'; - -import 'package:sqflite/sqflite.dart'; - -/// Represents a query to be executed, invoking it will actually execute the -/// query and returns a [Future] of the result. -typedef Future>> LazyQuery(); - -/// -/// Common API for [StreamDatabase] and [StreamTransaction] to execute SQL commands -/// -abstract class StreamDatabaseExecutor { - final DatabaseExecutor _db; - - StreamDatabaseExecutor(DatabaseExecutor db) : _db = db; - - void _sendTableTrigger(Iterable tables); - - /// Execute an SQL query with no return value. - /// No notifications will be sent to queries if [sql] affects the data of the - /// table. - Future execute(String sql, [List? arguments]) => - _db.execute(sql, arguments); - - /// Execute an SQL query with no return value. - /// A notification to queries for [tables] will be sent after the statement is - /// executed. - Future executeAndTrigger(Iterable tables, String sql, - [List? arguments]) async { - await _db.execute(sql, arguments); - _sendTableTrigger(tables); - } - - /// Execute a raw SQL INSERT query - /// A notification to queries for [tables] will be sent after the statement is - /// executed. - /// - /// @return The inserted record id. - Future rawInsert(Iterable tables, String sql, - [List? arguments]) async { - var rowId = await _db.rawInsert(sql, arguments); - if (rowId != -1) { - _sendTableTrigger(tables); - } - return rowId; - } - - /// Insert a row into a table, where the keys of [values] correspond to - /// column names. - /// A notification to queries for [table] will be sent after the statement is - /// executed. - Future insert(String table, Map values, - {String? nullColumnHack, ConflictAlgorithm? conflictAlgorithm}) async { - var rowId = - await _db.insert(table, values, conflictAlgorithm: conflictAlgorithm); - if (rowId != -1) { - _sendTableTrigger([table]); - } - return rowId; - } - - /// Execute a raw SQL SELECT query. - /// - /// @return A list of rows that were found. - Future>> rawQuery(String sql, - [List? arguments]) => - _db.rawQuery(sql, arguments); - - /// Helper to query a table. - /// - /// @param distinct true if you want each row to be unique, false otherwise. - /// @param table The table names to compile the query against. - /// @param columns A list of which columns to return. Passing null will - /// - /// - /// return all columns, which is discouraged to prevent reading - /// data from storage that isn't going to be used. - /// @param where A filter declaring which rows to return, formatted as an SQL - /// WHERE clause (excluding the WHERE itself). Passing null will - /// return all rows for the given URL. - /// @param groupBy A filter declaring how to group rows, formatted as an SQL - /// GROUP BY clause (excluding the GROUP BY itself). Passing null - /// will cause the rows to not be grouped. - /// @param having A filter declare which row groups to include in the cursor, - /// if row grouping is being used, formatted as an SQL HAVING - /// clause (excluding the HAVING itself). Passing null will cause - /// all row groups to be included, and is required when row - /// grouping is not being used. - /// @param orderBy How to order the rows, formatted as an SQL ORDER BY clause - /// (excluding the ORDER BY itself). Passing null will use the - /// default sort order, which may be unordered. - /// @param limit Limits the number of rows returned by the query, - /// @param offset starting index, - /// - /// @return The items found. - /// - Future>> query(String table, - {bool? distinct, - List? columns, - String? where, - List? whereArgs, - String? groupBy, - String? having, - String? orderBy, - int? limit, - int? offset}) { - return _db.query(table, - distinct: distinct, - columns: columns, - where: where, - whereArgs: whereArgs, - groupBy: groupBy, - having: having, - orderBy: orderBy, - limit: limit, - offset: offset); - } - - /// Execute a raw SQL SELECT query. - /// A notification to queries for [tables] will be sent after the statement is - /// executed. - /// - /// @return a list of rows that were found. - Future rawUpdate(Iterable tables, String sql, - [List? args]) async { - var rows = await _db.rawUpdate(sql, args); - if (rows > 0) { - _sendTableTrigger(tables); - } - return rows; - } - - /// Convenience method for updating rows in the database. - /// - /// Update [table] with [values], a map from column names to new column - /// values. null is a valid value that will be translated to NULL. - /// - /// [where] is the optional WHERE clause to apply when updating. - /// Passing null will update all rows. - /// - /// You may include ?s in the where clause, which will be replaced by the - /// values from [whereArgs] - /// - /// [conflictAlgorithm] (optional) specifies algorithm to use in case of a - /// conflict. See [ConflictResolver] docs for more details. - /// - /// A notification to queries for [table] will be sent after the statement is - /// executed. - Future update(String table, Map values, - {String? where, - List? whereArgs, - ConflictAlgorithm? conflictAlgorithm}) async { - var rows = await _db.update(table, values, - where: where, - whereArgs: whereArgs, - conflictAlgorithm: conflictAlgorithm); - if (rows > 0) { - _sendTableTrigger([table]); - } - return rows; - } - - /// Executes a raw SQL DELETE query. - /// - /// A notification to queries for [tables] will be sent after the statement is - /// executed. - /// - /// @return The number of changes made. - Future rawDelete(Iterable tables, String sql, - [List? args]) async { - var rows = await _db.rawDelete(sql, args); - if (rows > 0) { - _sendTableTrigger(tables); - } - return rows; - } - - /// Convenience method for deleting rows in the database. - /// - /// Delete from [table] - /// - /// [where] is the optional WHERE clause to apply when updating. Passing null - /// will update all rows. - /// - /// You may include ?s in the where clause, which will be replaced by the - /// values from [whereArgs] - /// - /// [conflictAlgorithm] (optional) specifies algorithm to use in case of a - /// conflict. See [ConflictResolver] docs for more details - /// - /// A notification to queries for [table] will be sent after the statement is - /// executed. - /// - /// @return The number of rows affected if a whereClause is passed in, 0 - /// otherwise. To remove all rows and get a count pass "1" as the - /// whereClause. - Future delete(String table, - {String? where, List? whereArgs}) async { - var rows = await _db.delete(table, where: where, whereArgs: whereArgs); - if (rows > 0) { - _sendTableTrigger([table]); - } - return rows; - } - - /// Creates a batch, used for performing multiple operation - /// in a single atomic operation. - /// - /// a batch can be commited using [StreamBatch.commit] - /// - /// If the batch was created in a transaction, it will be commited - /// when the transaction is done - StreamBatch batch() => StreamBatch(this); -} - -class QueryStream extends Stream { - final Stream _source; - - QueryStream(Stream source) : _source = source; - - @override - StreamSubscription listen(void Function(LazyQuery event)? onData, - {Function? onError, void Function()? onDone, bool? cancelOnError}) { - return _source.listen( - onData, - onError: onError, - onDone: onDone, - cancelOnError: cancelOnError - ); - } - - Stream mapToOne(T mapper(Map row)) { - return _source - .asyncMap((query) => query()) - .where((rows) => rows.isNotEmpty) - .map((rows) => mapper(rows.first)); - } - - Stream mapToOneOrDefault( - T mapper(Map row), T defaultValue) { - return _source - .asyncMap((query) => query()) - .map((rows) => rows.isNotEmpty ? mapper(rows.first) : defaultValue); - } - - Stream> mapToList(T mapper(Map row)) { - return _source.asyncMap((query) => query()).map((rows) { - var result = List.filled(rows.length, T as T, growable: false);//List(rows.length); - for (int i = 0; i < rows.length; i++) { - result[i] = mapper(rows[i]); - } - return result; - }); - } -} - -class StreamTransaction extends StreamDatabaseExecutor { - final Set _notify; - - StreamTransaction(Transaction transaction, Set notify) - : _notify = notify, - super(transaction); - - @override - _sendTableTrigger(Iterable tables) { - _notify.addAll(tables); - } -} - -/// -/// StreamDatabase to send sql commands, created by wrapping a [Database]. -/// -class StreamDatabase extends StreamDatabaseExecutor { - final StreamController> triggers = StreamController.broadcast(); - final Database _db; - - StreamDatabase(Database db) - : _db = db, - super(db); - - /// Calls in action must only be done using the transaction object - /// using the database will trigger a dead-lock. - Future transaction(Future action(StreamTransaction txn), - {bool? exclusive}) async { - var notify = Set(); - var result = await _db.transaction( - (t) => action(StreamTransaction(t, notify)), - exclusive: exclusive); - _sendTableTrigger(notify); - return result; - } - - /// Tell if the database is open, returns false once close has been called. - bool get isOpen => _db.isOpen; - - @override - void _sendTableTrigger(Iterable tables) { - triggers.add(tables.toSet()); - } - - /// Close the database. Cannot be accessed anymore. - Future close() => _db.close(); - - /// Creates a [Stream] that will notify listeners with a [LazyQuery] for - /// execution. Listeners will always receive an immediate notification with - /// initial data as well as subsequent notifications when the supplied [tables] - /// data changes through [insert], [update], and [delete] calls. Close the - /// [Stream] when you no longer want updates to the query. - /// - /// @see [rawQuery] - QueryStream createRawQuery(Iterable tables, String sql, - [List arguments = const []]) => - _createQuery(tables, () => _db.rawQuery(sql, arguments)); - - /// Creates a [Stream] that will notify listeners with a [LazyQuery] for - /// execution. Listeners will always receive an immediate notification with - /// initial data as well as subsequent notifications when the supplied [tables] - /// data changes through [insert], [update], and [delete] calls. Close the - /// [Stream] when you no longer want updates to the query. - /// - /// @see [query] - QueryStream createQuery(String table, - {bool? distinct, - List? columns, - String? where, - List? whereArgs, - String? groupBy, - String? having, - String? orderBy, - int? limit, - int? offset}) => - _createQuery( - [table], - () => _db.query(table, - distinct: distinct, - columns: columns, - where: where, - whereArgs: whereArgs, - groupBy: groupBy, - having: having, - orderBy: orderBy, - limit: limit, - offset: offset)); - - QueryStream _createQuery(Iterable tables, LazyQuery query) { - return QueryStream(triggers.stream - .where((strings) { - for (var table in tables) { - if (strings.contains(table)) { - return true; - } - } - return false; - }) - .map((strings) => query) - .transform(_StartWith(query))); - } -} - -class _StartWith extends StreamTransformerBase { - final T value; - - _StartWith(this.value); - - @override - Stream bind(Stream stream) { - StreamController controller = StreamController(); - controller.add(value); - controller.addStream(stream).whenComplete(() => controller.close()); - return controller.stream; - } -} - -/// -/// A batch is used to perform multiple operation as a single atomic unit. -/// A Batch object can be acquired by calling [StreamDatabase.batch]. It provides -/// methods for adding operation. None of the operation will be -/// executed (or visible locally) until commit() is called. -/// -class StreamBatch { - final StreamDatabaseExecutor _executor; - final Set _notify = Set(); - late Batch _batch; - - StreamBatch(StreamDatabaseExecutor executor) : _executor = executor { - _batch = executor._db.batch(); - } - - /// Commits all of the operations in this batch as a single atomic unit - /// The result is a list of the result of each operation in the same order - /// if [noResult] is true, the result list is empty (i.e. the id inserted - /// the count of item changed is not returned. - /// - /// The batch is stopped if any operation failed - /// If [continueOnError] is true, all the operations in the batch are executed - /// and the failure are ignored (i.e. the result for the given operation will - /// be a DatabaseException) - /// - Future> commit( - {bool? exclusive, bool? noResult, bool? continueOnError}) async { - final result = await _batch.commit( - exclusive: exclusive, - noResult: noResult, - continueOnError: continueOnError); - _executor._sendTableTrigger(_notify); - return result; - } - - /// See [StreamDatabase.rawInsert] - void rawInsert(Iterable tables, String sql, - [List? arguments]) { - _batch.rawInsert(sql, arguments); - _notify.addAll(tables); - } - - /// See [StreamDatabase.insert] - void insert(String table, Map values, - {String? nullColumnHack, ConflictAlgorithm? conflictAlgorithm}) { - _batch.insert(table, values, - nullColumnHack: nullColumnHack, conflictAlgorithm: conflictAlgorithm); - _notify.add(table); - } - - /// See [StreamDatabase.rawUpdate] - void rawUpdate(Iterable tables, String sql, - [List? arguments]) { - _batch.rawUpdate(sql, arguments); - _notify.addAll(tables); - } - - /// See [StreamDatabase.update] - void update(String table, Map values, - {String? where, - List? whereArgs, - ConflictAlgorithm? conflictAlgorithm}) { - _batch.update(table, values, - where: where, - whereArgs: whereArgs, - conflictAlgorithm: conflictAlgorithm); - _notify.add(table); - } - - /// See [StreamDatabase.rawDelete] - void rawDelete(Iterable tables, String sql, - [List? arguments]) { - _batch.rawDelete(sql, arguments); - _notify.addAll(tables); - } - - /// See [StreamDatabase.delete] - void delete(String table, {String? where, List? whereArgs}) { - _batch.delete(table, where: where, whereArgs: whereArgs); - _notify.add(table); - } - - /// See [StreamDatabase.execute]; - void execute(String sql, [List? arguments]) { - _batch.execute(sql, arguments); - } - - /// See [StreamDatabase.executeAndTrigger]; - void executeAndTrigger(Iterable tables, String sql, - [List? arguments]) { - _batch.execute(sql, arguments); - _notify.addAll(tables); - } - - /// See [StreamDatabase.query]; - void query(String table, - {bool? distinct, - List? columns, - String? where, - List? whereArgs, - String? groupBy, - String? having, - String? orderBy, - int? limit, - int? offset}) { - _batch.query(table, - columns: columns, - where: where, - whereArgs: whereArgs, - groupBy: groupBy, - having: having, - orderBy: orderBy, - limit: limit, - offset: offset); - } - - /// See [StreamDatabase.query]; - void rawQuery(String sql, [List? arguments]) { - _batch.rawQuery(sql, arguments); - } -} -*/ diff --git a/pubspec.yaml b/pubspec.yaml index 6262206..c1d932e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: streamqflite description: reactive stream wrapper around sqflite inspired by sqlbrite -version: 2.2.2 +version: 2.2.3 author: Evan Tatarka homepage: https://github.com/evant/streamqflite