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
|
/// Describes how to order rows
|
||||||
enum OrderingMode {
|
enum OrderingMode {
|
||||||
/// Ascending ordering mode (lowest items first)
|
/// Ascending ordering mode (lowest items first)
|
||||||
asc,
|
asc._('ASC'),
|
||||||
|
|
||||||
/// Descending ordering mode (highest items first)
|
/// Descending ordering mode (highest items first)
|
||||||
desc
|
desc._('DESC');
|
||||||
|
|
||||||
|
final String _mode;
|
||||||
|
|
||||||
|
const OrderingMode._(this._mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
const _modeToString = {
|
/// Describes how to order nulls
|
||||||
OrderingMode.asc: 'ASC',
|
enum NullsOrder {
|
||||||
OrderingMode.desc: 'DESC',
|
/// 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
|
/// A single term in a [OrderBy] clause. The priority of this term is determined
|
||||||
/// by its position in [OrderBy.terms].
|
/// by its position in [OrderBy.terms].
|
||||||
|
@ -23,18 +35,40 @@ class OrderingTerm extends Component {
|
||||||
/// The ordering mode (ascending or descending).
|
/// The ordering mode (ascending or descending).
|
||||||
final OrderingMode mode;
|
final OrderingMode mode;
|
||||||
|
|
||||||
/// Creates an ordering term by the [expression] and the [mode] (defaults to
|
/// How to order NULLs.
|
||||||
/// ascending).
|
/// When [nulls] is [null], then it's ignored.
|
||||||
OrderingTerm({required this.expression, this.mode = OrderingMode.asc});
|
///
|
||||||
|
/// 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].
|
/// Creates an ordering term by the [expression], the [mode] (defaults to
|
||||||
factory OrderingTerm.asc(Expression expression) {
|
/// ascending) and the [nulls].
|
||||||
return OrderingTerm(expression: expression, mode: OrderingMode.asc);
|
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].
|
/// Creates an ordering term that sorts for descending values
|
||||||
factory OrderingTerm.desc(Expression expression) {
|
/// of [expression] and the [nulls].
|
||||||
return OrderingTerm(expression: expression, mode: OrderingMode.desc);
|
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
|
/// Creates an ordering term to get a number of random rows
|
||||||
|
@ -47,7 +81,11 @@ class OrderingTerm extends Component {
|
||||||
void writeInto(GenerationContext context) {
|
void writeInto(GenerationContext context) {
|
||||||
expression.writeInto(context);
|
expression.writeInto(context);
|
||||||
context.writeWhitespace();
|
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