Add `isIn` methods based on expressions

This commit is contained in:
Simon Binder 2023-07-23 17:31:08 +02:00
parent addb68fb45
commit b3ea00b8af
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
4 changed files with 45 additions and 9 deletions

View File

@ -1,6 +1,8 @@
## 2.11.0
- Add support for subqueries in the Dart query builder.
- Add `isInExp` and `isNotInExp` to construct `IS IN` expressions with arbitrary
expressions.
## 2.10.0

View File

@ -142,13 +142,29 @@ abstract class Expression<D extends Object> implements FunctionParameter {
/// An expression that is true if `this` resolves to any of the values in
/// [values].
Expression<bool> isIn(Iterable<D> values) {
return _InExpression(this, values.toList(), false);
return isInExp([for (final value in values) Variable<D>(value)]);
}
/// An expression that is true if `this` does not resolve to any of the values
/// in [values].
Expression<bool> isNotIn(Iterable<D> values) {
return _InExpression(this, values.toList(), true);
return isNotInExp([for (final value in values) Variable<D>(value)]);
}
/// An expression that evaluates to `true` if this expression resolves to a
/// value that one of the [expressions] resolve to as well.
///
/// For an "is in" comparison with values, use [isIn].
Expression<bool> isInExp(List<Expression<D>> expressions) {
return _InExpression(this, expressions, false);
}
/// An expression that evaluates to `true` if this expression does not resolve
/// to any value that the [expressions] resolve to.
///
/// For an "is not in" comparison with values, use [isNotIn].
Expression<bool> isNotInExp(List<Expression<D>> expressions) {
return _InExpression(this, expressions, true);
}
/// An expression checking whether `this` is included in any row of the

View File

@ -1,6 +1,6 @@
part of '../query_builder.dart';
abstract class _BaseInExpression extends Expression<bool> {
sealed class _BaseInExpression extends Expression<bool> {
final Expression _expression;
final bool _not;
@ -25,8 +25,8 @@ abstract class _BaseInExpression extends Expression<bool> {
void _writeValues(GenerationContext context);
}
class _InExpression<T extends Object> extends _BaseInExpression {
final List<T> _values;
final class _InExpression<T extends Object> extends _BaseInExpression {
final List<Expression<T>> _values;
_InExpression(Expression expression, this._values, bool not)
: super(expression, not);
@ -35,15 +35,13 @@ class _InExpression<T extends Object> extends _BaseInExpression {
void _writeValues(GenerationContext context) {
var first = true;
for (final value in _values) {
final variable = Variable<T>(value);
if (first) {
first = false;
} else {
context.buffer.write(', ');
}
variable.writeInto(context);
value.writeInto(context);
}
}
@ -59,7 +57,7 @@ class _InExpression<T extends Object> extends _BaseInExpression {
}
}
class _InSelectExpression extends _BaseInExpression {
final class _InSelectExpression extends _BaseInExpression {
final BaseSelectStatement _select;
_InSelectExpression(this._select, Expression expression, bool not)

View File

@ -23,6 +23,26 @@ void main() {
});
});
group('expressions', () {
test('in', () {
final isInExpression = innerExpression.isInExp([
CustomExpression('a'),
CustomExpression('b'),
]);
expect(isInExpression, generates('name IN (a, b)'));
});
test('not in', () {
final isNotInExpression = innerExpression.isNotInExp([
CustomExpression('a'),
CustomExpression('b'),
]);
expect(isNotInExpression, generates('name NOT IN (a, b)'));
});
});
group('subquery', () {
test('in expressions are generated', () {
final isInExpression = innerExpression