mirror of https://github.com/AMT-Cheif/drift.git
Add `IS` operator to Dart query builder
This commit is contained in:
parent
53c14cd1aa
commit
6e35abb9c9
|
@ -1,3 +1,8 @@
|
|||
## 2.5.0-dev
|
||||
|
||||
- Add `isExp`, `isValue`, `isNotExp` and `isNotValue` methods to `Expression`
|
||||
to generate the `IS` operator in SQL.
|
||||
|
||||
## 2.4.2
|
||||
|
||||
- Fix an exception when a client disconnects from a drift remote server while
|
||||
|
|
|
@ -42,6 +42,9 @@ abstract class Expression<D extends Object> implements FunctionParameter {
|
|||
bool get isLiteral => false;
|
||||
|
||||
/// Whether this expression is equal to the given expression.
|
||||
///
|
||||
/// This generates an equals operator in SQL. To perform a comparison
|
||||
/// sensitive to `NULL` values, use [isExp] instead.
|
||||
Expression<bool> equalsExp(Expression<D> compare) =>
|
||||
_Comparison.equal(this, compare);
|
||||
|
||||
|
@ -52,7 +55,7 @@ abstract class Expression<D extends Object> implements FunctionParameter {
|
|||
///
|
||||
/// This method only supports comparing the value of the column to non-
|
||||
/// nullable values and translates to a direct `=` comparison in SQL.
|
||||
/// To compare this column to `null`, use [equalsNullable].
|
||||
/// To compare this column to `null`, use [isValue].
|
||||
Expression<bool> equals(D compare) =>
|
||||
_Comparison.equal(this, Variable<D>(compare));
|
||||
|
||||
|
@ -91,6 +94,51 @@ abstract class Expression<D extends Object> implements FunctionParameter {
|
|||
return _CastInSqlExpression<D, D2>(this);
|
||||
}
|
||||
|
||||
/// Generates an `IS` expression in SQL, comparing this expression with the
|
||||
/// Dart [value].
|
||||
///
|
||||
/// This is the SQL method most closely resembling the [Object.==] operator in
|
||||
/// Dart. When this expression and [value] are both non-null, this is the same
|
||||
/// as [equals]. Two `NULL` values are considered equal as well.
|
||||
Expression<bool> isValue(D value) {
|
||||
return isExp(Variable<D>(value));
|
||||
}
|
||||
|
||||
/// Generates an `IS NOT` expression in SQL, comparing this expression with
|
||||
/// the Dart [value].
|
||||
///
|
||||
/// This the inverse of [isValue].
|
||||
Expression<bool> isNotValue(D value) {
|
||||
return isNotExp(Variable<D>(value));
|
||||
}
|
||||
|
||||
/// Expression that is true if the inner expression resolves to a null value.
|
||||
Expression<bool> isNull() => isExp(const Constant(null));
|
||||
|
||||
/// Expression that is true if the inner expression resolves to a non-null
|
||||
/// value.
|
||||
Expression<bool> isNotNull() => isNotExp(const Constant(null));
|
||||
|
||||
/// Generates an `IS` expression in SQL, comparing this expression with the
|
||||
/// [other] expression.
|
||||
///
|
||||
/// This is the SQL method most closely resembling the [Object.==] operator in
|
||||
/// Dart. When this expression and [other] are both non-null, this is the same
|
||||
/// as [equalsExp]. Two `NULL` values are considered equal as well.
|
||||
Expression<bool> isExp(Expression<D> other) {
|
||||
return BaseInfixOperator(this, 'IS', other,
|
||||
precedence: Precedence.comparisonEq);
|
||||
}
|
||||
|
||||
/// Generates an `IS NOT` expression in SQL, comparing this expression with
|
||||
/// the [other] expression.
|
||||
///
|
||||
/// This the inverse of [isExp].
|
||||
Expression<bool> isNotExp(Expression<D> other) {
|
||||
return BaseInfixOperator(this, 'IS NOT', other,
|
||||
precedence: Precedence.comparisonEq);
|
||||
}
|
||||
|
||||
/// An expression that is true if `this` resolves to any of the values in
|
||||
/// [values].
|
||||
Expression<bool> isIn(Iterable<D> values) {
|
||||
|
@ -279,31 +327,27 @@ class Precedence implements Comparable<Precedence> {
|
|||
/// [_Comparison].
|
||||
enum _ComparisonOperator {
|
||||
/// '<' in sql
|
||||
less,
|
||||
less('<'),
|
||||
|
||||
/// '<=' in sql
|
||||
lessOrEqual,
|
||||
lessOrEqual('<='),
|
||||
|
||||
/// '=' in sql
|
||||
equal,
|
||||
equal('='),
|
||||
|
||||
/// '>=' in sql
|
||||
moreOrEqual,
|
||||
moreOrEqual('>='),
|
||||
|
||||
/// '>' in sql
|
||||
more
|
||||
more('>');
|
||||
|
||||
final String operator;
|
||||
|
||||
const _ComparisonOperator(this.operator);
|
||||
}
|
||||
|
||||
/// An expression that compares two child expressions.
|
||||
class _Comparison extends InfixOperator<bool> {
|
||||
static const Map<_ComparisonOperator, String> _operatorNames = {
|
||||
_ComparisonOperator.less: '<',
|
||||
_ComparisonOperator.lessOrEqual: '<=',
|
||||
_ComparisonOperator.equal: '=',
|
||||
_ComparisonOperator.moreOrEqual: '>=',
|
||||
_ComparisonOperator.more: '>'
|
||||
};
|
||||
|
||||
@override
|
||||
final Expression left;
|
||||
@override
|
||||
|
@ -313,7 +357,7 @@ class _Comparison extends InfixOperator<bool> {
|
|||
final _ComparisonOperator op;
|
||||
|
||||
@override
|
||||
String get operator => _operatorNames[op]!;
|
||||
String get operator => op.operator;
|
||||
|
||||
@override
|
||||
Precedence get precedence {
|
||||
|
|
|
@ -1,24 +1,13 @@
|
|||
part of '../query_builder.dart';
|
||||
|
||||
/// 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);
|
||||
@Deprecated('Use isNull on the Expression class')
|
||||
Expression<bool> isNull(Expression inner) => inner.isNull();
|
||||
|
||||
/// Expression that is true if the inner expression resolves to a non-null
|
||||
/// value.
|
||||
@Deprecated('Use isNotNull through the SqlIsNull extension')
|
||||
Expression<bool> isNotNull(Expression inner) => _NullCheck(inner, false);
|
||||
|
||||
/// Extension defines the `isNull` and `isNotNull` members to check whether the
|
||||
/// expression evaluates to null or not.
|
||||
extension SqlIsNull on Expression {
|
||||
/// Expression that is true if the inner expression resolves to a null value.
|
||||
Expression<bool> isNull() => _NullCheck(this, true);
|
||||
|
||||
/// Expression that is true if the inner expression resolves to a non-null
|
||||
/// value.
|
||||
Expression<bool> isNotNull() => _NullCheck(this, false);
|
||||
}
|
||||
@Deprecated('Use isNotNull on the Expression class')
|
||||
Expression<bool> isNotNull(Expression inner) => inner.isNotNull();
|
||||
|
||||
/// Evaluates to the first expression in [expressions] that's not null, or
|
||||
/// null if all [expressions] evaluate to null.
|
||||
|
@ -35,34 +24,3 @@ Expression<T> ifNull<T extends Object>(
|
|||
Expression<T> first, Expression<T> second) {
|
||||
return FunctionCallExpression<T>('IFNULL', [first, second]);
|
||||
}
|
||||
|
||||
class _NullCheck extends Expression<bool> {
|
||||
final Expression _inner;
|
||||
final bool _isNull;
|
||||
|
||||
@override
|
||||
final Precedence precedence = Precedence.comparisonEq;
|
||||
|
||||
_NullCheck(this._inner, this._isNull);
|
||||
|
||||
@override
|
||||
void writeInto(GenerationContext context) {
|
||||
writeInner(context, _inner);
|
||||
|
||||
context.buffer.write(' IS ');
|
||||
if (!_isNull) {
|
||||
context.buffer.write('NOT ');
|
||||
}
|
||||
context.buffer.write('NULL');
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(_inner, _isNull);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is _NullCheck &&
|
||||
other._inner == _inner &&
|
||||
other._isNull == _isNull;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name: drift
|
||||
description: Drift is a reactive library to store relational data in Dart and Flutter applications.
|
||||
version: 2.4.2
|
||||
version: 2.5.0-dev
|
||||
repository: https://github.com/simolus3/drift
|
||||
homepage: https://drift.simonbinder.eu/
|
||||
issue_tracker: https://github.com/simolus3/drift/issues
|
||||
|
|
|
@ -120,4 +120,15 @@ void main() {
|
|||
expect(a.equalsNullable(null), generates('a IS NULL'));
|
||||
expect(a.equalsExp(b), generates('a = b'));
|
||||
});
|
||||
|
||||
test('is', () {
|
||||
const a = CustomExpression<int>('a', precedence: Precedence.primary);
|
||||
const b = CustomExpression<int>('b', precedence: Precedence.primary);
|
||||
|
||||
expect(a.isValue(3), generates('a IS ?', [3]));
|
||||
expect(a.isNotValue(3), generates('a IS NOT ?', [3]));
|
||||
|
||||
expect(a.isExp(b), generates('a IS b'));
|
||||
expect(b.isNotExp(a), generates('b IS NOT a'));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ dependencies:
|
|||
io: ^1.0.3
|
||||
|
||||
# Drift-specific analysis and apis
|
||||
drift: '>=2.4.0 <2.5.0'
|
||||
drift: '>=2.5.0 <2.6.0'
|
||||
sqlite3: '>=0.1.6 <2.0.0'
|
||||
sqlparser: '^2.27.0-dev'
|
||||
|
||||
|
|
Loading…
Reference in New Issue