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
|
## 2.4.2
|
||||||
|
|
||||||
- Fix an exception when a client disconnects from a drift remote server while
|
- 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;
|
bool get isLiteral => false;
|
||||||
|
|
||||||
/// Whether this expression is equal to the given expression.
|
/// 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) =>
|
Expression<bool> equalsExp(Expression<D> compare) =>
|
||||||
_Comparison.equal(this, 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-
|
/// This method only supports comparing the value of the column to non-
|
||||||
/// nullable values and translates to a direct `=` comparison in SQL.
|
/// 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) =>
|
Expression<bool> equals(D compare) =>
|
||||||
_Comparison.equal(this, Variable<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);
|
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
|
/// An expression that is true if `this` resolves to any of the values in
|
||||||
/// [values].
|
/// [values].
|
||||||
Expression<bool> isIn(Iterable<D> values) {
|
Expression<bool> isIn(Iterable<D> values) {
|
||||||
|
@ -279,31 +327,27 @@ class Precedence implements Comparable<Precedence> {
|
||||||
/// [_Comparison].
|
/// [_Comparison].
|
||||||
enum _ComparisonOperator {
|
enum _ComparisonOperator {
|
||||||
/// '<' in sql
|
/// '<' in sql
|
||||||
less,
|
less('<'),
|
||||||
|
|
||||||
/// '<=' in sql
|
/// '<=' in sql
|
||||||
lessOrEqual,
|
lessOrEqual('<='),
|
||||||
|
|
||||||
/// '=' in sql
|
/// '=' in sql
|
||||||
equal,
|
equal('='),
|
||||||
|
|
||||||
/// '>=' in sql
|
/// '>=' in sql
|
||||||
moreOrEqual,
|
moreOrEqual('>='),
|
||||||
|
|
||||||
/// '>' in sql
|
/// '>' in sql
|
||||||
more
|
more('>');
|
||||||
|
|
||||||
|
final String operator;
|
||||||
|
|
||||||
|
const _ComparisonOperator(this.operator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An expression that compares two child expressions.
|
/// An expression that compares two child expressions.
|
||||||
class _Comparison extends InfixOperator<bool> {
|
class _Comparison extends InfixOperator<bool> {
|
||||||
static const Map<_ComparisonOperator, String> _operatorNames = {
|
|
||||||
_ComparisonOperator.less: '<',
|
|
||||||
_ComparisonOperator.lessOrEqual: '<=',
|
|
||||||
_ComparisonOperator.equal: '=',
|
|
||||||
_ComparisonOperator.moreOrEqual: '>=',
|
|
||||||
_ComparisonOperator.more: '>'
|
|
||||||
};
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final Expression left;
|
final Expression left;
|
||||||
@override
|
@override
|
||||||
|
@ -313,7 +357,7 @@ class _Comparison extends InfixOperator<bool> {
|
||||||
final _ComparisonOperator op;
|
final _ComparisonOperator op;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get operator => _operatorNames[op]!;
|
String get operator => op.operator;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Precedence get precedence {
|
Precedence get precedence {
|
||||||
|
|
|
@ -1,24 +1,13 @@
|
||||||
part of '../query_builder.dart';
|
part of '../query_builder.dart';
|
||||||
|
|
||||||
/// Expression that is true if the inner expression resolves to a null value.
|
/// Expression that is true if the inner expression resolves to a null value.
|
||||||
@Deprecated('Use isNull through the SqlIsNull extension')
|
@Deprecated('Use isNull on the Expression class')
|
||||||
Expression<bool> isNull(Expression inner) => _NullCheck(inner, true);
|
Expression<bool> isNull(Expression inner) => inner.isNull();
|
||||||
|
|
||||||
/// Expression that is true if the inner expression resolves to a non-null
|
/// Expression that is true if the inner expression resolves to a non-null
|
||||||
/// value.
|
/// value.
|
||||||
@Deprecated('Use isNotNull through the SqlIsNull extension')
|
@Deprecated('Use isNotNull on the Expression class')
|
||||||
Expression<bool> isNotNull(Expression inner) => _NullCheck(inner, false);
|
Expression<bool> isNotNull(Expression inner) => inner.isNotNull();
|
||||||
|
|
||||||
/// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Evaluates to the first expression in [expressions] that's not null, or
|
/// Evaluates to the first expression in [expressions] that's not null, or
|
||||||
/// null if all [expressions] evaluate to null.
|
/// null if all [expressions] evaluate to null.
|
||||||
|
@ -35,34 +24,3 @@ Expression<T> ifNull<T extends Object>(
|
||||||
Expression<T> first, Expression<T> second) {
|
Expression<T> first, Expression<T> second) {
|
||||||
return FunctionCallExpression<T>('IFNULL', [first, 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
|
name: drift
|
||||||
description: Drift is a reactive library to store relational data in Dart and Flutter applications.
|
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
|
repository: https://github.com/simolus3/drift
|
||||||
homepage: https://drift.simonbinder.eu/
|
homepage: https://drift.simonbinder.eu/
|
||||||
issue_tracker: https://github.com/simolus3/drift/issues
|
issue_tracker: https://github.com/simolus3/drift/issues
|
||||||
|
|
|
@ -120,4 +120,15 @@ void main() {
|
||||||
expect(a.equalsNullable(null), generates('a IS NULL'));
|
expect(a.equalsNullable(null), generates('a IS NULL'));
|
||||||
expect(a.equalsExp(b), generates('a = b'));
|
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
|
io: ^1.0.3
|
||||||
|
|
||||||
# Drift-specific analysis and apis
|
# 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'
|
sqlite3: '>=0.1.6 <2.0.0'
|
||||||
sqlparser: '^2.27.0-dev'
|
sqlparser: '^2.27.0-dev'
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue