queryer: deterministic result order — array aggregations emit ORDER BY entity.created_at, entity.id (creation order, id tiebreak; every entity-family type has the entity alias), fixing run-to-run row-order variance (flaky reads like invoice-lines order, unstable grids). Also: the snapshot formatter silently DROPPED aggregate ORDER BY clauses when re-rendering parsed SQL — now rendered (format_function_clauses), so snapshots can't hide ordering changes. 1280 tests green.

This commit is contained in:
2026-07-07 22:53:48 -04:00
parent 569eb1d2ea
commit 562e52e0eb
3 changed files with 56 additions and 25 deletions

View File

@ -389,6 +389,7 @@ impl SqlFormatter {
i += 2;
}
self.indent -= 2;
self.format_function_clauses(list);
self.push_line(")");
} else {
for (i, arg) in list.args.iter().enumerate() {
@ -396,6 +397,7 @@ impl SqlFormatter {
self.format_function_arg(arg);
self.push_str(comma);
}
self.format_function_clauses(list);
self.push_str(")");
}
} else {
@ -403,6 +405,25 @@ impl SqlFormatter {
}
}
// Aggregate clauses (e.g. jsonb_agg(x ORDER BY y)) — without this the
// snapshot silently drops the ORDER BY the compiler emits.
fn format_function_clauses(&mut self, list: &sqlparser::ast::FunctionArgumentList) {
for clause in &list.clauses {
if let sqlparser::ast::FunctionArgumentClause::OrderBy(order) = clause {
self.push_str(" ORDER BY ");
for (i, ob) in order.iter().enumerate() {
if i > 0 {
self.push_str(", ");
}
self.format_expr(&ob.expr);
if let Some(asc) = ob.options.asc {
self.push_str(if asc { " ASC" } else { " DESC" });
}
}
}
}
}
fn format_function_arg(&mut self, arg: &FunctionArg) {
match arg {
FunctionArg::Unnamed(sqlparser::ast::FunctionArgExpr::Expr(expr)) => self.format_expr(expr),