ensureStableOrder method

S ensureStableOrder()

page / chunk / cursorPage: used when the caller gave none, and as a tie-breaker when they gave some.

A keyless table cannot invent an order — the generic builder will not guess a unique key it does not have.

Implementation

S ensureStableOrder() {
  if (!binding.hasPrimaryKey) {
    if (state.orderBy.isEmpty) {
      throw StateError(
        '${binding.qualifiedName} has no primary key, so a page needs an '
        'explicit unique orderBy. The generic builder will not guess one.',
      );
    }
    return _self;
  }
  if (state.orderBy.isEmpty) {
    return rebuild(
      state.withOrderBy(<MssqlOrder>[
        for (final name in binding.primaryKey) Col(name).asc(),
      ]),
    );
  }
  // Append only the key columns the caller's ordering does not already
  // name. `orderBy((o) => [o.id.desc()])` must not become
  // `ORDER BY [Id] DESC, [Id] ASC`: the second term is unreachable, so the
  // ordering would claim a tie-break it does not have, and cursorPage
  // builds its keyset predicate from this list term by term — the same
  // column twice with opposite directions gives `[Id] < @a AND … [Id] >
  // @a`, which matches no row at all.
  return rebuild(
    state.withOrderBy(
      mssqlWithKeyTieBreak(state.orderBy, binding.primaryKey),
    ),
  );
}