Repository navigation
D-QSP-0 slice 1: scalar SUM is NULL on an empty or all-NULL selection - #1675
Conversation
…election Scalar Agg::SumI32 (MaskedSumI32) starts from the additive identity, so a selection with no non-NULL x answered 0 where PostgreSQL answers NULL. lower_sum(filter, val, valid) lowers the existing MaskedSumI32 and Count terminals, both over filter AND valid(val); sum_finish(sum, count) returns None when no value contributed. SumPlan is an alias of AvgPlan. No new terminal, operator or rule; set_algebra, set_rules, relalg and mask-risc are unchanged. Evidence: - tests/sql_aggregate_null.rs: COUNT(*), COUNT(x), SUM, MIN, MAX, AVG against a column-lane Kleene oracle over 1200 random WHERE clauses, with empty, all-NULL and real-zero cases asserted present; targeted NULL-vs-zero cases; P-EMPTYSUM (ungrouped one NULL, grouped zero groups). Disables D1-D4 each red. - examples/qsp_agg_pg_parity.rs: PostgreSQL 16.15, 3600 queries, Quack = PostgreSQL = oracle on all six aggregates; the naive scalar SUM differs on exactly the 1455 empty + 507 all-NULL queries. Prints SKIP without a server. Board: entry 2026-10-21-d-qsp-0-scalar-aggregates-null.md, STATUS_BOARD row, regenerated entries index. EXO-50 claim session_013z2e1YXkm6o6HNrDn5BPWA/026. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013z2e1YXkm6o6HNrDn5BPWA
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configuration
Warning Billing warning: we have not been able to collect payment for this subscription for more than 72 hours. Please update the payment method or pay any pending invoices in Billing to avoid service interruption. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
STATUS_BOARD D-TGB-4 row to Shipped, PR_ARC_INVENTORY and LATEST_STATE entries for #1674. Also regenerates the entries index, whose count went stale when #1674 and #1675 merged one after the other (421 -> 422). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019fbZ92dFKQ5BJHrA3YcH9A
…1680/#1682, boundaries Only this session's rows and entry: the STATUS_BOARD "D-QSP-0 remainder" row (In PR -> Shipped, slice 2 added), PR_ARC entries for #1675, #1680 and #1682 prepended, and the entry now states that Quack has no NULL-literal Filter variant, that the PostgreSQL examples are lab evidence and not CI, and #1682's final CI (18/18 green on 96e8010). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013z2e1YXkm6o6HNrDn5BPWA
This PR implements D-QSP-0 remainder slice 1 (track C in EXO-50
/033, claimed assession_013z2e1YXkm6o6HNrDn5BPWA/026). It closes gap G7 fromentries/2026-10-21-pg-classview-polyfill-map.md.Defect. Scalar
Agg::SumI32lowers toMaskedSumI32, which starts from 0. A selection with no non-NULLxtherefore answered0, where PostgreSQL answers NULL. Values that really sum to zero also answer0, so the two cases could not be told apart.Change (
crates/lance-graph-quack/src/lib.rs, next toAvgPlan):lower_sum(filter, val, valid)lowers the existingMaskedSumI32andCountterminals, both overfilter ∧ valid(val). Because the function takes the validity plane itself, the NULL gate cannot end up on one half and not the other.sum_finish(sum, count) -> Option<i64>returns NULL whencount == 0.SumPlanis a type alias ofAvgPlan.set_algebra,set_rules, relalg and mask-risc are untouched, and so is everySemijoinpath (ADMISSION B).Supported SQL subset, as pinned. One table with two nullable
int4columns.WHERE: any tree, depth ≤ 3, of comparisons (= <> < <= > >=) against an integer constant,IS [NOT] NULL,AND,ORandNOT, read throughsql_where.count(*),count(x),sum(x),min(x),max(x)andavg(x), ungrouped.WHEREgives one NULL ungrouped and zero groups grouped (GroupReduce { SumI32 }afternormalize_group_sink).Differential results
examples/qsp_agg_pg_parity.rs, 400 tables, 3600 queries): Quack, PostgreSQL and the Kleene oracle agree on all six aggregates, with 0 mismatches.avg(int)is numeric.SKIPand exits 0.tests/sql_aggregate_null.rscompares the same six aggregates against a column-lane Kleene oracle (folds over positions, no row objects) on 1200 randomWHEREclauses. It asserts that the corpus contains empty, all-NULL and real-zero cases. It also has targeted NULL-vs-zero cases and the P-EMPTYSUM pin.Disable runs (each red at an assertion line):
sum_finishalways returnsSome): both sum tests fail. The PostgreSQL example reports 1962sum(x)mismatches and exits 101.lower_sumignoresvalid): both sum tests fail.normalize_group_sinkmarks every slot present): only the P-EMPTYSUM test fails.Unsupported, listed in the entry:
Agg::GroupSumI32, which still coalesces an unreached group to 0 (documented);xare all NULL (T4), and NULL group keys (G2), which belong to the GROUP BY slice;NOT IN (…, NULL)(G1);COALESCEandNULLIF;int4sum overflow, andnumericAVG.There is no performance claim. SUM uses two passes, the same as AVG.
Board: entry
entries/2026-10-21-d-qsp-0-scalar-aggregates-null.md, the D-QSP STATUS_BOARD row, and the regenerated entries index. The quack crate passes every suite, and clippy-D warningsis clean (Rust 1.99.0).Generated by Claude Code