mirror of https://github.com/AMT-Cheif/drift.git
Merge pull request #924 from simolus3/nnbd
Migrate core package to null safety
This commit is contained in:
commit
74fc2cea3d
20
.cirrus.yml
20
.cirrus.yml
|
@ -1,20 +0,0 @@
|
|||
# Run tasks with the dart SDK installed by default
|
||||
container:
|
||||
dockerfile: tool/Dockerfile
|
||||
memory: 12G
|
||||
cpu: 4
|
||||
|
||||
task:
|
||||
pub_cache:
|
||||
folder: $HOME/.pub-cache
|
||||
environment:
|
||||
CODECOV_TOKEN: ENCRYPTED[6322a159d9b7692b999d13fa2bc7981c8b61ecb1ac18ae076864f1355ee9b65088b2bf9d97d7860196e58bf1db5708af]
|
||||
dart_version_script: dart --version
|
||||
pub_get_script: tool/pub_get.sh
|
||||
analyze_script: tool/analyze.sh
|
||||
test_moor_script: tool/test_moor.sh
|
||||
test_sqlparser_script: tool/test_sqlparser.sh
|
||||
misc_integration_test_script: tool/misc_integration_test.sh
|
||||
# We just get too many timeouts for moor_generator in the CI runner
|
||||
# test_moor_generator_script: tool/test_generator.sh
|
||||
format_coverage_script: tool/upload_coverage.sh
|
|
@ -0,0 +1,116 @@
|
|||
name: CI
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
env:
|
||||
PUB_ENVIRONMENT: bot.github
|
||||
|
||||
jobs:
|
||||
moor:
|
||||
name: "moor package"
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
# setup
|
||||
- uses: actions/checkout@v2
|
||||
- uses: cedx/setup-dart@v2
|
||||
with:
|
||||
release-channel: beta
|
||||
- run: sudo apt-get install -y libsqlite3-dev
|
||||
name: Install sqlite3 for tests
|
||||
- run: dart pub upgrade
|
||||
working-directory: moor
|
||||
# analysis
|
||||
- run: dart format -o none --set-exit-if-changed moor/
|
||||
name: dartfmt
|
||||
- run: dart analyze --fatal-infos --fatal-warnings
|
||||
working-directory: moor/
|
||||
# build, test and upload coverage
|
||||
- run: dart run build_runner build --delete-conflicting-outputs
|
||||
working-directory: moor
|
||||
- run: dart --no-sound-null-safety --null-assertions test #-x background_isolate --coverage=coverage
|
||||
working-directory: moor
|
||||
# - uses: actions/upload-artifact@v2
|
||||
# with:
|
||||
# name: moor-coverage-data
|
||||
# path: |
|
||||
# moor/coverage/
|
||||
# moor/.dart_tool/package_config.json
|
||||
# retention-days: 1
|
||||
|
||||
moor_generator:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
# setup
|
||||
- uses: actions/checkout@v2
|
||||
- uses: cedx/setup-dart@v2
|
||||
with:
|
||||
release-channel: beta
|
||||
- run: dart pub upgrade
|
||||
working-directory: moor_generator
|
||||
# analysis
|
||||
- run: dart format -o none --set-exit-if-changed moor_generator/
|
||||
name: dartfmt
|
||||
- run: dart analyze --fatal-infos --fatal-warnings
|
||||
working-directory: moor_generator/
|
||||
|
||||
sqlparser:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
# setup
|
||||
- uses: actions/checkout@v2
|
||||
- uses: cedx/setup-dart@v2
|
||||
- run: sudo apt-get install -y libsqlite3-dev
|
||||
name: Install sqlite3 for tests
|
||||
- run: dart pub upgrade
|
||||
working-directory: sqlparser
|
||||
# analysis
|
||||
- run: dart format -o none --set-exit-if-changed sqlparser/
|
||||
name: dartfmt
|
||||
- run: dart analyze --fatal-infos --fatal-warnings
|
||||
working-directory: sqlparser/
|
||||
# tests and coverage
|
||||
- run: dart test #--coverage=coverage
|
||||
working-directory: sqlparser
|
||||
# - uses: actions/upload-artifact@v2
|
||||
# with:
|
||||
# name: sqlparser-coverage-data
|
||||
# path: |
|
||||
# sqlparser/coverage/
|
||||
# sqlparser/.dart_tool/package_config.json
|
||||
# retention-days: 1
|
||||
|
||||
misc_integration_tests:
|
||||
name: "Integration tests"
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: cedx/setup-dart@v2
|
||||
with:
|
||||
release-channel: beta
|
||||
- run: sudo apt-get install -y libsqlite3-dev
|
||||
name: Install sqlite3 for tests
|
||||
- run: tool/misc_integration_test.sh
|
||||
|
||||
# upload_coverage:
|
||||
# runs-on: ubuntu-20.04
|
||||
# needs: [moor, sqlparser]
|
||||
# steps:
|
||||
# - uses: actions/checkout@v2
|
||||
# - uses: cedx/setup-dart@v2
|
||||
# - run: dart pub upgrade
|
||||
# name: "Setup coverage processor"
|
||||
# working-directory: extras/coverage_formatting
|
||||
# - uses: actions/download-artifact@v2
|
||||
# with:
|
||||
# name: moor-coverage-data
|
||||
# path: moor/
|
||||
# - uses: actions/download-artifact@v2
|
||||
# with:
|
||||
# name: sqlparser-coverage-data
|
||||
# path: sqlparser/
|
||||
# - run: dart run extras/coverage_formatting/bin/coverage.dart
|
||||
# name: "Format coverage from raw data"
|
||||
# - uses: codecov/codecov-action@v1
|
||||
# with:
|
||||
# file: lcov.info
|
|
@ -8,5 +8,6 @@ pubspec.lock
|
|||
.dart_tool/
|
||||
|
||||
benchmark_results.json
|
||||
.flutter-plugins
|
||||
.flutter-plugins-dependencies
|
||||
flutter_export_environment.sh
|
|
@ -13,6 +13,7 @@ analyzer:
|
|||
# Will be analyzed anyway, nobody knows why ¯\_(ツ)_/¯. We're only analyzing lib/ and test/ as a workaround
|
||||
- ".dart_tool/build/entrypoint/build.dart"
|
||||
- "tool/**"
|
||||
- "**/*.mocks.dart"
|
||||
|
||||
# this should always include all rules. Those we don't use are commented out
|
||||
linter:
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
name: benchmarks
|
||||
description: Runs simple and complex benchmarks to measure performance of moor and moor_ffi
|
||||
|
||||
environment:
|
||||
sdk: '>=2.6.0 <3.0.0'
|
||||
|
||||
dependencies:
|
||||
moor:
|
||||
sqlite3: ^0.1.3
|
||||
|
|
|
@ -31,7 +31,8 @@ Future runForProject(String projectName) async {
|
|||
final hitmap = await parseCoverage(files, 1);
|
||||
|
||||
final resolver = MoorResolver(
|
||||
projectRoot: projectName, packagesPath: p.join(projectName, '.packages'));
|
||||
projectRoot: projectName,
|
||||
packagesPath: p.join(projectName, '.dart_tool', 'package_config.json'));
|
||||
|
||||
final output =
|
||||
await LcovFormatter(resolver, reportOn: [p.join(projectName, 'lib')])
|
||||
|
|
|
@ -2,6 +2,9 @@ name: coverage_formatting
|
|||
publish_to: none
|
||||
description: Tool used for the CI to format VM coverage jsons to LCOV files
|
||||
|
||||
environment:
|
||||
sdk: '>=2.6.0 <3.0.0'
|
||||
|
||||
dependencies:
|
||||
coverage: '^0.14.0'
|
||||
path: ^1.6.4
|
|
@ -6,7 +6,6 @@ library encrypted_moor;
|
|||
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:path/path.dart';
|
||||
import 'package:moor/moor.dart';
|
||||
import 'package:moor/backends.dart';
|
||||
|
@ -19,21 +18,25 @@ typedef DatabaseCreator = FutureOr<void> Function(File file);
|
|||
|
||||
class _SqfliteDelegate extends DatabaseDelegate with _SqfliteExecutor {
|
||||
@override
|
||||
s.Database db;
|
||||
late s.Database db;
|
||||
bool _isOpen = false;
|
||||
|
||||
final bool inDbFolder;
|
||||
final String path;
|
||||
final String password;
|
||||
final String? password;
|
||||
|
||||
bool singleInstance;
|
||||
final DatabaseCreator creator;
|
||||
final DatabaseCreator? creator;
|
||||
|
||||
_SqfliteDelegate(this.inDbFolder, this.path,
|
||||
{this.singleInstance, this.creator, this.password}) {
|
||||
singleInstance ??= true;
|
||||
}
|
||||
_SqfliteDelegate(
|
||||
this.inDbFolder,
|
||||
this.path, {
|
||||
this.singleInstance = true,
|
||||
this.creator,
|
||||
this.password,
|
||||
});
|
||||
|
||||
DbVersionDelegate _delegate;
|
||||
DbVersionDelegate? _delegate;
|
||||
@override
|
||||
DbVersionDelegate get versionDelegate {
|
||||
return _delegate ??= _SqfliteVersionDelegate(db);
|
||||
|
@ -44,7 +47,7 @@ class _SqfliteDelegate extends DatabaseDelegate with _SqfliteExecutor {
|
|||
_SqfliteTransactionDelegate(this);
|
||||
|
||||
@override
|
||||
bool get isOpen => db != null;
|
||||
bool get isOpen => _isOpen;
|
||||
|
||||
@override
|
||||
Future<void> open(QueryExecutorUser user) async {
|
||||
|
@ -57,7 +60,7 @@ class _SqfliteDelegate extends DatabaseDelegate with _SqfliteExecutor {
|
|||
|
||||
final file = File(resolvedPath);
|
||||
if (creator != null && !await file.exists()) {
|
||||
await creator(file);
|
||||
await creator!(file);
|
||||
}
|
||||
|
||||
db = await s.openDatabase(
|
||||
|
@ -65,6 +68,7 @@ class _SqfliteDelegate extends DatabaseDelegate with _SqfliteExecutor {
|
|||
password: password,
|
||||
singleInstance: singleInstance,
|
||||
);
|
||||
_isOpen = true;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -98,7 +102,6 @@ class _SqfliteTransactionDelegate extends SupportedTransactionDelegate {
|
|||
@override
|
||||
void startTransaction(Future<void> Function(QueryDelegate) run) {
|
||||
delegate.db.transaction((transaction) async {
|
||||
assert(transaction != null);
|
||||
final executor = _SqfliteTransactionExecutor(transaction);
|
||||
await run(executor);
|
||||
}).catchError((_) {
|
||||
|
@ -131,23 +134,23 @@ mixin _SqfliteExecutor on QueryDelegate {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<void> runCustom(String statement, List args) {
|
||||
Future<void> runCustom(String statement, List<Object?> args) {
|
||||
return db.execute(statement, args);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> runInsert(String statement, List args) {
|
||||
Future<int> runInsert(String statement, List<Object?> args) {
|
||||
return db.rawInsert(statement, args);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<QueryResult> runSelect(String statement, List args) async {
|
||||
Future<QueryResult> runSelect(String statement, List<Object?> args) async {
|
||||
final result = await db.rawQuery(statement, args);
|
||||
return QueryResult.fromRows(result);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> runUpdate(String statement, List args) {
|
||||
Future<int> runUpdate(String statement, List<Object?> args) {
|
||||
return db.rawUpdate(statement, args);
|
||||
}
|
||||
}
|
||||
|
@ -165,11 +168,11 @@ class EncryptedExecutor extends DelegatedDatabase {
|
|||
/// [MigrationStrategy.onCreate] callback because it hasn't been created by
|
||||
/// moor.
|
||||
EncryptedExecutor(
|
||||
{@required String path,
|
||||
@required String password,
|
||||
bool logStatements,
|
||||
bool singleInstance,
|
||||
DatabaseCreator creator})
|
||||
{required String path,
|
||||
required String password,
|
||||
bool? logStatements,
|
||||
bool singleInstance = true,
|
||||
DatabaseCreator? creator})
|
||||
: super(
|
||||
_SqfliteDelegate(false, path,
|
||||
singleInstance: singleInstance,
|
||||
|
@ -189,11 +192,11 @@ class EncryptedExecutor extends DelegatedDatabase {
|
|||
/// [MigrationStrategy.onCreate] callback because it hasn't been created by
|
||||
/// moor.
|
||||
EncryptedExecutor.inDatabaseFolder(
|
||||
{@required String path,
|
||||
@required String password,
|
||||
bool logStatements,
|
||||
bool singleInstance,
|
||||
DatabaseCreator creator})
|
||||
{required String path,
|
||||
required String password,
|
||||
bool? logStatements,
|
||||
bool singleInstance = true,
|
||||
DatabaseCreator? creator})
|
||||
: super(
|
||||
_SqfliteDelegate(true, path,
|
||||
singleInstance: singleInstance,
|
||||
|
@ -212,8 +215,8 @@ class EncryptedExecutor extends DelegatedDatabase {
|
|||
///
|
||||
/// Note that this returns null until the moor database has been opened.
|
||||
/// A moor database is opened lazily when the first query runs.
|
||||
s.Database get sqfliteDb {
|
||||
s.Database? get sqfliteDb {
|
||||
final sqfliteDelegate = delegate as _SqfliteDelegate;
|
||||
return sqfliteDelegate.db;
|
||||
return sqfliteDelegate.isOpen ? sqfliteDelegate.db : null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,11 @@ version: 1.0.0
|
|||
author: Simon Binder <oss@simonbinder.eu>
|
||||
|
||||
environment:
|
||||
sdk: '>=2.4.0 <3.0.0'
|
||||
sdk: '>=2.12.0-0 <3.0.0'
|
||||
|
||||
dependencies:
|
||||
moor: ^3.0.0
|
||||
sqflite_sqlcipher: ^1.0.0+6
|
||||
sqflite_sqlcipher: ^2.0.0-nullsafety
|
||||
|
||||
dependency_overrides:
|
||||
moor:
|
||||
|
|
|
@ -2,6 +2,8 @@ name: flutter_db
|
|||
description: Moor integration tests running on sqflite
|
||||
version: 1.0.0+1
|
||||
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
sdk: ">=2.1.0 <3.0.0"
|
||||
flutter: ">=1.12.0"
|
||||
|
|
|
@ -16,4 +16,4 @@ dev_dependencies:
|
|||
|
||||
dependency_overrides:
|
||||
moor:
|
||||
path: ../../../moor
|
||||
path: ../../../moor
|
|
@ -23,4 +23,5 @@ dependency_overrides:
|
|||
path: ../../sqlparser
|
||||
|
||||
# todo: Remove after built_value supports analyzer ^0.40
|
||||
analyzer: 0.40.4
|
||||
analyzer: 0.40.4
|
||||
convert: ^3.0.0-nullsafety
|
|
@ -1,5 +1,8 @@
|
|||
## unreleased
|
||||
## unreleased (breaking - 4.0)
|
||||
|
||||
- __Breaking__: Changed the `args` parameter in `QueryExecutor` methods to `List<Object?>`
|
||||
- __Breaking__: Removed the second type parameter from `TypedResult.read`
|
||||
- Support null safety
|
||||
- Changed the sql representation of text types from `VARCHAR` to `TEXT`
|
||||
- Added extensions for `isNull` and `isNotNull`
|
||||
- Support creating a `VmDatabase` from a raw sqlite3 `Database` via `VmDatabase.opened`
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
# Moor
|
||||
Moor is a reactive persistence library for Flutter and Dart, built ontop of
|
||||
sqlite.
|
||||
|
|
|
@ -7,4 +7,5 @@ analyzer:
|
|||
exclude:
|
||||
- "example_web/**"
|
||||
- "example/**"
|
||||
- "**/*.g.dart"
|
||||
- "**/*.g.dart"
|
||||
- "**/*.mocks.dart"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
tags:
|
||||
integration:
|
||||
background_isolate:
|
||||
|
||||
platforms:
|
||||
- vm
|
||||
|
|
|
@ -9,15 +9,15 @@ part of 'example.dart';
|
|||
// ignore_for_file: unnecessary_brace_in_string_interps, unnecessary_this
|
||||
class Category extends DataClass implements Insertable<Category> {
|
||||
final int id;
|
||||
final String description;
|
||||
Category({@required this.id, this.description});
|
||||
final String? description;
|
||||
Category({required this.id, this.description});
|
||||
factory Category.fromData(Map<String, dynamic> data, GeneratedDatabase db,
|
||||
{String prefix}) {
|
||||
{String? prefix}) {
|
||||
final effectivePrefix = prefix ?? '';
|
||||
final intType = db.typeSystem.forDartType<int>();
|
||||
final stringType = db.typeSystem.forDartType<String>();
|
||||
return Category(
|
||||
id: intType.mapFromDatabaseResponse(data['${effectivePrefix}id']),
|
||||
id: intType.mapFromDatabaseResponse(data['${effectivePrefix}id'])!,
|
||||
description: stringType
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}description']),
|
||||
);
|
||||
|
@ -25,18 +25,16 @@ class Category extends DataClass implements Insertable<Category> {
|
|||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
if (!nullToAbsent || id != null) {
|
||||
map['id'] = Variable<int>(id);
|
||||
}
|
||||
map['id'] = Variable<int>(id);
|
||||
if (!nullToAbsent || description != null) {
|
||||
map['description'] = Variable<String>(description);
|
||||
map['description'] = Variable<String?>(description);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
CategoriesCompanion toCompanion(bool nullToAbsent) {
|
||||
return CategoriesCompanion(
|
||||
id: id == null && nullToAbsent ? const Value.absent() : Value(id),
|
||||
id: Value(id),
|
||||
description: description == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(description),
|
||||
|
@ -44,29 +42,29 @@ class Category extends DataClass implements Insertable<Category> {
|
|||
}
|
||||
|
||||
factory Category.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer serializer}) {
|
||||
{ValueSerializer? serializer}) {
|
||||
serializer ??= moorRuntimeOptions.defaultSerializer;
|
||||
return Category(
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
description: serializer.fromJson<String>(json['description']),
|
||||
description: serializer.fromJson<String?>(json['description']),
|
||||
);
|
||||
}
|
||||
factory Category.fromJsonString(String encodedJson,
|
||||
{ValueSerializer serializer}) =>
|
||||
{ValueSerializer? serializer}) =>
|
||||
Category.fromJson(
|
||||
DataClass.parseJson(encodedJson) as Map<String, dynamic>,
|
||||
serializer: serializer);
|
||||
@override
|
||||
Map<String, dynamic> toJson({ValueSerializer serializer}) {
|
||||
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
|
||||
serializer ??= moorRuntimeOptions.defaultSerializer;
|
||||
return <String, dynamic>{
|
||||
'id': serializer.toJson<int>(id),
|
||||
'description': serializer.toJson<String>(description),
|
||||
'description': serializer.toJson<String?>(description),
|
||||
};
|
||||
}
|
||||
|
||||
Category copyWith(
|
||||
{int id, Value<String> description = const Value.absent()}) =>
|
||||
{int? id, Value<String?> description = const Value.absent()}) =>
|
||||
Category(
|
||||
id: id ?? this.id,
|
||||
description: description.present ? description.value : this.description,
|
||||
|
@ -92,7 +90,7 @@ class Category extends DataClass implements Insertable<Category> {
|
|||
|
||||
class CategoriesCompanion extends UpdateCompanion<Category> {
|
||||
final Value<int> id;
|
||||
final Value<String> description;
|
||||
final Value<String?> description;
|
||||
const CategoriesCompanion({
|
||||
this.id = const Value.absent(),
|
||||
this.description = const Value.absent(),
|
||||
|
@ -102,8 +100,8 @@ class CategoriesCompanion extends UpdateCompanion<Category> {
|
|||
this.description = const Value.absent(),
|
||||
});
|
||||
static Insertable<Category> custom({
|
||||
Expression<int> id,
|
||||
Expression<String> description,
|
||||
Expression<int>? id,
|
||||
Expression<String?>? description,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (id != null) 'id': id,
|
||||
|
@ -111,7 +109,7 @@ class CategoriesCompanion extends UpdateCompanion<Category> {
|
|||
});
|
||||
}
|
||||
|
||||
CategoriesCompanion copyWith({Value<int> id, Value<String> description}) {
|
||||
CategoriesCompanion copyWith({Value<int>? id, Value<String?>? description}) {
|
||||
return CategoriesCompanion(
|
||||
id: id ?? this.id,
|
||||
description: description ?? this.description,
|
||||
|
@ -125,7 +123,7 @@ class CategoriesCompanion extends UpdateCompanion<Category> {
|
|||
map['id'] = Variable<int>(id.value);
|
||||
}
|
||||
if (description.present) {
|
||||
map['description'] = Variable<String>(description.value);
|
||||
map['description'] = Variable<String?>(description.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
@ -143,12 +141,11 @@ class CategoriesCompanion extends UpdateCompanion<Category> {
|
|||
class $CategoriesTable extends Categories
|
||||
with TableInfo<$CategoriesTable, Category> {
|
||||
final GeneratedDatabase _db;
|
||||
final String _alias;
|
||||
final String? _alias;
|
||||
$CategoriesTable(this._db, [this._alias]);
|
||||
final VerificationMeta _idMeta = const VerificationMeta('id');
|
||||
GeneratedIntColumn _id;
|
||||
@override
|
||||
GeneratedIntColumn get id => _id ??= _constructId();
|
||||
late final GeneratedIntColumn id = _constructId();
|
||||
GeneratedIntColumn _constructId() {
|
||||
return GeneratedIntColumn('id', $tableName, false,
|
||||
hasAutoIncrement: true, declaredAsPrimaryKey: true);
|
||||
|
@ -156,10 +153,8 @@ class $CategoriesTable extends Categories
|
|||
|
||||
final VerificationMeta _descriptionMeta =
|
||||
const VerificationMeta('description');
|
||||
GeneratedTextColumn _description;
|
||||
@override
|
||||
GeneratedTextColumn get description =>
|
||||
_description ??= _constructDescription();
|
||||
late final GeneratedTextColumn description = _constructDescription();
|
||||
GeneratedTextColumn _constructDescription() {
|
||||
return GeneratedTextColumn(
|
||||
'description',
|
||||
|
@ -182,13 +177,13 @@ class $CategoriesTable extends Categories
|
|||
final context = VerificationContext();
|
||||
final data = instance.toColumns(true);
|
||||
if (data.containsKey('id')) {
|
||||
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id'], _idMeta));
|
||||
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
||||
}
|
||||
if (data.containsKey('description')) {
|
||||
context.handle(
|
||||
_descriptionMeta,
|
||||
description.isAcceptableOrUnknown(
|
||||
data['description'], _descriptionMeta));
|
||||
data['description']!, _descriptionMeta));
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
@ -196,7 +191,7 @@ class $CategoriesTable extends Categories
|
|||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => {id};
|
||||
@override
|
||||
Category map(Map<String, dynamic> data, {String tablePrefix}) {
|
||||
Category map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null;
|
||||
return Category.fromData(data, _db, prefix: effectivePrefix);
|
||||
}
|
||||
|
@ -211,23 +206,23 @@ class Recipe extends DataClass implements Insertable<Recipe> {
|
|||
final int id;
|
||||
final String title;
|
||||
final String instructions;
|
||||
final int category;
|
||||
final int? category;
|
||||
Recipe(
|
||||
{@required this.id,
|
||||
@required this.title,
|
||||
@required this.instructions,
|
||||
{required this.id,
|
||||
required this.title,
|
||||
required this.instructions,
|
||||
this.category});
|
||||
factory Recipe.fromData(Map<String, dynamic> data, GeneratedDatabase db,
|
||||
{String prefix}) {
|
||||
{String? prefix}) {
|
||||
final effectivePrefix = prefix ?? '';
|
||||
final intType = db.typeSystem.forDartType<int>();
|
||||
final stringType = db.typeSystem.forDartType<String>();
|
||||
return Recipe(
|
||||
id: intType.mapFromDatabaseResponse(data['${effectivePrefix}id']),
|
||||
id: intType.mapFromDatabaseResponse(data['${effectivePrefix}id'])!,
|
||||
title:
|
||||
stringType.mapFromDatabaseResponse(data['${effectivePrefix}title']),
|
||||
stringType.mapFromDatabaseResponse(data['${effectivePrefix}title'])!,
|
||||
instructions: stringType
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}instructions']),
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}instructions'])!,
|
||||
category:
|
||||
intType.mapFromDatabaseResponse(data['${effectivePrefix}category']),
|
||||
);
|
||||
|
@ -235,29 +230,20 @@ class Recipe extends DataClass implements Insertable<Recipe> {
|
|||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
if (!nullToAbsent || id != null) {
|
||||
map['id'] = Variable<int>(id);
|
||||
}
|
||||
if (!nullToAbsent || title != null) {
|
||||
map['title'] = Variable<String>(title);
|
||||
}
|
||||
if (!nullToAbsent || instructions != null) {
|
||||
map['instructions'] = Variable<String>(instructions);
|
||||
}
|
||||
map['id'] = Variable<int>(id);
|
||||
map['title'] = Variable<String>(title);
|
||||
map['instructions'] = Variable<String>(instructions);
|
||||
if (!nullToAbsent || category != null) {
|
||||
map['category'] = Variable<int>(category);
|
||||
map['category'] = Variable<int?>(category);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
RecipesCompanion toCompanion(bool nullToAbsent) {
|
||||
return RecipesCompanion(
|
||||
id: id == null && nullToAbsent ? const Value.absent() : Value(id),
|
||||
title:
|
||||
title == null && nullToAbsent ? const Value.absent() : Value(title),
|
||||
instructions: instructions == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(instructions),
|
||||
id: Value(id),
|
||||
title: Value(title),
|
||||
instructions: Value(instructions),
|
||||
category: category == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(category),
|
||||
|
@ -265,35 +251,35 @@ class Recipe extends DataClass implements Insertable<Recipe> {
|
|||
}
|
||||
|
||||
factory Recipe.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer serializer}) {
|
||||
{ValueSerializer? serializer}) {
|
||||
serializer ??= moorRuntimeOptions.defaultSerializer;
|
||||
return Recipe(
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
title: serializer.fromJson<String>(json['title']),
|
||||
instructions: serializer.fromJson<String>(json['instructions']),
|
||||
category: serializer.fromJson<int>(json['category']),
|
||||
category: serializer.fromJson<int?>(json['category']),
|
||||
);
|
||||
}
|
||||
factory Recipe.fromJsonString(String encodedJson,
|
||||
{ValueSerializer serializer}) =>
|
||||
{ValueSerializer? serializer}) =>
|
||||
Recipe.fromJson(DataClass.parseJson(encodedJson) as Map<String, dynamic>,
|
||||
serializer: serializer);
|
||||
@override
|
||||
Map<String, dynamic> toJson({ValueSerializer serializer}) {
|
||||
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
|
||||
serializer ??= moorRuntimeOptions.defaultSerializer;
|
||||
return <String, dynamic>{
|
||||
'id': serializer.toJson<int>(id),
|
||||
'title': serializer.toJson<String>(title),
|
||||
'instructions': serializer.toJson<String>(instructions),
|
||||
'category': serializer.toJson<int>(category),
|
||||
'category': serializer.toJson<int?>(category),
|
||||
};
|
||||
}
|
||||
|
||||
Recipe copyWith(
|
||||
{int id,
|
||||
String title,
|
||||
String instructions,
|
||||
Value<int> category = const Value.absent()}) =>
|
||||
{int? id,
|
||||
String? title,
|
||||
String? instructions,
|
||||
Value<int?> category = const Value.absent()}) =>
|
||||
Recipe(
|
||||
id: id ?? this.id,
|
||||
title: title ?? this.title,
|
||||
|
@ -328,7 +314,7 @@ class RecipesCompanion extends UpdateCompanion<Recipe> {
|
|||
final Value<int> id;
|
||||
final Value<String> title;
|
||||
final Value<String> instructions;
|
||||
final Value<int> category;
|
||||
final Value<int?> category;
|
||||
const RecipesCompanion({
|
||||
this.id = const Value.absent(),
|
||||
this.title = const Value.absent(),
|
||||
|
@ -337,16 +323,16 @@ class RecipesCompanion extends UpdateCompanion<Recipe> {
|
|||
});
|
||||
RecipesCompanion.insert({
|
||||
this.id = const Value.absent(),
|
||||
@required String title,
|
||||
@required String instructions,
|
||||
required String title,
|
||||
required String instructions,
|
||||
this.category = const Value.absent(),
|
||||
}) : title = Value(title),
|
||||
instructions = Value(instructions);
|
||||
static Insertable<Recipe> custom({
|
||||
Expression<int> id,
|
||||
Expression<String> title,
|
||||
Expression<String> instructions,
|
||||
Expression<int> category,
|
||||
Expression<int>? id,
|
||||
Expression<String>? title,
|
||||
Expression<String>? instructions,
|
||||
Expression<int?>? category,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (id != null) 'id': id,
|
||||
|
@ -357,10 +343,10 @@ class RecipesCompanion extends UpdateCompanion<Recipe> {
|
|||
}
|
||||
|
||||
RecipesCompanion copyWith(
|
||||
{Value<int> id,
|
||||
Value<String> title,
|
||||
Value<String> instructions,
|
||||
Value<int> category}) {
|
||||
{Value<int>? id,
|
||||
Value<String>? title,
|
||||
Value<String>? instructions,
|
||||
Value<int?>? category}) {
|
||||
return RecipesCompanion(
|
||||
id: id ?? this.id,
|
||||
title: title ?? this.title,
|
||||
|
@ -382,7 +368,7 @@ class RecipesCompanion extends UpdateCompanion<Recipe> {
|
|||
map['instructions'] = Variable<String>(instructions.value);
|
||||
}
|
||||
if (category.present) {
|
||||
map['category'] = Variable<int>(category.value);
|
||||
map['category'] = Variable<int?>(category.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
@ -401,31 +387,27 @@ class RecipesCompanion extends UpdateCompanion<Recipe> {
|
|||
|
||||
class $RecipesTable extends Recipes with TableInfo<$RecipesTable, Recipe> {
|
||||
final GeneratedDatabase _db;
|
||||
final String _alias;
|
||||
final String? _alias;
|
||||
$RecipesTable(this._db, [this._alias]);
|
||||
final VerificationMeta _idMeta = const VerificationMeta('id');
|
||||
GeneratedIntColumn _id;
|
||||
@override
|
||||
GeneratedIntColumn get id => _id ??= _constructId();
|
||||
late final GeneratedIntColumn id = _constructId();
|
||||
GeneratedIntColumn _constructId() {
|
||||
return GeneratedIntColumn('id', $tableName, false,
|
||||
hasAutoIncrement: true, declaredAsPrimaryKey: true);
|
||||
}
|
||||
|
||||
final VerificationMeta _titleMeta = const VerificationMeta('title');
|
||||
GeneratedTextColumn _title;
|
||||
@override
|
||||
GeneratedTextColumn get title => _title ??= _constructTitle();
|
||||
late final GeneratedTextColumn title = _constructTitle();
|
||||
GeneratedTextColumn _constructTitle() {
|
||||
return GeneratedTextColumn('title', $tableName, false, maxTextLength: 16);
|
||||
}
|
||||
|
||||
final VerificationMeta _instructionsMeta =
|
||||
const VerificationMeta('instructions');
|
||||
GeneratedTextColumn _instructions;
|
||||
@override
|
||||
GeneratedTextColumn get instructions =>
|
||||
_instructions ??= _constructInstructions();
|
||||
late final GeneratedTextColumn instructions = _constructInstructions();
|
||||
GeneratedTextColumn _constructInstructions() {
|
||||
return GeneratedTextColumn(
|
||||
'instructions',
|
||||
|
@ -435,9 +417,8 @@ class $RecipesTable extends Recipes with TableInfo<$RecipesTable, Recipe> {
|
|||
}
|
||||
|
||||
final VerificationMeta _categoryMeta = const VerificationMeta('category');
|
||||
GeneratedIntColumn _category;
|
||||
@override
|
||||
GeneratedIntColumn get category => _category ??= _constructCategory();
|
||||
late final GeneratedIntColumn category = _constructCategory();
|
||||
GeneratedIntColumn _constructCategory() {
|
||||
return GeneratedIntColumn(
|
||||
'category',
|
||||
|
@ -460,11 +441,11 @@ class $RecipesTable extends Recipes with TableInfo<$RecipesTable, Recipe> {
|
|||
final context = VerificationContext();
|
||||
final data = instance.toColumns(true);
|
||||
if (data.containsKey('id')) {
|
||||
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id'], _idMeta));
|
||||
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
||||
}
|
||||
if (data.containsKey('title')) {
|
||||
context.handle(
|
||||
_titleMeta, title.isAcceptableOrUnknown(data['title'], _titleMeta));
|
||||
_titleMeta, title.isAcceptableOrUnknown(data['title']!, _titleMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_titleMeta);
|
||||
}
|
||||
|
@ -472,13 +453,13 @@ class $RecipesTable extends Recipes with TableInfo<$RecipesTable, Recipe> {
|
|||
context.handle(
|
||||
_instructionsMeta,
|
||||
instructions.isAcceptableOrUnknown(
|
||||
data['instructions'], _instructionsMeta));
|
||||
data['instructions']!, _instructionsMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_instructionsMeta);
|
||||
}
|
||||
if (data.containsKey('category')) {
|
||||
context.handle(_categoryMeta,
|
||||
category.isAcceptableOrUnknown(data['category'], _categoryMeta));
|
||||
category.isAcceptableOrUnknown(data['category']!, _categoryMeta));
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
@ -486,7 +467,7 @@ class $RecipesTable extends Recipes with TableInfo<$RecipesTable, Recipe> {
|
|||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => {id};
|
||||
@override
|
||||
Recipe map(Map<String, dynamic> data, {String tablePrefix}) {
|
||||
Recipe map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null;
|
||||
return Recipe.fromData(data, _db, prefix: effectivePrefix);
|
||||
}
|
||||
|
@ -502,46 +483,38 @@ class Ingredient extends DataClass implements Insertable<Ingredient> {
|
|||
final String name;
|
||||
final int caloriesPer100g;
|
||||
Ingredient(
|
||||
{@required this.id, @required this.name, @required this.caloriesPer100g});
|
||||
{required this.id, required this.name, required this.caloriesPer100g});
|
||||
factory Ingredient.fromData(Map<String, dynamic> data, GeneratedDatabase db,
|
||||
{String prefix}) {
|
||||
{String? prefix}) {
|
||||
final effectivePrefix = prefix ?? '';
|
||||
final intType = db.typeSystem.forDartType<int>();
|
||||
final stringType = db.typeSystem.forDartType<String>();
|
||||
return Ingredient(
|
||||
id: intType.mapFromDatabaseResponse(data['${effectivePrefix}id']),
|
||||
name: stringType.mapFromDatabaseResponse(data['${effectivePrefix}name']),
|
||||
id: intType.mapFromDatabaseResponse(data['${effectivePrefix}id'])!,
|
||||
name: stringType.mapFromDatabaseResponse(data['${effectivePrefix}name'])!,
|
||||
caloriesPer100g:
|
||||
intType.mapFromDatabaseResponse(data['${effectivePrefix}calories']),
|
||||
intType.mapFromDatabaseResponse(data['${effectivePrefix}calories'])!,
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
if (!nullToAbsent || id != null) {
|
||||
map['id'] = Variable<int>(id);
|
||||
}
|
||||
if (!nullToAbsent || name != null) {
|
||||
map['name'] = Variable<String>(name);
|
||||
}
|
||||
if (!nullToAbsent || caloriesPer100g != null) {
|
||||
map['calories'] = Variable<int>(caloriesPer100g);
|
||||
}
|
||||
map['id'] = Variable<int>(id);
|
||||
map['name'] = Variable<String>(name);
|
||||
map['calories'] = Variable<int>(caloriesPer100g);
|
||||
return map;
|
||||
}
|
||||
|
||||
IngredientsCompanion toCompanion(bool nullToAbsent) {
|
||||
return IngredientsCompanion(
|
||||
id: id == null && nullToAbsent ? const Value.absent() : Value(id),
|
||||
name: name == null && nullToAbsent ? const Value.absent() : Value(name),
|
||||
caloriesPer100g: caloriesPer100g == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(caloriesPer100g),
|
||||
id: Value(id),
|
||||
name: Value(name),
|
||||
caloriesPer100g: Value(caloriesPer100g),
|
||||
);
|
||||
}
|
||||
|
||||
factory Ingredient.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer serializer}) {
|
||||
{ValueSerializer? serializer}) {
|
||||
serializer ??= moorRuntimeOptions.defaultSerializer;
|
||||
return Ingredient(
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
|
@ -550,12 +523,12 @@ class Ingredient extends DataClass implements Insertable<Ingredient> {
|
|||
);
|
||||
}
|
||||
factory Ingredient.fromJsonString(String encodedJson,
|
||||
{ValueSerializer serializer}) =>
|
||||
{ValueSerializer? serializer}) =>
|
||||
Ingredient.fromJson(
|
||||
DataClass.parseJson(encodedJson) as Map<String, dynamic>,
|
||||
serializer: serializer);
|
||||
@override
|
||||
Map<String, dynamic> toJson({ValueSerializer serializer}) {
|
||||
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
|
||||
serializer ??= moorRuntimeOptions.defaultSerializer;
|
||||
return <String, dynamic>{
|
||||
'id': serializer.toJson<int>(id),
|
||||
|
@ -564,7 +537,8 @@ class Ingredient extends DataClass implements Insertable<Ingredient> {
|
|||
};
|
||||
}
|
||||
|
||||
Ingredient copyWith({int id, String name, int caloriesPer100g}) => Ingredient(
|
||||
Ingredient copyWith({int? id, String? name, int? caloriesPer100g}) =>
|
||||
Ingredient(
|
||||
id: id ?? this.id,
|
||||
name: name ?? this.name,
|
||||
caloriesPer100g: caloriesPer100g ?? this.caloriesPer100g,
|
||||
|
@ -602,14 +576,14 @@ class IngredientsCompanion extends UpdateCompanion<Ingredient> {
|
|||
});
|
||||
IngredientsCompanion.insert({
|
||||
this.id = const Value.absent(),
|
||||
@required String name,
|
||||
@required int caloriesPer100g,
|
||||
}) : name = Value(name),
|
||||
required String name,
|
||||
required int caloriesPer100g,
|
||||
}) : name = Value(name),
|
||||
caloriesPer100g = Value(caloriesPer100g);
|
||||
static Insertable<Ingredient> custom({
|
||||
Expression<int> id,
|
||||
Expression<String> name,
|
||||
Expression<int> caloriesPer100g,
|
||||
Expression<int>? id,
|
||||
Expression<String>? name,
|
||||
Expression<int>? caloriesPer100g,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (id != null) 'id': id,
|
||||
|
@ -619,7 +593,7 @@ class IngredientsCompanion extends UpdateCompanion<Ingredient> {
|
|||
}
|
||||
|
||||
IngredientsCompanion copyWith(
|
||||
{Value<int> id, Value<String> name, Value<int> caloriesPer100g}) {
|
||||
{Value<int>? id, Value<String>? name, Value<int>? caloriesPer100g}) {
|
||||
return IngredientsCompanion(
|
||||
id: id ?? this.id,
|
||||
name: name ?? this.name,
|
||||
|
@ -656,21 +630,19 @@ class IngredientsCompanion extends UpdateCompanion<Ingredient> {
|
|||
class $IngredientsTable extends Ingredients
|
||||
with TableInfo<$IngredientsTable, Ingredient> {
|
||||
final GeneratedDatabase _db;
|
||||
final String _alias;
|
||||
final String? _alias;
|
||||
$IngredientsTable(this._db, [this._alias]);
|
||||
final VerificationMeta _idMeta = const VerificationMeta('id');
|
||||
GeneratedIntColumn _id;
|
||||
@override
|
||||
GeneratedIntColumn get id => _id ??= _constructId();
|
||||
late final GeneratedIntColumn id = _constructId();
|
||||
GeneratedIntColumn _constructId() {
|
||||
return GeneratedIntColumn('id', $tableName, false,
|
||||
hasAutoIncrement: true, declaredAsPrimaryKey: true);
|
||||
}
|
||||
|
||||
final VerificationMeta _nameMeta = const VerificationMeta('name');
|
||||
GeneratedTextColumn _name;
|
||||
@override
|
||||
GeneratedTextColumn get name => _name ??= _constructName();
|
||||
late final GeneratedTextColumn name = _constructName();
|
||||
GeneratedTextColumn _constructName() {
|
||||
return GeneratedTextColumn(
|
||||
'name',
|
||||
|
@ -681,10 +653,8 @@ class $IngredientsTable extends Ingredients
|
|||
|
||||
final VerificationMeta _caloriesPer100gMeta =
|
||||
const VerificationMeta('caloriesPer100g');
|
||||
GeneratedIntColumn _caloriesPer100g;
|
||||
@override
|
||||
GeneratedIntColumn get caloriesPer100g =>
|
||||
_caloriesPer100g ??= _constructCaloriesPer100g();
|
||||
late final GeneratedIntColumn caloriesPer100g = _constructCaloriesPer100g();
|
||||
GeneratedIntColumn _constructCaloriesPer100g() {
|
||||
return GeneratedIntColumn(
|
||||
'calories',
|
||||
|
@ -707,11 +677,11 @@ class $IngredientsTable extends Ingredients
|
|||
final context = VerificationContext();
|
||||
final data = instance.toColumns(true);
|
||||
if (data.containsKey('id')) {
|
||||
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id'], _idMeta));
|
||||
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
||||
}
|
||||
if (data.containsKey('name')) {
|
||||
context.handle(
|
||||
_nameMeta, name.isAcceptableOrUnknown(data['name'], _nameMeta));
|
||||
_nameMeta, name.isAcceptableOrUnknown(data['name']!, _nameMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_nameMeta);
|
||||
}
|
||||
|
@ -719,7 +689,7 @@ class $IngredientsTable extends Ingredients
|
|||
context.handle(
|
||||
_caloriesPer100gMeta,
|
||||
caloriesPer100g.isAcceptableOrUnknown(
|
||||
data['calories'], _caloriesPer100gMeta));
|
||||
data['calories']!, _caloriesPer100gMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_caloriesPer100gMeta);
|
||||
}
|
||||
|
@ -729,7 +699,7 @@ class $IngredientsTable extends Ingredients
|
|||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => {id};
|
||||
@override
|
||||
Ingredient map(Map<String, dynamic> data, {String tablePrefix}) {
|
||||
Ingredient map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null;
|
||||
return Ingredient.fromData(data, _db, prefix: effectivePrefix);
|
||||
}
|
||||
|
@ -746,52 +716,42 @@ class IngredientInRecipe extends DataClass
|
|||
final int ingredient;
|
||||
final int amountInGrams;
|
||||
IngredientInRecipe(
|
||||
{@required this.recipe,
|
||||
@required this.ingredient,
|
||||
@required this.amountInGrams});
|
||||
{required this.recipe,
|
||||
required this.ingredient,
|
||||
required this.amountInGrams});
|
||||
factory IngredientInRecipe.fromData(
|
||||
Map<String, dynamic> data, GeneratedDatabase db,
|
||||
{String prefix}) {
|
||||
{String? prefix}) {
|
||||
final effectivePrefix = prefix ?? '';
|
||||
final intType = db.typeSystem.forDartType<int>();
|
||||
return IngredientInRecipe(
|
||||
recipe: intType.mapFromDatabaseResponse(data['${effectivePrefix}recipe']),
|
||||
ingredient:
|
||||
intType.mapFromDatabaseResponse(data['${effectivePrefix}ingredient']),
|
||||
recipe:
|
||||
intType.mapFromDatabaseResponse(data['${effectivePrefix}recipe'])!,
|
||||
ingredient: intType
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}ingredient'])!,
|
||||
amountInGrams:
|
||||
intType.mapFromDatabaseResponse(data['${effectivePrefix}amount']),
|
||||
intType.mapFromDatabaseResponse(data['${effectivePrefix}amount'])!,
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
if (!nullToAbsent || recipe != null) {
|
||||
map['recipe'] = Variable<int>(recipe);
|
||||
}
|
||||
if (!nullToAbsent || ingredient != null) {
|
||||
map['ingredient'] = Variable<int>(ingredient);
|
||||
}
|
||||
if (!nullToAbsent || amountInGrams != null) {
|
||||
map['amount'] = Variable<int>(amountInGrams);
|
||||
}
|
||||
map['recipe'] = Variable<int>(recipe);
|
||||
map['ingredient'] = Variable<int>(ingredient);
|
||||
map['amount'] = Variable<int>(amountInGrams);
|
||||
return map;
|
||||
}
|
||||
|
||||
IngredientInRecipesCompanion toCompanion(bool nullToAbsent) {
|
||||
return IngredientInRecipesCompanion(
|
||||
recipe:
|
||||
recipe == null && nullToAbsent ? const Value.absent() : Value(recipe),
|
||||
ingredient: ingredient == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(ingredient),
|
||||
amountInGrams: amountInGrams == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(amountInGrams),
|
||||
recipe: Value(recipe),
|
||||
ingredient: Value(ingredient),
|
||||
amountInGrams: Value(amountInGrams),
|
||||
);
|
||||
}
|
||||
|
||||
factory IngredientInRecipe.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer serializer}) {
|
||||
{ValueSerializer? serializer}) {
|
||||
serializer ??= moorRuntimeOptions.defaultSerializer;
|
||||
return IngredientInRecipe(
|
||||
recipe: serializer.fromJson<int>(json['recipe']),
|
||||
|
@ -800,12 +760,12 @@ class IngredientInRecipe extends DataClass
|
|||
);
|
||||
}
|
||||
factory IngredientInRecipe.fromJsonString(String encodedJson,
|
||||
{ValueSerializer serializer}) =>
|
||||
{ValueSerializer? serializer}) =>
|
||||
IngredientInRecipe.fromJson(
|
||||
DataClass.parseJson(encodedJson) as Map<String, dynamic>,
|
||||
serializer: serializer);
|
||||
@override
|
||||
Map<String, dynamic> toJson({ValueSerializer serializer}) {
|
||||
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
|
||||
serializer ??= moorRuntimeOptions.defaultSerializer;
|
||||
return <String, dynamic>{
|
||||
'recipe': serializer.toJson<int>(recipe),
|
||||
|
@ -815,7 +775,7 @@ class IngredientInRecipe extends DataClass
|
|||
}
|
||||
|
||||
IngredientInRecipe copyWith(
|
||||
{int recipe, int ingredient, int amountInGrams}) =>
|
||||
{int? recipe, int? ingredient, int? amountInGrams}) =>
|
||||
IngredientInRecipe(
|
||||
recipe: recipe ?? this.recipe,
|
||||
ingredient: ingredient ?? this.ingredient,
|
||||
|
@ -853,16 +813,16 @@ class IngredientInRecipesCompanion extends UpdateCompanion<IngredientInRecipe> {
|
|||
this.amountInGrams = const Value.absent(),
|
||||
});
|
||||
IngredientInRecipesCompanion.insert({
|
||||
@required int recipe,
|
||||
@required int ingredient,
|
||||
@required int amountInGrams,
|
||||
}) : recipe = Value(recipe),
|
||||
required int recipe,
|
||||
required int ingredient,
|
||||
required int amountInGrams,
|
||||
}) : recipe = Value(recipe),
|
||||
ingredient = Value(ingredient),
|
||||
amountInGrams = Value(amountInGrams);
|
||||
static Insertable<IngredientInRecipe> custom({
|
||||
Expression<int> recipe,
|
||||
Expression<int> ingredient,
|
||||
Expression<int> amountInGrams,
|
||||
Expression<int>? recipe,
|
||||
Expression<int>? ingredient,
|
||||
Expression<int>? amountInGrams,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (recipe != null) 'recipe': recipe,
|
||||
|
@ -872,7 +832,7 @@ class IngredientInRecipesCompanion extends UpdateCompanion<IngredientInRecipe> {
|
|||
}
|
||||
|
||||
IngredientInRecipesCompanion copyWith(
|
||||
{Value<int> recipe, Value<int> ingredient, Value<int> amountInGrams}) {
|
||||
{Value<int>? recipe, Value<int>? ingredient, Value<int>? amountInGrams}) {
|
||||
return IngredientInRecipesCompanion(
|
||||
recipe: recipe ?? this.recipe,
|
||||
ingredient: ingredient ?? this.ingredient,
|
||||
|
@ -909,12 +869,11 @@ class IngredientInRecipesCompanion extends UpdateCompanion<IngredientInRecipe> {
|
|||
class $IngredientInRecipesTable extends IngredientInRecipes
|
||||
with TableInfo<$IngredientInRecipesTable, IngredientInRecipe> {
|
||||
final GeneratedDatabase _db;
|
||||
final String _alias;
|
||||
final String? _alias;
|
||||
$IngredientInRecipesTable(this._db, [this._alias]);
|
||||
final VerificationMeta _recipeMeta = const VerificationMeta('recipe');
|
||||
GeneratedIntColumn _recipe;
|
||||
@override
|
||||
GeneratedIntColumn get recipe => _recipe ??= _constructRecipe();
|
||||
late final GeneratedIntColumn recipe = _constructRecipe();
|
||||
GeneratedIntColumn _constructRecipe() {
|
||||
return GeneratedIntColumn(
|
||||
'recipe',
|
||||
|
@ -924,9 +883,8 @@ class $IngredientInRecipesTable extends IngredientInRecipes
|
|||
}
|
||||
|
||||
final VerificationMeta _ingredientMeta = const VerificationMeta('ingredient');
|
||||
GeneratedIntColumn _ingredient;
|
||||
@override
|
||||
GeneratedIntColumn get ingredient => _ingredient ??= _constructIngredient();
|
||||
late final GeneratedIntColumn ingredient = _constructIngredient();
|
||||
GeneratedIntColumn _constructIngredient() {
|
||||
return GeneratedIntColumn(
|
||||
'ingredient',
|
||||
|
@ -937,10 +895,8 @@ class $IngredientInRecipesTable extends IngredientInRecipes
|
|||
|
||||
final VerificationMeta _amountInGramsMeta =
|
||||
const VerificationMeta('amountInGrams');
|
||||
GeneratedIntColumn _amountInGrams;
|
||||
@override
|
||||
GeneratedIntColumn get amountInGrams =>
|
||||
_amountInGrams ??= _constructAmountInGrams();
|
||||
late final GeneratedIntColumn amountInGrams = _constructAmountInGrams();
|
||||
GeneratedIntColumn _constructAmountInGrams() {
|
||||
return GeneratedIntColumn(
|
||||
'amount',
|
||||
|
@ -964,7 +920,7 @@ class $IngredientInRecipesTable extends IngredientInRecipes
|
|||
final data = instance.toColumns(true);
|
||||
if (data.containsKey('recipe')) {
|
||||
context.handle(_recipeMeta,
|
||||
recipe.isAcceptableOrUnknown(data['recipe'], _recipeMeta));
|
||||
recipe.isAcceptableOrUnknown(data['recipe']!, _recipeMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_recipeMeta);
|
||||
}
|
||||
|
@ -972,7 +928,7 @@ class $IngredientInRecipesTable extends IngredientInRecipes
|
|||
context.handle(
|
||||
_ingredientMeta,
|
||||
ingredient.isAcceptableOrUnknown(
|
||||
data['ingredient'], _ingredientMeta));
|
||||
data['ingredient']!, _ingredientMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_ingredientMeta);
|
||||
}
|
||||
|
@ -980,7 +936,7 @@ class $IngredientInRecipesTable extends IngredientInRecipes
|
|||
context.handle(
|
||||
_amountInGramsMeta,
|
||||
amountInGrams.isAcceptableOrUnknown(
|
||||
data['amount'], _amountInGramsMeta));
|
||||
data['amount']!, _amountInGramsMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_amountInGramsMeta);
|
||||
}
|
||||
|
@ -990,7 +946,7 @@ class $IngredientInRecipesTable extends IngredientInRecipes
|
|||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => {recipe, ingredient};
|
||||
@override
|
||||
IngredientInRecipe map(Map<String, dynamic> data, {String tablePrefix}) {
|
||||
IngredientInRecipe map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null;
|
||||
return IngredientInRecipe.fromData(data, _db, prefix: effectivePrefix);
|
||||
}
|
||||
|
@ -1004,15 +960,11 @@ class $IngredientInRecipesTable extends IngredientInRecipes
|
|||
abstract class _$Database extends GeneratedDatabase {
|
||||
_$Database(QueryExecutor e) : super(SqlTypeSystem.defaultInstance, e);
|
||||
_$Database.connect(DatabaseConnection c) : super.connect(c);
|
||||
$CategoriesTable _categories;
|
||||
$CategoriesTable get categories => _categories ??= $CategoriesTable(this);
|
||||
$RecipesTable _recipes;
|
||||
$RecipesTable get recipes => _recipes ??= $RecipesTable(this);
|
||||
$IngredientsTable _ingredients;
|
||||
$IngredientsTable get ingredients => _ingredients ??= $IngredientsTable(this);
|
||||
$IngredientInRecipesTable _ingredientInRecipes;
|
||||
$IngredientInRecipesTable get ingredientInRecipes =>
|
||||
_ingredientInRecipes ??= $IngredientInRecipesTable(this);
|
||||
late final $CategoriesTable categories = $CategoriesTable(this);
|
||||
late final $RecipesTable recipes = $RecipesTable(this);
|
||||
late final $IngredientsTable ingredients = $IngredientsTable(this);
|
||||
late final $IngredientInRecipesTable ingredientInRecipes =
|
||||
$IngredientInRecipesTable(this);
|
||||
Selectable<TotalWeightResult> totalWeight() {
|
||||
return customSelect(
|
||||
'SELECT r.title, SUM(ir.amount) AS total_weight\n FROM recipes r\n INNER JOIN recipe_ingredients ir ON ir.recipe = r.id\n GROUP BY r.id',
|
||||
|
@ -1037,9 +989,9 @@ class TotalWeightResult extends CustomResultSet {
|
|||
final String title;
|
||||
final int totalWeight;
|
||||
TotalWeightResult({
|
||||
@required QueryRow row,
|
||||
this.title,
|
||||
this.totalWeight,
|
||||
required QueryRow row,
|
||||
required this.title,
|
||||
required this.totalWeight,
|
||||
}) : super(row);
|
||||
@override
|
||||
int get hashCode => $mrjf($mrjc(title.hashCode, totalWeight.hashCode));
|
||||
|
|
|
@ -12,7 +12,7 @@ import 'package:meta/meta.dart';
|
|||
import '../moor.dart';
|
||||
|
||||
/// Defines extensions on string expressions to support the json1 api from Dart.
|
||||
extension JsonExtensions on Expression<String> {
|
||||
extension JsonExtensions on Expression<String?> {
|
||||
/// Assuming that this string is a json array, returns the length of this json
|
||||
/// array.
|
||||
///
|
||||
|
@ -28,7 +28,7 @@ extension JsonExtensions on Expression<String> {
|
|||
///
|
||||
/// See also:
|
||||
/// - the [sqlite documentation for this function](https://www.sqlite.org/json1.html#the_json_array_length_function)
|
||||
Expression<int> jsonArrayLength([String path]) {
|
||||
Expression<int> jsonArrayLength([String? path]) {
|
||||
return FunctionCallExpression('json_array_length', [
|
||||
this,
|
||||
if (path != null) Variable.withString(path),
|
||||
|
|
|
@ -11,7 +11,7 @@ import 'package:moor/moor.dart';
|
|||
/// instead of `NaN`.
|
||||
///
|
||||
/// This function is only available when using `moor_ffi`.
|
||||
Expression<num> sqlPow(Expression<num> base, Expression<num> exponent) {
|
||||
Expression<num?> sqlPow(Expression<num?> base, Expression<num?> exponent) {
|
||||
return FunctionCallExpression('pow', [base, exponent]);
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ Expression<num> sqlPow(Expression<num> base, Expression<num> exponent) {
|
|||
/// of `NaN` for negative values.
|
||||
///
|
||||
/// This function is only available when using `moor_ffi`.
|
||||
Expression<num> sqlSqrt(Expression<num> value) {
|
||||
Expression<num?> sqlSqrt(Expression<num?> value) {
|
||||
return FunctionCallExpression('sqrt', [value]);
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ Expression<num> sqlSqrt(Expression<num> value) {
|
|||
/// This function is equivalent to [sin].
|
||||
///
|
||||
/// This function is only available when using `moor_ffi`.
|
||||
Expression<num> sqlSin(Expression<num> value) {
|
||||
Expression<num?> sqlSin(Expression<num?> value) {
|
||||
return FunctionCallExpression('sin', [value]);
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ Expression<num> sqlSin(Expression<num> value) {
|
|||
/// This function is equivalent to [sin].
|
||||
///
|
||||
/// This function is only available when using `moor_ffi`.
|
||||
Expression<num> sqlCos(Expression<num> value) {
|
||||
Expression<num?> sqlCos(Expression<num?> value) {
|
||||
return FunctionCallExpression('cos', [value]);
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ Expression<num> sqlCos(Expression<num> value) {
|
|||
/// This function is equivalent to [tan].
|
||||
///
|
||||
/// This function is only available when using `moor_ffi`.
|
||||
Expression<num> sqlTan(Expression<num> value) {
|
||||
Expression<num?> sqlTan(Expression<num?> value) {
|
||||
return FunctionCallExpression('tan', [value]);
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ Expression<num> sqlTan(Expression<num> value) {
|
|||
/// instead of `NaN`.
|
||||
///
|
||||
/// This function is only available when using `moor_ffi`.
|
||||
Expression<num> sqlAsin(Expression<num> value) {
|
||||
Expression<num?> sqlAsin(Expression<num?> value) {
|
||||
return FunctionCallExpression('asin', [value]);
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ Expression<num> sqlAsin(Expression<num> value) {
|
|||
/// instead of `NaN`.
|
||||
///
|
||||
/// This function is only available when using `moor_ffi`.
|
||||
Expression<num> sqlAcos(Expression<num> value) {
|
||||
Expression<num?> sqlAcos(Expression<num?> value) {
|
||||
return FunctionCallExpression('acos', [value]);
|
||||
}
|
||||
|
||||
|
@ -78,13 +78,13 @@ Expression<num> sqlAcos(Expression<num> value) {
|
|||
/// instead of `NaN`.
|
||||
///
|
||||
/// This function is only available when using `moor_ffi`.
|
||||
Expression<num> sqlAtan(Expression<num> value) {
|
||||
Expression<num?> sqlAtan(Expression<num?> value) {
|
||||
return FunctionCallExpression('atan', [value]);
|
||||
}
|
||||
|
||||
/// Adds functionality to string expressions that only work when using
|
||||
/// `moor_ffi`.
|
||||
extension MoorFfiSpecificStringExtensions on Expression<String> {
|
||||
extension MoorFfiSpecificStringExtensions on Expression<String?> {
|
||||
/// Version of `contains` that allows controlling case sensitivity better.
|
||||
///
|
||||
/// The default `contains` method uses sqlite's `LIKE`, which is case-
|
||||
|
@ -102,7 +102,7 @@ extension MoorFfiSpecificStringExtensions on Expression<String> {
|
|||
///
|
||||
/// Note that this is only available when using `moor_ffi` version 0.6.0 or
|
||||
/// greater.
|
||||
Expression<bool> containsCase(String substring,
|
||||
Expression<bool?> containsCase(String substring,
|
||||
{bool caseSensitive = false}) {
|
||||
return FunctionCallExpression('moor_contains', [
|
||||
this,
|
||||
|
|
|
@ -8,24 +8,24 @@ abstract class Column<T> extends Expression<T> {
|
|||
}
|
||||
|
||||
/// A column that stores int values.
|
||||
abstract class IntColumn extends Column<int> {}
|
||||
abstract class IntColumn extends Column<int?> {}
|
||||
|
||||
/// A column that stores boolean values. Booleans will be stored as an integer
|
||||
/// that can either be 0 (false) or 1 (true).
|
||||
abstract class BoolColumn extends Column<bool> {}
|
||||
abstract class BoolColumn extends Column<bool?> {}
|
||||
|
||||
/// A column that stores text.
|
||||
abstract class TextColumn extends Column<String> {}
|
||||
abstract class TextColumn extends Column<String?> {}
|
||||
|
||||
/// A column that stores a [DateTime]. Times will be stored as unix timestamp
|
||||
/// and will thus have a second accuracy.
|
||||
abstract class DateTimeColumn extends Column<DateTime> {}
|
||||
abstract class DateTimeColumn extends Column<DateTime?> {}
|
||||
|
||||
/// A column that stores arbitrary blobs of data as a [Uint8List].
|
||||
abstract class BlobColumn extends Column<Uint8List> {}
|
||||
abstract class BlobColumn extends Column<Uint8List?> {}
|
||||
|
||||
/// A column that stores floating point numeric values.
|
||||
abstract class RealColumn extends Column<double> {}
|
||||
abstract class RealColumn extends Column<double?> {}
|
||||
|
||||
/// A column builder is used to specify which columns should appear in a table.
|
||||
/// All of the methods defined in this class and its subclasses are not meant to
|
||||
|
@ -173,7 +173,8 @@ class ColumnBuilder<Builder, ResultColumn extends Column<ResultDartType>,
|
|||
|
||||
/// Tells the generator to build an [IntColumn]. See the docs at [ColumnBuilder]
|
||||
/// for details.
|
||||
class IntColumnBuilder extends ColumnBuilder<IntColumnBuilder, IntColumn, int> {
|
||||
class IntColumnBuilder
|
||||
extends ColumnBuilder<IntColumnBuilder, IntColumn, int?> {
|
||||
/// Enables auto-increment for this column, which will also make this column
|
||||
/// the primary key of the table.
|
||||
///
|
||||
|
@ -185,35 +186,37 @@ class IntColumnBuilder extends ColumnBuilder<IntColumnBuilder, IntColumn, int> {
|
|||
/// Tells the generator to build an [BoolColumn]. See the docs at
|
||||
/// [ColumnBuilder] for details.
|
||||
class BoolColumnBuilder
|
||||
extends ColumnBuilder<BoolColumnBuilder, BoolColumn, bool> {}
|
||||
extends ColumnBuilder<BoolColumnBuilder, BoolColumn, bool?> {}
|
||||
|
||||
/// Tells the generator to build an [BlobColumn]. See the docs at
|
||||
/// [ColumnBuilder] for details.
|
||||
class BlobColumnBuilder
|
||||
extends ColumnBuilder<BlobColumnBuilder, BlobColumn, Uint8List> {}
|
||||
extends ColumnBuilder<BlobColumnBuilder, BlobColumn, Uint8List?> {}
|
||||
|
||||
/// Tells the generator to build an [RealColumn]. See the docs at
|
||||
/// [ColumnBuilder] for details.
|
||||
class RealColumnBuilder
|
||||
extends ColumnBuilder<RealColumnBuilder, RealColumn, num> {}
|
||||
extends ColumnBuilder<RealColumnBuilder, RealColumn, num?> {}
|
||||
|
||||
/// Tells the generator to build an [TextColumn]. See the docs at
|
||||
/// [ColumnBuilder] for details.
|
||||
class TextColumnBuilder
|
||||
extends ColumnBuilder<TextColumnBuilder, TextColumn, String> {
|
||||
extends ColumnBuilder<TextColumnBuilder, TextColumn, String?> {
|
||||
/// Puts a constraint on the minimum and maximum length of text that can be
|
||||
/// stored in this column (will be validated whenever this column is updated
|
||||
/// or a value is inserted). If [min] is not null and one tries to write a
|
||||
/// string so that [String.length] is smaller than [min], the query will throw
|
||||
/// an exception when executed and no data will be written. The same applies
|
||||
/// for [max].
|
||||
TextColumnBuilder withLength({int min, int max}) => _isGenerated();
|
||||
/// stored in this column.
|
||||
///
|
||||
/// Both [min] and [max] are inclusive. This constraint will be validated in
|
||||
/// Dart, it doesn't have an impact on the database schema. If [min] is not
|
||||
/// null and one tries to write a string which [String.length] is
|
||||
/// _strictly less_ than [min], an exception will be thrown. Similarly, you
|
||||
/// can't insert strings with a length _strictly greater_ than [max].
|
||||
TextColumnBuilder withLength({int? min, int? max}) => _isGenerated();
|
||||
}
|
||||
|
||||
/// Tells the generator to build an [DateTimeColumn]. See the docs at
|
||||
/// [ColumnBuilder] for details.
|
||||
class DateTimeColumnBuilder
|
||||
extends ColumnBuilder<DateTimeColumnBuilder, DateTimeColumn, DateTime> {}
|
||||
extends ColumnBuilder<DateTimeColumnBuilder, DateTimeColumn, DateTime?> {}
|
||||
|
||||
/// Annotation to use on column getters inside of a [Table] to define the name
|
||||
/// of the column in the json used by [DataClass.toJson].
|
||||
|
|
|
@ -30,7 +30,7 @@ part 'table.dart';
|
|||
/// );
|
||||
/// }
|
||||
/// ```
|
||||
Null /* = Never */ _isGenerated() {
|
||||
Never _isGenerated() {
|
||||
throw UnsupportedError(
|
||||
'This method should not be called at runtime. Are you sure you re-ran the '
|
||||
'builder after changing your tables or databases?',
|
||||
|
|
|
@ -15,7 +15,7 @@ abstract class Table {
|
|||
/// valid, whereas `@override final String tableName = 'my_table';` or
|
||||
/// `@override String get tableName => createMyTableName();` is not.
|
||||
@visibleForOverriding
|
||||
String get tableName => null;
|
||||
String? get tableName => null;
|
||||
|
||||
/// Whether to append a `WITHOUT ROWID` clause in the `CREATE TABLE`
|
||||
/// statement. This is intended to be used by generated code only.
|
||||
|
@ -45,7 +45,7 @@ abstract class Table {
|
|||
/// As an auto-incremented `IntColumn` is recognized by moor to be the
|
||||
/// primary key, doing so will result in an exception thrown at runtime.
|
||||
@visibleForOverriding
|
||||
Set<Column> get primaryKey => null;
|
||||
Set<Column>? get primaryKey => null;
|
||||
|
||||
/// Custom table constraints that should be added to the table.
|
||||
///
|
||||
|
|
|
@ -96,12 +96,12 @@ extension EnableMoorFunctions on Database {
|
|||
deterministic: true,
|
||||
directOnly: false,
|
||||
argumentCount: const AllowedArgumentCount(0),
|
||||
function: (List<dynamic> args) => DateTime.now().millisecondsSinceEpoch,
|
||||
function: (List<Object?> args) => DateTime.now().millisecondsSinceEpoch,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
num _pow(List<dynamic> args) {
|
||||
num? _pow(List<Object?> args) {
|
||||
final first = args[0];
|
||||
final second = args[1];
|
||||
|
||||
|
@ -109,7 +109,7 @@ num _pow(List<dynamic> args) {
|
|||
return null;
|
||||
}
|
||||
|
||||
return pow(first as num, second as num);
|
||||
return pow(first, second);
|
||||
}
|
||||
|
||||
/// Base implementation for a sqlite function that takes one numerical argument
|
||||
|
@ -117,8 +117,8 @@ num _pow(List<dynamic> args) {
|
|||
///
|
||||
/// When not called with a number, returns will null. Otherwise, returns with
|
||||
/// [calculation].
|
||||
num Function(List<dynamic>) _unaryNumFunction(num Function(num) calculation) {
|
||||
return (List<dynamic> args) {
|
||||
num? Function(List<Object?>) _unaryNumFunction(num Function(num) calculation) {
|
||||
return (List<Object?> args) {
|
||||
// sqlite will ensure that this is only called with one argument
|
||||
final value = args[0];
|
||||
if (value is num) {
|
||||
|
@ -129,7 +129,7 @@ num Function(List<dynamic>) _unaryNumFunction(num Function(num) calculation) {
|
|||
};
|
||||
}
|
||||
|
||||
bool _regexpImpl(List<dynamic> args) {
|
||||
bool? _regexpImpl(List<Object?> args) {
|
||||
var multiLine = false;
|
||||
var caseSensitive = true;
|
||||
var unicode = false;
|
||||
|
@ -165,7 +165,7 @@ bool _regexpImpl(List<dynamic> args) {
|
|||
RegExp regex;
|
||||
try {
|
||||
regex = RegExp(
|
||||
firstParam as String,
|
||||
firstParam,
|
||||
multiLine: multiLine,
|
||||
caseSensitive: caseSensitive,
|
||||
unicode: unicode,
|
||||
|
@ -175,7 +175,7 @@ bool _regexpImpl(List<dynamic> args) {
|
|||
throw 'Invalid regex';
|
||||
}
|
||||
|
||||
return regex.hasMatch(secondParam as String);
|
||||
return regex.hasMatch(secondParam);
|
||||
}
|
||||
|
||||
bool _containsImpl(List<dynamic> args) {
|
||||
|
@ -193,12 +193,9 @@ bool _containsImpl(List<dynamic> args) {
|
|||
|
||||
final caseSensitive = argCount == 3 && args[2] == 1;
|
||||
|
||||
final firstAsString = first as String;
|
||||
final secondAsString = second as String;
|
||||
|
||||
final result = caseSensitive
|
||||
? firstAsString.contains(secondAsString)
|
||||
: firstAsString.toLowerCase().contains(secondAsString.toLowerCase());
|
||||
? first.contains(second)
|
||||
: first.toLowerCase().contains(second.toLowerCase());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -32,14 +32,15 @@ class VmDatabase extends DelegatedDatabase {
|
|||
/// SQLCipher implementations.
|
||||
/// {@endtemplate}
|
||||
factory VmDatabase(File file,
|
||||
{bool logStatements = false, DatabaseSetup setup}) {
|
||||
{bool logStatements = false, DatabaseSetup? setup}) {
|
||||
return VmDatabase._(_VmDelegate(file, setup), logStatements);
|
||||
}
|
||||
|
||||
/// Creates an in-memory database won't persist its changes on disk.
|
||||
///
|
||||
/// {@macro moor_vm_database_factory}
|
||||
factory VmDatabase.memory({bool logStatements = false, DatabaseSetup setup}) {
|
||||
factory VmDatabase.memory(
|
||||
{bool logStatements = false, DatabaseSetup? setup}) {
|
||||
return VmDatabase._(_VmDelegate(null, setup), logStatements);
|
||||
}
|
||||
|
||||
|
@ -51,7 +52,7 @@ class VmDatabase extends DelegatedDatabase {
|
|||
///
|
||||
/// {@macro moor_vm_database_factory}
|
||||
factory VmDatabase.opened(Database database,
|
||||
{bool logStatements = false, DatabaseSetup setup}) {
|
||||
{bool logStatements = false, DatabaseSetup? setup}) {
|
||||
return VmDatabase._(_VmDelegate._opened(database, setup), logStatements);
|
||||
}
|
||||
|
||||
|
@ -106,11 +107,11 @@ class VmDatabase extends DelegatedDatabase {
|
|||
}
|
||||
|
||||
class _VmDelegate extends DatabaseDelegate {
|
||||
Database _db;
|
||||
late Database _db;
|
||||
bool _isOpen = false;
|
||||
|
||||
final File file;
|
||||
final DatabaseSetup setup;
|
||||
final File? file;
|
||||
final DatabaseSetup? setup;
|
||||
|
||||
_VmDelegate(this.file, this.setup);
|
||||
|
||||
|
@ -122,14 +123,14 @@ class _VmDelegate extends DatabaseDelegate {
|
|||
TransactionDelegate get transactionDelegate => const NoTransactionDelegate();
|
||||
|
||||
@override
|
||||
DbVersionDelegate versionDelegate;
|
||||
late DbVersionDelegate versionDelegate;
|
||||
|
||||
@override
|
||||
Future<bool> get isOpen => Future.value(_isOpen);
|
||||
|
||||
@override
|
||||
Future<void> open(QueryExecutorUser user) async {
|
||||
if (_db == null) {
|
||||
if (!_isOpen) {
|
||||
_createDatabase();
|
||||
}
|
||||
_initializeDatabase();
|
||||
|
@ -138,7 +139,9 @@ class _VmDelegate extends DatabaseDelegate {
|
|||
}
|
||||
|
||||
void _createDatabase() {
|
||||
assert(_db == null);
|
||||
assert(!_isOpen);
|
||||
|
||||
final file = this.file;
|
||||
if (file != null) {
|
||||
// Create the parent directory if it doesn't exist. sqlite will emit
|
||||
// confusing misuse warnings otherwise
|
||||
|
@ -156,9 +159,7 @@ class _VmDelegate extends DatabaseDelegate {
|
|||
|
||||
void _initializeDatabase() {
|
||||
_db.useMoorVersions();
|
||||
if (setup != null) {
|
||||
setup(_db);
|
||||
}
|
||||
setup?.call(_db);
|
||||
versionDelegate = _VmVersionDelegate(_db);
|
||||
}
|
||||
|
||||
|
@ -181,7 +182,7 @@ class _VmDelegate extends DatabaseDelegate {
|
|||
return Future.value();
|
||||
}
|
||||
|
||||
Future _runWithArgs(String statement, List<dynamic> args) async {
|
||||
Future _runWithArgs(String statement, List<Object?> args) async {
|
||||
if (args.isEmpty) {
|
||||
_db.execute(statement);
|
||||
} else {
|
||||
|
@ -192,24 +193,24 @@ class _VmDelegate extends DatabaseDelegate {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<void> runCustom(String statement, List args) async {
|
||||
Future<void> runCustom(String statement, List<Object?> args) async {
|
||||
await _runWithArgs(statement, args);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> runInsert(String statement, List args) async {
|
||||
Future<int> runInsert(String statement, List<Object?> args) async {
|
||||
await _runWithArgs(statement, args);
|
||||
return _db.lastInsertRowId;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> runUpdate(String statement, List args) async {
|
||||
Future<int> runUpdate(String statement, List<Object?> args) async {
|
||||
await _runWithArgs(statement, args);
|
||||
return _db.getUpdatedRows();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<QueryResult> runSelect(String statement, List args) async {
|
||||
Future<QueryResult> runSelect(String statement, List<Object?> args) async {
|
||||
final stmt = _db.prepare(statement);
|
||||
final result = stmt.select(args);
|
||||
stmt.dispose();
|
||||
|
|
|
@ -38,7 +38,7 @@ class Batch {
|
|||
/// - [InsertStatement.insert], which would be used outside a [Batch].
|
||||
void insert<T extends Table, D extends DataClass>(
|
||||
TableInfo<T, D> table, Insertable<D> row,
|
||||
{InsertMode mode, DoUpdate<T, D> onConflict}) {
|
||||
{InsertMode? mode, DoUpdate<T, D>? onConflict}) {
|
||||
_addUpdate(table, UpdateKind.insert);
|
||||
final actualMode = mode ?? InsertMode.insert;
|
||||
final context = InsertStatement<Table, D>(_engine, table)
|
||||
|
@ -60,7 +60,7 @@ class Batch {
|
|||
/// support it. For details and examples, see [InsertStatement.insert].
|
||||
void insertAll<T extends Table, D extends DataClass>(
|
||||
TableInfo<T, D> table, List<Insertable<D>> rows,
|
||||
{InsertMode mode, DoUpdate<T, D> onConflict}) {
|
||||
{InsertMode? mode, DoUpdate<T, D>? onConflict}) {
|
||||
for (final row in rows) {
|
||||
insert<T, D>(table, row, mode: mode, onConflict: onConflict);
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ class Batch {
|
|||
/// [UpdateStatement.write] or the [documentation with examples](https://moor.simonbinder.eu/docs/getting-started/writing_queries/#updates-and-deletes)
|
||||
void update<T extends Table, D extends DataClass>(
|
||||
TableInfo<T, D> table, Insertable<D> row,
|
||||
{Expression<bool> Function(T table) where}) {
|
||||
{Expression<bool> Function(T table)? where}) {
|
||||
_addUpdate(table, UpdateKind.update);
|
||||
final stmt = UpdateStatement(_engine, table);
|
||||
if (where != null) stmt.where(where);
|
||||
|
@ -148,8 +148,8 @@ class Batch {
|
|||
/// See also:
|
||||
/// - [QueryEngine.customStatement], the equivalent method outside of
|
||||
/// batches.
|
||||
void customStatement(String sql, [List<dynamic> args]) {
|
||||
_addSqlAndArguments(sql, args);
|
||||
void customStatement(String sql, [List<dynamic>? args]) {
|
||||
_addSqlAndArguments(sql, args ?? const []);
|
||||
}
|
||||
|
||||
void _addContext(GenerationContext ctx) {
|
||||
|
@ -171,17 +171,17 @@ class Batch {
|
|||
await _engine.executor.ensureOpen(_engine.attachedDatabase);
|
||||
|
||||
if (_startTransaction) {
|
||||
TransactionExecutor transaction;
|
||||
TransactionExecutor? transaction;
|
||||
|
||||
try {
|
||||
transaction = _engine.executor.beginTransaction();
|
||||
await transaction.ensureOpen(null);
|
||||
await transaction.ensureOpen(_engine.attachedDatabase);
|
||||
|
||||
await _runWith(transaction);
|
||||
|
||||
await transaction.send();
|
||||
} catch (e) {
|
||||
await transaction.rollback();
|
||||
await transaction?.rollback();
|
||||
rethrow;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -52,12 +52,10 @@ class DatabaseConnection {
|
|||
return connection;
|
||||
}
|
||||
|
||||
final future = connection as Future<DatabaseConnection>;
|
||||
|
||||
return DatabaseConnection(
|
||||
SqlTypeSystem.defaultInstance,
|
||||
LazyDatabase(() async => (await future).executor),
|
||||
DelayedStreamQueryStore(future.then((conn) => conn.streamQueries)),
|
||||
LazyDatabase(() async => (await connection).executor),
|
||||
DelayedStreamQueryStore(connection.then((conn) => conn.streamQueries)),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -89,16 +87,16 @@ abstract class DatabaseConnectionUser {
|
|||
/// Constructs a database connection user, which is responsible to store query
|
||||
/// streams, wrap the underlying executor and perform type mapping.
|
||||
DatabaseConnectionUser(SqlTypeSystem typeSystem, QueryExecutor executor,
|
||||
{StreamQueryStore streamQueries})
|
||||
{StreamQueryStore? streamQueries})
|
||||
: connection = DatabaseConnection(
|
||||
typeSystem, executor, streamQueries ?? StreamQueryStore());
|
||||
|
||||
/// Creates another [DatabaseConnectionUser] by referencing the implementation
|
||||
/// from the [other] user.
|
||||
DatabaseConnectionUser.delegate(DatabaseConnectionUser other,
|
||||
{SqlTypeSystem typeSystem,
|
||||
QueryExecutor executor,
|
||||
StreamQueryStore streamQueries})
|
||||
{SqlTypeSystem? typeSystem,
|
||||
QueryExecutor? executor,
|
||||
StreamQueryStore? streamQueries})
|
||||
: connection = DatabaseConnection(
|
||||
typeSystem ?? other.connection.typeSystem,
|
||||
executor ?? other.connection.executor,
|
||||
|
|
|
@ -30,7 +30,7 @@ abstract class GeneratedDatabase extends DatabaseConnectionUser
|
|||
/// changes in your schema, you'll need a custom migration strategy to create
|
||||
/// the new tables or change the columns.
|
||||
MigrationStrategy get migration => MigrationStrategy();
|
||||
MigrationStrategy _cachedMigration;
|
||||
MigrationStrategy? _cachedMigration;
|
||||
MigrationStrategy get _resolvedMigration => _cachedMigration ??= migration;
|
||||
|
||||
/// The collection of update rules contains information on how updates on
|
||||
|
@ -58,7 +58,7 @@ abstract class GeneratedDatabase extends DatabaseConnectionUser
|
|||
|
||||
/// Used by generated code
|
||||
GeneratedDatabase(SqlTypeSystem types, QueryExecutor executor,
|
||||
{StreamQueryStore streamStore})
|
||||
{StreamQueryStore? streamStore})
|
||||
: super(types, executor, streamQueries: streamStore) {
|
||||
assert(_handleInstantiated());
|
||||
}
|
||||
|
@ -75,7 +75,9 @@ abstract class GeneratedDatabase extends DatabaseConnectionUser
|
|||
_openedDbCount[runtimeType] = 1;
|
||||
return true;
|
||||
}
|
||||
final count = ++_openedDbCount[runtimeType];
|
||||
|
||||
final count =
|
||||
_openedDbCount[runtimeType] = _openedDbCount[runtimeType]! + 1;
|
||||
if (count > 1) {
|
||||
// ignore: avoid_print
|
||||
print(
|
||||
|
@ -117,7 +119,7 @@ abstract class GeneratedDatabase extends DatabaseConnectionUser
|
|||
} else if (details.hadUpgrade) {
|
||||
final migrator = createMigrator();
|
||||
await _resolvedMigration.onUpgrade(
|
||||
migrator, details.versionBefore, details.versionNow);
|
||||
migrator, details.versionBefore!, details.versionNow);
|
||||
}
|
||||
|
||||
await _resolvedMigration.beforeOpen?.call(details);
|
||||
|
@ -131,7 +133,7 @@ abstract class GeneratedDatabase extends DatabaseConnectionUser
|
|||
|
||||
assert(() {
|
||||
if (_openedDbCount[runtimeType] != null) {
|
||||
_openedDbCount[runtimeType]--;
|
||||
_openedDbCount[runtimeType] = _openedDbCount[runtimeType]! - 1;
|
||||
}
|
||||
return true;
|
||||
}());
|
||||
|
|
|
@ -47,7 +47,7 @@ mixin QueryEngine on DatabaseConnectionUser {
|
|||
// if an overridden executor has been specified for this zone (this will
|
||||
// happen for transactions), use that one.
|
||||
final resolved = Zone.current[_zoneRootUserKey];
|
||||
return (resolved as QueryEngine) ?? this;
|
||||
return (resolved as QueryEngine?) ?? this;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,8 +201,8 @@ mixin QueryEngine on DatabaseConnectionUser {
|
|||
Future<int> customUpdate(
|
||||
String query, {
|
||||
List<Variable> variables = const [],
|
||||
Set<TableInfo> updates,
|
||||
UpdateKind updateKind,
|
||||
Set<TableInfo>? updates,
|
||||
UpdateKind? updateKind,
|
||||
}) async {
|
||||
return _customWrite(
|
||||
query,
|
||||
|
@ -221,7 +221,7 @@ mixin QueryEngine on DatabaseConnectionUser {
|
|||
/// [updates] parameter. Query-streams running on any of these tables will
|
||||
/// then be re-run.
|
||||
Future<int> customInsert(String query,
|
||||
{List<Variable> variables = const [], Set<TableInfo> updates}) {
|
||||
{List<Variable> variables = const [], Set<TableInfo>? updates}) {
|
||||
return _customWrite(
|
||||
query,
|
||||
variables,
|
||||
|
@ -239,8 +239,8 @@ mixin QueryEngine on DatabaseConnectionUser {
|
|||
Future<T> _customWrite<T>(
|
||||
String query,
|
||||
List<Variable> variables,
|
||||
Set<TableInfo> updates,
|
||||
UpdateKind updateKind,
|
||||
Set<TableInfo>? updates,
|
||||
UpdateKind? updateKind,
|
||||
_CustomWriter<T> writer,
|
||||
) async {
|
||||
final engine = _resolvedEngine;
|
||||
|
@ -273,7 +273,6 @@ mixin QueryEngine on DatabaseConnectionUser {
|
|||
Selectable<QueryRow> customSelect(String query,
|
||||
{List<Variable> variables = const [],
|
||||
Set<TableInfo> readsFrom = const {}}) {
|
||||
readsFrom ??= {};
|
||||
return CustomSelectStatement(query, variables, readsFrom, _resolvedEngine);
|
||||
}
|
||||
|
||||
|
@ -294,7 +293,7 @@ mixin QueryEngine on DatabaseConnectionUser {
|
|||
}
|
||||
|
||||
/// Executes the custom sql [statement] on the database.
|
||||
Future<void> customStatement(String statement, [List<dynamic> args]) {
|
||||
Future<void> customStatement(String statement, [List<dynamic>? args]) {
|
||||
final engine = _resolvedEngine;
|
||||
|
||||
return engine.doWhenOpened((executor) {
|
||||
|
@ -408,7 +407,7 @@ mixin QueryEngine on DatabaseConnectionUser {
|
|||
|
||||
/// Will be used by generated code to resolve inline Dart components in sql.
|
||||
@protected
|
||||
GenerationContext $write(Component component, {bool hasMultipleTables}) {
|
||||
GenerationContext $write(Component component, {bool? hasMultipleTables}) {
|
||||
final context = GenerationContext.fromDb(this);
|
||||
if (hasMultipleTables != null) {
|
||||
context.hasMultipleTables = hasMultipleTables;
|
||||
|
|
|
@ -60,8 +60,7 @@ class WritePropagation extends UpdateRule {
|
|||
final List<TableUpdate> result;
|
||||
|
||||
/// Default constructor. See [WritePropagation] for details.
|
||||
const WritePropagation({@required this.on, @required this.result})
|
||||
: super._();
|
||||
const WritePropagation({required this.on, required this.result}) : super._();
|
||||
}
|
||||
|
||||
/// Classifies a [TableUpdate] by what kind of write happened - an insert, an
|
||||
|
@ -83,7 +82,7 @@ class TableUpdate {
|
|||
/// What kind of update was applied to the [table].
|
||||
///
|
||||
/// Can be null, which indicates that the update is not known.
|
||||
final UpdateKind /*?*/ kind;
|
||||
final UpdateKind? kind;
|
||||
|
||||
/// Name of the table that was updated.
|
||||
final String table;
|
||||
|
@ -93,7 +92,7 @@ class TableUpdate {
|
|||
|
||||
/// Creates a [TableUpdate] instance based on a [TableInfo] instead of the raw
|
||||
/// name.
|
||||
factory TableUpdate.onTable(TableInfo table, {UpdateKind kind}) {
|
||||
factory TableUpdate.onTable(TableInfo table, {UpdateKind? kind}) {
|
||||
return TableUpdate(table.actualTableName, kind: kind);
|
||||
}
|
||||
|
||||
|
@ -131,14 +130,14 @@ abstract class TableUpdateQuery {
|
|||
/// The optional [limitUpdateKind] parameter can be used to limit the updates
|
||||
/// to a certain kind.
|
||||
const factory TableUpdateQuery.onTableName(String table,
|
||||
{UpdateKind limitUpdateKind}) = SpecificUpdateQuery;
|
||||
{UpdateKind? limitUpdateKind}) = SpecificUpdateQuery;
|
||||
|
||||
/// A query that listens for all updates on a specific [table].
|
||||
///
|
||||
/// The optional [limitUpdateKind] parameter can be used to limit the updates
|
||||
/// to a certain kind.
|
||||
factory TableUpdateQuery.onTable(TableInfo table,
|
||||
{UpdateKind limitUpdateKind}) {
|
||||
{UpdateKind? limitUpdateKind}) {
|
||||
return TableUpdateQuery.onTableName(
|
||||
table.actualTableName,
|
||||
limitUpdateKind: limitUpdateKind,
|
||||
|
|
|
@ -32,13 +32,13 @@ abstract class DataClass {
|
|||
/// [json]. The [serializer] can be used to configure how individual values
|
||||
/// will be encoded. By default, [MoorRuntimeOptions.defaultSerializer] will
|
||||
/// be used. See [ValueSerializer.defaults] for details.
|
||||
Map<String, dynamic> toJson({ValueSerializer serializer});
|
||||
Map<String, dynamic> toJson({ValueSerializer? serializer});
|
||||
|
||||
/// Converts this object into a json representation. The [serializer] can be
|
||||
/// used to configure how individual values will be encoded. By default,
|
||||
/// [MoorRuntimeOptions.defaultSerializer] will be used. See
|
||||
/// [ValueSerializer.defaults] for details.
|
||||
String toJsonString({ValueSerializer serializer}) {
|
||||
String toJsonString({ValueSerializer? serializer}) {
|
||||
return json.encode(toJson(serializer: serializer));
|
||||
}
|
||||
|
||||
|
@ -73,11 +73,7 @@ abstract class UpdateCompanion<D extends DataClass> implements Insertable<D> {
|
|||
if (identical(this, other)) return true;
|
||||
if (other is! UpdateCompanion<D>) return false;
|
||||
|
||||
return _mapEquality.equals(
|
||||
// ignore: test_types_in_equals
|
||||
(other as UpdateCompanion<D>).toColumns(false),
|
||||
toColumns(false),
|
||||
);
|
||||
return _mapEquality.equals(other.toColumns(false), toColumns(false));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,16 +107,20 @@ class Value<T> {
|
|||
/// inserted or updated.
|
||||
final bool present;
|
||||
|
||||
final T? _value;
|
||||
|
||||
/// If this value is [present], contains the value to update or insert.
|
||||
final T value;
|
||||
T get value => _value as T;
|
||||
|
||||
/// Create a (present) value by wrapping the [value] provided.
|
||||
const Value(this.value) : present = true;
|
||||
const Value(T value)
|
||||
: _value = value,
|
||||
present = true;
|
||||
|
||||
/// Create an absent value that will not be written into the database, the
|
||||
/// default value or null will be used instead.
|
||||
const Value.absent()
|
||||
: value = null,
|
||||
: _value = null,
|
||||
present = false;
|
||||
|
||||
@override
|
||||
|
@ -164,20 +164,22 @@ class _DefaultValueSerializer extends ValueSerializer {
|
|||
@override
|
||||
T fromJson<T>(dynamic json) {
|
||||
if (json == null) {
|
||||
return null;
|
||||
return null as T;
|
||||
}
|
||||
|
||||
if (T == DateTime) {
|
||||
final _typeList = <T>[];
|
||||
|
||||
if (_typeList is List<DateTime?>) {
|
||||
return DateTime.fromMillisecondsSinceEpoch(json as int) as T;
|
||||
}
|
||||
|
||||
if (T == double && json is int) {
|
||||
if (_typeList is List<double> && json is int) {
|
||||
return json.toDouble() as T;
|
||||
}
|
||||
|
||||
// blobs are encoded as a regular json array, so we manually convert that to
|
||||
// a Uint8List
|
||||
if (T == Uint8List && json is! Uint8List) {
|
||||
if (_typeList is List<Uint8List> && json is! Uint8List) {
|
||||
final asList = (json as List).cast<int>();
|
||||
return Uint8List.fromList(asList) as T;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ class VerificationResult {
|
|||
|
||||
/// If not [success]-ful, contains a human readable description of what went
|
||||
/// wrong.
|
||||
final String message;
|
||||
final String? message;
|
||||
|
||||
/// Used internally by moor
|
||||
const VerificationResult(this.success, this.message);
|
||||
|
|
|
@ -23,14 +23,14 @@ class MoorWrappedException implements Exception {
|
|||
final String message;
|
||||
|
||||
/// The underlying exception caught by moor
|
||||
final dynamic cause;
|
||||
final Object? cause;
|
||||
|
||||
/// The original stacktrace when caught by moor
|
||||
final StackTrace trace;
|
||||
final StackTrace? trace;
|
||||
|
||||
/// Creates a new [MoorWrappedException] to provide additional details about
|
||||
/// an underlying error from the database.
|
||||
MoorWrappedException({this.message, this.cause, this.trace});
|
||||
MoorWrappedException({required this.message, this.cause, this.trace});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import 'package:meta/meta.dart';
|
||||
import 'package:moor/backends.dart';
|
||||
import 'package:moor/moor.dart';
|
||||
|
||||
|
@ -10,7 +9,7 @@ abstract class MultiExecutor extends QueryExecutor {
|
|||
/// with [write]. Select statements outside of a transaction are executed on
|
||||
/// [read].
|
||||
factory MultiExecutor(
|
||||
{@required QueryExecutor read, @required QueryExecutor write}) {
|
||||
{required QueryExecutor read, required QueryExecutor write}) {
|
||||
return _MultiExecutorImpl(read, write);
|
||||
}
|
||||
|
||||
|
@ -44,28 +43,28 @@ class _MultiExecutorImpl extends MultiExecutor {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<void> runCustom(String statement, [List args]) async {
|
||||
Future<void> runCustom(String statement, [List<Object?>? args]) async {
|
||||
await _writes.runCustom(statement, args);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> runDelete(String statement, List args) async {
|
||||
Future<int> runDelete(String statement, List<Object?> args) async {
|
||||
return await _writes.runDelete(statement, args);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> runInsert(String statement, List args) async {
|
||||
Future<int> runInsert(String statement, List<Object?> args) async {
|
||||
return await _writes.runInsert(statement, args);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Map<String, dynamic>>> runSelect(
|
||||
String statement, List args) async {
|
||||
Future<List<Map<String, Object?>>> runSelect(
|
||||
String statement, List<Object?> args) async {
|
||||
return await _reads.runSelect(statement, args);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> runUpdate(String statement, List args) async {
|
||||
Future<int> runUpdate(String statement, List<Object?> args) async {
|
||||
return await _writes.runUpdate(statement, args);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ import 'stream_queries.dart';
|
|||
/// This class is internal and should not be exposed to moor users. It's used
|
||||
/// through a delayed database connection.
|
||||
class DelayedStreamQueryStore implements StreamQueryStore {
|
||||
Future<StreamQueryStore> _delegate;
|
||||
StreamQueryStore _resolved;
|
||||
late Future<StreamQueryStore> _delegate;
|
||||
StreamQueryStore? _resolved;
|
||||
|
||||
/// Creates a [StreamQueryStore] that will work after [delegate] is
|
||||
/// available.
|
||||
|
|
|
@ -23,23 +23,23 @@ abstract class QueryExecutor {
|
|||
|
||||
/// Runs a select statement with the given variables and returns the raw
|
||||
/// results.
|
||||
Future<List<Map<String, dynamic>>> runSelect(
|
||||
String statement, List<dynamic> args);
|
||||
Future<List<Map<String, Object?>>> runSelect(
|
||||
String statement, List<Object?> args);
|
||||
|
||||
/// Runs an insert statement with the given variables. Returns the row id or
|
||||
/// the auto_increment id of the inserted row.
|
||||
Future<int> runInsert(String statement, List<dynamic> args);
|
||||
Future<int> runInsert(String statement, List<Object?> args);
|
||||
|
||||
/// Runs an update statement with the given variables and returns how many
|
||||
/// rows where affected.
|
||||
Future<int> runUpdate(String statement, List<dynamic> args);
|
||||
Future<int> runUpdate(String statement, List<Object?> args);
|
||||
|
||||
/// Runs an delete statement and returns how many rows where affected.
|
||||
Future<int> runDelete(String statement, List<dynamic> args);
|
||||
Future<int> runDelete(String statement, List<Object?> args);
|
||||
|
||||
/// Runs a custom SQL statement without any variables. The result of that
|
||||
/// statement will be ignored.
|
||||
Future<void> runCustom(String statement, [List<dynamic> args]);
|
||||
Future<void> runCustom(String statement, [List<Object?>? args]);
|
||||
|
||||
/// Prepares and runs [statements].
|
||||
///
|
||||
|
@ -119,7 +119,7 @@ class ArgumentsForBatchedStatement {
|
|||
final int statementIndex;
|
||||
|
||||
/// Bound arguments for the referenced statement.
|
||||
final List<dynamic> arguments;
|
||||
final List<Object?> arguments;
|
||||
|
||||
/// Used internally by moor.
|
||||
ArgumentsForBatchedStatement(this.statementIndex, this.arguments);
|
||||
|
|
|
@ -76,7 +76,7 @@ abstract class QueryDelegate {
|
|||
///
|
||||
/// If the statement can't be executed, an exception should be thrown. See
|
||||
/// the class documentation of [DatabaseDelegate] on what types are supported.
|
||||
Future<QueryResult> runSelect(String statement, List<dynamic> args);
|
||||
Future<QueryResult> runSelect(String statement, List<Object?> args);
|
||||
|
||||
/// Prepares and executes the [statement] with the variables bound to [args].
|
||||
/// The statement will either be an `UPDATE` or `DELETE` statement.
|
||||
|
@ -84,7 +84,7 @@ abstract class QueryDelegate {
|
|||
/// If the statement completes successfully, the amount of changed rows should
|
||||
/// be returned, or `0` if no rows where updated. Should throw if the
|
||||
/// statement can't be executed.
|
||||
Future<int> runUpdate(String statement, List<dynamic> args);
|
||||
Future<int> runUpdate(String statement, List<Object?> args);
|
||||
|
||||
/// Prepares and executes the [statement] with the variables bound to [args].
|
||||
/// The statement will be an `INSERT` statement.
|
||||
|
@ -92,11 +92,11 @@ abstract class QueryDelegate {
|
|||
/// If the statement completes successfully, the insert id of the row can be
|
||||
/// returned. If that information is not available, `null` can be returned.
|
||||
/// The method should throw if the statement can't be executed.
|
||||
Future<int> runInsert(String statement, List<dynamic> args);
|
||||
Future<int> runInsert(String statement, List<Object?> args);
|
||||
|
||||
/// Runs a custom [statement] with the given [args]. Ignores all results, but
|
||||
/// throws when the statement can't be executed.
|
||||
Future<void> runCustom(String statement, List<dynamic> args);
|
||||
Future<void> runCustom(String statement, List<Object?> args);
|
||||
|
||||
/// Runs multiple [statements] without having to prepare the same statement
|
||||
/// multiple times.
|
||||
|
|
|
@ -26,15 +26,15 @@ mixin _ExecutorWithQueryDelegate on QueryExecutor {
|
|||
}
|
||||
}
|
||||
|
||||
void _log(String sql, List<dynamic> args) {
|
||||
void _log(String sql, List<Object?> args) {
|
||||
if (logStatements) {
|
||||
print('Moor: Sent $sql with args $args');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Map<String, dynamic>>> runSelect(
|
||||
String statement, List args) async {
|
||||
Future<List<Map<String, Object?>>> runSelect(
|
||||
String statement, List<Object?> args) async {
|
||||
assert(_ensureOpenCalled);
|
||||
final result = await _synchronized(() {
|
||||
_log(statement, args);
|
||||
|
@ -44,7 +44,7 @@ mixin _ExecutorWithQueryDelegate on QueryExecutor {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<int> runUpdate(String statement, List args) {
|
||||
Future<int> runUpdate(String statement, List<Object?> args) {
|
||||
assert(_ensureOpenCalled);
|
||||
return _synchronized(() {
|
||||
_log(statement, args);
|
||||
|
@ -53,7 +53,7 @@ mixin _ExecutorWithQueryDelegate on QueryExecutor {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<int> runDelete(String statement, List args) {
|
||||
Future<int> runDelete(String statement, List<Object?> args) {
|
||||
assert(_ensureOpenCalled);
|
||||
return _synchronized(() {
|
||||
_log(statement, args);
|
||||
|
@ -62,7 +62,7 @@ mixin _ExecutorWithQueryDelegate on QueryExecutor {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<int> runInsert(String statement, List args) {
|
||||
Future<int> runInsert(String statement, List<Object?> args) {
|
||||
assert(_ensureOpenCalled);
|
||||
return _synchronized(() {
|
||||
_log(statement, args);
|
||||
|
@ -71,7 +71,7 @@ mixin _ExecutorWithQueryDelegate on QueryExecutor {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<void> runCustom(String statement, [List<dynamic> args]) {
|
||||
Future<void> runCustom(String statement, [List<Object?>? args]) {
|
||||
assert(_ensureOpenCalled);
|
||||
return _synchronized(() {
|
||||
final resolvedArgs = args ?? const [];
|
||||
|
@ -97,7 +97,7 @@ class _TransactionExecutor extends TransactionExecutor
|
|||
final DelegatedDatabase _db;
|
||||
|
||||
@override
|
||||
QueryDelegate impl;
|
||||
late QueryDelegate impl;
|
||||
|
||||
@override
|
||||
bool get isSequential => _db.isSequential;
|
||||
|
@ -106,10 +106,10 @@ class _TransactionExecutor extends TransactionExecutor
|
|||
bool get logStatements => _db.logStatements;
|
||||
|
||||
final Completer<void> _sendCalled = Completer();
|
||||
Completer<bool> _openingCompleter;
|
||||
Completer<bool>? _openingCompleter;
|
||||
|
||||
String _sendOnCommit;
|
||||
String _sendOnRollback;
|
||||
String? _sendOnCommit;
|
||||
String? _sendOnRollback;
|
||||
|
||||
Future get completed => _sendCalled.future;
|
||||
bool _sendFakeErrorOnRollback = false;
|
||||
|
@ -133,7 +133,7 @@ class _TransactionExecutor extends TransactionExecutor
|
|||
|
||||
_ensureOpenCalled = true;
|
||||
if (_openingCompleter != null) {
|
||||
return await _openingCompleter.future;
|
||||
return await _openingCompleter!.future;
|
||||
}
|
||||
|
||||
_openingCompleter = Completer();
|
||||
|
@ -178,7 +178,7 @@ class _TransactionExecutor extends TransactionExecutor
|
|||
}
|
||||
|
||||
await transactionStarted.future;
|
||||
_openingCompleter.complete(true);
|
||||
_openingCompleter!.complete(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,7 @@ class _TransactionExecutor extends TransactionExecutor
|
|||
if (_openingCompleter == null) return;
|
||||
|
||||
if (_sendOnCommit != null) {
|
||||
await runCustom(_sendOnCommit, const []);
|
||||
await runCustom(_sendOnCommit!, const []);
|
||||
_db.delegate.isInTransaction = false;
|
||||
}
|
||||
|
||||
|
@ -202,7 +202,7 @@ class _TransactionExecutor extends TransactionExecutor
|
|||
if (_openingCompleter == null) return;
|
||||
|
||||
if (_sendOnRollback != null) {
|
||||
await runCustom(_sendOnRollback, const []);
|
||||
await runCustom(_sendOnRollback!, const []);
|
||||
_db.delegate.isInTransaction = false;
|
||||
}
|
||||
|
||||
|
@ -238,10 +238,8 @@ class DelegatedDatabase extends QueryExecutor with _ExecutorWithQueryDelegate {
|
|||
|
||||
/// Constructs a delegated database by providing the [delegate].
|
||||
DelegatedDatabase(this.delegate,
|
||||
{this.logStatements, this.isSequential = false}) {
|
||||
// not using default value because it's commonly set to null
|
||||
logStatements ??= false;
|
||||
}
|
||||
{bool? logStatements, this.isSequential = false})
|
||||
: logStatements = logStatements ?? false;
|
||||
|
||||
@override
|
||||
Future<bool> ensureOpen(QueryExecutorUser user) {
|
||||
|
@ -260,7 +258,7 @@ class DelegatedDatabase extends QueryExecutor with _ExecutorWithQueryDelegate {
|
|||
|
||||
Future<void> _runMigrations(QueryExecutorUser user) async {
|
||||
final versionDelegate = delegate.versionDelegate;
|
||||
int oldVersion;
|
||||
int? oldVersion;
|
||||
final currentVersion = user.schemaVersion;
|
||||
|
||||
if (versionDelegate is NoVersionDelegate) {
|
||||
|
|
|
@ -5,17 +5,17 @@ class QueryResult {
|
|||
|
||||
/// The data returned by the select statement. Each list represents a row,
|
||||
/// which has the data in the same order as [columnNames].
|
||||
final List<List<dynamic>> rows;
|
||||
final List<List<Object?>> rows;
|
||||
|
||||
Map<String, int> _columnIndexes;
|
||||
final Map<String, int> _columnIndexes;
|
||||
|
||||
/// Constructs a [QueryResult] by specifying the order of column names in
|
||||
/// [columnNames] and the associated data in [rows].
|
||||
QueryResult(this.columnNames, this.rows) {
|
||||
_columnIndexes = {
|
||||
for (var column in columnNames) column: columnNames.lastIndexOf(column)
|
||||
};
|
||||
}
|
||||
QueryResult(this.columnNames, this.rows)
|
||||
: _columnIndexes = {
|
||||
for (var column in columnNames)
|
||||
column: columnNames.lastIndexOf(column)
|
||||
};
|
||||
|
||||
/// Converts the [rows] into [columnNames] and raw data [QueryResult.rows].
|
||||
/// We assume that each map in [rows] has the same keys.
|
||||
|
@ -38,7 +38,7 @@ class QueryResult {
|
|||
Iterable<Map<String, dynamic>> get asMap {
|
||||
return rows.map((row) {
|
||||
return {
|
||||
for (var column in columnNames) column: row[_columnIndexes[column]],
|
||||
for (var column in columnNames) column: row[_columnIndexes[column]!],
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ import 'dart:async';
|
|||
import 'dart:collection';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:moor/moor.dart';
|
||||
import 'package:moor/src/utils/start_with_value_transformer.dart';
|
||||
import 'package:pedantic/pedantic.dart';
|
||||
|
@ -22,13 +21,13 @@ class QueryStreamFetcher<T> {
|
|||
|
||||
/// Key that can be used to check whether two fetchers will yield the same
|
||||
/// result when operating on the same data.
|
||||
final StreamKey key;
|
||||
final StreamKey? key;
|
||||
|
||||
/// Function that asynchronously fetches the latest set of data.
|
||||
final Future<T> Function() fetchData;
|
||||
|
||||
QueryStreamFetcher(
|
||||
{@required this.readsFrom, this.key, @required this.fetchData});
|
||||
{required this.readsFrom, this.key, required this.fetchData});
|
||||
}
|
||||
|
||||
/// Key that uniquely identifies a select statement. If two keys created from
|
||||
|
@ -67,7 +66,7 @@ class StreamKey {
|
|||
/// updates them when needed.
|
||||
class StreamQueryStore {
|
||||
final Map<StreamKey, QueryStream> _activeKeyStreams = {};
|
||||
final HashSet<StreamKey> _keysPendingRemoval = HashSet<StreamKey>();
|
||||
final HashSet<StreamKey?> _keysPendingRemoval = HashSet<StreamKey?>();
|
||||
|
||||
bool _isShuttingDown = false;
|
||||
// we track pending timers since Flutter throws an exception when timers
|
||||
|
@ -185,17 +184,15 @@ class QueryStream<T> {
|
|||
final QueryStreamFetcher<T> _fetcher;
|
||||
final StreamQueryStore _store;
|
||||
|
||||
StreamController<T> _controller;
|
||||
StreamSubscription _tablesChangedSubscription;
|
||||
late final StreamController<T> _controller = StreamController.broadcast(
|
||||
onListen: _onListen,
|
||||
onCancel: _onCancel,
|
||||
);
|
||||
StreamSubscription? _tablesChangedSubscription;
|
||||
|
||||
T _lastData;
|
||||
T? _lastData;
|
||||
|
||||
Stream<T> get stream {
|
||||
_controller ??= StreamController.broadcast(
|
||||
onListen: _onListen,
|
||||
onCancel: _onCancel,
|
||||
);
|
||||
|
||||
return _controller.stream.transform(StartWithValueTransformer(_cachedData));
|
||||
}
|
||||
|
||||
|
@ -205,7 +202,7 @@ class QueryStream<T> {
|
|||
|
||||
/// Called when we have a new listener, makes the stream query behave similar
|
||||
/// to an `BehaviorSubject` from rxdart.
|
||||
T _cachedData() => _lastData;
|
||||
T? _cachedData() => _lastData;
|
||||
|
||||
void _onListen() {
|
||||
_store.markAsOpened(this);
|
||||
|
@ -282,7 +279,7 @@ class MultipleUpdateQuery extends TableUpdateQuery {
|
|||
}
|
||||
|
||||
class SpecificUpdateQuery extends TableUpdateQuery {
|
||||
final UpdateKind limitUpdateKind;
|
||||
final UpdateKind? limitUpdateKind;
|
||||
final String table;
|
||||
|
||||
const SpecificUpdateQuery(this.table, {this.limitUpdateKind});
|
||||
|
|
|
@ -3,20 +3,18 @@ part of 'moor_isolate.dart';
|
|||
class _MoorClient {
|
||||
final IsolateCommunication _channel;
|
||||
final SqlTypeSystem typeSystem;
|
||||
_IsolateStreamQueryStore _streamStore;
|
||||
|
||||
DatabaseConnection _connection;
|
||||
late final _IsolateStreamQueryStore _streamStore =
|
||||
_IsolateStreamQueryStore(this);
|
||||
late final DatabaseConnection _connection = DatabaseConnection(
|
||||
typeSystem,
|
||||
_IsolateQueryExecutor(this),
|
||||
_streamStore,
|
||||
);
|
||||
|
||||
QueryExecutorUser _connectedDb;
|
||||
late QueryExecutorUser _connectedDb;
|
||||
|
||||
_MoorClient(this._channel, this.typeSystem) {
|
||||
_streamStore = _IsolateStreamQueryStore(this);
|
||||
|
||||
_connection = DatabaseConnection(
|
||||
typeSystem,
|
||||
_IsolateQueryExecutor(this),
|
||||
_streamStore,
|
||||
);
|
||||
_channel.setRequestHandler(_handleRequest);
|
||||
}
|
||||
|
||||
|
@ -44,7 +42,7 @@ class _MoorClient {
|
|||
|
||||
abstract class _BaseExecutor extends QueryExecutor {
|
||||
final _MoorClient client;
|
||||
int _executorId;
|
||||
int? _executorId;
|
||||
|
||||
_BaseExecutor(this.client, [this._executorId]);
|
||||
|
||||
|
@ -54,13 +52,14 @@ abstract class _BaseExecutor extends QueryExecutor {
|
|||
.request(_ExecuteBatchedStatement(statements, _executorId));
|
||||
}
|
||||
|
||||
Future<T> _runRequest<T>(_StatementMethod method, String sql, List args) {
|
||||
Future<T> _runRequest<T>(
|
||||
_StatementMethod method, String sql, List<Object?>? args) {
|
||||
return client._channel
|
||||
.request<T>(_ExecuteQuery(method, sql, args ?? const [], _executorId));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> runCustom(String statement, [List args]) {
|
||||
Future<void> runCustom(String statement, [List<Object?>? args]) {
|
||||
return _runRequest(
|
||||
_StatementMethod.custom,
|
||||
statement,
|
||||
|
@ -69,31 +68,32 @@ abstract class _BaseExecutor extends QueryExecutor {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<int> runDelete(String statement, List args) {
|
||||
Future<int> runDelete(String statement, List<Object?> args) {
|
||||
return _runRequest(_StatementMethod.deleteOrUpdate, statement, args);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> runUpdate(String statement, List args) {
|
||||
Future<int> runUpdate(String statement, List<Object?> args) {
|
||||
return _runRequest(_StatementMethod.deleteOrUpdate, statement, args);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> runInsert(String statement, List args) {
|
||||
Future<int> runInsert(String statement, List<Object?> args) {
|
||||
return _runRequest(_StatementMethod.insert, statement, args);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Map<String, dynamic>>> runSelect(String statement, List args) {
|
||||
Future<List<Map<String, Object?>>> runSelect(
|
||||
String statement, List<Object?> args) {
|
||||
return _runRequest(_StatementMethod.select, statement, args);
|
||||
}
|
||||
}
|
||||
|
||||
class _IsolateQueryExecutor extends _BaseExecutor {
|
||||
_IsolateQueryExecutor(_MoorClient client, [int executorId])
|
||||
_IsolateQueryExecutor(_MoorClient client, [int? executorId])
|
||||
: super(client, executorId);
|
||||
|
||||
Completer<void> _setSchemaVersion;
|
||||
Completer<void>? _setSchemaVersion;
|
||||
|
||||
@override
|
||||
TransactionExecutor beginTransaction() {
|
||||
|
@ -104,7 +104,7 @@ class _IsolateQueryExecutor extends _BaseExecutor {
|
|||
Future<bool> ensureOpen(QueryExecutorUser user) async {
|
||||
client._connectedDb = user;
|
||||
if (_setSchemaVersion != null) {
|
||||
await _setSchemaVersion.future;
|
||||
await _setSchemaVersion!.future;
|
||||
_setSchemaVersion = null;
|
||||
}
|
||||
return client._channel
|
||||
|
@ -123,17 +123,18 @@ class _IsolateQueryExecutor extends _BaseExecutor {
|
|||
|
||||
class _TransactionIsolateExecutor extends _BaseExecutor
|
||||
implements TransactionExecutor {
|
||||
final int _outerExecutorId;
|
||||
final int? _outerExecutorId;
|
||||
|
||||
_TransactionIsolateExecutor(_MoorClient client, this._outerExecutorId)
|
||||
: super(client);
|
||||
|
||||
Completer<bool> _pendingOpen;
|
||||
Completer<bool>? _pendingOpen;
|
||||
bool _done = false;
|
||||
|
||||
// nested transactions aren't supported
|
||||
@override
|
||||
TransactionExecutor beginTransaction() => null;
|
||||
TransactionExecutor beginTransaction() {
|
||||
throw UnsupportedError('Nested transactions');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> ensureOpen(_) {
|
||||
|
@ -143,8 +144,8 @@ class _TransactionIsolateExecutor extends _BaseExecutor
|
|||
'somewhere?',
|
||||
);
|
||||
|
||||
_pendingOpen ??= Completer()..complete(_openAtServer());
|
||||
return _pendingOpen.future;
|
||||
final completer = _pendingOpen ??= Completer()..complete(_openAtServer());
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
Future<bool> _openAtServer() async {
|
||||
|
|
|
@ -19,7 +19,7 @@ class IsolateCommunication {
|
|||
/// primitive objects.
|
||||
final MessageCodec messageCodec;
|
||||
|
||||
StreamSubscription _inputSubscription;
|
||||
StreamSubscription? _inputSubscription;
|
||||
|
||||
// note that there are two IsolateCommunication instances in each connection,
|
||||
// and each of them has an independent _currentRequestId field!
|
||||
|
@ -102,7 +102,7 @@ class IsolateCommunication {
|
|||
if (completer != null) {
|
||||
if (msg is _ErrorResponse) {
|
||||
final trace = msg.stackTrace != null
|
||||
? StackTrace.fromString(msg.stackTrace)
|
||||
? StackTrace.fromString(msg.stackTrace!)
|
||||
: null;
|
||||
|
||||
completer.completeError(msg.error, trace);
|
||||
|
@ -146,7 +146,7 @@ class IsolateCommunication {
|
|||
}
|
||||
|
||||
/// Sends an erroneous response for a [Request].
|
||||
void respondError(Request request, dynamic error, [StackTrace trace]) {
|
||||
void respondError(Request request, dynamic error, [StackTrace? trace]) {
|
||||
// sending a message while closed will throw, so don't even try.
|
||||
if (isClosed) return;
|
||||
|
||||
|
@ -390,9 +390,9 @@ class _Response implements IsolateMessage {
|
|||
class _ErrorResponse extends _Response {
|
||||
static const _tag = 6;
|
||||
|
||||
final String stackTrace;
|
||||
final String? stackTrace;
|
||||
|
||||
dynamic get error => response;
|
||||
Object get error => response as Object;
|
||||
|
||||
_ErrorResponse(int requestId, dynamic error, [this.stackTrace])
|
||||
: super(requestId, error);
|
||||
|
|
|
@ -63,7 +63,7 @@ class _MoorCodec extends MessageCodec {
|
|||
for (final update in payload.updates)
|
||||
[
|
||||
update.table,
|
||||
update.kind.index,
|
||||
update.kind?.index,
|
||||
]
|
||||
];
|
||||
} else if (payload is SqlTypeSystem) {
|
||||
|
@ -80,7 +80,7 @@ class _MoorCodec extends MessageCodec {
|
|||
if (encoded == null || encoded is bool) return encoded;
|
||||
|
||||
int tag;
|
||||
List fullMessage;
|
||||
List? fullMessage;
|
||||
|
||||
if (encoded is int) {
|
||||
tag = encoded;
|
||||
|
@ -89,7 +89,8 @@ class _MoorCodec extends MessageCodec {
|
|||
tag = fullMessage[0] as int;
|
||||
}
|
||||
|
||||
int readInt(int index) => fullMessage[index] as int;
|
||||
int readInt(int index) => fullMessage![index] as int;
|
||||
int? readNullableInt(int index) => fullMessage![index] as int?;
|
||||
|
||||
switch (tag) {
|
||||
case _tag_NoArgsRequest_getTypeSystem:
|
||||
|
@ -98,12 +99,12 @@ class _MoorCodec extends MessageCodec {
|
|||
return _NoArgsRequest.terminateAll;
|
||||
case _tag_ExecuteQuery:
|
||||
final method = _StatementMethod.values[readInt(1)];
|
||||
final sql = fullMessage[2] as String;
|
||||
final sql = fullMessage![2] as String;
|
||||
final args = (fullMessage[3] as List).map(_decodeDbValue).toList();
|
||||
final executorId = fullMessage[4] as int /*?*/;
|
||||
final executorId = readNullableInt(4);
|
||||
return _ExecuteQuery(method, sql, args, executorId);
|
||||
case _tag_ExecuteBatchedStatement:
|
||||
final sql = (fullMessage[1] as List).cast<String>();
|
||||
final sql = (fullMessage![1] as List).cast<String>();
|
||||
final args = <ArgumentsForBatchedStatement>[];
|
||||
|
||||
for (var i = 2; i < fullMessage.length - 1; i++) {
|
||||
|
@ -118,19 +119,19 @@ class _MoorCodec extends MessageCodec {
|
|||
BatchedStatements(sql, args), executorId);
|
||||
case _tag_RunTransactionAction:
|
||||
final control = _TransactionControl.values[readInt(1)];
|
||||
return _RunTransactionAction(control, readInt(2));
|
||||
return _RunTransactionAction(control, readNullableInt(2));
|
||||
case _tag_EnsureOpen:
|
||||
return _EnsureOpen(readInt(1), readInt(2));
|
||||
return _EnsureOpen(readInt(1), readNullableInt(2));
|
||||
case _tag_RunBeforeOpen:
|
||||
return _RunBeforeOpen(
|
||||
OpeningDetails(readInt(1), readInt(2)),
|
||||
OpeningDetails(readNullableInt(1), readInt(2)),
|
||||
readInt(3),
|
||||
);
|
||||
case _tag_DefaultSqlTypeSystem:
|
||||
return SqlTypeSystem.defaultInstance;
|
||||
case _tag_NotifyTablesUpdated:
|
||||
final updates = <TableUpdate>[];
|
||||
for (var i = 1; i < fullMessage.length; i++) {
|
||||
for (var i = 1; i < fullMessage!.length; i++) {
|
||||
final encodedUpdate = fullMessage[i] as List;
|
||||
updates.add(
|
||||
TableUpdate(encodedUpdate[0] as String,
|
||||
|
@ -186,7 +187,7 @@ class _ExecuteQuery {
|
|||
final _StatementMethod method;
|
||||
final String sql;
|
||||
final List<dynamic> args;
|
||||
final int executorId;
|
||||
final int? executorId;
|
||||
|
||||
_ExecuteQuery(this.method, this.sql, this.args, [this.executorId]);
|
||||
|
||||
|
@ -202,7 +203,7 @@ class _ExecuteQuery {
|
|||
/// Sent from the client to run [BatchedStatements]
|
||||
class _ExecuteBatchedStatement {
|
||||
final BatchedStatements stmts;
|
||||
final int executorId;
|
||||
final int? executorId;
|
||||
|
||||
_ExecuteBatchedStatement(this.stmts, [this.executorId]);
|
||||
}
|
||||
|
@ -219,7 +220,7 @@ enum _TransactionControl {
|
|||
/// Sent from the client to commit or rollback a transaction
|
||||
class _RunTransactionAction {
|
||||
final _TransactionControl control;
|
||||
final int executorId;
|
||||
final int? executorId;
|
||||
|
||||
_RunTransactionAction(this.control, this.executorId);
|
||||
|
||||
|
@ -233,7 +234,7 @@ class _RunTransactionAction {
|
|||
/// database connection, using the [schemaVersion].
|
||||
class _EnsureOpen {
|
||||
final int schemaVersion;
|
||||
final int executorId;
|
||||
final int? executorId;
|
||||
|
||||
_EnsureOpen(this.schemaVersion, this.executorId);
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ part of 'moor_isolate.dart';
|
|||
class _MoorServer {
|
||||
final Server server;
|
||||
|
||||
DatabaseConnection connection;
|
||||
final DatabaseConnection connection;
|
||||
|
||||
final Map<int, QueryExecutor> _managedExecutors = {};
|
||||
int _currentExecutorId = 0;
|
||||
|
@ -19,20 +19,20 @@ class _MoorServer {
|
|||
final StreamController<void> _backlogUpdated =
|
||||
StreamController.broadcast(sync: true);
|
||||
|
||||
_IsolateDelegatedUser _dbUser;
|
||||
late final _IsolateDelegatedUser _dbUser = _IsolateDelegatedUser(this);
|
||||
|
||||
SendPort get portToOpenConnection => server.portToOpenConnection;
|
||||
|
||||
_MoorServer(DatabaseOpener opener) : server = Server(const _MoorCodec()) {
|
||||
_MoorServer(DatabaseOpener opener)
|
||||
: connection = opener(),
|
||||
server = Server(const _MoorCodec()) {
|
||||
server.openedConnections.listen((connection) {
|
||||
connection.setRequestHandler(_handleRequest);
|
||||
});
|
||||
connection = opener();
|
||||
_dbUser = _IsolateDelegatedUser(this);
|
||||
}
|
||||
|
||||
/// Returns the first connected client, or null if no client is connected.
|
||||
IsolateCommunication get firstClient {
|
||||
IsolateCommunication? get firstClient {
|
||||
final channels = server.currentChannels;
|
||||
return channels.isEmpty ? null : channels.first;
|
||||
}
|
||||
|
@ -74,8 +74,8 @@ class _MoorServer {
|
|||
return await executor.ensureOpen(_dbUser);
|
||||
}
|
||||
|
||||
Future<dynamic> _runQuery(
|
||||
_StatementMethod method, String sql, List args, int transactionId) async {
|
||||
Future<dynamic> _runQuery(_StatementMethod method, String sql,
|
||||
List<Object?> args, int? transactionId) async {
|
||||
final executor = await _loadExecutor(transactionId);
|
||||
|
||||
switch (method) {
|
||||
|
@ -88,23 +88,21 @@ class _MoorServer {
|
|||
case _StatementMethod.select:
|
||||
return executor.runSelect(sql, args);
|
||||
}
|
||||
|
||||
throw AssertionError("Unknown _StatementMethod, this can't happen.");
|
||||
}
|
||||
|
||||
Future<void> _runBatched(BatchedStatements stmts, int transactionId) async {
|
||||
Future<void> _runBatched(BatchedStatements stmts, int? transactionId) async {
|
||||
final executor = await _loadExecutor(transactionId);
|
||||
await executor.runBatched(stmts);
|
||||
}
|
||||
|
||||
Future<QueryExecutor> _loadExecutor(int transactionId) async {
|
||||
Future<QueryExecutor> _loadExecutor(int? transactionId) async {
|
||||
await _waitForTurn(transactionId);
|
||||
return transactionId != null
|
||||
? _managedExecutors[transactionId]
|
||||
? _managedExecutors[transactionId]!
|
||||
: connection.executor;
|
||||
}
|
||||
|
||||
Future<int> _spawnTransaction(int executor) async {
|
||||
Future<int> _spawnTransaction(int? executor) async {
|
||||
final transaction = (await _loadExecutor(executor)).beginTransaction();
|
||||
final id = _putExecutor(transaction, beforeCurrent: true);
|
||||
|
||||
|
@ -126,7 +124,7 @@ class _MoorServer {
|
|||
}
|
||||
|
||||
Future<dynamic> _transactionControl(
|
||||
_TransactionControl action, int executorId) async {
|
||||
_TransactionControl action, int? executorId) async {
|
||||
if (action == _TransactionControl.begin) {
|
||||
return await _spawnTransaction(executorId);
|
||||
}
|
||||
|
@ -142,21 +140,19 @@ class _MoorServer {
|
|||
);
|
||||
}
|
||||
|
||||
final transaction = executor as TransactionExecutor;
|
||||
|
||||
try {
|
||||
switch (action) {
|
||||
case _TransactionControl.commit:
|
||||
await transaction.send();
|
||||
await executor.send();
|
||||
break;
|
||||
case _TransactionControl.rollback:
|
||||
await transaction.rollback();
|
||||
await executor.rollback();
|
||||
break;
|
||||
default:
|
||||
assert(false, 'Unknown TransactionControl');
|
||||
}
|
||||
} finally {
|
||||
_releaseExecutor(executorId);
|
||||
_releaseExecutor(executorId!);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,7 +162,7 @@ class _MoorServer {
|
|||
_notifyActiveExecutorUpdated();
|
||||
}
|
||||
|
||||
Future<void> _waitForTurn(int transactionId) {
|
||||
Future<void> _waitForTurn(int? transactionId) {
|
||||
bool idIsActive() {
|
||||
if (transactionId == null) {
|
||||
return _executorBacklog.isEmpty;
|
||||
|
@ -202,7 +198,7 @@ class _IsolateDelegatedUser implements QueryExecutorUser {
|
|||
QueryExecutor executor, OpeningDetails details) async {
|
||||
final id = server._putExecutor(executor, beforeCurrent: true);
|
||||
try {
|
||||
await server.firstClient.request(_RunBeforeOpen(details, id));
|
||||
await server.firstClient!.request(_RunBeforeOpen(details, id));
|
||||
} finally {
|
||||
server._releaseExecutor(id);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ class GroupBy extends Component {
|
|||
final List<Expression> groupBy;
|
||||
|
||||
/// Optional, a having clause to exclude some groups.
|
||||
final Expression<bool> /*?*/ having;
|
||||
final Expression<bool?>? having;
|
||||
|
||||
GroupBy._(this.groupBy, this.having);
|
||||
|
||||
|
@ -17,7 +17,7 @@ class GroupBy extends Component {
|
|||
|
||||
if (having != null) {
|
||||
context.buffer.write(' HAVING ');
|
||||
having.writeInto(context);
|
||||
having!.writeInto(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ class Join<T extends Table, D extends DataClass> extends Component {
|
|||
|
||||
/// For joins that aren't [_JoinType.cross], contains an additional predicate
|
||||
/// that must be matched for the join.
|
||||
final Expression<bool> on;
|
||||
final Expression<bool>? on;
|
||||
|
||||
/// Whether [table] should appear in the result set (defaults to true).
|
||||
///
|
||||
|
@ -41,7 +41,7 @@ class Join<T extends Table, D extends DataClass> extends Component {
|
|||
|
||||
/// Constructs a [Join] by providing the relevant fields. [on] is optional for
|
||||
/// [_JoinType.cross].
|
||||
Join._(this.type, this.table, this.on, {bool includeInResult})
|
||||
Join._(this.type, this.table, this.on, {bool? includeInResult})
|
||||
: includeInResult = includeInResult ?? true;
|
||||
|
||||
@override
|
||||
|
@ -53,7 +53,7 @@ class Join<T extends Table, D extends DataClass> extends Component {
|
|||
|
||||
if (type != _JoinType.cross) {
|
||||
context.buffer.write(' ON ');
|
||||
on.writeInto(context);
|
||||
on!.writeInto(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ class Join<T extends Table, D extends DataClass> extends Component {
|
|||
/// - http://www.sqlitetutorial.net/sqlite-inner-join/
|
||||
Join innerJoin<T extends Table, D extends DataClass>(
|
||||
TableInfo<T, D> other, Expression<bool> on,
|
||||
{bool useColumns}) {
|
||||
{bool? useColumns}) {
|
||||
return Join._(_JoinType.inner, other, on, includeInResult: useColumns);
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ Join innerJoin<T extends Table, D extends DataClass>(
|
|||
/// - http://www.sqlitetutorial.net/sqlite-left-join/
|
||||
Join leftOuterJoin<T extends Table, D extends DataClass>(
|
||||
TableInfo<T, D> other, Expression<bool> on,
|
||||
{bool useColumns}) {
|
||||
{bool? useColumns}) {
|
||||
return Join._(_JoinType.leftOuter, other, on, includeInResult: useColumns);
|
||||
}
|
||||
|
||||
|
@ -97,6 +97,6 @@ Join leftOuterJoin<T extends Table, D extends DataClass>(
|
|||
/// See also:
|
||||
/// - https://moor.simonbinder.eu/docs/advanced-features/joins/#joins
|
||||
/// - http://www.sqlitetutorial.net/sqlite-cross-join/
|
||||
Join crossJoin<T, D>(TableInfo other, {bool useColumns}) {
|
||||
Join crossJoin<T, D>(TableInfo other, {bool? useColumns}) {
|
||||
return Join._(_JoinType.cross, other, null, includeInResult: useColumns);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ class Limit extends Component {
|
|||
|
||||
/// When the offset is non null, the first offset rows will be skipped an not
|
||||
/// included in the result.
|
||||
final int offset;
|
||||
final int? offset;
|
||||
|
||||
/// Construct a limit clause from the [amount] of rows to include an a
|
||||
/// nullable [offset].
|
||||
|
|
|
@ -25,7 +25,7 @@ class OrderingTerm extends Component {
|
|||
|
||||
/// Creates an ordering term by the [expression] and the [mode] (defaults to
|
||||
/// ascending).
|
||||
OrderingTerm({@required this.expression, this.mode = OrderingMode.asc});
|
||||
OrderingTerm({required this.expression, this.mode = OrderingMode.asc});
|
||||
|
||||
/// Creates an ordering term that sorts for ascending values of [expression].
|
||||
factory OrderingTerm.asc(Expression expression) {
|
||||
|
|
|
@ -4,7 +4,7 @@ part of '../query_builder.dart';
|
|||
class Where extends Component {
|
||||
/// The expression that determines whether a given row should be included in
|
||||
/// the result.
|
||||
final Expression<bool> predicate;
|
||||
final Expression<bool?> predicate;
|
||||
|
||||
/// Construct a [Where] clause from its [predicate].
|
||||
Where(this.predicate);
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
part of '../query_builder.dart';
|
||||
|
||||
// todo: We should have a detailed article on group-by clauses and aggregate
|
||||
// expressions on the website
|
||||
|
||||
/// Returns the amount of rows in the current group matching the optional
|
||||
/// [filter].
|
||||
///
|
||||
|
@ -12,7 +9,7 @@ part of '../query_builder.dart';
|
|||
///
|
||||
/// This is equivalent to the `COUNT(*) FILTER (WHERE filter)` sql function. The
|
||||
/// filter will be omitted if null.
|
||||
Expression<int> countAll({Expression<bool> filter}) {
|
||||
Expression<int> countAll({Expression<bool>? filter}) {
|
||||
return _AggregateExpression('COUNT', const _StarFunctionParameter(),
|
||||
filter: filter);
|
||||
}
|
||||
|
@ -27,7 +24,7 @@ extension BaseAggregate<DT> on Expression<DT> {
|
|||
/// counted twice. An optional [filter] can be used to only include values
|
||||
/// matching the filter. Note that [filter] is only available from sqlite
|
||||
/// 3.30 and most devices will use an older sqlite version.
|
||||
Expression<int> count({bool distinct, Expression<bool> filter}) {
|
||||
Expression<int> count({bool? distinct, Expression<bool>? filter}) {
|
||||
return _AggregateExpression('COUNT', this,
|
||||
filter: filter, distinct: distinct);
|
||||
}
|
||||
|
@ -52,19 +49,19 @@ extension BaseAggregate<DT> on Expression<DT> {
|
|||
}
|
||||
|
||||
/// Provides aggregate functions that are available for numeric expressions.
|
||||
extension ArithmeticAggregates<DT extends num> on Expression<DT> {
|
||||
extension ArithmeticAggregates<DT extends num> on Expression<DT?> {
|
||||
/// Return the average of all non-null values in this group.
|
||||
Expression<double> avg() => _AggregateExpression('AVG', this);
|
||||
Expression<double?> avg() => _AggregateExpression('AVG', this);
|
||||
|
||||
/// Return the maximum of all non-null values in this group.
|
||||
///
|
||||
/// If there are no non-null values in the group, returns null.
|
||||
Expression<DT> max() => _AggregateExpression('MAX', this);
|
||||
Expression<DT?> max() => _AggregateExpression('MAX', this);
|
||||
|
||||
/// Return the minimum of all non-null values in this group.
|
||||
///
|
||||
/// If there are no non-null values in the group, returns null.
|
||||
Expression<DT> min() => _AggregateExpression('MIN', this);
|
||||
Expression<DT?> min() => _AggregateExpression('MIN', this);
|
||||
|
||||
/// Calculate the sum of all non-null values in the group.
|
||||
///
|
||||
|
@ -74,13 +71,13 @@ extension ArithmeticAggregates<DT extends num> on Expression<DT> {
|
|||
///
|
||||
/// See also [total], which behaves similarly but returns a floating point
|
||||
/// value and doesn't throw an overflow exception.
|
||||
Expression<DT> sum() => _AggregateExpression('SUM', this);
|
||||
Expression<DT?> sum() => _AggregateExpression('SUM', this);
|
||||
|
||||
/// Calculate the sum of all non-null values in the group.
|
||||
///
|
||||
/// If all values in the group are null, [total] returns `0.0`. This function
|
||||
/// uses floating-point values internally.
|
||||
Expression<double> total() => _AggregateExpression('TOTAL', this);
|
||||
Expression<double?> total() => _AggregateExpression('TOTAL', this);
|
||||
}
|
||||
|
||||
class _AggregateExpression<D> extends Expression<D> {
|
||||
|
@ -88,10 +85,10 @@ class _AggregateExpression<D> extends Expression<D> {
|
|||
final bool distinct;
|
||||
final FunctionParameter parameter;
|
||||
|
||||
final Where /*?*/ filter;
|
||||
final Where? filter;
|
||||
|
||||
_AggregateExpression(this.functionName, this.parameter,
|
||||
{Expression<bool> filter, bool distinct})
|
||||
{Expression<bool>? filter, bool? distinct})
|
||||
: filter = filter != null ? Where(filter) : null,
|
||||
distinct = distinct ?? false;
|
||||
|
||||
|
@ -111,7 +108,7 @@ class _AggregateExpression<D> extends Expression<D> {
|
|||
|
||||
if (filter != null) {
|
||||
context.buffer.write(' FILTER (');
|
||||
filter.writeInto(context);
|
||||
filter!.writeInto(context);
|
||||
context.buffer.write(')');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
part of '../query_builder.dart';
|
||||
|
||||
/// Defines the `-`, `*` and `/` operators on sql expressions that support it.
|
||||
extension ArithmeticExpr<DT extends num> on Expression<DT> {
|
||||
extension ArithmeticExpr<DT extends num?> on Expression<DT> {
|
||||
/// Performs an addition (`this` + [other]) in sql.
|
||||
Expression<DT> operator +(Expression<DT> other) {
|
||||
return _BaseInfixOperator(this, '+', other,
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
part of '../query_builder.dart';
|
||||
|
||||
/// Defines operations on boolean values.
|
||||
extension BooleanExpressionOperators on Expression<bool> {
|
||||
extension BooleanExpressionOperators on Expression<bool?> {
|
||||
/// Negates this boolean expression. The returned expression is true if
|
||||
/// `this` is false, and vice versa.
|
||||
Expression<bool> not() => _NotExpression(this);
|
||||
Expression<bool?> not() => _NotExpression(this);
|
||||
|
||||
/// Returns an expression that is true iff both `this` and [other] are true.
|
||||
Expression<bool> operator &(Expression<bool> other) {
|
||||
Expression<bool?> operator &(Expression<bool?> other) {
|
||||
return _BaseInfixOperator(this, 'AND', other, precedence: Precedence.and);
|
||||
}
|
||||
|
||||
/// Returns an expression that is true if `this` or [other] are true.
|
||||
Expression<bool> operator |(Expression<bool> other) {
|
||||
Expression<bool?> operator |(Expression<bool?> other) {
|
||||
return _BaseInfixOperator(this, 'OR', other, precedence: Precedence.or);
|
||||
}
|
||||
}
|
||||
|
||||
class _NotExpression extends Expression<bool> {
|
||||
final Expression<bool> inner;
|
||||
class _NotExpression extends Expression<bool?> {
|
||||
final Expression<bool?> inner;
|
||||
|
||||
_NotExpression(this.inner);
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
part of '../query_builder.dart';
|
||||
|
||||
/// Defines extension functions to express comparisons in sql
|
||||
extension ComparableExpr<DT extends Comparable<dynamic>> on Expression<DT> {
|
||||
extension ComparableExpr<DT extends Comparable<dynamic>?> on Expression<DT> {
|
||||
/// Returns an expression that is true if this expression is strictly bigger
|
||||
/// than the other expression.
|
||||
Expression<bool> isBiggerThan(Expression<DT> other) {
|
||||
|
@ -84,9 +84,9 @@ class _BetweenExpression extends Expression<bool> {
|
|||
final Expression higher;
|
||||
|
||||
_BetweenExpression(
|
||||
{@required this.target,
|
||||
@required this.lower,
|
||||
@required this.higher,
|
||||
{required this.target,
|
||||
required this.lower,
|
||||
required this.higher,
|
||||
this.not = false});
|
||||
|
||||
@override
|
||||
|
|
|
@ -19,27 +19,27 @@ class _CustomDateTimeExpression extends CustomExpression<DateTime> {
|
|||
|
||||
/// Provides expressions to extract information from date time values, or to
|
||||
/// calculate the difference between datetimes.
|
||||
extension DateTimeExpressions on Expression<DateTime> {
|
||||
extension DateTimeExpressions on Expression<DateTime?> {
|
||||
/// Extracts the (UTC) year from `this` datetime expression.
|
||||
Expression<int> get year => _StrftimeSingleFieldExpression('%Y', this);
|
||||
Expression<int?> get year => _StrftimeSingleFieldExpression('%Y', this);
|
||||
|
||||
/// Extracts the (UTC) month from `this` datetime expression.
|
||||
Expression<int> get month => _StrftimeSingleFieldExpression('%m', this);
|
||||
Expression<int?> get month => _StrftimeSingleFieldExpression('%m', this);
|
||||
|
||||
/// Extracts the (UTC) day from `this` datetime expression.
|
||||
Expression<int> get day => _StrftimeSingleFieldExpression('%d', this);
|
||||
Expression<int?> get day => _StrftimeSingleFieldExpression('%d', this);
|
||||
|
||||
/// Extracts the (UTC) hour from `this` datetime expression.
|
||||
Expression<int> get hour => _StrftimeSingleFieldExpression('%H', this);
|
||||
Expression<int?> get hour => _StrftimeSingleFieldExpression('%H', this);
|
||||
|
||||
/// Extracts the (UTC) minute from `this` datetime expression.
|
||||
Expression<int> get minute => _StrftimeSingleFieldExpression('%M', this);
|
||||
Expression<int?> get minute => _StrftimeSingleFieldExpression('%M', this);
|
||||
|
||||
/// Extracts the (UTC) second from `this` datetime expression.
|
||||
Expression<int> get second => _StrftimeSingleFieldExpression('%S', this);
|
||||
Expression<int?> get second => _StrftimeSingleFieldExpression('%S', this);
|
||||
|
||||
/// Formats this datetime in the format `year-month-day`.
|
||||
Expression<String> get date {
|
||||
Expression<String?> get date {
|
||||
return FunctionCallExpression(
|
||||
'DATE',
|
||||
[this, const Constant<String>('unixepoch')],
|
||||
|
@ -68,9 +68,9 @@ extension DateTimeExpressions on Expression<DateTime> {
|
|||
|
||||
/// Expression that extracts components out of a date time by using the builtin
|
||||
/// sqlite function "strftime" and casting the result to an integer.
|
||||
class _StrftimeSingleFieldExpression extends Expression<int> {
|
||||
class _StrftimeSingleFieldExpression extends Expression<int?> {
|
||||
final String format;
|
||||
final Expression<DateTime> date;
|
||||
final Expression<DateTime?> date;
|
||||
|
||||
_StrftimeSingleFieldExpression(this.format, this.date);
|
||||
|
||||
|
|
|
@ -264,7 +264,7 @@ class _Comparison extends _InfixOperator<bool> {
|
|||
final _ComparisonOperator op;
|
||||
|
||||
@override
|
||||
String get operator => _operatorNames[op];
|
||||
String get operator => _operatorNames[op]!;
|
||||
|
||||
@override
|
||||
Precedence get precedence {
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
part of '../query_builder.dart';
|
||||
|
||||
// we're not using extensions for this because I'm not sure if / how this could
|
||||
// look together with NNBD in the future
|
||||
|
||||
/// Expression that is true if the inner expression resolves to a null value.
|
||||
@Deprecated('Use isNull through the SqlIsNull extension')
|
||||
Expression<bool> isNull(Expression inner) => _NullCheck(inner, true);
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
part of '../query_builder.dart';
|
||||
|
||||
/// Defines methods that operate on a column storing [String] values.
|
||||
extension StringExpressionOperators on Expression<String> {
|
||||
extension StringExpressionOperators on Expression<String?> {
|
||||
/// Whether this column matches the given pattern. For details on what patters
|
||||
/// are valid and how they are interpreted, check out
|
||||
/// [this tutorial](http://www.sqlitetutorial.net/sqlite-like/).
|
||||
Expression<bool> like(String regex) {
|
||||
Expression<bool?> like(String regex) {
|
||||
return _LikeOperator(this, Variable.withString(regex));
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ extension StringExpressionOperators on Expression<String> {
|
|||
///
|
||||
/// Note that this function is only available when using `moor_ffi`. If you
|
||||
/// need to support the web or `moor_flutter`, consider using [like] instead.
|
||||
Expression<bool> regexp(
|
||||
Expression<bool?> regexp(
|
||||
String regex, {
|
||||
bool multiLine = false,
|
||||
bool caseSensitive = true,
|
||||
|
@ -62,7 +62,7 @@ extension StringExpressionOperators on Expression<String> {
|
|||
/// Note that this is case-insensitive for the English alphabet only.
|
||||
///
|
||||
/// This is equivalent to calling [like] with `%<substring>%`.
|
||||
Expression<bool> contains(String substring) {
|
||||
Expression<bool?> contains(String substring) {
|
||||
return like('%$substring%');
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,7 @@ extension StringExpressionOperators on Expression<String> {
|
|||
}
|
||||
|
||||
/// Performs a string concatenation in sql by appending [other] to `this`.
|
||||
Expression<String> operator +(Expression<String> other) {
|
||||
Expression<String> operator +(Expression<String?> other) {
|
||||
return _BaseInfixOperator(this, '||', other,
|
||||
precedence: Precedence.stringConcatenation);
|
||||
}
|
||||
|
@ -102,19 +102,19 @@ extension StringExpressionOperators on Expression<String> {
|
|||
///
|
||||
/// See also:
|
||||
/// - https://www.w3resource.com/sqlite/core-functions-length.php
|
||||
Expression<int> get length {
|
||||
Expression<int?> get length {
|
||||
return FunctionCallExpression('LENGTH', [this]);
|
||||
}
|
||||
}
|
||||
|
||||
/// A `text LIKE pattern` expression that will be true if the first expression
|
||||
/// matches the pattern given by the second expression.
|
||||
class _LikeOperator extends Expression<bool> {
|
||||
class _LikeOperator extends Expression<bool?> {
|
||||
/// The target expression that will be tested
|
||||
final Expression<String> target;
|
||||
final Expression<String?> target;
|
||||
|
||||
/// The regex-like expression to test the [target] against.
|
||||
final Expression<String> regex;
|
||||
final Expression<String?> regex;
|
||||
|
||||
/// The operator to use when matching. Defaults to `LIKE`.
|
||||
final String operator;
|
||||
|
|
|
@ -16,7 +16,7 @@ class GenerationContext {
|
|||
final SqlDialect dialect;
|
||||
|
||||
/// The actual [QueryEngine] that's going to execute the generated query.
|
||||
final QueryEngine executor;
|
||||
final QueryEngine? executor;
|
||||
|
||||
final List<dynamic> _boundVariables = [];
|
||||
|
||||
|
@ -40,8 +40,9 @@ class GenerationContext {
|
|||
/// Constructs a [GenerationContext] by copying the relevant fields from the
|
||||
/// database.
|
||||
GenerationContext.fromDb(this.executor)
|
||||
: typeSystem = executor.typeSystem,
|
||||
dialect = executor.executor?.dialect ?? SqlDialect.sqlite;
|
||||
: typeSystem = executor?.typeSystem ?? SqlTypeSystem.defaultInstance,
|
||||
// ignore: invalid_null_aware_operator, (doesn't seem to actually work)
|
||||
dialect = executor?.executor?.dialect ?? SqlDialect.sqlite;
|
||||
|
||||
/// Constructs a custom [GenerationContext] by setting the fields manually.
|
||||
/// See [GenerationContext.fromDb] for a more convenient factory.
|
||||
|
|
|
@ -35,7 +35,7 @@ class MigrationStrategy {
|
|||
/// and all migrations ran), but before any other queries will be sent. This
|
||||
/// makes it a suitable place to populate data after the database has been
|
||||
/// created or set sqlite `PRAGMAS` that you need.
|
||||
final OnBeforeOpen /*?*/ beforeOpen;
|
||||
final OnBeforeOpen? beforeOpen;
|
||||
|
||||
/// Construct a migration strategy from the provided [onCreate] and
|
||||
/// [onUpgrade] methods.
|
||||
|
@ -121,7 +121,7 @@ class Migrator {
|
|||
@experimental
|
||||
Future<void> alterTable(TableMigration migration) async {
|
||||
final foreignKeysEnabled =
|
||||
(await _db.customSelect('PRAGMA foreign_keys').getSingle())
|
||||
(await _db.customSelect('PRAGMA foreign_keys').getSingle())!
|
||||
.readBool('foreign_keys');
|
||||
|
||||
if (foreignKeysEnabled) {
|
||||
|
@ -251,7 +251,7 @@ class Migrator {
|
|||
// as table constraint if it has already been written on a primary key
|
||||
// column, even though that column appears in table.$primaryKey because we
|
||||
// need to know all primary keys for the update(table).replace(row) API
|
||||
final hasPrimaryKey = table.$primaryKey?.isNotEmpty ?? false;
|
||||
final hasPrimaryKey = table.$primaryKey.isNotEmpty;
|
||||
final dontWritePk = dslTable.dontWriteConstraints || hasAutoIncrement;
|
||||
if (hasPrimaryKey && !dontWritePk) {
|
||||
context.buffer.write(', PRIMARY KEY (');
|
||||
|
@ -266,7 +266,7 @@ class Migrator {
|
|||
context.buffer.write(')');
|
||||
}
|
||||
|
||||
final constraints = dslTable.customConstraints ?? [];
|
||||
final constraints = dslTable.customConstraints;
|
||||
|
||||
for (var i = 0; i < constraints.length; i++) {
|
||||
context.buffer..write(', ')..write(constraints[i]);
|
||||
|
@ -369,11 +369,11 @@ class Migrator {
|
|||
|
||||
/// Executes the custom query.
|
||||
@Deprecated('Use customStatement in the database class')
|
||||
Future<void> issueCustomQuery(String sql, [List<dynamic> args]) {
|
||||
Future<void> issueCustomQuery(String sql, [List<dynamic>? args]) {
|
||||
return _issueCustomQuery(sql, args);
|
||||
}
|
||||
|
||||
Future<void> _issueCustomQuery(String sql, [List<dynamic> args]) {
|
||||
Future<void> _issueCustomQuery(String sql, [List<dynamic>? args]) {
|
||||
return _db.customStatement(sql, args);
|
||||
}
|
||||
}
|
||||
|
@ -383,7 +383,7 @@ class Migrator {
|
|||
class OpeningDetails {
|
||||
/// The schema version before the database has been opened, or `null` if the
|
||||
/// database has just been created.
|
||||
final int versionBefore;
|
||||
final int? versionBefore;
|
||||
|
||||
/// The schema version after running migrations.
|
||||
final int versionNow;
|
||||
|
@ -395,7 +395,9 @@ class OpeningDetails {
|
|||
bool get hadUpgrade => !wasCreated && versionBefore != versionNow;
|
||||
|
||||
/// Used internally by moor when opening a database.
|
||||
const OpeningDetails(this.versionBefore, this.versionNow);
|
||||
const OpeningDetails(this.versionBefore, this.versionNow)
|
||||
// Should use null instead of 0 for consistency
|
||||
: assert(versionBefore != 0);
|
||||
}
|
||||
|
||||
/// Extension providing the [destructiveFallback] strategy.
|
||||
|
|
|
@ -21,11 +21,11 @@ abstract class GeneratedColumn<T> extends Column<T> {
|
|||
/// If custom constraints have been specified for this column via
|
||||
/// [ColumnBuilder.customConstraint], these are kept here. Otherwise, this
|
||||
/// field is going to be null.
|
||||
final String $customConstraints;
|
||||
final String? $customConstraints;
|
||||
|
||||
/// The default expression to be used during inserts when no value has been
|
||||
/// specified. Can be null if no default value is set.
|
||||
final Expression<T> defaultValue;
|
||||
final Expression<T>? defaultValue;
|
||||
|
||||
/// A function that yields a default column for inserts if no value has been
|
||||
/// set. This is different to [defaultValue] since the function is written in
|
||||
|
@ -33,7 +33,7 @@ abstract class GeneratedColumn<T> extends Column<T> {
|
|||
/// [defaultValue] and [clientDefault] are non-null.
|
||||
///
|
||||
/// See also: [ColumnBuilder.clientDefault].
|
||||
T Function() clientDefault;
|
||||
T Function()? clientDefault;
|
||||
|
||||
/// Used by generated code.
|
||||
GeneratedColumn(this.$name, this.tableName, this.$nullable,
|
||||
|
@ -48,6 +48,7 @@ abstract class GeneratedColumn<T> extends Column<T> {
|
|||
if ($customConstraints == null) {
|
||||
into.buffer.write($nullable ? ' NULL' : ' NOT NULL');
|
||||
|
||||
final defaultValue = this.defaultValue;
|
||||
if (defaultValue != null) {
|
||||
into.buffer.write(' DEFAULT ');
|
||||
|
||||
|
@ -137,18 +138,18 @@ abstract class GeneratedColumn<T> extends Column<T> {
|
|||
}
|
||||
|
||||
Variable _evaluateClientDefault() {
|
||||
return Variable<T>(clientDefault());
|
||||
return Variable<T>(clientDefault!());
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation for [TextColumn].
|
||||
class GeneratedTextColumn extends GeneratedColumn<String>
|
||||
class GeneratedTextColumn extends GeneratedColumn<String?>
|
||||
implements TextColumn {
|
||||
/// Optional. The minimum text length.
|
||||
final int minTextLength;
|
||||
final int? minTextLength;
|
||||
|
||||
/// Optional. The maximum text length.
|
||||
final int maxTextLength;
|
||||
final int? maxTextLength;
|
||||
|
||||
/// Used by generated code.
|
||||
GeneratedTextColumn(
|
||||
|
@ -157,8 +158,8 @@ class GeneratedTextColumn extends GeneratedColumn<String>
|
|||
bool nullable, {
|
||||
this.minTextLength,
|
||||
this.maxTextLength,
|
||||
String $customConstraints,
|
||||
Expression<String> defaultValue,
|
||||
String? $customConstraints,
|
||||
Expression<String?>? defaultValue,
|
||||
}) : super(name, tableName, nullable,
|
||||
$customConstraints: $customConstraints, defaultValue: defaultValue);
|
||||
|
||||
|
@ -166,16 +167,16 @@ class GeneratedTextColumn extends GeneratedColumn<String>
|
|||
final String typeName = 'TEXT';
|
||||
|
||||
@override
|
||||
VerificationResult isAcceptableValue(String value, VerificationMeta meta) {
|
||||
VerificationResult isAcceptableValue(String? value, VerificationMeta meta) {
|
||||
// handle nullability check in common column
|
||||
if (value == null) return super.isAcceptableValue(null, meta);
|
||||
|
||||
final length = value.length;
|
||||
if (minTextLength != null && minTextLength > length) {
|
||||
if (minTextLength != null && minTextLength! > length) {
|
||||
return VerificationResult.failure(
|
||||
'Must at least be $minTextLength characters long.');
|
||||
}
|
||||
if (maxTextLength != null && maxTextLength < length) {
|
||||
if (maxTextLength != null && maxTextLength! < length) {
|
||||
return VerificationResult.failure(
|
||||
'Must at most be $maxTextLength characters long.');
|
||||
}
|
||||
|
@ -185,10 +186,10 @@ class GeneratedTextColumn extends GeneratedColumn<String>
|
|||
}
|
||||
|
||||
/// Implementation for [BoolColumn].
|
||||
class GeneratedBoolColumn extends GeneratedColumn<bool> implements BoolColumn {
|
||||
class GeneratedBoolColumn extends GeneratedColumn<bool?> implements BoolColumn {
|
||||
/// Used by generated code
|
||||
GeneratedBoolColumn(String name, String tableName, bool nullable,
|
||||
{String $customConstraints, Expression<bool> defaultValue})
|
||||
{String? $customConstraints, Expression<bool?>? defaultValue})
|
||||
: super(name, tableName, nullable,
|
||||
$customConstraints: $customConstraints, defaultValue: defaultValue);
|
||||
|
||||
|
@ -202,7 +203,7 @@ class GeneratedBoolColumn extends GeneratedColumn<bool> implements BoolColumn {
|
|||
}
|
||||
|
||||
/// Implementation for [IntColumn]
|
||||
class GeneratedIntColumn extends GeneratedColumn<int> implements IntColumn {
|
||||
class GeneratedIntColumn extends GeneratedColumn<int?> implements IntColumn {
|
||||
/// Whether this column was declared to be a primary key via a column
|
||||
/// constraint. The only way to do this in Dart is with
|
||||
/// [IntColumnBuilder.autoIncrement]. In `.moor` files, declaring a column
|
||||
|
@ -226,8 +227,8 @@ class GeneratedIntColumn extends GeneratedColumn<int> implements IntColumn {
|
|||
bool nullable, {
|
||||
this.declaredAsPrimaryKey = false,
|
||||
this.hasAutoIncrement = false,
|
||||
String $customConstraints,
|
||||
Expression<int> defaultValue,
|
||||
String? $customConstraints,
|
||||
Expression<int?>? defaultValue,
|
||||
}) : super(name, tableName, nullable,
|
||||
$customConstraints: $customConstraints, defaultValue: defaultValue);
|
||||
|
||||
|
@ -248,15 +249,15 @@ class GeneratedIntColumn extends GeneratedColumn<int> implements IntColumn {
|
|||
}
|
||||
|
||||
/// Implementation for [DateTimeColumn].
|
||||
class GeneratedDateTimeColumn extends GeneratedColumn<DateTime>
|
||||
class GeneratedDateTimeColumn extends GeneratedColumn<DateTime?>
|
||||
implements DateTimeColumn {
|
||||
/// Used by generated code.
|
||||
GeneratedDateTimeColumn(
|
||||
String $name,
|
||||
String tableName,
|
||||
bool $nullable, {
|
||||
String $customConstraints,
|
||||
Expression<DateTime> defaultValue,
|
||||
String? $customConstraints,
|
||||
Expression<DateTime?>? defaultValue,
|
||||
}) : super($name, tableName, $nullable,
|
||||
$customConstraints: $customConstraints, defaultValue: defaultValue);
|
||||
|
||||
|
@ -265,11 +266,11 @@ class GeneratedDateTimeColumn extends GeneratedColumn<DateTime>
|
|||
}
|
||||
|
||||
/// Implementation for [BlobColumn]
|
||||
class GeneratedBlobColumn extends GeneratedColumn<Uint8List>
|
||||
class GeneratedBlobColumn extends GeneratedColumn<Uint8List?>
|
||||
implements BlobColumn {
|
||||
/// Used by generated code.
|
||||
GeneratedBlobColumn(String $name, String tableName, bool $nullable,
|
||||
{String $customConstraints, Expression<Uint8List> defaultValue})
|
||||
{String? $customConstraints, Expression<Uint8List?>? defaultValue})
|
||||
: super($name, tableName, $nullable,
|
||||
$customConstraints: $customConstraints, defaultValue: defaultValue);
|
||||
|
||||
|
@ -278,15 +279,15 @@ class GeneratedBlobColumn extends GeneratedColumn<Uint8List>
|
|||
}
|
||||
|
||||
/// Implementation for [RealColumn]
|
||||
class GeneratedRealColumn extends GeneratedColumn<double>
|
||||
class GeneratedRealColumn extends GeneratedColumn<double?>
|
||||
implements RealColumn {
|
||||
/// Used by generated code
|
||||
GeneratedRealColumn(
|
||||
String $name,
|
||||
String tableName,
|
||||
bool $nullable, {
|
||||
Expression<double> defaultValue,
|
||||
String $customConstraints,
|
||||
Expression<double>? defaultValue,
|
||||
String? $customConstraints,
|
||||
}) : super($name, tableName, $nullable,
|
||||
defaultValue: defaultValue, $customConstraints: $customConstraints);
|
||||
|
||||
|
|
|
@ -9,12 +9,12 @@ mixin TableInfo<TableDsl extends Table, D extends DataClass> on Table
|
|||
/// [TableInfo] and [TableDsl] and can thus just return their instance.
|
||||
TableDsl get asDslTable;
|
||||
|
||||
/// The primary key of this table. Can be null or empty if no custom primary
|
||||
/// key has been specified.
|
||||
/// The primary key of this table. Can be empty if no custom primary key has
|
||||
/// been specified.
|
||||
///
|
||||
/// Additional to the [Table.primaryKey] columns declared by an user, this
|
||||
/// also contains auto-increment integers, which are primary key by default.
|
||||
Set<GeneratedColumn> get $primaryKey => null;
|
||||
Set<GeneratedColumn> get $primaryKey => const {};
|
||||
|
||||
// ensure the primaryKey getter is consistent with $primaryKey, which can
|
||||
// contain additional columns.
|
||||
|
@ -35,7 +35,7 @@ mixin TableInfo<TableDsl extends Table, D extends DataClass> on Table
|
|||
/// All columns defined in this table.
|
||||
List<GeneratedColumn> get $columns;
|
||||
|
||||
Map<String, GeneratedColumn> _columnsByName;
|
||||
Map<String, GeneratedColumn>? _columnsByName;
|
||||
|
||||
/// Gets all [$columns] in this table, indexed by their (non-escaped) name.
|
||||
Map<String, GeneratedColumn> get columnsByName {
|
||||
|
@ -54,7 +54,7 @@ mixin TableInfo<TableDsl extends Table, D extends DataClass> on Table
|
|||
}
|
||||
|
||||
/// Maps the given row returned by the database into the fitting data class.
|
||||
D map(Map<String, dynamic> data, {String tablePrefix});
|
||||
D map(Map<String, dynamic> data, {String? tablePrefix});
|
||||
|
||||
/// Converts a [companion] to the real model class, [D].
|
||||
///
|
||||
|
@ -120,13 +120,13 @@ extension TableInfoUtils<TableDsl extends Table, D extends DataClass>
|
|||
}
|
||||
|
||||
/// Like [map], but from a [row] instead of the low-level map.
|
||||
D mapFromRow(QueryRow row, {String tablePrefix}) {
|
||||
D mapFromRow(QueryRow row, {String? tablePrefix}) {
|
||||
return map(row.data, tablePrefix: tablePrefix);
|
||||
}
|
||||
|
||||
/// Like [mapFromRow], but returns null if a non-nullable column of this table
|
||||
/// is null in [row].
|
||||
D /*?*/ mapFromRowOrNull(QueryRow row, {String tablePrefix}) {
|
||||
D? mapFromRowOrNull(QueryRow row, {String? tablePrefix}) {
|
||||
final resolvedPrefix = tablePrefix == null ? '' : '$tablePrefix.';
|
||||
|
||||
final notInRow = $columns
|
||||
|
@ -153,7 +153,7 @@ extension TableInfoUtils<TableDsl extends Table, D extends DataClass>
|
|||
/// `'c2': 'bar'` in [alias].
|
||||
D mapFromRowWithAlias(QueryRow row, Map<String, String> alias) {
|
||||
return map({
|
||||
for (final entry in row.data.entries) alias[entry.key]: entry.value,
|
||||
for (final entry in row.data.entries) alias[entry.key]!: entry.value,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ class DeleteStatement<T extends Table, D extends DataClass> extends Query<T, D>
|
|||
Future<int> go() async {
|
||||
final ctx = constructQuery();
|
||||
|
||||
return ctx.executor.doWhenOpened((e) async {
|
||||
return ctx.executor!.doWhenOpened((e) async {
|
||||
final rows = await e.runDelete(ctx.sql, ctx.boundVariables);
|
||||
|
||||
if (rows > 0) {
|
||||
|
|
|
@ -60,8 +60,8 @@ class InsertStatement<T extends Table, D extends DataClass> {
|
|||
/// Still, the future will always complete with an error if the insert fails.
|
||||
Future<int> insert(
|
||||
Insertable<D> entity, {
|
||||
InsertMode mode,
|
||||
DoUpdate<T, D> onConflict,
|
||||
InsertMode? mode,
|
||||
DoUpdate<T, D>? onConflict,
|
||||
}) async {
|
||||
final ctx = createContext(entity, mode ?? InsertMode.insert,
|
||||
onConflict: onConflict);
|
||||
|
@ -94,7 +94,7 @@ class InsertStatement<T extends Table, D extends DataClass> {
|
|||
///
|
||||
/// This method is used internally by moor. Consider using [insert] instead.
|
||||
GenerationContext createContext(Insertable<D> entry, InsertMode mode,
|
||||
{DoUpdate<T, D> onConflict}) {
|
||||
{DoUpdate<T, D>? onConflict}) {
|
||||
_validateIntegrity(entry);
|
||||
|
||||
final rawValues = entry.toColumns(true);
|
||||
|
@ -105,7 +105,7 @@ class InsertStatement<T extends Table, D extends DataClass> {
|
|||
final columnName = column.$name;
|
||||
|
||||
if (rawValues.containsKey(columnName)) {
|
||||
map[columnName] = rawValues[columnName];
|
||||
map[columnName] = rawValues[columnName]!;
|
||||
} else {
|
||||
if (column.clientDefault != null) {
|
||||
map[columnName] = column._evaluateClientDefault();
|
||||
|
@ -165,6 +165,12 @@ class InsertStatement<T extends Table, D extends DataClass> {
|
|||
ctx.buffer.write(' ON CONFLICT(');
|
||||
|
||||
final conflictTarget = onConflict.target ?? table.$primaryKey.toList();
|
||||
|
||||
if (conflictTarget.isEmpty) {
|
||||
throw ArgumentError(
|
||||
'Table has no primary key, so a conflict target is needed.');
|
||||
}
|
||||
|
||||
var first = true;
|
||||
for (final target in conflictTarget) {
|
||||
if (!first) ctx.buffer.write(', ');
|
||||
|
@ -190,7 +196,7 @@ class InsertStatement<T extends Table, D extends DataClass> {
|
|||
return ctx;
|
||||
}
|
||||
|
||||
void _validateIntegrity(Insertable<D> d) {
|
||||
void _validateIntegrity(Insertable<D>? d) {
|
||||
if (d == null) {
|
||||
throw InvalidDataException(
|
||||
'Cannot write null row into ${table.$tableName}');
|
||||
|
@ -254,7 +260,7 @@ class DoUpdate<T extends Table, D extends DataClass> {
|
|||
/// specifies the uniqueness constraint that will trigger the upsert.
|
||||
///
|
||||
/// By default, the primary key of the table will be used.
|
||||
final List<Column> /*?*/ target;
|
||||
final List<Column>? target;
|
||||
|
||||
/// For an example, see [InsertStatement.insert].
|
||||
DoUpdate(Insertable<D> Function(T old) update, {this.target})
|
||||
|
|
|
@ -16,17 +16,17 @@ abstract class Query<T extends Table, D extends DataClass> {
|
|||
|
||||
/// The `WHERE` clause for this statement
|
||||
@protected
|
||||
Where whereExpr;
|
||||
Where? whereExpr;
|
||||
|
||||
/// The `ORDER BY` clause for this statement
|
||||
@protected
|
||||
OrderBy orderByExpr;
|
||||
OrderBy? orderByExpr;
|
||||
|
||||
/// The `LIMIT` clause for this statement.
|
||||
@protected
|
||||
Limit limitExpr;
|
||||
Limit? limitExpr;
|
||||
|
||||
GroupBy _groupBy;
|
||||
GroupBy? _groupBy;
|
||||
|
||||
/// Subclasses must override this and write the part of the statement that
|
||||
/// comes before the where and limit expression..
|
||||
|
@ -44,7 +44,7 @@ abstract class Query<T extends Table, D extends DataClass> {
|
|||
// whether we need to insert a space before writing the next component
|
||||
var needsWhitespace = false;
|
||||
|
||||
void writeWithSpace(Component /*?*/ component) {
|
||||
void writeWithSpace(Component? component) {
|
||||
if (component == null) return;
|
||||
|
||||
if (needsWhitespace) ctx.writeWhitespace();
|
||||
|
@ -96,7 +96,7 @@ abstract class Selectable<T> {
|
|||
/// one row, for instance because you used `limit(1)` or you know the `where`
|
||||
/// clause will only allow one row.
|
||||
/// {@endtemplate}
|
||||
Future<T> getSingle() async {
|
||||
Future<T?> getSingle() async {
|
||||
final list = await get();
|
||||
final iterator = list.iterator;
|
||||
|
||||
|
@ -119,7 +119,7 @@ abstract class Selectable<T> {
|
|||
/// will be added to the stream instead.
|
||||
///
|
||||
/// {@macro moor_single_query_expl}
|
||||
Stream<T> watchSingle() {
|
||||
Stream<T?> watchSingle() {
|
||||
return watch().transform(singleElements());
|
||||
}
|
||||
|
||||
|
@ -182,7 +182,7 @@ mixin SingleTableQueryMixin<T extends Table, D extends DataClass>
|
|||
if (whereExpr == null) {
|
||||
whereExpr = Where(predicate);
|
||||
} else {
|
||||
whereExpr = Where(whereExpr.predicate & predicate);
|
||||
whereExpr = Where(whereExpr!.predicate & predicate);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -190,7 +190,7 @@ mixin SingleTableQueryMixin<T extends Table, D extends DataClass>
|
|||
/// [d] will be matched.
|
||||
void whereSamePrimaryKey(Insertable<D> d) {
|
||||
assert(
|
||||
table.$primaryKey != null && table.$primaryKey.isNotEmpty,
|
||||
table.$primaryKey.isNotEmpty,
|
||||
'When using Query.whereSamePrimaryKey, which is also called from '
|
||||
'DeleteStatement.delete and UpdateStatement.replace, the affected table'
|
||||
'must have a primary key. You can either specify a primary implicitly '
|
||||
|
@ -212,10 +212,10 @@ mixin SingleTableQueryMixin<T extends Table, D extends DataClass>
|
|||
final primaryKeyValues = Map.fromEntries(updatedFields.entries
|
||||
.where((entry) => primaryKeyColumns.containsKey(entry.key)))
|
||||
.map((columnName, value) {
|
||||
return MapEntry(primaryKeyColumns[columnName], value);
|
||||
return MapEntry(primaryKeyColumns[columnName]!, value);
|
||||
});
|
||||
|
||||
Expression<bool> predicate;
|
||||
Expression<bool?>? predicate;
|
||||
for (final entry in primaryKeyValues.entries) {
|
||||
final comparison =
|
||||
_Comparison(entry.key, _ComparisonOperator.equal, entry.value);
|
||||
|
@ -227,7 +227,7 @@ mixin SingleTableQueryMixin<T extends Table, D extends DataClass>
|
|||
}
|
||||
}
|
||||
|
||||
whereExpr = Where(predicate);
|
||||
whereExpr = Where(predicate!);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,7 +236,7 @@ mixin LimitContainerMixin<T extends Table, D extends DataClass> on Query<T, D> {
|
|||
/// Limits the amount of rows returned by capping them at [limit]. If [offset]
|
||||
/// is provided as well, the first [offset] rows will be skipped and not
|
||||
/// included in the result.
|
||||
void limit(int limit, {int offset}) {
|
||||
void limit(int limit, {int? offset}) {
|
||||
limitExpr = Limit(limit, offset);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,11 +73,11 @@ class QueryRow {
|
|||
|
||||
/// Reads an arbitrary value from the row and maps it to a fitting dart type.
|
||||
/// The dart type [T] must be supported by the type system of the database
|
||||
/// used (mostly contains booleans, strings, integers and dates).
|
||||
/// used (mostly contains booleans, strings, numbers and dates).
|
||||
T read<T>(String key) {
|
||||
final type = _db.typeSystem.forDartType<T>();
|
||||
|
||||
return type.mapFromDatabaseResponse(data[key]);
|
||||
return type.mapFromDatabaseResponse(data[key]) as T;
|
||||
}
|
||||
|
||||
/// Reads a bool from the column named [key].
|
||||
|
|
|
@ -36,7 +36,7 @@ class SimpleSelectStatement<T extends Table, D extends DataClass>
|
|||
}
|
||||
|
||||
Future<List<D>> _getWithQuery(GenerationContext ctx) async {
|
||||
final results = await ctx.executor.doWhenOpened((e) async {
|
||||
final results = await ctx.executor!.doWhenOpened((e) async {
|
||||
return await e.runSelect(ctx.sql, ctx.boundVariables);
|
||||
});
|
||||
return results.map(table.map).toList();
|
||||
|
@ -69,10 +69,10 @@ class SimpleSelectStatement<T extends Table, D extends DataClass>
|
|||
final statement = JoinedSelectStatement(database, table, joins, distinct);
|
||||
|
||||
if (whereExpr != null) {
|
||||
statement.where(whereExpr.predicate);
|
||||
statement.where(whereExpr!.predicate);
|
||||
}
|
||||
if (orderByExpr != null) {
|
||||
statement.orderBy(orderByExpr.terms);
|
||||
statement.orderBy(orderByExpr!.terms);
|
||||
}
|
||||
if (limitExpr != null) {
|
||||
statement.limitExpr = limitExpr;
|
||||
|
@ -129,7 +129,7 @@ class TypedResult {
|
|||
TypedResult(this._parsedData, this.rawData, [this._parsedExpressions]);
|
||||
|
||||
final Map<TableInfo, dynamic> _parsedData;
|
||||
final Map<Expression, dynamic> _parsedExpressions;
|
||||
final Map<Expression, dynamic>? _parsedExpressions;
|
||||
|
||||
/// The raw data contained in this row.
|
||||
final QueryRow rawData;
|
||||
|
@ -142,10 +142,10 @@ class TypedResult {
|
|||
/// Reads a single column from an [expr]. The expression must have been added
|
||||
/// as a column, for instance via [JoinedSelectStatement.addColumns].
|
||||
///
|
||||
/// To access the underlying columns directly, use
|
||||
D read<D, T extends SqlType<D>>(Expression<D> expr) {
|
||||
/// To access the underlying columns directly, use [rawData].
|
||||
D? read<D>(Expression<D> expr) {
|
||||
if (_parsedExpressions != null) {
|
||||
return _parsedExpressions[expr] as D;
|
||||
return _parsedExpressions![expr] as D;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -109,11 +109,11 @@ class JoinedSelectStatement<FirstT extends Table, FirstD extends DataClass>
|
|||
/// ])
|
||||
/// ..where(todos.name.like("%Important") & categories.name.equals("Work"));
|
||||
/// ```
|
||||
void where(Expression<bool> predicate) {
|
||||
void where(Expression<bool?> predicate) {
|
||||
if (whereExpr == null) {
|
||||
whereExpr = Where(predicate);
|
||||
} else {
|
||||
whereExpr = Where(whereExpr.predicate & predicate);
|
||||
whereExpr = Where(whereExpr!.predicate & predicate);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,7 +165,7 @@ class JoinedSelectStatement<FirstT extends Table, FirstD extends DataClass>
|
|||
/// Groups the result by values in [expressions].
|
||||
///
|
||||
/// An optional [having] attribute can be set to exclude certain groups.
|
||||
void groupBy(Iterable<Expression> expressions, {Expression<bool> having}) {
|
||||
void groupBy(Iterable<Expression> expressions, {Expression<bool>? having}) {
|
||||
_groupBy = GroupBy._(expressions.toList(), having);
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,7 @@ class JoinedSelectStatement<FirstT extends Table, FirstD extends DataClass>
|
|||
}
|
||||
|
||||
Future<List<TypedResult>> _getWithQuery(GenerationContext ctx) async {
|
||||
final results = await ctx.executor.doWhenOpened((e) async {
|
||||
final results = await ctx.executor!.doWhenOpened((e) async {
|
||||
try {
|
||||
return await e.runSelect(ctx.sql, ctx.boundVariables);
|
||||
} catch (e, s) {
|
||||
|
|
|
@ -7,7 +7,7 @@ class UpdateStatement<T extends Table, D extends DataClass> extends Query<T, D>
|
|||
UpdateStatement(QueryEngine database, TableInfo<T, D> table)
|
||||
: super(database, table);
|
||||
|
||||
Map<String, Expression> _updatedFields;
|
||||
late Map<String, Expression> _updatedFields;
|
||||
|
||||
@override
|
||||
void writeStartPart(GenerationContext ctx) {
|
||||
|
@ -31,7 +31,7 @@ class UpdateStatement<T extends Table, D extends DataClass> extends Query<T, D>
|
|||
|
||||
Future<int> _performQuery() async {
|
||||
final ctx = constructQuery();
|
||||
final rows = await ctx.executor.doWhenOpened((e) async {
|
||||
final rows = await ctx.executor!.doWhenOpened((e) async {
|
||||
return await e.runUpdate(ctx.sql, ctx.boundVariables);
|
||||
});
|
||||
|
||||
|
@ -123,7 +123,7 @@ class UpdateStatement<T extends Table, D extends DataClass> extends Query<T, D>
|
|||
// if a default value exists and no value is set, apply the default
|
||||
if (column.defaultValue != null &&
|
||||
!_updatedFields.containsKey(column.$name)) {
|
||||
_updatedFields[column.$name] = column.defaultValue;
|
||||
_updatedFields[column.$name] = column.defaultValue!;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,12 +13,11 @@ abstract class TypeConverter<D, S> {
|
|||
const TypeConverter();
|
||||
|
||||
/// Map a value from an object in Dart into something that will be understood
|
||||
/// by the database. Be aware that [value] is nullable.
|
||||
S mapToSql(D value);
|
||||
/// by the database.
|
||||
S? mapToSql(D? value);
|
||||
|
||||
/// Maps a column from the database back to Dart. Be aware that [fromDb] is
|
||||
/// nullable.
|
||||
D mapToDart(S fromDb);
|
||||
/// Maps a column from the database back to Dart.
|
||||
D? mapToDart(S? fromDb);
|
||||
}
|
||||
|
||||
/// Implementation for an enum to int converter that uses the index of the enum
|
||||
|
@ -31,12 +30,12 @@ class EnumIndexConverter<T> extends TypeConverter<T, int> {
|
|||
const EnumIndexConverter(this.values);
|
||||
|
||||
@override
|
||||
T mapToDart(int fromDb) {
|
||||
T? mapToDart(int? fromDb) {
|
||||
return fromDb == null ? null : values[fromDb];
|
||||
}
|
||||
|
||||
@override
|
||||
int mapToSql(T value) {
|
||||
int? mapToSql(T? value) {
|
||||
return (value as dynamic)?.index as int;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:typed_data';
|
||||
|
||||
// ignore: import_of_legacy_library_into_null_safe
|
||||
import 'package:convert/convert.dart';
|
||||
import 'package:moor/moor.dart';
|
||||
|
||||
|
@ -17,14 +18,14 @@ abstract class SqlType<T> {
|
|||
|
||||
/// Maps the [content] to a value that we can send together with a prepared
|
||||
/// statement to represent the given value.
|
||||
dynamic mapToSqlVariable(T content);
|
||||
dynamic mapToSqlVariable(T? content);
|
||||
|
||||
/// Maps the given content to a sql literal that can be included in the query
|
||||
/// string.
|
||||
String mapToSqlConstant(T content);
|
||||
String? mapToSqlConstant(T? content);
|
||||
|
||||
/// Maps the response from sql back to a readable dart type.
|
||||
T mapFromDatabaseResponse(dynamic response);
|
||||
T? mapFromDatabaseResponse(dynamic response);
|
||||
}
|
||||
|
||||
/// A mapper for boolean values in sql. Booleans are represented as integers,
|
||||
|
@ -37,14 +38,14 @@ class BoolType extends SqlType<bool> {
|
|||
String get sqlName => 'INTEGER';
|
||||
|
||||
@override
|
||||
bool mapFromDatabaseResponse(dynamic response) {
|
||||
bool? mapFromDatabaseResponse(dynamic response) {
|
||||
// ignore: avoid_returning_null
|
||||
if (response == null) return null;
|
||||
return response != 0;
|
||||
}
|
||||
|
||||
@override
|
||||
String mapToSqlConstant(bool content) {
|
||||
String mapToSqlConstant(bool? content) {
|
||||
if (content == null) {
|
||||
return 'NULL';
|
||||
}
|
||||
|
@ -52,7 +53,7 @@ class BoolType extends SqlType<bool> {
|
|||
}
|
||||
|
||||
@override
|
||||
int mapToSqlVariable(bool content) {
|
||||
int? mapToSqlVariable(bool? content) {
|
||||
if (content == null) {
|
||||
// ignore: avoid_returning_null
|
||||
return null;
|
||||
|
@ -70,10 +71,12 @@ class StringType extends SqlType<String> {
|
|||
String get sqlName => 'TEXT';
|
||||
|
||||
@override
|
||||
String mapFromDatabaseResponse(dynamic response) => response?.toString();
|
||||
String? mapFromDatabaseResponse(dynamic response) => response?.toString();
|
||||
|
||||
@override
|
||||
String mapToSqlConstant(String content) {
|
||||
String mapToSqlConstant(String? content) {
|
||||
if (content == null) return 'NULL';
|
||||
|
||||
// From the sqlite docs: (https://www.sqlite.org/lang_expr.html)
|
||||
// A string constant is formed by enclosing the string in single quotes (').
|
||||
// A single quote within the string can be encoded by putting two single
|
||||
|
@ -84,7 +87,7 @@ class StringType extends SqlType<String> {
|
|||
}
|
||||
|
||||
@override
|
||||
String mapToSqlVariable(String content) => content;
|
||||
String? mapToSqlVariable(String? content) => content;
|
||||
}
|
||||
|
||||
/// Maps [int] values from and to sql
|
||||
|
@ -96,16 +99,16 @@ class IntType extends SqlType<int> {
|
|||
String get sqlName => 'INTEGER';
|
||||
|
||||
@override
|
||||
int mapFromDatabaseResponse(dynamic response) {
|
||||
if (response == null || response is int /*?*/) return response as int /*?*/;
|
||||
int? mapFromDatabaseResponse(dynamic response) {
|
||||
if (response == null || response is int?) return response as int?;
|
||||
return int.parse(response.toString());
|
||||
}
|
||||
|
||||
@override
|
||||
String mapToSqlConstant(int content) => content?.toString() ?? 'NULL';
|
||||
String mapToSqlConstant(int? content) => content?.toString() ?? 'NULL';
|
||||
|
||||
@override
|
||||
int mapToSqlVariable(int content) {
|
||||
int? mapToSqlVariable(int? content) {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +122,7 @@ class DateTimeType extends SqlType<DateTime> {
|
|||
String get sqlName => 'INTEGER';
|
||||
|
||||
@override
|
||||
DateTime mapFromDatabaseResponse(dynamic response) {
|
||||
DateTime? mapFromDatabaseResponse(dynamic response) {
|
||||
if (response == null) return null;
|
||||
|
||||
final unixSeconds = response as int;
|
||||
|
@ -128,14 +131,14 @@ class DateTimeType extends SqlType<DateTime> {
|
|||
}
|
||||
|
||||
@override
|
||||
String mapToSqlConstant(DateTime content) {
|
||||
String mapToSqlConstant(DateTime? content) {
|
||||
if (content == null) return 'NULL';
|
||||
|
||||
return (content.millisecondsSinceEpoch ~/ 1000).toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int mapToSqlVariable(DateTime content) {
|
||||
int? mapToSqlVariable(DateTime? content) {
|
||||
// ignore: avoid_returning_null
|
||||
if (content == null) return null;
|
||||
|
||||
|
@ -152,17 +155,20 @@ class BlobType extends SqlType<Uint8List> {
|
|||
String get sqlName => 'BLOB';
|
||||
|
||||
@override
|
||||
Uint8List mapFromDatabaseResponse(dynamic response) => response as Uint8List;
|
||||
Uint8List? mapFromDatabaseResponse(dynamic response) {
|
||||
return response as Uint8List?;
|
||||
}
|
||||
|
||||
@override
|
||||
String mapToSqlConstant(Uint8List content) {
|
||||
String mapToSqlConstant(Uint8List? content) {
|
||||
if (content == null) return 'NULL';
|
||||
// BLOB literals are string literals containing hexadecimal data and
|
||||
// preceded by a single "x" or "X" character. Example: X'53514C697465'
|
||||
return "x'${hex.encode(content)}'";
|
||||
}
|
||||
|
||||
@override
|
||||
Uint8List mapToSqlVariable(Uint8List content) => content;
|
||||
Uint8List? mapToSqlVariable(Uint8List? content) => content;
|
||||
}
|
||||
|
||||
/// Maps [double] values from and to sql
|
||||
|
@ -174,12 +180,12 @@ class RealType extends SqlType<double> {
|
|||
String get sqlName => 'REAL';
|
||||
|
||||
@override
|
||||
double mapFromDatabaseResponse(dynamic response) {
|
||||
return (response as num)?.toDouble();
|
||||
double? mapFromDatabaseResponse(dynamic response) {
|
||||
return (response as num?)?.toDouble();
|
||||
}
|
||||
|
||||
@override
|
||||
String mapToSqlConstant(num content) {
|
||||
String mapToSqlConstant(num? content) {
|
||||
if (content == null) {
|
||||
return 'NULL';
|
||||
}
|
||||
|
@ -187,5 +193,5 @@ class RealType extends SqlType<double> {
|
|||
}
|
||||
|
||||
@override
|
||||
num mapToSqlVariable(num content) => content;
|
||||
num? mapToSqlVariable(num? content) => content;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ class SqlTypeSystem {
|
|||
RealType(),
|
||||
]);
|
||||
|
||||
/// Constant field of [SqlTypeSystem.withDefaults()]. This field exists as a
|
||||
/// Constant field of [SqlTypeSystem.withDefaults]. This field exists as a
|
||||
/// workaround for an analyzer bug: https://dartbug.com/38658
|
||||
///
|
||||
/// Used internally by generated code.
|
||||
|
|
|
@ -9,8 +9,10 @@ typedef DatabaseOpener = FutureOr<QueryExecutor> Function();
|
|||
/// A special database executor that delegates work to another [QueryExecutor].
|
||||
/// The other executor is lazily opened by a [DatabaseOpener].
|
||||
class LazyDatabase extends QueryExecutor {
|
||||
QueryExecutor _delegate;
|
||||
Completer<void> _openDelegate;
|
||||
late QueryExecutor _delegate;
|
||||
bool _delegateAvailable = false;
|
||||
|
||||
Completer<void>? _openDelegate;
|
||||
|
||||
/// The function that will open the database when this [LazyDatabase] gets
|
||||
/// opened for the first time.
|
||||
|
@ -21,17 +23,18 @@ class LazyDatabase extends QueryExecutor {
|
|||
LazyDatabase(this.opener);
|
||||
|
||||
Future<void> _awaitOpened() {
|
||||
if (_delegate != null) {
|
||||
if (_delegateAvailable) {
|
||||
return Future.value();
|
||||
} else if (_openDelegate != null) {
|
||||
return _openDelegate.future;
|
||||
return _openDelegate!.future;
|
||||
} else {
|
||||
_openDelegate = Completer();
|
||||
final delegate = _openDelegate = Completer();
|
||||
Future.value(opener()).then((database) {
|
||||
_delegate = database;
|
||||
_openDelegate.complete();
|
||||
_delegateAvailable = true;
|
||||
delegate.complete();
|
||||
});
|
||||
return _openDelegate.future;
|
||||
return delegate.future;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,28 +51,30 @@ class LazyDatabase extends QueryExecutor {
|
|||
_delegate.runBatched(statements);
|
||||
|
||||
@override
|
||||
Future<void> runCustom(String statement, [List args]) =>
|
||||
Future<void> runCustom(String statement, [List<Object?>? args]) =>
|
||||
_delegate.runCustom(statement, args);
|
||||
|
||||
@override
|
||||
Future<int> runDelete(String statement, List args) =>
|
||||
Future<int> runDelete(String statement, List<Object?> args) =>
|
||||
_delegate.runDelete(statement, args);
|
||||
|
||||
@override
|
||||
Future<int> runInsert(String statement, List args) =>
|
||||
Future<int> runInsert(String statement, List<Object?> args) =>
|
||||
_delegate.runInsert(statement, args);
|
||||
|
||||
@override
|
||||
Future<List<Map<String, dynamic>>> runSelect(String statement, List args) =>
|
||||
_delegate.runSelect(statement, args);
|
||||
Future<List<Map<String, Object?>>> runSelect(
|
||||
String statement, List<Object?> args) {
|
||||
return _delegate.runSelect(statement, args);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> runUpdate(String statement, List args) =>
|
||||
Future<int> runUpdate(String statement, List<Object?> args) =>
|
||||
_delegate.runUpdate(statement, args);
|
||||
|
||||
@override
|
||||
Future<void> close() {
|
||||
if (_delegate != null) {
|
||||
if (_delegateAvailable) {
|
||||
return _delegate.close();
|
||||
} else {
|
||||
return Future.value();
|
||||
|
|
|
@ -2,7 +2,7 @@ import 'dart:async';
|
|||
|
||||
/// Transforms a stream of lists into a stream of single elements, assuming
|
||||
/// that each list is a singleton.
|
||||
StreamTransformer<List<T>, T> singleElements<T>() {
|
||||
StreamTransformer<List<T>, T?> singleElements<T>() {
|
||||
return StreamTransformer.fromHandlers(handleData: (data, sink) {
|
||||
try {
|
||||
if (data.isEmpty) {
|
||||
|
|
|
@ -2,7 +2,7 @@ import 'dart:async';
|
|||
|
||||
/// Signature of a function that returns the latest current value of a
|
||||
/// [StartWithValueTransformer].
|
||||
typedef LatestValue<T> = T Function();
|
||||
typedef LatestValue<T> = T? Function();
|
||||
|
||||
/// Lightweight implementation that turns a [StreamController] into a behavior
|
||||
/// subject (we try to avoid depending on rxdart because of its size).
|
||||
|
@ -29,8 +29,8 @@ class _StartWithValueStream<T> extends Stream<T> {
|
|||
bool get isBroadcast => _inner.isBroadcast;
|
||||
|
||||
@override
|
||||
StreamSubscription<T> listen(void Function(T event) onData,
|
||||
{Function onError, void Function() onDone, bool cancelOnError}) {
|
||||
StreamSubscription<T> listen(void Function(T event)? onData,
|
||||
{Function? onError, void Function()? onDone, bool? cancelOnError}) {
|
||||
final data = _value();
|
||||
return _StartWithValueSubscription(_inner, data, onData,
|
||||
onError: onError, onDone: onDone, cancelOnError: cancelOnError);
|
||||
|
@ -38,32 +38,33 @@ class _StartWithValueStream<T> extends Stream<T> {
|
|||
}
|
||||
|
||||
class _StartWithValueSubscription<T> extends StreamSubscription<T> {
|
||||
StreamSubscription<T> _inner;
|
||||
final T initialData;
|
||||
late final StreamSubscription<T> _inner;
|
||||
final T? initialData;
|
||||
|
||||
bool needsInitialData = true;
|
||||
void Function(T data) _onData;
|
||||
void Function(T data)? _onData;
|
||||
|
||||
_StartWithValueSubscription(
|
||||
Stream<T> innerStream, this.initialData, this._onData,
|
||||
{Function onError, void Function() onDone, bool cancelOnError}) {
|
||||
{Function? onError, void Function()? onDone, bool? cancelOnError}) {
|
||||
_inner = innerStream.listen(_wrappedDataCallback(_onData),
|
||||
onError: onError, onDone: onDone, cancelOnError: cancelOnError);
|
||||
|
||||
// Dart's stream contract specifies that listeners are only notified
|
||||
// after the .listen() code completes. So, we add the initial data in
|
||||
// a later microtask.
|
||||
if (initialData != null) {
|
||||
final data = initialData;
|
||||
if (data != null) {
|
||||
scheduleMicrotask(() {
|
||||
if (needsInitialData) {
|
||||
_onData?.call(initialData);
|
||||
_onData?.call(data);
|
||||
needsInitialData = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Function(T data) _wrappedDataCallback(void Function(T data) onData) {
|
||||
void Function(T data) _wrappedDataCallback(void Function(T data)? onData) {
|
||||
return (event) {
|
||||
needsInitialData = false;
|
||||
onData?.call(event);
|
||||
|
@ -71,7 +72,7 @@ class _StartWithValueSubscription<T> extends StreamSubscription<T> {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<E> asFuture<E>([E futureValue]) => _inner.asFuture();
|
||||
Future<E> asFuture<E>([E? futureValue]) => _inner.asFuture(futureValue);
|
||||
|
||||
@override
|
||||
Future<void> cancel() {
|
||||
|
@ -83,20 +84,20 @@ class _StartWithValueSubscription<T> extends StreamSubscription<T> {
|
|||
bool get isPaused => _inner.isPaused;
|
||||
|
||||
@override
|
||||
void onData(void Function(T data) handleData) {
|
||||
void onData(void Function(T data)? handleData) {
|
||||
_onData = handleData;
|
||||
|
||||
_inner.onData(_wrappedDataCallback(handleData));
|
||||
}
|
||||
|
||||
@override
|
||||
void onDone(void Function() handleDone) => _inner.onDone(handleDone);
|
||||
void onDone(void Function()? handleDone) => _inner.onDone(handleDone);
|
||||
|
||||
@override
|
||||
void onError(Function handleError) => _inner.onError(handleError);
|
||||
void onError(Function? handleError) => _inner.onError(handleError);
|
||||
|
||||
@override
|
||||
void pause([Future<void> resumeSignal]) {
|
||||
void pause([Future<void>? resumeSignal]) {
|
||||
needsInitialData = false;
|
||||
_inner.pause(resumeSignal);
|
||||
}
|
||||
|
|
|
@ -7,12 +7,12 @@ import 'dart:typed_data';
|
|||
// This way, projects using moor can run on flutter as long as they don't import
|
||||
// this file.
|
||||
|
||||
Completer<SqlJsModule> _moduleCompleter;
|
||||
Completer<SqlJsModule>? _moduleCompleter;
|
||||
|
||||
/// Calls the `initSqlJs` function from the native sql.js library.
|
||||
Future<SqlJsModule> initSqlJs() {
|
||||
if (_moduleCompleter != null) {
|
||||
return _moduleCompleter.future;
|
||||
return _moduleCompleter!.future;
|
||||
}
|
||||
|
||||
_moduleCompleter = Completer();
|
||||
|
@ -26,7 +26,7 @@ Future<SqlJsModule> initSqlJs() {
|
|||
(context.callMethod('initSqlJs') as JsObject)
|
||||
.callMethod('then', [_handleModuleResolved]);
|
||||
|
||||
return _moduleCompleter.future;
|
||||
return _moduleCompleter!.future;
|
||||
}
|
||||
|
||||
// We're extracting this into its own method so that we don't have to call
|
||||
|
@ -34,7 +34,7 @@ Future<SqlJsModule> initSqlJs() {
|
|||
// todo figure out why dart2js generates invalid js when wrapping this in
|
||||
// allowInterop
|
||||
void _handleModuleResolved(dynamic module) {
|
||||
_moduleCompleter.complete(SqlJsModule._(module as JsObject));
|
||||
_moduleCompleter!.complete(SqlJsModule._(module as JsObject));
|
||||
}
|
||||
|
||||
/// `sql.js` module from the underlying library
|
||||
|
@ -43,7 +43,7 @@ class SqlJsModule {
|
|||
SqlJsModule._(this._obj);
|
||||
|
||||
/// Constructs a new [SqlJsDatabase], optionally from the [data] blob.
|
||||
SqlJsDatabase createDatabase([Uint8List data]) {
|
||||
SqlJsDatabase createDatabase([Uint8List? data]) {
|
||||
final dbObj = _createInternally(data);
|
||||
assert(() {
|
||||
// set the window.db variable to make debugging easier
|
||||
|
@ -54,7 +54,7 @@ class SqlJsModule {
|
|||
return SqlJsDatabase._(dbObj);
|
||||
}
|
||||
|
||||
JsObject _createInternally(Uint8List data) {
|
||||
JsObject _createInternally(Uint8List? data) {
|
||||
final constructor = _obj['Database'] as JsFunction;
|
||||
|
||||
if (data != null) {
|
||||
|
|
|
@ -13,7 +13,7 @@ abstract class MoorWebStorage {
|
|||
/// Restore the last database version that was saved with [store].
|
||||
///
|
||||
/// If no saved data was found, returns null.
|
||||
Future<Uint8List> restore();
|
||||
Future<Uint8List?> restore();
|
||||
|
||||
/// Store the entire database.
|
||||
Future<void> store(Uint8List data);
|
||||
|
@ -72,8 +72,8 @@ abstract class MoorWebStorage {
|
|||
}
|
||||
|
||||
abstract class _CustomSchemaVersionSave implements MoorWebStorage {
|
||||
int /*?*/ get schemaVersion;
|
||||
set schemaVersion(int value);
|
||||
int? get schemaVersion;
|
||||
set schemaVersion(int? value);
|
||||
}
|
||||
|
||||
String _persistenceKeyForLocalStorage(String name) {
|
||||
|
@ -84,7 +84,7 @@ String _legacyVersionKeyForLocalStorage(String name) {
|
|||
return 'moor_db_version_$name';
|
||||
}
|
||||
|
||||
Uint8List /*?*/ _restoreLocalStorage(String name) {
|
||||
Uint8List? _restoreLocalStorage(String name) {
|
||||
final raw = window.localStorage[_persistenceKeyForLocalStorage(name)];
|
||||
if (raw != null) {
|
||||
return bin2str.decode(raw);
|
||||
|
@ -101,7 +101,7 @@ class _LocalStorageImpl implements MoorWebStorage, _CustomSchemaVersionSave {
|
|||
const _LocalStorageImpl(this.name);
|
||||
|
||||
@override
|
||||
int get schemaVersion {
|
||||
int? get schemaVersion {
|
||||
final versionStr = window.localStorage[_versionKey];
|
||||
// ignore: avoid_returning_null
|
||||
if (versionStr == null) return null;
|
||||
|
@ -110,8 +110,14 @@ class _LocalStorageImpl implements MoorWebStorage, _CustomSchemaVersionSave {
|
|||
}
|
||||
|
||||
@override
|
||||
set schemaVersion(int value) {
|
||||
window.localStorage[_versionKey] = value.toString();
|
||||
set schemaVersion(int? value) {
|
||||
final key = _versionKey;
|
||||
|
||||
if (value == null) {
|
||||
window.localStorage.remove(key);
|
||||
} else {
|
||||
window.localStorage[_versionKey] = value.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -121,7 +127,7 @@ class _LocalStorageImpl implements MoorWebStorage, _CustomSchemaVersionSave {
|
|||
Future<void> open() => Future.value();
|
||||
|
||||
@override
|
||||
Future<Uint8List> restore() async {
|
||||
Future<Uint8List?> restore() async {
|
||||
return _restoreLocalStorage(name);
|
||||
}
|
||||
|
||||
|
@ -141,7 +147,7 @@ class _IndexedDbStorage implements MoorWebStorage {
|
|||
final bool migrateFromLocalStorage;
|
||||
final bool inWebWorker;
|
||||
|
||||
Database _database;
|
||||
late Database _database;
|
||||
|
||||
_IndexedDbStorage(this.name,
|
||||
{this.migrateFromLocalStorage = true, this.inWebWorker = false});
|
||||
|
@ -153,7 +159,7 @@ class _IndexedDbStorage implements MoorWebStorage {
|
|||
final indexedDb =
|
||||
inWebWorker ? WorkerGlobalScope.instance.indexedDB : window.indexedDB;
|
||||
|
||||
_database = await indexedDb.open(
|
||||
_database = await indexedDb!.open(
|
||||
_objectStoreName,
|
||||
version: 1,
|
||||
onUpgradeNeeded: (event) {
|
||||
|
@ -188,12 +194,12 @@ class _IndexedDbStorage implements MoorWebStorage {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> restore() async {
|
||||
Future<Uint8List?> restore() async {
|
||||
final transaction =
|
||||
_database.transactionStore(_objectStoreName, 'readonly');
|
||||
final store = transaction.objectStore(_objectStoreName);
|
||||
|
||||
final result = await store.getObject(name) as Blob /*?*/;
|
||||
final result = await store.getObject(name) as Blob?;
|
||||
if (result == null) return null;
|
||||
|
||||
final reader = FileReader();
|
||||
|
|
|
@ -13,7 +13,7 @@ class WebDatabase extends DelegatedDatabase {
|
|||
/// [name] can be used to identify multiple databases. The optional
|
||||
/// [initializer] can be used to initialize the database if it doesn't exist.
|
||||
WebDatabase(String name,
|
||||
{bool logStatements = false, CreateWebDatabase initializer})
|
||||
{bool logStatements = false, CreateWebDatabase? initializer})
|
||||
: super(_WebDelegate(MoorWebStorage(name), initializer),
|
||||
logStatements: logStatements, isSequential: true);
|
||||
|
||||
|
@ -23,15 +23,17 @@ class WebDatabase extends DelegatedDatabase {
|
|||
/// constructor of [MoorWebStorage] will use local storage for that, but an
|
||||
/// IndexedDB-based implementation is available via.
|
||||
WebDatabase.withStorage(MoorWebStorage storage,
|
||||
{bool logStatements = false, CreateWebDatabase initializer})
|
||||
{bool logStatements = false, CreateWebDatabase? initializer})
|
||||
: super(_WebDelegate(storage, initializer),
|
||||
logStatements: logStatements, isSequential: true);
|
||||
}
|
||||
|
||||
class _WebDelegate extends DatabaseDelegate {
|
||||
final MoorWebStorage storage;
|
||||
final CreateWebDatabase initializer;
|
||||
SqlJsDatabase _db;
|
||||
final CreateWebDatabase? initializer;
|
||||
|
||||
late SqlJsDatabase _db;
|
||||
bool _isOpen = false;
|
||||
|
||||
bool _inTransaction = false;
|
||||
|
||||
|
@ -56,13 +58,13 @@ class _WebDelegate extends DatabaseDelegate {
|
|||
@override
|
||||
DbVersionDelegate get versionDelegate =>
|
||||
_versionDelegate ??= _WebVersionDelegate(this);
|
||||
DbVersionDelegate _versionDelegate;
|
||||
DbVersionDelegate? _versionDelegate;
|
||||
|
||||
@override
|
||||
bool get isOpen => _db != null;
|
||||
bool get isOpen => _isOpen;
|
||||
|
||||
@override
|
||||
Future<void> open([QueryExecutorUser db]) async {
|
||||
Future<void> open(QueryExecutorUser db) async {
|
||||
final dbVersion = db.schemaVersion;
|
||||
assert(dbVersion >= 1, 'Database schema version needs to be at least 1');
|
||||
|
||||
|
@ -72,11 +74,15 @@ class _WebDelegate extends DatabaseDelegate {
|
|||
var restored = await storage.restore();
|
||||
|
||||
if (restored == null && initializer != null) {
|
||||
restored = await initializer();
|
||||
await storage.store(restored);
|
||||
restored = await initializer?.call();
|
||||
|
||||
if (restored != null) {
|
||||
await storage.store(restored);
|
||||
}
|
||||
}
|
||||
|
||||
_db = module.createDatabase(restored);
|
||||
_isOpen = true;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -100,13 +106,13 @@ class _WebDelegate extends DatabaseDelegate {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<void> runCustom(String statement, List args) {
|
||||
Future<void> runCustom(String statement, List<Object?> args) {
|
||||
_db.runWithArgs(statement, args);
|
||||
return Future.value();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> runInsert(String statement, List args) async {
|
||||
Future<int> runInsert(String statement, List<Object?> args) async {
|
||||
_db.runWithArgs(statement, args);
|
||||
final insertId = _db.lastInsertId();
|
||||
await _handlePotentialUpdate();
|
||||
|
@ -114,11 +120,11 @@ class _WebDelegate extends DatabaseDelegate {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<QueryResult> runSelect(String statement, List args) {
|
||||
Future<QueryResult> runSelect(String statement, List<Object?> args) {
|
||||
// todo at least for stream queries we should cache prepared statements.
|
||||
final stmt = _db.prepare(statement)..executeWith(args);
|
||||
|
||||
List<String> columnNames;
|
||||
List<String>? columnNames;
|
||||
final rows = <List<dynamic>>[];
|
||||
|
||||
while (stmt.step()) {
|
||||
|
@ -133,7 +139,7 @@ class _WebDelegate extends DatabaseDelegate {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<int> runUpdate(String statement, List args) {
|
||||
Future<int> runUpdate(String statement, List<Object?> args) {
|
||||
_db.runWithArgs(statement, args);
|
||||
return _handlePotentialUpdate();
|
||||
}
|
||||
|
@ -141,7 +147,10 @@ class _WebDelegate extends DatabaseDelegate {
|
|||
@override
|
||||
Future<void> close() async {
|
||||
await _storeDb();
|
||||
_db?.close();
|
||||
if (_isOpen) {
|
||||
_db.close();
|
||||
}
|
||||
|
||||
await storage.close();
|
||||
}
|
||||
|
||||
|
@ -181,7 +190,7 @@ class _WebVersionDelegate extends DynamicVersionDelegate {
|
|||
@override
|
||||
Future<int> get schemaVersion async {
|
||||
final storage = delegate.storage;
|
||||
int version;
|
||||
int? version;
|
||||
if (storage is _CustomSchemaVersionSave) {
|
||||
version = storage.schemaVersion;
|
||||
}
|
||||
|
|
|
@ -6,27 +6,50 @@ homepage: https://moor.simonbinder.eu/
|
|||
issue_tracker: https://github.com/simolus3/moor/issues
|
||||
|
||||
environment:
|
||||
sdk: '>=2.6.0 <3.0.0'
|
||||
sdk: '>=2.12.0-0 <3.0.0'
|
||||
|
||||
dependencies:
|
||||
meta: ^1.1.8
|
||||
convert: ^2.1.1
|
||||
collection: ^1.0.0
|
||||
synchronized: ^2.1.0
|
||||
pedantic: ^1.0.0
|
||||
sqlite3: ^0.1.6
|
||||
meta: ^1.3.0-nullsafety.6
|
||||
# We'd prefer convert ^3.0.0 for nullsafety, (we have a dependency_override) for that, but large chunks of the Dart
|
||||
# ecosystem don't support version 3.0.0 yet, we support older versions for compatibility.
|
||||
convert: ">=2.1.1 <4.0.0"
|
||||
collection: ^1.15.0-nullsafety.5
|
||||
synchronized: ^3.0.0-nullsafety
|
||||
pedantic: ^1.10.0-nullsafety.3
|
||||
sqlite3: ^0.1.9-nullsafety
|
||||
|
||||
dev_dependencies:
|
||||
analyzer: ^0.40.6
|
||||
build_test: ^1.3.0
|
||||
build_runner_core: ^6.1.0
|
||||
moor_generator: ^3.2.0
|
||||
uuid: ^2.0.0
|
||||
path: ^1.6.4
|
||||
build_runner: '^1.10.1'
|
||||
test: ^1.9.0
|
||||
mockito: ^4.1.0
|
||||
build_runner: '^1.10.4'
|
||||
test: ^1.16.0-nullsafety
|
||||
mockito: ^4.1.3
|
||||
rxdart: ^0.24.0 # used to test compatibility with stream queries
|
||||
|
||||
dependency_overrides:
|
||||
moor_generator:
|
||||
path: ../moor_generator
|
||||
sqlparser:
|
||||
path: ../sqlparser
|
||||
path: ../sqlparser
|
||||
|
||||
# Remove after https://github.com/dart-lang/mockito/issues/297 is fixed
|
||||
mockito:
|
||||
git:
|
||||
url: https://github.com/simolus3/mockito.git
|
||||
ref: generate-inheritance
|
||||
|
||||
uuid:
|
||||
git:
|
||||
url: https://github.com/simolus3/dart-uuid.git
|
||||
ref: null-safety
|
||||
|
||||
crypto:
|
||||
git:
|
||||
url: https://github.com/dart-lang/crypto.git
|
||||
ref: "3.0"
|
||||
|
||||
convert: ^3.0.0-nullsafety
|
|
@ -1,3 +1,5 @@
|
|||
//@dart=2.9
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:moor/moor.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
|
|
|
@ -2,12 +2,12 @@ import 'package:moor/moor.dart';
|
|||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
final nullable = GeneratedDateTimeColumn('name', null, true);
|
||||
final nonNull = GeneratedDateTimeColumn('name', null, false);
|
||||
final nullable = GeneratedDateTimeColumn('name', 'table', true);
|
||||
final nonNull = GeneratedDateTimeColumn('name', 'table', false);
|
||||
|
||||
test('should write column definition', () {
|
||||
final nonNullQuery = GenerationContext(null, null);
|
||||
final nullableQuery = GenerationContext(null, null);
|
||||
final nonNullQuery = GenerationContext.fromDb(null);
|
||||
final nullableQuery = GenerationContext.fromDb(null);
|
||||
nonNull.writeColumnDefinition(nonNullQuery);
|
||||
nullable.writeColumnDefinition(nullableQuery);
|
||||
|
||||
|
@ -16,7 +16,7 @@ void main() {
|
|||
});
|
||||
|
||||
test('can compare', () {
|
||||
final ctx = GenerationContext(null, null);
|
||||
final ctx = GenerationContext.fromDb(null);
|
||||
nonNull.isSmallerThan(currentDateAndTime).writeInto(ctx);
|
||||
|
||||
expect(ctx.sql, "name < strftime('%s', CURRENT_TIMESTAMP)");
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//@dart=2.9
|
||||
import 'package:test/test.dart';
|
||||
import 'package:moor/moor.dart';
|
||||
|
||||
|
@ -13,7 +14,7 @@ void main() {
|
|||
hasAutoIncrement: true,
|
||||
);
|
||||
|
||||
final context = GenerationContext.fromDb(TodoDb(null));
|
||||
final context = GenerationContext.fromDb(TodoDb());
|
||||
column.writeColumnDefinition(context);
|
||||
|
||||
expect(
|
||||
|
@ -29,7 +30,7 @@ void main() {
|
|||
hasAutoIncrement: false,
|
||||
);
|
||||
|
||||
final context = GenerationContext.fromDb(TodoDb(null));
|
||||
final context = GenerationContext.fromDb(TodoDb());
|
||||
column.writeColumnDefinition(context);
|
||||
|
||||
expect(context.sql, equals('foo INTEGER NOT NULL PRIMARY KEY'));
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//@dart=2.9
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:moor/moor.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
|
|
|
@ -10,14 +10,14 @@ class SyncTypeConverter extends TypeConverter<SyncType, int> {
|
|||
const SyncTypeConverter();
|
||||
|
||||
@override
|
||||
SyncType mapToDart(int fromDb) {
|
||||
SyncType? mapToDart(int? fromDb) {
|
||||
if (fromDb == null) return null;
|
||||
|
||||
return SyncType.values[fromDb];
|
||||
}
|
||||
|
||||
@override
|
||||
int mapToSql(SyncType value) {
|
||||
int? mapToSql(SyncType? value) {
|
||||
return value?.index;
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,9 @@
|
|||
import 'package:moor/moor.dart';
|
||||
// ignore: import_of_legacy_library_into_null_safe
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
import '../utils/null_executor.dart';
|
||||
|
||||
part 'todos.g.dart';
|
||||
|
||||
mixin AutoIncrement on Table {
|
||||
|
@ -80,12 +83,12 @@ class MyCustomObject {
|
|||
class CustomConverter extends TypeConverter<MyCustomObject, String> {
|
||||
const CustomConverter();
|
||||
@override
|
||||
MyCustomObject mapToDart(String fromDb) {
|
||||
MyCustomObject? mapToDart(String? fromDb) {
|
||||
return fromDb == null ? null : MyCustomObject(fromDb);
|
||||
}
|
||||
|
||||
@override
|
||||
String mapToSql(MyCustomObject value) {
|
||||
String? mapToSql(MyCustomObject? value) {
|
||||
return value?.data;
|
||||
}
|
||||
}
|
||||
|
@ -111,7 +114,7 @@ class CustomConverter extends TypeConverter<MyCustomObject, String> {
|
|||
},
|
||||
)
|
||||
class TodoDb extends _$TodoDb {
|
||||
TodoDb(QueryExecutor e) : super(e) {
|
||||
TodoDb([QueryExecutor? e]) : super(e ?? const NullExecutor()) {
|
||||
moorRuntimeOptions.dontWarnAboutMultipleDatabases = true;
|
||||
}
|
||||
TodoDb.connect(DatabaseConnection connection) : super.connect(connection) {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -10,7 +10,7 @@ Matcher generates(dynamic sql, [dynamic variables]) {
|
|||
|
||||
class _GeneratesSqlMatcher extends Matcher {
|
||||
final Matcher _matchSql;
|
||||
final Matcher _matchVariables;
|
||||
final Matcher? _matchVariables;
|
||||
|
||||
_GeneratesSqlMatcher(this._matchSql, this._matchVariables);
|
||||
|
||||
|
@ -44,7 +44,7 @@ class _GeneratesSqlMatcher extends Matcher {
|
|||
|
||||
mismatchDescription =
|
||||
mismatchDescription.add('generated variables $vars, which ');
|
||||
mismatchDescription = _matchVariables.describeMismatch(
|
||||
mismatchDescription = _matchVariables!.describeMismatch(
|
||||
vars, mismatchDescription, matchState['vars_match'] as Map, verbose);
|
||||
}
|
||||
return mismatchDescription;
|
||||
|
@ -57,9 +57,8 @@ class _GeneratesSqlMatcher extends Matcher {
|
|||
return false;
|
||||
}
|
||||
|
||||
final component = item as Component;
|
||||
final ctx = GenerationContext(SqlTypeSystem.defaultInstance, null);
|
||||
component.writeInto(ctx);
|
||||
item.writeInto(ctx);
|
||||
|
||||
var matches = true;
|
||||
|
||||
|
@ -72,7 +71,7 @@ class _GeneratesSqlMatcher extends Matcher {
|
|||
|
||||
final argsMatchState = {};
|
||||
if (_matchVariables != null &&
|
||||
!_matchVariables.matches(ctx.boundVariables, argsMatchState)) {
|
||||
!_matchVariables!.matches(ctx.boundVariables, argsMatchState)) {
|
||||
matchState['vars'] = ctx.boundVariables;
|
||||
matchState['vars_match'] = argsMatchState;
|
||||
matches = false;
|
||||
|
|
|
@ -1,18 +1,36 @@
|
|||
import 'dart:async';
|
||||
|
||||
// ignore: import_of_legacy_library_into_null_safe
|
||||
import 'package:mockito/annotations.dart';
|
||||
// ignore: import_of_legacy_library_into_null_safe
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:moor/moor.dart';
|
||||
import 'package:moor/src/runtime/executor/stream_queries.dart';
|
||||
|
||||
export 'package:mockito/mockito.dart';
|
||||
import 'mocks.mocks.dart';
|
||||
export 'mocks.mocks.dart';
|
||||
|
||||
class MockExecutor extends Mock implements QueryExecutor {
|
||||
@GenerateMocks(
|
||||
[],
|
||||
customMocks: [
|
||||
MockSpec<QueryExecutor>(as: #MockExecutorInternal),
|
||||
MockSpec<TransactionExecutor>(as: #MockTransactionsInternal),
|
||||
MockSpec<StreamQueryStore>(
|
||||
as: #MockStreamQueries, returnNullOnMissingStub: true)
|
||||
],
|
||||
)
|
||||
// ignore: unused_element
|
||||
void _pleaseGenerateMocks() {
|
||||
// needed so that mockito generates classes for us.
|
||||
}
|
||||
|
||||
class MockExecutor extends MockExecutorInternal {
|
||||
final MockTransactionExecutor transactions = MockTransactionExecutor();
|
||||
final OpeningDetails openingDetails;
|
||||
|
||||
var _opened = false;
|
||||
final OpeningDetails? openingDetails;
|
||||
bool _opened = false;
|
||||
|
||||
MockExecutor([this.openingDetails]) {
|
||||
when(dialect).thenReturn(SqlDialect.sqlite);
|
||||
when(runSelect(any, any)).thenAnswer((_) {
|
||||
assert(_opened);
|
||||
return Future.value([]);
|
||||
|
@ -33,6 +51,10 @@ class MockExecutor extends Mock implements QueryExecutor {
|
|||
assert(_opened);
|
||||
return Future.value();
|
||||
});
|
||||
when(runBatched(any)).thenAnswer((_) {
|
||||
assert(_opened);
|
||||
return Future.value();
|
||||
});
|
||||
when(beginTransaction()).thenAnswer((_) {
|
||||
assert(_opened);
|
||||
return transactions;
|
||||
|
@ -42,7 +64,7 @@ class MockExecutor extends Mock implements QueryExecutor {
|
|||
if (!_opened && openingDetails != null) {
|
||||
_opened = true;
|
||||
await (i.positionalArguments.single as QueryExecutorUser)
|
||||
.beforeOpen(this, openingDetails);
|
||||
.beforeOpen(this, openingDetails!);
|
||||
}
|
||||
|
||||
_opened = true;
|
||||
|
@ -56,23 +78,24 @@ class MockExecutor extends Mock implements QueryExecutor {
|
|||
}
|
||||
}
|
||||
|
||||
class MockTransactionExecutor extends Mock implements TransactionExecutor {
|
||||
class MockTransactionExecutor extends MockTransactionsInternal {
|
||||
MockTransactionExecutor() {
|
||||
when(dialect).thenReturn(SqlDialect.sqlite);
|
||||
when(runSelect(any, any)).thenAnswer((_) => Future.value([]));
|
||||
when(runUpdate(any, any)).thenAnswer((_) => Future.value(0));
|
||||
when(runDelete(any, any)).thenAnswer((_) => Future.value(0));
|
||||
when(runInsert(any, any)).thenAnswer((_) => Future.value(0));
|
||||
when(ensureOpen(any)).thenAnswer((_) => Future.value());
|
||||
when(runCustom(any, any)).thenAnswer((_) => Future.value());
|
||||
when(runBatched(any)).thenAnswer((_) => Future.value());
|
||||
when(ensureOpen(any)).thenAnswer((_) => Future.value(true));
|
||||
|
||||
when(send()).thenAnswer((_) => Future.value(null));
|
||||
when(rollback()).thenAnswer((_) => Future.value(null));
|
||||
}
|
||||
}
|
||||
|
||||
class MockStreamQueries extends Mock implements StreamQueryStore {}
|
||||
|
||||
DatabaseConnection createConnection(QueryExecutor executor,
|
||||
[StreamQueryStore streams]) {
|
||||
[StreamQueryStore? streams]) {
|
||||
return DatabaseConnection(
|
||||
SqlTypeSystem.defaultInstance, executor, streams ?? StreamQueryStore());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
import 'package:mockito/mockito.dart' as _i1;
|
||||
import 'package:moor/src/runtime/executor/executor.dart' as _i2;
|
||||
import 'package:moor/src/runtime/query_builder/query_builder.dart' as _i3;
|
||||
import 'dart:async' as _i4;
|
||||
import 'package:moor/src/runtime/executor/stream_queries.dart' as _i5;
|
||||
import 'package:moor/src/runtime/api/runtime_api.dart' as _i6;
|
||||
|
||||
class _FakeTransactionExecutor extends _i1.Fake
|
||||
implements _i2.TransactionExecutor {}
|
||||
|
||||
/// A class which mocks [QueryExecutor].
|
||||
///
|
||||
/// See the documentation for Mockito's code generation for more information.
|
||||
class MockExecutorInternal extends _i1.Mock implements _i2.QueryExecutor {
|
||||
MockExecutorInternal() {
|
||||
_i1.throwOnMissingStub(this);
|
||||
}
|
||||
|
||||
_i3.SqlDialect get dialect =>
|
||||
super.noSuchMethod(Invocation.getter(#dialect), _i3.SqlDialect.sqlite);
|
||||
_i4.Future<bool> ensureOpen(_i2.QueryExecutorUser? user) =>
|
||||
super.noSuchMethod(
|
||||
Invocation.method(#ensureOpen, [user]), Future.value(false));
|
||||
_i4.Future<List<Map<String, Object?>>> runSelect(
|
||||
String? statement, List<Object?>? args) =>
|
||||
super.noSuchMethod(Invocation.method(#runSelect, [statement, args]),
|
||||
Future.value(<Map<String, Object?>>[]));
|
||||
_i4.Future<int> runInsert(String? statement, List<Object?>? args) =>
|
||||
super.noSuchMethod(
|
||||
Invocation.method(#runInsert, [statement, args]), Future.value(0));
|
||||
_i4.Future<int> runUpdate(String? statement, List<Object?>? args) =>
|
||||
super.noSuchMethod(
|
||||
Invocation.method(#runUpdate, [statement, args]), Future.value(0));
|
||||
_i4.Future<int> runDelete(String? statement, List<Object?>? args) =>
|
||||
super.noSuchMethod(
|
||||
Invocation.method(#runDelete, [statement, args]), Future.value(0));
|
||||
_i4.Future<void> runCustom(String? statement, [List<Object?>? args]) =>
|
||||
super.noSuchMethod(
|
||||
Invocation.method(#runCustom, [statement, args]), Future.value(null));
|
||||
_i4.Future<void> runBatched(_i2.BatchedStatements? statements) =>
|
||||
super.noSuchMethod(
|
||||
Invocation.method(#runBatched, [statements]), Future.value(null));
|
||||
_i2.TransactionExecutor beginTransaction() => super.noSuchMethod(
|
||||
Invocation.method(#beginTransaction, []), _FakeTransactionExecutor());
|
||||
_i4.Future<void> close() =>
|
||||
super.noSuchMethod(Invocation.method(#close, []), Future.value(null));
|
||||
}
|
||||
|
||||
/// A class which mocks [TransactionExecutor].
|
||||
///
|
||||
/// See the documentation for Mockito's code generation for more information.
|
||||
class MockTransactionsInternal extends _i1.Mock
|
||||
implements _i2.TransactionExecutor {
|
||||
MockTransactionsInternal() {
|
||||
_i1.throwOnMissingStub(this);
|
||||
}
|
||||
|
||||
_i4.Future<void> send() =>
|
||||
super.noSuchMethod(Invocation.method(#send, []), Future.value(null));
|
||||
_i4.Future<void> rollback() =>
|
||||
super.noSuchMethod(Invocation.method(#rollback, []), Future.value(null));
|
||||
_i4.Future<bool> ensureOpen(_i2.QueryExecutorUser? user) =>
|
||||
super.noSuchMethod(
|
||||
Invocation.method(#ensureOpen, [user]), Future.value(false));
|
||||
_i4.Future<List<Map<String, Object?>>> runSelect(
|
||||
String? statement, List<Object?>? args) =>
|
||||
super.noSuchMethod(Invocation.method(#runSelect, [statement, args]),
|
||||
Future.value(<Map<String, Object?>>[]));
|
||||
_i4.Future<int> runInsert(String? statement, List<Object?>? args) =>
|
||||
super.noSuchMethod(
|
||||
Invocation.method(#runInsert, [statement, args]), Future.value(0));
|
||||
_i4.Future<int> runUpdate(String? statement, List<Object?>? args) =>
|
||||
super.noSuchMethod(
|
||||
Invocation.method(#runUpdate, [statement, args]), Future.value(0));
|
||||
_i4.Future<int> runDelete(String? statement, List<Object?>? args) =>
|
||||
super.noSuchMethod(
|
||||
Invocation.method(#runDelete, [statement, args]), Future.value(0));
|
||||
_i4.Future<void> runCustom(String? statement, [List<Object?>? args]) =>
|
||||
super.noSuchMethod(
|
||||
Invocation.method(#runCustom, [statement, args]), Future.value(null));
|
||||
_i4.Future<void> runBatched(_i2.BatchedStatements? statements) =>
|
||||
super.noSuchMethod(
|
||||
Invocation.method(#runBatched, [statements]), Future.value(null));
|
||||
_i2.TransactionExecutor beginTransaction() => super.noSuchMethod(
|
||||
Invocation.method(#beginTransaction, []), _FakeTransactionExecutor());
|
||||
_i4.Future<void> close() =>
|
||||
super.noSuchMethod(Invocation.method(#close, []), Future.value(null));
|
||||
}
|
||||
|
||||
/// A class which mocks [StreamQueryStore].
|
||||
///
|
||||
/// See the documentation for Mockito's code generation for more information.
|
||||
class MockStreamQueries extends _i1.Mock implements _i5.StreamQueryStore {
|
||||
_i4.Stream<T> registerStream<T>(_i5.QueryStreamFetcher<T>? fetcher) =>
|
||||
super.noSuchMethod(
|
||||
Invocation.method(#registerStream, [fetcher]), Stream<T>.empty());
|
||||
_i4.Stream<Null?> updatesForSync(_i6.TableUpdateQuery? query) =>
|
||||
super.noSuchMethod(
|
||||
Invocation.method(#updatesForSync, [query]), Stream<Null?>.empty());
|
||||
void handleTableUpdates(Set<_i6.TableUpdate>? updates) =>
|
||||
super.noSuchMethod(Invocation.method(#handleTableUpdates, [updates]));
|
||||
void markAsClosed(
|
||||
_i5.QueryStream<dynamic>? stream, dynamic Function()? whenRemoved) =>
|
||||
super.noSuchMethod(
|
||||
Invocation.method(#markAsClosed, [stream, whenRemoved]));
|
||||
void markAsOpened(_i5.QueryStream<dynamic>? stream) =>
|
||||
super.noSuchMethod(Invocation.method(#markAsOpened, [stream]));
|
||||
_i4.Future<void> close() =>
|
||||
super.noSuchMethod(Invocation.method(#close, []), Future.value(null));
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
import 'package:moor/backends.dart';
|
||||
|
||||
class NullExecutor implements QueryExecutor {
|
||||
const NullExecutor();
|
||||
|
||||
@override
|
||||
TransactionExecutor beginTransaction() {
|
||||
throw UnsupportedError('beginTransaction');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> ensureOpen(QueryExecutorUser user) {
|
||||
throw UnsupportedError('ensureOpen');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> runBatched(BatchedStatements statements) {
|
||||
throw UnsupportedError('runBatched');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> runCustom(String statement, [List<Object?>? args]) {
|
||||
throw UnsupportedError('runCustom');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> runDelete(String statement, List<Object?> args) {
|
||||
throw UnsupportedError('runDelete');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> runInsert(String statement, List<Object?> args) {
|
||||
throw UnsupportedError('runInsert');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Map<String, Object?>>> runSelect(
|
||||
String statement, List<Object?> args) {
|
||||
throw UnsupportedError('runSelect');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> runUpdate(String statement, List<Object?> args) {
|
||||
throw UnsupportedError('runUpdate');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() => Future.value();
|
||||
|
||||
@override
|
||||
SqlDialect get dialect => SqlDialect.sqlite;
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
//@dart=2.9
|
||||
import 'package:moor/moor.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
|
@ -19,13 +20,9 @@ void main() {
|
|||
});
|
||||
|
||||
test('can deserialize ints as doubles', () {
|
||||
final entry = TableWithoutPKData.fromJson({
|
||||
'notReallyAnId': 3,
|
||||
'someFloat': 4,
|
||||
});
|
||||
const serializer = ValueSerializer.defaults();
|
||||
|
||||
expect(entry,
|
||||
TableWithoutPKData(notReallyAnId: 3, someFloat: 4, custom: null));
|
||||
expect(serializer.fromJson<double>(3), 3.0);
|
||||
});
|
||||
|
||||
test('default serializer can be overridden globally', () {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import 'package:test/test.dart';
|
||||
//@dart=2.9
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:moor/moor.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'data/tables/todos.dart';
|
||||
import 'data/utils/mocks.dart';
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
//@dart=2.9
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:moor/moor.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//@dart=2.9
|
||||
@TestOn('vm')
|
||||
import 'dart:io';
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//@dart=2.9
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:moor/moor.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//@dart=2.9
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:moor/backends.dart';
|
||||
import 'package:moor/moor.dart';
|
||||
|
@ -42,19 +43,20 @@ void main() {
|
|||
final db = DelegatedDatabase(delegate, isSequential: sequential);
|
||||
await db.ensureOpen(_FakeExecutorUser());
|
||||
|
||||
expect(await db.runSelect(null, null), isEmpty);
|
||||
expect(await db.runUpdate(null, null), 3);
|
||||
expect(await db.runInsert(null, null), 4);
|
||||
await db.runCustom(null);
|
||||
await db.runBatched(null);
|
||||
expect(await db.runSelect('select', const []), isEmpty);
|
||||
expect(await db.runUpdate('update', const []), 3);
|
||||
expect(await db.runInsert('insert', const []), 4);
|
||||
await db.runCustom('custom');
|
||||
final batched = BatchedStatements([], []);
|
||||
await db.runBatched(batched);
|
||||
|
||||
verifyInOrder([
|
||||
delegate.isOpen,
|
||||
delegate.runSelect(null, null),
|
||||
delegate.runUpdate(null, null),
|
||||
delegate.runInsert(null, null),
|
||||
delegate.runCustom(null, []),
|
||||
delegate.runBatched(null),
|
||||
delegate.runSelect('select', const []),
|
||||
delegate.runUpdate('update', const []),
|
||||
delegate.runInsert('insert', const []),
|
||||
delegate.runCustom('custom', const []),
|
||||
delegate.runBatched(batched),
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
@ -149,12 +151,12 @@ void main() {
|
|||
|
||||
final transaction = db.beginTransaction();
|
||||
await transaction.ensureOpen(_FakeExecutorUser());
|
||||
await transaction.runSelect(null, null);
|
||||
await transaction.runSelect('SELECT 1;', const []);
|
||||
await transaction.send();
|
||||
|
||||
verifyInOrder([
|
||||
delegate.runCustom('BEGIN TRANSACTION', []),
|
||||
delegate.runSelect(null, null),
|
||||
delegate.runSelect('SELECT 1;', const []),
|
||||
delegate.runCustom('COMMIT TRANSACTION', []),
|
||||
]);
|
||||
});
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//@dart=2.9
|
||||
import 'package:moor/moor.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ import '../data/tables/todos.dart';
|
|||
import '../data/utils/expect_equality.dart';
|
||||
|
||||
void main() {
|
||||
final expression = GeneratedIntColumn('col', null, false);
|
||||
final db = TodoDb(null);
|
||||
final expression = GeneratedIntColumn('col', 'table', false);
|
||||
final db = TodoDb();
|
||||
|
||||
final comparisons = {
|
||||
expression.isSmallerThan: '<',
|
||||
|
@ -23,7 +23,7 @@ void main() {
|
|||
};
|
||||
|
||||
group('can compare with other expressions', () {
|
||||
final compare = GeneratedIntColumn('compare', null, false);
|
||||
final compare = GeneratedIntColumn('compare', 'table', false);
|
||||
|
||||
comparisons.forEach((fn, value) {
|
||||
test('for operator $value', () {
|
||||
|
@ -53,8 +53,8 @@ void main() {
|
|||
|
||||
group('between', () {
|
||||
test('other expressions', () {
|
||||
final low = GeneratedIntColumn('low', null, false);
|
||||
final high = GeneratedIntColumn('high', null, false);
|
||||
final low = GeneratedIntColumn('low', 'table', false);
|
||||
final high = GeneratedIntColumn('high', 'table', false);
|
||||
|
||||
final ctx = GenerationContext.fromDb(db);
|
||||
expression.isBetween(low, high).writeInto(ctx);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//@dart=2.9
|
||||
import 'package:moor/moor.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
|
@ -31,7 +32,7 @@ void main() {
|
|||
}
|
||||
|
||||
void testStringMapping(String dart, String expectedLiteral) {
|
||||
final ctx = GenerationContext.fromDb(TodoDb(null));
|
||||
final ctx = GenerationContext.fromDb(TodoDb());
|
||||
final constant = Constant(dart);
|
||||
|
||||
constant.writeInto(ctx);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//@dart=2.9
|
||||
import 'package:moor/moor.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
|
@ -7,7 +8,7 @@ import '../data/utils/expect_generated.dart';
|
|||
typedef _Extractor = Expression<int> Function(Expression<DateTime> d);
|
||||
|
||||
void main() {
|
||||
final column = GeneratedDateTimeColumn('val', null, false);
|
||||
final column = GeneratedDateTimeColumn('val', 'table', false);
|
||||
|
||||
group('extracting information via top-level method', () {
|
||||
final expectedResults = <_Extractor, String>{
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//@dart=2.9
|
||||
@TestOn('vm')
|
||||
import 'package:moor/ffi.dart';
|
||||
import 'package:moor/moor.dart';
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue