mirror of https://github.com/AMT-Cheif/drift.git
Support filters for all aggregate expressions
This commit is contained in:
parent
f42357c1d9
commit
9fffebbae6
|
@ -3,9 +3,11 @@ part of '../query_builder.dart';
|
||||||
/// Returns the amount of rows in the current group matching the optional
|
/// Returns the amount of rows in the current group matching the optional
|
||||||
/// [filter].
|
/// [filter].
|
||||||
///
|
///
|
||||||
/// To only count rows matching a predicate, you can set the optional [filter].
|
/// {@templace moor_aggregate_filter}
|
||||||
/// Note that [filter] is only available from sqlite 3.30, released on
|
/// To only consider rows matching a predicate, you can set the optional
|
||||||
|
/// [filter]. Note that [filter] is only available from sqlite 3.30, released on
|
||||||
/// 2019-10-04. Most devices will use an older sqlite version.
|
/// 2019-10-04. Most devices will use an older sqlite version.
|
||||||
|
/// {@endtemplate}
|
||||||
///
|
///
|
||||||
/// This is equivalent to the `COUNT(*) FILTER (WHERE filter)` sql function. The
|
/// This is equivalent to the `COUNT(*) FILTER (WHERE filter)` sql function. The
|
||||||
/// filter will be omitted if null.
|
/// filter will be omitted if null.
|
||||||
|
@ -21,9 +23,8 @@ extension BaseAggregate<DT> on Expression<DT> {
|
||||||
/// For `COUNT(*)`, which would count all rows, see [countAll].
|
/// For `COUNT(*)`, which would count all rows, see [countAll].
|
||||||
///
|
///
|
||||||
/// If [distinct] is set (defaults to false), duplicate values will not be
|
/// If [distinct] is set (defaults to false), duplicate values will not be
|
||||||
/// counted twice. An optional [filter] can be used to only include values
|
/// counted twice.
|
||||||
/// matching the filter. Note that [filter] is only available from sqlite
|
/// {@macro moor_aggregate_filter}
|
||||||
/// 3.30 and most devices will use an older sqlite version.
|
|
||||||
Expression<int> count({bool? distinct, Expression<bool?>? filter}) {
|
Expression<int> count({bool? distinct, Expression<bool?>? filter}) {
|
||||||
return _AggregateExpression('COUNT', this,
|
return _AggregateExpression('COUNT', this,
|
||||||
filter: filter, distinct: distinct);
|
filter: filter, distinct: distinct);
|
||||||
|
@ -51,17 +52,24 @@ extension BaseAggregate<DT> on Expression<DT> {
|
||||||
/// Provides aggregate functions that are available for numeric expressions.
|
/// Provides aggregate functions that are available for numeric expressions.
|
||||||
extension ArithmeticAggregates<DT extends num> on Expression<DT?> {
|
extension ArithmeticAggregates<DT extends num> on Expression<DT?> {
|
||||||
/// Return the average of all non-null values in this group.
|
/// Return the average of all non-null values in this group.
|
||||||
Expression<double?> avg() => _AggregateExpression('AVG', this);
|
///
|
||||||
|
/// {@macro moor_aggregate_filter}
|
||||||
|
Expression<double?> avg({Expression<bool?>? filter}) =>
|
||||||
|
_AggregateExpression('AVG', this, filter: filter);
|
||||||
|
|
||||||
/// Return the maximum of all non-null values in this group.
|
/// Return the maximum of all non-null values in this group.
|
||||||
///
|
///
|
||||||
/// If there are no non-null values in the group, returns null.
|
/// If there are no non-null values in the group, returns null.
|
||||||
Expression<DT?> max() => _AggregateExpression('MAX', this);
|
/// {@macro moor_aggregate_filter}
|
||||||
|
Expression<DT?> max({Expression<bool?>? filter}) =>
|
||||||
|
_AggregateExpression('MAX', this, filter: filter);
|
||||||
|
|
||||||
/// Return the minimum of all non-null values in this group.
|
/// Return the minimum of all non-null values in this group.
|
||||||
///
|
///
|
||||||
/// If there are no non-null values in the group, returns null.
|
/// If there are no non-null values in the group, returns null.
|
||||||
Expression<DT?> min() => _AggregateExpression('MIN', this);
|
/// {@macro moor_aggregate_filter}
|
||||||
|
Expression<DT?> min({Expression<bool?>? filter}) =>
|
||||||
|
_AggregateExpression('MIN', this, filter: filter);
|
||||||
|
|
||||||
/// Calculate the sum of all non-null values in the group.
|
/// Calculate the sum of all non-null values in the group.
|
||||||
///
|
///
|
||||||
|
@ -71,29 +79,39 @@ extension ArithmeticAggregates<DT extends num> on Expression<DT?> {
|
||||||
///
|
///
|
||||||
/// See also [total], which behaves similarly but returns a floating point
|
/// See also [total], which behaves similarly but returns a floating point
|
||||||
/// value and doesn't throw an overflow exception.
|
/// value and doesn't throw an overflow exception.
|
||||||
Expression<DT?> sum() => _AggregateExpression('SUM', this);
|
/// {@macro moor_aggregate_filter}
|
||||||
|
Expression<DT?> sum({Expression<bool?>? filter}) =>
|
||||||
|
_AggregateExpression('SUM', this, filter: filter);
|
||||||
|
|
||||||
/// Calculate the sum of all non-null values in the group.
|
/// Calculate the sum of all non-null values in the group.
|
||||||
///
|
///
|
||||||
/// If all values in the group are null, [total] returns `0.0`. This function
|
/// If all values in the group are null, [total] returns `0.0`. This function
|
||||||
/// uses floating-point values internally.
|
/// uses floating-point values internally.
|
||||||
Expression<double?> total() => _AggregateExpression('TOTAL', this);
|
/// {@macro moor_aggregate_filter}
|
||||||
|
Expression<double?> total({Expression<bool?>? filter}) =>
|
||||||
|
_AggregateExpression('TOTAL', this, filter: filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Provides aggregate functions that are available on date time expressions.
|
/// Provides aggregate functions that are available on date time expressions.
|
||||||
extension DateTimeAggregate on Expression<DateTime?> {
|
extension DateTimeAggregate on Expression<DateTime?> {
|
||||||
/// Return the average of all non-null values in this group.
|
/// Return the average of all non-null values in this group.
|
||||||
Expression<DateTime> avg() => secondsSinceEpoch.avg().roundToInt().dartCast();
|
/// {@macro moor_aggregate_filter}
|
||||||
|
Expression<DateTime> avg({Expression<bool?>? filter}) =>
|
||||||
|
secondsSinceEpoch.avg(filter: filter).roundToInt().dartCast();
|
||||||
|
|
||||||
/// Return the maximum of all non-null values in this group.
|
/// Return the maximum of all non-null values in this group.
|
||||||
///
|
///
|
||||||
/// If there are no non-null values in the group, returns null.
|
/// If there are no non-null values in the group, returns null.
|
||||||
Expression<DateTime> max() => _AggregateExpression('MAX', this);
|
/// {@macro moor_aggregate_filter}
|
||||||
|
Expression<DateTime> max({Expression<bool?>? filter}) =>
|
||||||
|
_AggregateExpression('MAX', this, filter: filter);
|
||||||
|
|
||||||
/// Return the minimum of all non-null values in this group.
|
/// Return the minimum of all non-null values in this group.
|
||||||
///
|
///
|
||||||
/// If there are no non-null values in the group, returns null.
|
/// If there are no non-null values in the group, returns null.
|
||||||
Expression<DateTime> min() => _AggregateExpression('MIN', this);
|
/// {@macro moor_aggregate_filter}
|
||||||
|
Expression<DateTime> min({Expression<bool?>? filter}) =>
|
||||||
|
_AggregateExpression('MIN', this, filter: filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AggregateExpression<D> extends Expression<D> {
|
class _AggregateExpression<D> extends Expression<D> {
|
||||||
|
|
|
@ -43,6 +43,8 @@ void main() {
|
||||||
|
|
||||||
test('avg', () {
|
test('avg', () {
|
||||||
expect(foo.avg(), generates('AVG(foo)'));
|
expect(foo.avg(), generates('AVG(foo)'));
|
||||||
|
expect(foo.avg(filter: foo.isBiggerOrEqualValue(3)),
|
||||||
|
generates('AVG(foo) FILTER (WHERE foo >= ?)', [3]));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('max', () {
|
test('max', () {
|
||||||
|
|
|
@ -19,8 +19,8 @@ void main() {
|
||||||
|
|
||||||
tearDown(() => db.close());
|
tearDown(() => db.close());
|
||||||
|
|
||||||
Future<T> eval<T>(Expression<T> expr) {
|
Future<T> eval<T>(Expression<T> expr, {TableInfo? onTable}) {
|
||||||
final query = db.selectOnly(db.users)..addColumns([expr]);
|
final query = db.selectOnly(onTable ?? db.users)..addColumns([expr]);
|
||||||
return query.getSingle().then((row) => row.read(expr));
|
return query.getSingle().then((row) => row.read(expr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,6 +73,26 @@ void main() {
|
||||||
completion(DateTime(2021, 5, 10, 12)));
|
completion(DateTime(2021, 5, 10, 12)));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('aggregate filters', () async {
|
||||||
|
await db.delete(db.users).go();
|
||||||
|
|
||||||
|
await db
|
||||||
|
.into(db.tableWithoutPK)
|
||||||
|
.insert(TableWithoutPKCompanion.insert(notReallyAnId: 3, someFloat: 7));
|
||||||
|
await db
|
||||||
|
.into(db.tableWithoutPK)
|
||||||
|
.insert(TableWithoutPKCompanion.insert(notReallyAnId: 2, someFloat: 1));
|
||||||
|
|
||||||
|
expect(
|
||||||
|
eval(
|
||||||
|
db.tableWithoutPK.someFloat
|
||||||
|
.sum(filter: db.tableWithoutPK.someFloat.isBiggerOrEqualValue(3)),
|
||||||
|
onTable: db.tableWithoutPK,
|
||||||
|
),
|
||||||
|
completion(7),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
group('text', () {
|
group('text', () {
|
||||||
test('contains', () {
|
test('contains', () {
|
||||||
const stringLiteral = Constant('Some sql string literal');
|
const stringLiteral = Constant('Some sql string literal');
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
## 0.18.0
|
## 0.18.0-dev
|
||||||
|
|
||||||
- Fix unecessary errors around `fts5` tables
|
- Fix unecessary errors around `fts5` tables
|
||||||
- Merge all moor-specific nodes into a single `visitMoorSpecific` visitor method
|
- Merge all moor-specific nodes into a single `visitMoorSpecific` visitor method
|
||||||
|
|
Loading…
Reference in New Issue