Added Optional package
This commit is contained in:
parent
7644d8c2d2
commit
d241d7ca77
11 changed files with 74 additions and 56 deletions
|
@ -15,7 +15,9 @@ void main() async {
|
|||
..join('companies', 'company_id', 'id');
|
||||
|
||||
var richPerson = await query.getOne(_FakeExecutor());
|
||||
print(richPerson?.toJson());
|
||||
if (richPerson.isPresent) {
|
||||
print(richPerson.first.toJson());
|
||||
}
|
||||
}
|
||||
|
||||
class _FakeExecutor extends QueryExecutor {
|
||||
|
@ -24,7 +26,7 @@ class _FakeExecutor extends QueryExecutor {
|
|||
@override
|
||||
Future<List<List>> query(
|
||||
String tableName, String? query, Map<String, dynamic> substitutionValues,
|
||||
[returningFields]) async {
|
||||
[returningFields = const []]) async {
|
||||
var now = DateTime.now();
|
||||
print(
|
||||
'_FakeExecutor received query: $query and values: $substitutionValues');
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'query_base.dart';
|
|||
import 'query_executor.dart';
|
||||
import 'query_values.dart';
|
||||
import 'query_where.dart';
|
||||
import 'package:optional/optional.dart';
|
||||
|
||||
/// A SQL `SELECT` query builder.
|
||||
abstract class Query<T, Where extends QueryWhere?> extends QueryBase<T> {
|
||||
|
@ -125,7 +126,7 @@ abstract class Query<T, Where extends QueryWhere?> extends QueryBase<T> {
|
|||
}
|
||||
|
||||
String _joinAlias(Set<String>? trampoline) {
|
||||
int i = _joins.length;
|
||||
var i = _joins.length;
|
||||
|
||||
while (true) {
|
||||
var a = 'a$i';
|
||||
|
@ -137,13 +138,13 @@ abstract class Query<T, Where extends QueryWhere?> extends QueryBase<T> {
|
|||
}
|
||||
}
|
||||
|
||||
String? Function() _compileJoin(tableName, Set<String>? trampoline) {
|
||||
String? Function() _compileJoin(tableName, Set<String> trampoline) {
|
||||
if (tableName is String) {
|
||||
return () => tableName;
|
||||
} else if (tableName is Query) {
|
||||
return () {
|
||||
var c = tableName.compile(trampoline);
|
||||
if (c == null) return c;
|
||||
//if (c == null) return c;
|
||||
return '($c)';
|
||||
};
|
||||
} else {
|
||||
|
@ -160,7 +161,7 @@ abstract class Query<T, Where extends QueryWhere?> extends QueryBase<T> {
|
|||
String foreignKey,
|
||||
String op,
|
||||
List<String> additionalFields) {
|
||||
trampoline ??= Set();
|
||||
trampoline ??= <String>{};
|
||||
|
||||
// Pivot tables guard against ambiguous fields by excluding tables
|
||||
// that have already been queried in this scope.
|
||||
|
@ -170,19 +171,17 @@ abstract class Query<T, Where extends QueryWhere?> extends QueryBase<T> {
|
|||
}
|
||||
|
||||
var to = _compileJoin(tableName, trampoline);
|
||||
if (to != null) {
|
||||
var alias = _joinAlias(trampoline);
|
||||
if (tableName is Query) {
|
||||
for (var field in tableName.fields) {
|
||||
tableName.aliases[field] = '${alias}_$field';
|
||||
}
|
||||
var alias = _joinAlias(trampoline);
|
||||
if (tableName is Query) {
|
||||
for (var field in tableName.fields) {
|
||||
tableName.aliases[field] = '${alias}_$field';
|
||||
}
|
||||
_joins.add(JoinBuilder(type, this, to, localKey, foreignKey,
|
||||
op: op,
|
||||
alias: alias,
|
||||
additionalFields: additionalFields,
|
||||
aliasAllFields: tableName is Query));
|
||||
}
|
||||
_joins.add(JoinBuilder(type, this, to, localKey, foreignKey,
|
||||
op: op,
|
||||
alias: alias,
|
||||
additionalFields: additionalFields,
|
||||
aliasAllFields: tableName is Query));
|
||||
}
|
||||
|
||||
/// Execute an `INNER JOIN` against another table.
|
||||
|
@ -231,14 +230,15 @@ abstract class Query<T, Where extends QueryWhere?> extends QueryBase<T> {
|
|||
}
|
||||
|
||||
@override
|
||||
String? compile(Set<String>? trampoline,
|
||||
String compile(Set<String> trampoline,
|
||||
{bool includeTableName = false,
|
||||
String? preamble,
|
||||
bool withFields = true,
|
||||
String? fromQuery}) {
|
||||
// One table MAY appear multiple times in a query.
|
||||
if (!canCompile(trampoline)) {
|
||||
return null;
|
||||
//return null;
|
||||
throw Exception('One table appear multiple times in a query');
|
||||
}
|
||||
|
||||
includeTableName = includeTableName || _joins.isNotEmpty;
|
||||
|
@ -320,7 +320,7 @@ abstract class Query<T, Where extends QueryWhere?> extends QueryBase<T> {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<T?> getOne(QueryExecutor executor) {
|
||||
Future<Optional<T>> getOne(QueryExecutor executor) {
|
||||
//limit(1);
|
||||
return super.getOne(executor);
|
||||
}
|
||||
|
@ -358,7 +358,7 @@ abstract class Query<T, Where extends QueryWhere?> extends QueryBase<T> {
|
|||
} else {
|
||||
// TODO: How to do this in a non-Postgres DB?
|
||||
var returning = fields.map(adornWithTableName).join(', ');
|
||||
var sql = compile({})!;
|
||||
var sql = compile({});
|
||||
sql = 'WITH $tableName as ($insertion RETURNING $returning) ' + sql;
|
||||
return executor
|
||||
.query(tableName, sql, substitutionValues)
|
||||
|
@ -381,7 +381,7 @@ abstract class Query<T, Where extends QueryWhere?> extends QueryBase<T> {
|
|||
if (_limit != null) updateSql.write(' LIMIT $_limit');
|
||||
|
||||
var returning = fields.map(adornWithTableName).join(', ');
|
||||
var sql = compile({})!;
|
||||
var sql = compile({});
|
||||
sql = 'WITH $tableName as ($updateSql RETURNING $returning) ' + sql;
|
||||
|
||||
return executor
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'dart:async';
|
||||
import 'query_executor.dart';
|
||||
import 'union.dart';
|
||||
import 'package:optional/optional.dart';
|
||||
|
||||
/// A base class for objects that compile to SQL queries, typically within an ORM.
|
||||
abstract class QueryBase<T> {
|
||||
|
@ -32,9 +33,9 @@ abstract class QueryBase<T> {
|
|||
}
|
||||
}).join(', ');
|
||||
|
||||
String? compile(Set<String> trampoline,
|
||||
String compile(Set<String> trampoline,
|
||||
{bool includeTableName = false,
|
||||
String? preamble,
|
||||
String preamble = '',
|
||||
bool withFields = true});
|
||||
|
||||
T deserialize(List row);
|
||||
|
@ -46,8 +47,10 @@ abstract class QueryBase<T> {
|
|||
.then((it) => it.map(deserialize).toList());
|
||||
}
|
||||
|
||||
Future<T?> getOne(QueryExecutor executor) {
|
||||
return get(executor).then((it) => it.isEmpty ? null : it.first);
|
||||
Future<Optional<T>> getOne(QueryExecutor executor) {
|
||||
//return get(executor).then((it) => it.isEmpty ? : it.first);
|
||||
return get(executor).then(
|
||||
(it) => it.isEmpty ? Optional.empty() : Optional.ofNullable(it.first));
|
||||
}
|
||||
|
||||
Union<T> union(QueryBase<T> other) {
|
||||
|
|
|
@ -8,8 +8,8 @@ abstract class QueryExecutor {
|
|||
|
||||
/// Executes a single query.
|
||||
Future<List<List>> query(
|
||||
String tableName, String? query, Map<String, dynamic> substitutionValues,
|
||||
[List<String>? returningFields]);
|
||||
String tableName, String query, Map<String, dynamic> substitutionValues,
|
||||
[List<String> returningFields = const []]);
|
||||
|
||||
/// Enters a database transaction, performing the actions within,
|
||||
/// and returning the results of [f].
|
||||
|
|
|
@ -28,3 +28,4 @@ dev_dependencies:
|
|||
build_runner: ^2.0.1
|
||||
pedantic: ^1.11.0
|
||||
test: ^1.17.3
|
||||
optional: ^6.0.0-nullsafety.2
|
||||
|
|
|
@ -27,3 +27,8 @@ dev_dependencies:
|
|||
ref: sdk-2.12.x_nnbd
|
||||
path: packages/pretty_logging
|
||||
test: ^1.17.3
|
||||
#dependency_overrides:
|
||||
# angel_orm_test:
|
||||
# path: ../angel_orm_test
|
||||
# angel_orm:
|
||||
# path: ../angel_orm
|
||||
|
|
|
@ -160,13 +160,13 @@ class TreeQuery extends Query<Tree?, TreeQueryWhere?> {
|
|||
@override
|
||||
delete(QueryExecutor executor) {
|
||||
return super.delete(executor).then((result) {
|
||||
return result.fold<List<Tree?>>([], (out, model) {
|
||||
var idx = out.indexWhere((m) => m!.id == model!.id);
|
||||
return result.fold<List<Tree>>([], (out, model) {
|
||||
var idx = out.indexWhere((m) => m.id == model!.id);
|
||||
|
||||
if (idx == -1) {
|
||||
return out..add(model);
|
||||
return out..add(model!);
|
||||
} else {
|
||||
var l = out[idx]!;
|
||||
var l = out[idx];
|
||||
return out
|
||||
..[idx] = l.copyWith(
|
||||
fruits: List<_Fruit>.from(l.fruits ?? [])
|
||||
|
|
|
@ -304,18 +304,21 @@ class WeirdJoinQuery extends Query<WeirdJoin?, WeirdJoinQueryWhere?> {
|
|||
@override
|
||||
get(QueryExecutor executor) {
|
||||
return super.get(executor).then((result) {
|
||||
return result.fold<List<WeirdJoin?>>([], (out, model) {
|
||||
var idx = out.indexWhere((m) => m!.id == model!.id);
|
||||
return result.fold<List<WeirdJoin>>([], (out, model) {
|
||||
var idx = out.indexWhere((m) => m.id == model!.id);
|
||||
|
||||
if (idx == -1) {
|
||||
return out..add(model);
|
||||
return out..add(model!);
|
||||
} else {
|
||||
var l = out[idx]!;
|
||||
var l = out[idx];
|
||||
return out
|
||||
..[idx] = l.copyWith(
|
||||
numbas: List<_Numba?>.from(l.numbas ?? [])
|
||||
..addAll(model!.numbas ?? []),
|
||||
foos: List<_Foo?>.from(l.foos ?? [])..addAll(model.foos ?? []));
|
||||
numbas: List<_Numba>.from(l.numbas ?? [])
|
||||
..addAll(model == null
|
||||
? []
|
||||
: List<_Numba>.from(model.numbas ?? [])),
|
||||
foos: List<_Foo?>.from(l.foos ?? [])
|
||||
..addAll(model?.foos ?? []));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -324,13 +327,13 @@ class WeirdJoinQuery extends Query<WeirdJoin?, WeirdJoinQueryWhere?> {
|
|||
@override
|
||||
update(QueryExecutor executor) {
|
||||
return super.update(executor).then((result) {
|
||||
return result.fold<List<WeirdJoin?>>([], (out, model) {
|
||||
var idx = out.indexWhere((m) => m!.id == model!.id);
|
||||
return result.fold<List<WeirdJoin>>([], (out, model) {
|
||||
var idx = out.indexWhere((m) => m.id == model!.id);
|
||||
|
||||
if (idx == -1) {
|
||||
return out..add(model);
|
||||
return out..add(model!);
|
||||
} else {
|
||||
var l = out[idx]!;
|
||||
var l = out[idx];
|
||||
return out
|
||||
..[idx] = l.copyWith(
|
||||
numbas: List<_Numba?>.from(l.numbas ?? [])
|
||||
|
@ -344,13 +347,13 @@ class WeirdJoinQuery extends Query<WeirdJoin?, WeirdJoinQueryWhere?> {
|
|||
@override
|
||||
delete(QueryExecutor executor) {
|
||||
return super.delete(executor).then((result) {
|
||||
return result.fold<List<WeirdJoin?>>([], (out, model) {
|
||||
var idx = out.indexWhere((m) => m!.id == model!.id);
|
||||
return result.fold<List<WeirdJoin>>([], (out, model) {
|
||||
var idx = out.indexWhere((m) => m.id == model!.id);
|
||||
|
||||
if (idx == -1) {
|
||||
return out..add(model);
|
||||
return out..add(model!);
|
||||
} else {
|
||||
var l = out[idx]!;
|
||||
var l = out[idx];
|
||||
return out
|
||||
..[idx] = l.copyWith(
|
||||
numbas: List<_Numba?>.from(l.numbas ?? [])
|
||||
|
|
|
@ -473,13 +473,13 @@ class RoleQuery extends Query<Role?, RoleQueryWhere?> {
|
|||
@override
|
||||
get(QueryExecutor executor) {
|
||||
return super.get(executor).then((result) {
|
||||
return result.fold<List<Role?>>([], (out, model) {
|
||||
var idx = out.indexWhere((m) => m!.id == model!.id);
|
||||
return result.fold<List<Role>>([], (out, model) {
|
||||
var idx = out.indexWhere((m) => m.id == model!.id);
|
||||
|
||||
if (idx == -1) {
|
||||
return out..add(model);
|
||||
return out..add(model!);
|
||||
} else {
|
||||
var l = out[idx]!;
|
||||
var l = out[idx];
|
||||
return out
|
||||
..[idx] = l.copyWith(
|
||||
users: List<_User>.from(l.users)..addAll(model!.users));
|
||||
|
@ -509,13 +509,13 @@ class RoleQuery extends Query<Role?, RoleQueryWhere?> {
|
|||
@override
|
||||
delete(QueryExecutor executor) {
|
||||
return super.delete(executor).then((result) {
|
||||
return result.fold<List<Role?>>([], (out, model) {
|
||||
var idx = out.indexWhere((m) => m!.id == model!.id);
|
||||
return result.fold<List<Role>>([], (out, model) {
|
||||
var idx = out.indexWhere((m) => m.id == model!.id);
|
||||
|
||||
if (idx == -1) {
|
||||
return out..add(model);
|
||||
return out..add(model!);
|
||||
} else {
|
||||
var l = out[idx]!;
|
||||
var l = out[idx];
|
||||
return out
|
||||
..[idx] = l.copyWith(
|
||||
users: List<_User>.from(l.users)..addAll(model!.users));
|
||||
|
|
|
@ -130,7 +130,7 @@ standaloneTests(FutureOr<QueryExecutor> Function() createExecutor,
|
|||
..orWhere((w) => w!.familyFriendly.isTrue);
|
||||
print(query.compile(Set(), preamble: 'DELETE FROM "cars"'));
|
||||
|
||||
List<Car?> cars = await query.delete(executor);
|
||||
List<Car?>? cars = await query.delete(executor);
|
||||
expect(cars, hasLength(1));
|
||||
expect(cars.first!.toJson(), ferrari!.toJson());
|
||||
});
|
||||
|
|
|
@ -38,3 +38,7 @@ dev_dependencies:
|
|||
ref: sdk-2.12.x_nnbd
|
||||
path: packages/framework
|
||||
build_runner: ^2.0.1
|
||||
|
||||
#dependency_overrides:
|
||||
# angel_orm:
|
||||
# path: ../angel_orm
|
||||
|
|
Loading…
Reference in a new issue