Skip to content

Expression errors still fold silently inside aggregates, GROUP BY keys, window functions, and join probes (follow-up to #216/#226) #228

Description

@emanzx

Version / build tested against

PR #226's branch (fix/216-suppressed-expression-errors on top of origin/main); the behavior also exists on current main in its pre-#226 form (everything folds). Filed as the tracked follow-up to #226's documented deferral.

Deployment mode

Origin — single node (local), via pgwire.

Engine(s) involved

SQL execution — aggregate accumulators, GROUP BY key building, window functions, hash-join probe path.

Summary

#226 makes scalar expression contexts raise 22012/42883 instead of folding to NULL, but expressions evaluated inside certain pervasive hot paths still fold errors silently (each site carries an in-code deferral comment): aggregate arguments (an error row is skipped, so sum(10/d) over a table containing d = 0 returns a number silently missing rows), GROUP BY key expressions (zero-divisor rows group under NULL), window-function arguments / PARTITION BY / ORDER BY, and the hash-join residual-predicate probe path (matching row-pairs silently dropped). The result is an internal inconsistency with real corruption potential: SELECT 10/d FROM t errors, while SELECT sum(10/d) FROM t on the same table succeeds with a silently wrong total — the exact "silent wrong result" class #216 exists to eliminate, one context over.

Steps to reproduce

On a #226 build:

CREATE COLLECTION agg_probe (id TEXT PRIMARY KEY, d INT);
INSERT INTO agg_probe (id, d) VALUES ('a', 1), ('b', 0), ('c', 2);
SELECT 10 / d FROM agg_probe;        -- ERROR 22012 (correct, post-#226)
SELECT sum(10 / d) FROM agg_probe;   -- succeeds, returns 15 — silently missing row 'b'
SELECT 10 / d AS k FROM agg_probe GROUP BY k;  -- zero-divisor row groups under NULL

Expected behavior

Error contexts behave uniformly: an expression that raises 22012 in a scalar context also raises it when evaluated as an aggregate argument, GROUP BY key, window argument, or join predicate — matching Postgres.

Actual behavior

The four listed paths swallow the error per-row: aggregates skip the row, GROUP BY buckets it under NULL, joins drop the pair — all with green results.

What actually happened? (check all that are true)

  • Acknowledged/committed data was lost, corrupted, or silently wrong
  • The process crashed, hung, or failed to start
  • A security or isolation boundary was crossed
  • Core functionality is broken with no acceptable workaround
  • A workaround exists (pre-filter or guard divisors; move the expression to a scalar context first)

Proposed severity

SEV-2 — High: silently-wrong query results; stored data intact.

Reproducibility

Always — every attempt.

Last known-good version / commit (if a regression)

Not a regression — these paths have folded since introduction; #226 makes the inconsistency visible by fixing the scalar half.

Environment & logs

Linux x86_64, source build. Why deferred out of #226: these are infallible-by-signature hot paths spanning ~10 files each (accumulator feed, group-key builder, both window evaluators, grace-hash probe); converting them is a materially larger, perf-sensitive change than the ~19 mechanical call-site conversions #226 shipped. Each site carries an in-code comment naming this issue class. Suggested shape: same EvalError propagation, threaded through the accumulator/group-key/window/join result types, with attention to the spill/shuffle variants used by cluster mode.

Before submitting

Metadata

Metadata

Assignees

Labels

area:sqlParser, planner, SQL semanticspriority:P2Scheduled, not urgentsev:2-highMajor functionality broken; no acceptable workaroundtype:bugA defect — broken, incorrect, or lost data

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions