cursorPage method
Future<MssqlCursorPage<R> >
cursorPage({
- int size = 25,
- MssqlCursor? after,
- MssqlCursor? before,
- MssqlReadConsistency consistency = MssqlReadConsistency.committed,
A keyset page of projected rows. after and before are exclusive.
Implementation
Future<MssqlCursorPage<R>> cursorPage({
int size = 25,
MssqlCursor? after,
MssqlCursor? before,
MssqlReadConsistency consistency = MssqlReadConsistency.committed,
}) async {
if (after != null && before != null) {
throw ArgumentError('cursorPage cannot take after and before together.');
}
if (size <= 0) {
throw ArgumentError.value(size, 'size', 'Must be positive.');
}
final dialect = await _resolvedDialect();
final base = _select;
if (base.ordering.isEmpty) {
throw StateError(
'Projection ${projection.name} needs an explicit unique orderBy '
'before cursorPage().',
);
}
MssqlKeyset.requireProjectedColumns(
base.ordering,
projection.columns.map((c) => c.alias),
projection.name,
);
final orders = base.ordering;
final orderSig = MssqlKeyset.orderSignature(orders, dialect);
final filterSig = MssqlKeyset.queryFilterSignature(base, dialect);
if (after != null) {
MssqlKeyset.check(
after,
orderSignature: orderSig,
filterSignature: filterSig,
keyCount: orders.length,
);
}
if (before != null) {
MssqlKeyset.check(
before,
orderSignature: orderSig,
filterSignature: filterSig,
keyCount: orders.length,
);
}
final walking = before != null ? MssqlKeyset.reverseOrders(orders) : orders;
final cursor = after ?? before;
return mssqlRunConsistent(
session: session,
consistency: consistency,
body: (s) async {
var query = base.orderBy(walking);
if (cursor != null) {
query = query.where(MssqlKeyset.after(walking, cursor.keys));
}
final fetched = await query
.top(size + 1)
.get(
s,
dialect: dialect,
timeout: timeout,
cancellationToken: options.cancellationToken,
options: options,
);
final hasExtra = fetched.length > size;
final kept = hasExtra ? fetched.sublist(0, size) : fetched;
var mapped = kept.map(_map).toList();
if (before != null) {
mapped = mapped.reversed.toList();
}
if (kept.isEmpty) {
return MssqlCursorPage<R>(rows: mapped, hasMore: false);
}
final firstRaw = before != null ? kept.last : kept.first;
final lastRaw = before != null ? kept.first : kept.last;
MssqlCursor make(MssqlRow row) => MssqlKeyset.encode(
orderSignature: orderSig,
filterSignature: filterSig,
keys: MssqlKeyset.keysFromRow(row, orders),
);
return MssqlCursorPage<R>(
rows: mapped,
hasMore: hasExtra,
next: before != null || hasExtra ? make(lastRaw) : null,
previous: after != null || (before != null && hasExtra)
? make(firstRaw)
: null,
);
},
);
}