mirror of https://github.com/AMT-Cheif/drift.git
Merge pull request #2024 from Vorkytaka/order_by_nulls
Add `NULLS FIRST\LAST` to the `OrderingTerm`
This commit is contained in:
commit
98cb4be7cc
|
@ -3,16 +3,28 @@ part of '../query_builder.dart';
|
|||
/// Describes how to order rows
|
||||
enum OrderingMode {
|
||||
/// Ascending ordering mode (lowest items first)
|
||||
asc,
|
||||
asc._('ASC'),
|
||||
|
||||
/// Descending ordering mode (highest items first)
|
||||
desc
|
||||
desc._('DESC');
|
||||
|
||||
final String _mode;
|
||||
|
||||
const OrderingMode._(this._mode);
|
||||
}
|
||||
|
||||
const _modeToString = {
|
||||
OrderingMode.asc: 'ASC',
|
||||
OrderingMode.desc: 'DESC',
|
||||
};
|
||||
/// Describes how to order nulls
|
||||
enum NullsOrder {
|
||||
/// Place NULLs at the start
|
||||
first._('NULLS FIRST'),
|
||||
|
||||
/// Place NULLs at the end
|
||||
last._('NULLS LAST');
|
||||
|
||||
final String _order;
|
||||
|
||||
const NullsOrder._(this._order);
|
||||
}
|
||||
|
||||
/// A single term in a [OrderBy] clause. The priority of this term is determined
|
||||
/// by its position in [OrderBy.terms].
|
||||
|
@ -23,18 +35,40 @@ class OrderingTerm extends Component {
|
|||
/// The ordering mode (ascending or descending).
|
||||
final OrderingMode mode;
|
||||
|
||||
/// Creates an ordering term by the [expression] and the [mode] (defaults to
|
||||
/// ascending).
|
||||
OrderingTerm({required this.expression, this.mode = OrderingMode.asc});
|
||||
/// How to order NULLs.
|
||||
/// When [nulls] is [null], then it's ignored.
|
||||
///
|
||||
/// Note that this feature are only available in sqlite3 version `3.30.0` and
|
||||
/// newer. When using `sqlite3_flutter_libs` or a web database, this is not
|
||||
/// a problem.
|
||||
final NullsOrder? nulls;
|
||||
|
||||
/// Creates an ordering term that sorts for ascending values of [expression].
|
||||
factory OrderingTerm.asc(Expression expression) {
|
||||
return OrderingTerm(expression: expression, mode: OrderingMode.asc);
|
||||
/// Creates an ordering term by the [expression], the [mode] (defaults to
|
||||
/// ascending) and the [nulls].
|
||||
OrderingTerm({
|
||||
required this.expression,
|
||||
this.mode = OrderingMode.asc,
|
||||
this.nulls,
|
||||
});
|
||||
|
||||
/// Creates an ordering term that sorts for ascending values
|
||||
/// of [expression] and the [nulls].
|
||||
factory OrderingTerm.asc(Expression expression, [NullsOrder? nulls]) {
|
||||
return OrderingTerm(
|
||||
expression: expression,
|
||||
mode: OrderingMode.asc,
|
||||
nulls: nulls,
|
||||
);
|
||||
}
|
||||
|
||||
/// Creates an ordering term that sorts for descending values of [expression].
|
||||
factory OrderingTerm.desc(Expression expression) {
|
||||
return OrderingTerm(expression: expression, mode: OrderingMode.desc);
|
||||
/// Creates an ordering term that sorts for descending values
|
||||
/// of [expression] and the [nulls].
|
||||
factory OrderingTerm.desc(Expression expression, [NullsOrder? nulls]) {
|
||||
return OrderingTerm(
|
||||
expression: expression,
|
||||
mode: OrderingMode.desc,
|
||||
nulls: nulls,
|
||||
);
|
||||
}
|
||||
|
||||
/// Creates an ordering term to get a number of random rows
|
||||
|
@ -47,7 +81,11 @@ class OrderingTerm extends Component {
|
|||
void writeInto(GenerationContext context) {
|
||||
expression.writeInto(context);
|
||||
context.writeWhitespace();
|
||||
context.buffer.write(_modeToString[mode]);
|
||||
context.buffer.write(mode._mode);
|
||||
if (nulls != null) {
|
||||
context.writeWhitespace();
|
||||
context.buffer.write(nulls?._order);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
import 'package:drift/drift.dart' hide isNull;
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../../generated/todos.dart';
|
||||
import '../../test_utils/test_utils.dart';
|
||||
|
||||
void main() {
|
||||
late TodoDb db;
|
||||
late MockExecutor executor;
|
||||
|
||||
setUp(() {
|
||||
executor = MockExecutor();
|
||||
db = TodoDb(executor);
|
||||
});
|
||||
|
||||
test('when nullsOrder is null it ignored', () async {
|
||||
final query = db.select(db.users);
|
||||
query.orderBy([(tbl) => OrderingTerm(expression: tbl.name)]);
|
||||
await query.get();
|
||||
verify(executor.runSelect(
|
||||
'SELECT * FROM users ORDER BY name ASC;',
|
||||
argThat(isEmpty),
|
||||
));
|
||||
});
|
||||
|
||||
test('nullsOrder is last', () async {
|
||||
final query = db.select(db.users);
|
||||
query.orderBy([
|
||||
(tbl) => OrderingTerm(
|
||||
expression: tbl.name,
|
||||
nulls: NullsOrder.last,
|
||||
),
|
||||
]);
|
||||
await query.get();
|
||||
verify(executor.runSelect(
|
||||
'SELECT * FROM users ORDER BY name ASC NULLS LAST;',
|
||||
argThat(isEmpty),
|
||||
));
|
||||
});
|
||||
|
||||
test('nullsOrder is first', () async {
|
||||
final query = db.select(db.users);
|
||||
query.orderBy([
|
||||
(tbl) => OrderingTerm(
|
||||
expression: tbl.name,
|
||||
nulls: NullsOrder.first,
|
||||
),
|
||||
]);
|
||||
await query.get();
|
||||
verify(executor.runSelect(
|
||||
'SELECT * FROM users ORDER BY name ASC NULLS FIRST;',
|
||||
argThat(isEmpty),
|
||||
));
|
||||
});
|
||||
|
||||
test('complex order by with different nullsOrder', () async {
|
||||
final query = db.select(db.users);
|
||||
query.orderBy([
|
||||
(tbl) => OrderingTerm(
|
||||
expression: tbl.name,
|
||||
nulls: NullsOrder.first,
|
||||
),
|
||||
(tbl) => OrderingTerm(
|
||||
expression: tbl.creationTime,
|
||||
),
|
||||
(tbl) => OrderingTerm(
|
||||
expression: tbl.profilePicture,
|
||||
nulls: NullsOrder.last,
|
||||
),
|
||||
]);
|
||||
await query.get();
|
||||
verify(executor.runSelect(
|
||||
'SELECT * FROM users ORDER BY name ASC NULLS FIRST, creation_time ASC, profile_picture ASC NULLS LAST;',
|
||||
argThat(isEmpty),
|
||||
));
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue