Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions test/check_ledger.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -2571,6 +2571,75 @@ native_groupagg native_groupagg toggle sum signed-zero (-0 preserved) [node fire
native_groupagg native_groupagg while a matching-type predicate still gets one 15;16;17;18;19 never -
native_groupagg native_groupagg with no time bound at all, a truncating key is bounded from the zone maps 15;16;17;18;19 never -
native_groupagg native_groupagg with only a lower time bound, a truncating key is still bounded 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch <> filter: answers match the heap mirror 15;16;17;18;19 2026-10-16 columnar_vector.c: the batch gates' exactness test dropped, so a <> filter's rows are folded
native_groupagg_batch native_groupagg_batch <> filter: the excluded rows really are excluded 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch <> filter: the fold declined 15;16;17;18;19 2026-10-16 columnar_vector.c: the batch gates' exactness test dropped, so a <> filter's rows are folded
native_groupagg_batch native_groupagg_batch add column: ANALYZE reports the row-path run 15;16;17;18;19 2026-10-16 columnar_vector.c: the grouped node's ANALYZE prints the predicted fold, not what ran (the #602 shape)
native_groupagg_batch native_groupagg_batch add column: plain EXPLAIN reports the prediction 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch add column: the answer is still right 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch count(*): answers match the heap mirror 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch count(*): the fold ran (work done) 15;16;17;18;19 2026-10-16 columnar_vector.c: pgcolumnar_groupagg_build never calls the grouped batch fold (the removal proof)
native_groupagg_batch native_groupagg_batch count(*): the grouped node is planned 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch date key: answers match the heap mirror 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch date key: the fold ran (work done) 15;16;17;18;19 2026-10-16 columnar_vector.c: pgcolumnar_groupagg_build never calls the grouped batch fold (the removal proof)
native_groupagg_batch native_groupagg_batch date key: the grouped node is planned 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch deletes: answers match the heap mirror 15;16;17;18;19 2026-10-16 columnar_vector.c: the grouped fold ignores the delete mask
native_groupagg_batch native_groupagg_batch deletes: the fold still ran 15;16;17;18;19 2026-10-16 columnar_vector.c: pgcolumnar_groupagg_build never calls the grouped batch fold (the removal proof)
native_groupagg_batch native_groupagg_batch expression key: answers match the heap mirror 15;16;17;18;19 2026-10-16 columnar_vector.c: an expression key's -1 attidx is not refused by the grouped fold's eligibility
native_groupagg_batch native_groupagg_batch expression key: the fold declined 15;16;17;18;19 2026-10-16 columnar_vector.c: an expression key's -1 attidx is not refused by the grouped fold's eligibility
native_groupagg_batch native_groupagg_batch filtered: answers match the heap mirror 15;16;17;18;19 2026-10-16 columnar_vector.c: the grouped fold applies no scan key per row
native_groupagg_batch native_groupagg_batch filtered: the fold ran (work done) 15;16;17;18;19 2026-10-16 columnar_vector.c: pgcolumnar_groupagg_build never calls the grouped batch fold (the removal proof)
native_groupagg_batch native_groupagg_batch filtered: the grouped node is planned 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch float8 key: answers match the heap mirror 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch float8 key: the fold ran (work done) 15;16;17;18;19 2026-10-16 columnar_vector.c: pgcolumnar_groupagg_build never calls the grouped batch fold (the removal proof)
native_groupagg_batch native_groupagg_batch float8 key: the grouped node is planned 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch float8 zero: -0.0 and 0.0 are one group, exactly as the heap says 15;16;17;18;19 2026-10-16 columnar_vector.c: float8 admitted as a simple key, so its group keys are hashed and compared by bits
native_groupagg_batch native_groupagg_batch float8 zero: and a positive one beside it 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch float8 zero: and the fold actually ran on it 15;16;17;18;19 2026-10-16 columnar_vector.c: pgcolumnar_groupagg_build never calls the grouped batch fold (the removal proof)
native_groupagg_batch native_groupagg_batch float8 zero: the fixture really stores a NEGATIVE zero 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch float8 zero: the grouped node is planned 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch float8 zero: the grouped sums match the heap 15;16;17;18;19 2026-10-16 columnar_vector.c: float8 admitted as a simple key, so its group keys are hashed and compared by bits
native_groupagg_batch native_groupagg_batch min/max: answers match the heap mirror 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch min/max: the fold declined 15;16;17;18;19 2026-10-16 columnar_vector.c: min and max admitted as batch fold kinds
native_groupagg_batch native_groupagg_batch parallel: and they equal the heap mirror 15;16;17;18;19 2026-10-16 columnar_vector.c: a partial grouped node folds without the shared row-group counter;columnar_vector.c: the grouped fold ignores the delete mask
native_groupagg_batch native_groupagg_batch parallel: our parallel-aware grouped node is under the Gather 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch parallel: premise: the value arm's own plan launches workers 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch parallel: the answers equal the serial fold, byte for byte 15;16;17;18;19 2026-10-16 columnar_vector.c: a partial grouped node folds without the shared row-group counter
native_groupagg_batch native_groupagg_batch parallel: the fold ran in the partial node (work done) 15;16;17;18;19 2026-10-16 columnar_vector.c: pgcolumnar_groupagg_build never calls the grouped batch fold (the removal proof)
native_groupagg_batch native_groupagg_batch parallel: workers actually launched for that node 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch plain: answers match the heap mirror 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch plain: the fold ran (work done) 15;16;17;18;19 2026-10-16 columnar_vector.c: pgcolumnar_groupagg_build never calls the grouped batch fold (the removal proof)
native_groupagg_batch native_groupagg_batch plain: the grouped node is planned 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch premise: fixture loaded every row (columnar) 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch premise: fixture loaded every row (heap) 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch premise: the <> filter excludes something at all 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch premise: the delete removed rows 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch premise: the fixture really has null keys 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch premise: the fixture spans more than one row group 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch skipped vectors: and their sums match the heap mirror 15;16;17;18;19 2026-10-16 columnar_vector.c: a skipped vector's present slots are not consumed, so later vectors misalign;columnar_vector.c: the grouped fold applies no scan key per row
native_groupagg_batch native_groupagg_batch skipped vectors: answers match the heap mirror 15;16;17;18;19 2026-10-16 columnar_vector.c: a skipped vector's present slots are not consumed, so later vectors misalign;columnar_vector.c: the grouped fold applies no scan key per row
native_groupagg_batch native_groupagg_batch skipped vectors: premise: a row group was still read 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch skipped vectors: premise: the scan really skipped vectors 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch skipped vectors: premise: the wide arm is still the grouped node 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch skipped vectors: the fold ran 15;16;17;18;19 2026-10-16 columnar_vector.c: pgcolumnar_groupagg_build never calls the grouped batch fold (the removal proof)
native_groupagg_batch native_groupagg_batch skipped vectors: the fold ran on the four-payload arm 15;16;17;18;19 2026-10-16 columnar_vector.c: pgcolumnar_groupagg_build never calls the grouped batch fold (the removal proof)
native_groupagg_batch native_groupagg_batch text key: answers match the heap mirror 15;16;17;18;19 2026-10-16 columnar_vector.c: the batch gates' by-value test dropped, so a text key reaches the gather
native_groupagg_batch native_groupagg_batch text key: the fold declined 15;16;17;18;19 2026-10-16 columnar_vector.c: the batch gates' by-value test dropped, so a text key reaches the gather;columnar_vector.c: the grouped path is not planned for a text group key
native_groupagg_batch native_groupagg_batch timestamp key: answers match the heap mirror 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch timestamp key: the fold ran (work done) 15;16;17;18;19 2026-10-16 columnar_vector.c: pgcolumnar_groupagg_build never calls the grouped batch fold (the removal proof)
native_groupagg_batch native_groupagg_batch timestamp key: the grouped node is planned 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch toggle-differential: filtered 15;16;17;18;19 2026-10-16 columnar_vector.c: the grouped fold applies no scan key per row;columnar_vector.c: the grouped fold ignores the delete mask
native_groupagg_batch native_groupagg_batch toggle-differential: filtered [premise: node fires with the path on] 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch toggle-differential: filtered [premise: the off arm is not the grouped node] 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch toggle-differential: plain 15;16;17;18;19 2026-10-16 columnar_vector.c: the grouped fold ignores the delete mask
native_groupagg_batch native_groupagg_batch toggle-differential: plain [premise: node fires with the path on] 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch toggle-differential: plain [premise: the off arm is not the grouped node] 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch toggle-differential: two keys 15;16;17;18;19 2026-10-16 columnar_vector.c: the grouped fold ignores the delete mask
native_groupagg_batch native_groupagg_batch toggle-differential: two keys [premise: node fires with the path on] 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch toggle-differential: two keys [premise: the off arm is not the grouped node] 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch two keys: answers match the heap mirror 15;16;17;18;19 never -
native_groupagg_batch native_groupagg_batch two keys: the fold ran (work done) 15;16;17;18;19 2026-10-16 columnar_vector.c: pgcolumnar_groupagg_build never calls the grouped batch fold (the removal proof)
native_groupagg_batch native_groupagg_batch two keys: the grouped node is planned 15;16;17;18;19 never -
native_index_projection native_index_projection a parallel build projects one column of twenty, not all twenty 15;16;17;18;19 never -
native_index_projection native_index_projection a parallel expression build projects its expression's columns 15;16;17;18;19 2026-10-16 columnar_tableam.c: the index build's projection omits ii_Expressions' columns
native_index_projection native_index_projection a parallel partial build projects the predicate's columns too 15;16;17;18;19 2026-10-16 columnar_tableam.c: the index build's projection omits ii_Predicate's columns
Expand Down
22 changes: 20 additions & 2 deletions test/check_ledger_budget.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#
# Adding a check to a suite that is already covered does not move it, which is
# what makes it safe to bound.
suites_not_covered 201
suites_not_covered 200
#
# checks_never_observed_red -- A CENSUS. NOT a ceiling, and it must not become
# one.
Expand Down Expand Up @@ -3285,4 +3285,22 @@ suites_not_covered 201
# never 2941 + 1 = 2942
# dated 1160 + 0 = 1160
# 2942 + 1160 == 4102
checks_never_observed_red 2942
#
# #1341, native_groupagg_batch seeded, with its twin (OffgridwithJD): 2942 -> 2980,
# and suites_not_covered 201 -> 200. The suite had no rows. It enters with all 69
# checks from five-major runs (69/69 on each of 15-19). 31 are dated by twelve
# mutations of the grouped fold: the fold never called, float8 keys compared by
# bits, the delete mask ignored, a skipped vector's slots not consumed, no scan key
# applied, the by-value, exactness and expression-key gates dropped, min and max
# admitted, the partial node without its shared counter, ANALYZE printing the
# prediction, and the grouped path refusing a text key. Thirty-eight arrive never:
# sixteen premises and the two float8 fixture facts; the eight "grouped node is
# planned" arms and the two parallel plan arms, which no fold mutation reaches;
# seven heap-mirror oracles that none of these mutations moves; the <> count, read
# by an ungrouped count(*); and the add-column prediction and answer.
#
# ledger rows 4102 + 69 = 4171
# never 2942 + 38 = 2980
# dated 1160 + 31 = 1191
# 2980 + 1191 == 4171
checks_never_observed_red 2980
11 changes: 7 additions & 4 deletions test/native_groupagg_batch.sh
Original file line number Diff line number Diff line change
Expand Up @@ -170,13 +170,16 @@ for pair in "text key:$Q_TEXTKEY" "expression key:$Q_EXPRKEY" \
"min/max:$Q_MINMAX" "<> filter:$Q_NEQ"; do
label="${pair%%:*}"; tmpl="${pair#*:}"
qcol="${tmpl//%T/gbb}"
# The decline must be the FOLD's, read off the grouped node. This branch was
# a check_skip, and it never fired on 15-19: with the node gone the gate
# under test is unreachable, so a skip there was a silent pass. A shape the
# node stops taking is now a red under the arm's own name.
if [ "$(is_groupvec "$qcol")" = yes ]; then
check_text "$label: the fold declined" \
"$(fold_of "$ANALYZE_PFX" "$qcol")" no
else
# The node itself declined the shape; there is no fold line to read and
# nothing for this suite to gate. Say so rather than assert a missing line.
check_skip "$label" "SKIP $label: the grouped node is not planned for this shape" "the grouped node is not planned for this shape"
check_text "$label: the fold declined" \
"the grouped node is not planned" no
fi
agree "$label: answers match the heap mirror" "$tmpl"
done
Expand Down Expand Up @@ -315,7 +318,7 @@ agree_in gbs "skipped vectors: answers match the heap mirror" "$Q_SKIP"
Q_SKIP4="SELECT k, count(*), sum(p1), sum(p2), sum(p3), sum(p4) FROM %T WHERE sel = 1 GROUP BY k"
check_text "skipped vectors: premise: the wide arm is still the grouped node" \
"$(is_groupvec "${Q_SKIP4//%T/gbs}")" yes
check_text "skipped vectors: four payload columns all stay in step" \
check_text "skipped vectors: the fold ran on the four-payload arm" \
"$(fold_of "$ANALYZE_PFX" "${Q_SKIP4//%T/gbs}")" yes
agree_in gbs "skipped vectors: and their sums match the heap mirror" "$Q_SKIP4"

Expand Down
18 changes: 18 additions & 0 deletions test/pytest/TESTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ behaviour, the source of that number is named.
- [162. test_native_vecskip.py: per-vector skipping by the zone maps](#162-test_native_vecskippy-per-vector-skipping-by-the-zone-maps)
- [163. test_native_index_projection.py: CREATE INDEX projects only what it needs](#163-test_native_index_projectionpy-create-index-projects-only-what-it-needs)
- [164. test_native_saop_pushdown.py: IN-lists and = ANY(array) prune row groups](#164-test_native_saop_pushdownpy-in-lists-and--anyarray-prune-row-groups)
- [165. test_native_groupagg_batch.py: the grouped aggregate folds column-at-a-time](#165-test_native_groupagg_batchpy-the-grouped-aggregate-folds-column-at-a-time)

## 1. How to read a test in here

Expand Down Expand Up @@ -7659,3 +7660,20 @@ The pytest twin of `test/native_saop_pushdown.sh` (ported for #1341), every chec
| `test_the_batch_fold_never_takes_the_set_keys_as_exact` | the batch fold refuses the IN-list but accepts the equivalent range, and the vectorized count stays exact |
| `test_a_correlated_array_is_not_frozen_and_the_backend_lives` | a correlated LATERAL array is not frozen, and the session's backend is still alive; a crash is a named red |
| `test_the_reader_refuses_every_special_flag_but_the_array_one` | the reader's reject expression names every special scan-key flag, and SK_SEARCHARRAY reaches its own arm |

## 165. test_native_groupagg_batch.py: the grouped aggregate folds column-at-a-time

The pytest twin of `test/native_groupagg_batch.sh` (ported for #1341), every check by the shell's name. The grouped vectorized aggregate folds a whole row group at a time (#708), and two things are proved separately. The answers must be unchanged: each shape agrees with a heap mirror, and with the same rows when the path is off. The work must happen: "Columnar Batch Fold: yes" under EXPLAIN ANALYZE is the only check that goes red when the fold stops running. Each shape the fold must decline is read off the grouped node, so a shape the node stops taking is a red, not a skip.

### Every test

| test | what it holds |
| --- | --- |
| `test_the_fold_takes_every_eligible_shape_and_answers_as_the_heap_does` | seven shapes (plain, filtered, two keys, float8, count(*), timestamp and date keys) plan the grouped node, fold, and match the heap |
| `test_the_fold_declines_every_ineligible_shape_and_still_answers` | a text key, an expression key, min/max and a `<>` filter make the fold decline on the grouped node, and each still matches the heap |
| `test_the_fold_honours_the_delete_mask` | after deletes the fold still runs and matches the heap |
| `test_the_fold_equals_the_row_path_over_the_same_rows` | three shapes answer the same with the path off and on, and the off arm really is not the grouped node |
| `test_float8_keys_group_by_the_types_equality_not_by_bits` | a stored -0.0 and 0.0 are one group on the fold, as on the heap |
| `test_the_fold_steps_over_skipped_vectors` | a scan that really skips vectors folds, and its one-column and four-column sums match the heap |
| `test_the_parallel_partial_fold_equals_the_serial_one` | our parallel-aware node launches workers and folds, and equals the serial fold and the heap |
| `test_a_column_added_after_some_row_groups_runs_the_row_path` | plain EXPLAIN predicts the fold, ANALYZE reports the row path that ran, and the answer is right |
4 changes: 3 additions & 1 deletion test/pytest/expected_tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -791,4 +791,6 @@ guard_tests 438
# four tests, by collection over the cluster files on this tree.
# cluster_tests 702 -> 710 for #1341's test_native_saop_pushdown.py, the twin of native_saop_pushdown.sh:
# eight tests, by collection over the cluster files on this tree.
cluster_tests 710
# cluster_tests 710 -> 718 for #1341's test_native_groupagg_batch.py, the twin of native_groupagg_batch.sh:
# eight tests, by collection over the cluster files on this tree.
cluster_tests 718
3 changes: 2 additions & 1 deletion test/pytest/test_compare_to_bash.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@
"native_encdesc_golden",
"native_fetch_coalesce",
"native_groupagg",
"native_groupagg_batch",
"native_index_fetch_stripe_cost",
"native_index_projection",
"native_join_vector_agg",
Expand Down Expand Up @@ -410,7 +411,7 @@ def test_the_loop_reader_invents_nothing_in_this_corpus(expect):
"every name the loop reader returns appears verbatim in the file it "
"came from")
expect.text(", ".join(files),
"build_refusal, differential, join_runtime_filter, "
"build_refusal, differential, join_runtime_filter, native_groupagg_batch, "
"native_index_projection, native_reclaim, native_repack, "
"native_saop_pushdown, native_vacuum_race, native_vecskip, sorted_pathkeys",
"and it is these files, so another appearing is a diff a reviewer "
Expand Down
Loading
Loading