Use extensions methods for Dart query api (#195)

This commit is contained in:
Simon Binder 2019-11-06 12:16:55 +01:00
parent e3d3bcd99e
commit 77cc6b2d88
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
15 changed files with 77 additions and 66 deletions

View File

@ -116,7 +116,7 @@ class Database extends _$Database {
return transaction(() async {
final id = user.id;
await (delete(friendships)
..where((f) => or(f.firstUser.equals(id), f.secondUser.equals(id))))
..where((f) => f.firstUser.equals(id) | f.secondUser.equals(id)))
.go();
if (fail) {

View File

@ -5,36 +5,24 @@ part of 'dsl.dart';
abstract class Column<T, S extends SqlType<T>> extends Expression<T, S> {}
/// A column that stores int values.
abstract class IntColumn extends Column<int, IntType> implements IntExpression {
}
abstract class IntColumn extends Column<int, IntType> {}
/// 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, BoolType> {}
/// A column that stores text.
abstract class TextColumn extends Column<String, StringType> {
/// 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, BoolType> like(String regex);
/// Uses the given [collate] sequence when comparing this column to other
/// values.
Expression<String, StringType> collate(Collate collate);
}
abstract class TextColumn extends Column<String, StringType> {}
/// 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, DateTimeType>
implements DateTimeExpression {}
abstract class DateTimeColumn extends Column<DateTime, DateTimeType> {}
/// A column that stores arbitrary blobs of data as a [Uint8List].
abstract class BlobColumn extends Column<Uint8List, BlobType> {}
/// A column that stores floating point numeric values.
abstract class RealColumn extends Column<double, RealType>
implements DoubleExpression {}
abstract class RealColumn extends Column<double, RealType> {}
/// 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
@ -94,9 +82,10 @@ class ColumnBuilder<
/// has been specified.
///
/// Note: Unless most other methods used to declare tables, the parameter
/// [e] which denotes the default expression, doesn't have to be constant.
/// Particularly, you can use methods like [and], [or] and [not] to form
/// expressions here.
/// [e] which denotes the default expression, doesn't have to be a Dart
/// constant.
/// Particularly, you can use operators like those defined in
/// [BooleanExpressionOperators] to form expressions here.
///
/// If you need a column that just stores a static default value, you could
/// use this method with a [Constant]:

View File

@ -470,6 +470,7 @@ abstract class GeneratedDatabase extends DatabaseConnectionUser
/// A [Type] can't be sent across isolates. Instances of this class shouldn't
/// be sent over isolates either, so let's keep a reference to a [Type] that
/// definitely prohibits this.
// ignore: unused_field
final Type _$dontSendThisOverIsolates = Null;
/// Used by generated code

View File

@ -1,19 +1,45 @@
part of '../query_builder.dart';
/// Returns an expression that is true iff both [a] and [b] are true.
///
/// This is now deprecated. Instead of `and(a, b)`, use `a & b`.
@Deprecated('Use the operator on BooleanExpressionOperators instead')
Expression<bool, BoolType> and(
Expression<bool, BoolType> a, Expression<bool, BoolType> b) =>
_AndExpression(a, b);
/// Returns an expression that is true iff [a], [b] or both are true.
///
/// This is now deprecated. Instead of `or(a, b)`, use `a | b`;
@Deprecated('Use the operator on BooleanExpressionOperators instead')
Expression<bool, BoolType> or(
Expression<bool, BoolType> a, Expression<bool, BoolType> b) =>
_OrExpression(a, b);
/// Returns an expression that is true iff [a] is not true.
///
/// This is now deprecated. Instead of `not(a)`, prefer to use `a.not()` now.
@Deprecated('Use BooleanExpressionOperators.not() as a extension instead')
Expression<bool, BoolType> not(Expression<bool, BoolType> a) =>
_NotExpression(a);
/// Defines operations on boolean values.
extension BooleanExpressionOperators on Expression<bool, BoolType> {
/// Negates this boolean expression. The returned expression is true if
/// `this` is false, and vice versa.
Expression<bool, BoolType> not() => _NotExpression(this);
/// Returns an expression that is true iff both `this` and [other] are true.
Expression<bool, BoolType> operator &(Expression<bool, BoolType> other) {
return _AndExpression(this, other);
}
/// Returns an expression that is true if `this` or [other] are true.
Expression<bool, BoolType> operator |(Expression<bool, BoolType> other) {
return _OrExpression(this, other);
}
}
class _AndExpression extends _InfixOperator<bool, BoolType> {
@override
Expression<bool, BoolType> left, right;

View File

@ -1,23 +1,8 @@
part of '../query_builder.dart';
// todo: Can we replace these classes with an extension on expression?
/// An [Expression] that operates on ints. Declared as a class so that we can
/// mixin [ComparableExpr].
abstract class IntExpression extends Expression<int, IntType>
implements ComparableExpr<int, IntType> {}
/// An [Expression] that operates on doubles. Declared as a class so that we can
/// mixin [ComparableExpr].
abstract class DoubleExpression extends Expression<double, RealType>
implements ComparableExpr<double, RealType> {}
/// An [Expression] that operates on datetimes. Declared as a class so that we
/// can mixin [ComparableExpr].
abstract class DateTimeExpression extends Expression<DateTime, DateTimeType>
implements ComparableExpr<DateTime, DateTimeType> {}
mixin ComparableExpr<DT, ST extends SqlType<DT>> on Expression<DT, ST> {
/// Defines extension functions to express comparisons in sql
extension ComparableExpr<DT, ST extends SqlType<DT>, Comparable>
on Expression<DT, ST> {
/// Returns an expression that is true if this expression is strictly bigger
/// than the other expression.
Expression<bool, BoolType> isBiggerThan(Expression<DT, ST> other) {

View File

@ -32,17 +32,16 @@ Expression<int, IntType> second(Expression<DateTime, DateTimeType> date) =>
/// A sql expression that evaluates to the current date represented as a unix
/// timestamp. The hour, minute and second fields will be set to 0.
const DateTimeExpression currentDate =
const Expression<DateTime, DateTimeType> currentDate =
_CustomDateTimeExpression("strftime('%s', CURRENT_DATE)");
/// A sql expression that evaluates to the current date and time, similar to
/// [DateTime.now]. Timestamps are stored with a second accuracy.
const DateTimeExpression currentDateAndTime =
const Expression<DateTime, DateTimeType> currentDateAndTime =
_CustomDateTimeExpression("strftime('%s', CURRENT_TIMESTAMP)");
class _CustomDateTimeExpression extends CustomExpression<DateTime, DateTimeType>
with ComparableExpr
implements DateTimeExpression {
class _CustomDateTimeExpression
extends CustomExpression<DateTime, DateTimeType> {
const _CustomDateTimeExpression(String content) : super(content);
}

View File

@ -1,5 +1,21 @@
part of '../query_builder.dart';
/// Defines methods that operate on a column storing [String] values.
extension StringExpressionOperators on Column<String, StringType> {
/// 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, BoolType> like(String regex) {
return _LikeOperator(this, Variable.withString(regex));
}
/// Uses the given [collate] sequence when comparing this column to other
/// values.
Expression<String, StringType> collate(Collate collate) {
return _CollateOperator(this, collate);
}
}
/// 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, BoolType> {

View File

@ -2,7 +2,10 @@
// at runtime.
import 'package:meta/meta.dart';
import 'package:moor/moor.dart';
// todo we're hiding the extensions because the analyzer complains about
// ambigous extensions (once via import, once via part of), even though they're
// the same. We should probably file a bug report.
import 'package:moor/moor.dart' hide BooleanExpressionOperators;
import 'package:moor/sqlite_keywords.dart';
import 'package:moor/src/runtime/executor/stream_queries.dart';
import 'package:moor/src/utils/single_transformer.dart';

View File

@ -124,15 +124,6 @@ class GeneratedTextColumn extends GeneratedColumn<String, StringType>
}) : super(name, tableName, nullable,
$customConstraints: $customConstraints, defaultValue: defaultValue);
@override
Expression<bool, BoolType> like(String pattern) =>
_LikeOperator(this, Variable<String, StringType>(pattern));
@override
Expression<String, StringType> collate(Collate collate) {
return _CollateOperator(this, collate);
}
@override
final String typeName = 'VARCHAR';
@ -175,7 +166,6 @@ class GeneratedBoolColumn extends GeneratedColumn<bool, BoolType>
/// Implementation for [IntColumn]
class GeneratedIntColumn extends GeneratedColumn<int, IntType>
with ComparableExpr
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
@ -223,7 +213,6 @@ class GeneratedIntColumn extends GeneratedColumn<int, IntType>
/// Implementation for [DateTimeColumn].
class GeneratedDateTimeColumn extends GeneratedColumn<DateTime, DateTimeType>
with ComparableExpr
implements DateTimeColumn {
/// Used by generated code.
GeneratedDateTimeColumn(
@ -254,7 +243,6 @@ class GeneratedBlobColumn extends GeneratedColumn<Uint8List, BlobType>
/// Implementation for [RealColumn]
class GeneratedRealColumn extends GeneratedColumn<double, RealType>
with ComparableExpr
implements RealColumn {
/// Used by generated code
GeneratedRealColumn(

View File

@ -184,7 +184,7 @@ mixin SingleTableQueryMixin<T extends Table, D extends DataClass>
if (whereExpr == null) {
whereExpr = Where(predicate);
} else {
whereExpr = Where(and(whereExpr.predicate, predicate));
whereExpr = Where(whereExpr.predicate & predicate);
}
}
@ -221,7 +221,7 @@ mixin SingleTableQueryMixin<T extends Table, D extends DataClass>
if (predicate == null) {
predicate = comparison;
} else {
predicate = and(predicate, comparison);
predicate = predicate & comparison;
}
}

View File

@ -85,7 +85,7 @@ class JoinedSelectStatement<FirstT extends Table, FirstD extends DataClass>
if (whereExpr == null) {
whereExpr = Where(predicate);
} else {
whereExpr = Where(and(whereExpr.predicate, predicate));
whereExpr = Where(whereExpr.predicate & predicate);
}
}

View File

@ -23,6 +23,10 @@ abstract class SqlType<T> {
T mapFromDatabaseResponse(dynamic response);
}
/// A marker interface for [SqlType]s that can be compared using the comparison
/// operators in sql.
abstract class ComparableType {}
/// A mapper for boolean values in sql. Booleans are represented as integers,
/// where 0 means false and any other value means true.
class BoolType extends SqlType<bool> {
@ -77,7 +81,7 @@ class StringType extends SqlType<String> {
}
/// Maps [int] values from and to sql
class IntType extends SqlType<int> {
class IntType extends SqlType<int> implements ComparableType {
/// Constant constructor used by the type system
const IntType();
@ -94,7 +98,7 @@ class IntType extends SqlType<int> {
}
/// Maps [DateTime] values from and to sql
class DateTimeType extends SqlType<DateTime> {
class DateTimeType extends SqlType<DateTime> implements ComparableType {
/// Constant constructor used by the type system
const DateTimeType();
@ -123,7 +127,7 @@ class DateTimeType extends SqlType<DateTime> {
}
/// Maps [Uint8List] values from and to sql
class BlobType extends SqlType<Uint8List> {
class BlobType extends SqlType<Uint8List> implements ComparableType {
/// Constant constructor used by the type system
const BlobType();
@ -142,7 +146,7 @@ class BlobType extends SqlType<Uint8List> {
}
/// Maps [double] values from and to sql
class RealType extends SqlType<double> {
class RealType extends SqlType<double> implements ComparableType {
/// Constant constructor used by the type system
const RealType();

View File

@ -9,7 +9,7 @@ authors:
maintainer: Simon Binder (@simolus3)
environment:
sdk: '>=2.3.0 <3.0.0'
sdk: '>=2.6.0 <3.0.0'
dependencies:
meta: ^1.0.0

View File

@ -28,7 +28,7 @@ void main() {
test('for complex components', () async {
await (db.delete(db.users)
..where((u) => or(not(u.isAwesome), u.id.isSmallerThanValue(100))))
..where((u) => u.isAwesome.not() | u.id.isSmallerThanValue(100)))
.go();
verify(executor.runDelete(

View File

@ -66,7 +66,7 @@ void main() {
test('with complex predicates', () {
(db.select(db.users)
..where((u) =>
and(not(u.name.equals('Dash')), (u.id.isBiggerThanValue(12)))))
u.name.equals('Dash').not() & u.id.isBiggerThanValue(12)))
.get();
verify(executor.runSelect(