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:
@ -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),
|
||||
|
||||
Reference in New Issue
Block a user