Skip to content

Finish #1909: join batch growth coverage, per-row nrows, observable grow-refusal warning - #2064

Merged
justinjoy merged 3 commits into
mainfrom
claude/1909-diff-join-batch-lazy
Oct 4, 2026
Merged

justinjoy merged 3 commits into
mainfrom
claude/1909-diff-join-batch-lazy

Conversation

@justinjoy

Copy link
Copy Markdown
Collaborator

Summary

This closes #1909. Earlier work had already done most of it on the differential side: c946139 gave diff_join_batch.c lazy scratch growth that tells a refusal from an allocation failure, per-row nrows, and a timestamped and projected growth test. These three commits finish the remaining items on the non-differential producer, join_batch.c:

  1. test(columnar): cover projected and timestamped join batch scratch growth. Adds two cases that start at the 64-row floor, grow inside one batch, and compare with the one-shot oracle: a 90-row projected output and a 141-row timestamped one. The existing projected case ran at seven rows per batch, so projection had never met a reallocation.
  2. fix(columnar): publish the join batch live prefix after every row. nrows is now kept current after each written row, as the differential producer already does, instead of being synced only inside grow_scratch before the reserve. A future reallocation site has no sync point to forget. Removing the per-row store fails 7 growth oracle cases. Also corrects the col_join_write_pair_at comment, which now covers all four callers.
  3. test(columnar): observe the join batch grow-refusal warning. Captures the JOIN log section to a per-process file under TMPDIR, restoring the caller's WL_LOG/WL_LOG_FILE. It asserts a single warning that names "allocation failed" across two refused grows, and "admission denied" for a governor refusal, then finishes the scan against the oracle. It reports SKIP when the compile-time ceiling strips WARN.

Validation

  • Mutation checks:
    • Dropping the nrows sync or the per-row store fails 7 cases.
    • Rotating the WARN reasons fails 2 cases, removing its once-only gate fails 1, and removing the WARN fails 2.
    • The unmodified (null) mutant passes.
  • meson test: 416 OK, 0 failed, 14 skipped. --suite tidy: 4/4 OK. uncrustify is clean.
  • Peer review: approved after two rounds. Comment and commit-message claims were corrected, and its nits on log-file isolation, environment restore and a stale header comment were applied.

Fixes #1909

…owth

The non-differential join batch producer grows its scratch from the 64-row
floor while filling a batch, and col_rel_prepare_resize copies exactly
nrows rows and, for a timestamped scratch, nrows timestamps. The growth
oracle cases used only untimestamped, unprojected fixtures, and the
projected case runs at seven rows per batch, so projection had never met a
reallocation and a timestamped scratch had never grown.

Add two cases that start at the floor, grow inside one batch, and compare
with the one-shot oracle: a projected output of 90 rows, and a timestamped
left and output of 141 rows, which also checks the sink publishes zero
timestamps. Both fail when grow_scratch stops publishing nrows before the
reserve.

Refs #1909
The non-differential join batch producer zeroed the scratch's nrows while
filling and synced it to the written count only inside grow_scratch,
before the reserve. col_rel_prepare_resize copies exactly nrows rows and
timestamps, so the invariant was "remember to sync before any
reallocation": a second reallocation site added to the fill loop would
silently drop every row written so far, which neither ASan nor UBSan
reports.

Publish nrows after each written row instead, as the differential
producer already does, and drop the sync from grow_scratch. A relocation
anywhere in the loop now sees the live prefix without a sync point to
remember. Removing the per-row store fails the seven growth oracle cases,
including the projected and timestamped ones.

Refs #1909
The WARN that join_batch's grow_scratch emits when the scratch cannot grow
was unobservable from the producer tests: the binary did not initialise
the logger until its last test, so no producer case could see the line.
Removing the warning, removing its once-per-producer gate, or rotating its
reason strings all survived the suite.

Capture the JOIN section to a per-process file under TMPDIR through
WL_LOG_FILE, restoring the caller's WL_LOG and WL_LOG_FILE afterwards, and
publish batch by batch. One case refuses the scratch resize of two
consecutive batches and expects a single warning naming "allocation
failed". The other leaves the governor room for a 64-row payload but not
for growing to 128 rows, and expects "admission denied". Both then lift the
refusal, finish the scan and compare with the one-shot oracle. Removing
the warning, removing its gate, or rotating the reasons now fails. The case
reports SKIP when the compile-time ceiling strips WARN.

With this, #1909's remaining items are done. The differential producer's
lazy, refusal-aware growth with per-row nrows, and its timestamped and
projected growth case, came with c946139. The non-differential producer's
growth coverage and per-row nrows came in the two preceding commits.

Fixes #1909
@justinjoy
justinjoy merged commit e36822d into main Oct 4, 2026
30 checks passed
@justinjoy
justinjoy deleted the claude/1909-diff-join-batch-lazy branch October 4, 2026 11:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

diff_join_batch.c still reserves its scratch eagerly, and the nrows trap is live there too

1 participant