docs(clickhouse): coverage gap audit for the last 4 months of ClickHouse changes (25 prioritized items) - #10
Merged
Conversation
…tems) Backlog plan auditing every ClickHouse change merged in the last four months against what this fork can generate and assert today, ranked by expected bug-finding value. Successor to the 2026-06-13 30-ideas plan, whose items have all shipped. Method: 150 new_feature + 58 experimental + 737 semantics-relevant improvement/performance PRs from qa_intelligence for the window; open human-filed wrong-result issues from the same window grouped by component as ground truth for where other sources find bugs we do not; a regex capability sweep over src/sqlancer/clickhouse for every setting, clause, type and function the change inventory names; and a finding-by- finding triage of the five NightlySQLancer runs from 2026-08-01 to 08-13 with every reproducer replayed against head 26.8.1.1424. The plan is grounded in a measured miss. On 2026-08-13 the SQLancerPP job (10 minutes of upstream SQLancer) found a silent wrong result this fork's 98 oracles have never surfaced: NOT (NOT key) in value position collapses to the bare key in KeyCondition, deriving a bogus key range and pruning parts that hold matching rows. Wrong on 24.8 through head, so long standing rather than a regression. ClickHouseKeyConditionOracle would have caught it on the first iteration that emitted the shape; the grammar never emits it. Item 1 closes that, and Appendix C makes the rule general: anything the upstream job finds and this fork does not is a grammar gap and goes straight to P0. Two of the five triaged nightly families are our own false positives, and both are landed here as prerequisite fixes 0a and 0b because they cost triage time on every run: ComparatorHelper.trimTrailingDotZeros normalises '0.0' to '0' and breaks the LIMIT BY per-key cap assertion, and the engine pool accepts a Bool sorting key for ReplacingMergeTree so visible cardinality changes mid-iteration. Every one of the 179 referenced PRs and issues was verified to exist with the correct pull/issues path. Each entry carries goal, ClickHouse surface with links, invariant or emission, bug class, evidence that the gap is real, soundness risk, file targets, effort and verification, so any single entry can be promoted to an implementation plan.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
A research/backlog plan auditing every ClickHouse change merged between 2026-04-15 and 2026-08-15 against what this fork can actually generate and assert today, ranked by expected bug-finding value. It is the successor to
docs/plans/2026-06-13-001-feat-clickhouse-coverage-backlog-30-ideas-plan.md, whose 30 items have all shipped as 29 oracles.One file, no code:
docs/plans/2026-08-15-001-feat-clickhouse-4month-coverage-gap-plan.md.25 coverage items plus 2 prerequisite fixes. Each entry carries goal, ClickHouse surface with links, the invariant or emission, bug class, evidence that the gap is real, soundness risk, file targets, effort, verification, so any single entry can be promoted to an implementation plan on its own.
Why now: a measured miss
On 2026-08-13 the
SQLancerPPjob (10 minutes of upstream SQLancer,general --database-engine CLICKHOUSE) found a silent wrong result that this fork's 98 oracles have never surfaced:EXPLAIN indexes = 1printsCondition: (c1 in (-Inf, 3]). InKeyCondition.cppthename == "not"branch ofcloneDAGWithInversionPushDowntreatsnotas purely logical, flippingneed_inversionand recursing while ignoring theboolean_contextflag, so the two flips cancel andNOT NOT c1becomes barec1. For a non-Bool column that is unsound:NOT NOT c1meansc1 != 0and lives in {0, 1}, so the comparison against 3.14 is universally true, and the derived range prunes any part whose rows all lie above 3. Wrong on 24.8.14.39, 25.8.29.51, 26.3.12.3, 26.6.2.160 and head 26.8.1.1424, so long standing rather than a regression.ClickHouseKeyConditionOraclewould have caught this on the first iteration that emitted the shape. The grammar never emits the shape. A repo-wide grep returns zero hits forNOT (NOT,IS TRUE,IS FALSE,IS UNKNOWN,IS NOT DISTINCT FROM,ESCAPEandindexHint, while ClickHouse shipped or extended index pruning for most of those shapes inside this very window. Item 1 closes it, and Appendix C promotes the lesson to a rule: anything the upstream job finds and this fork does not is a grammar gap by definition and goes straight to P0.The underlying ClickHouse bug is not yet filed.
The three structural patterns behind every gap
make_distributed_plan,serialize_query_plan, the DPhyp and DPsub join enumerators, the new statistics types, pipe operators, IEJoin,GROUPSwindow frames and the second wave of text-index work all landed in this window. Several already have open wrong-result issues filed by other sources.Prerequisite fixes, from the same triage
Two of the five nightly failure families are our own false positives, and both are checklist violations, so they land before new surface is added:
ComparatorHelper.trimTrailingDotZerosnormalises'0.0'into'0', socheckLimitByCapsees one String key twice and reports a cap violation that does not exist. Replay against head showsuniqExact(c0) = count() = 10000andLIMIT 1 BYreturning exactly 10000 rows. Fix: assert the cap server-side.ReplacingMergeTree() ORDER BY c0withc0 Booland no ver column, so a background merge collapsed 7 visible rows to 2 between the two TLP queries (91 = 7x13, 26 = 2x13). Fix: reject degenerate-domain dedupe keys, or always emit the ver argument.Full triage of the five runs behind this plan
Runs 2026-08-01, 08-04, 08-07, 08-10 and 08-13, all on CH 26.8.1.1 asan+ubsan. Every reproducer was replayed against fresh
clickhouse/clickhouse-server:head26.8.1.1424 on the dev VM.LimitRanking LIMIT-BY cap violationTLPWhere: result sets mismatch (91 and 26)Sorted vs plain UNION ALL diverged under outer LIMIT_BYLOGICAL_ERROR: Left and right columns have same names, server abortresult sets mismatch (9 and 7)Two side findings recorded in the plan:
mini (k UInt32, v_nonzero Int32, v_zero UInt8) ENGINE = SummingMergeTree ORDER BY kand two identical inserts of(1,100,0),(2,200,0),SELECT k, v_nonzero, v_zero FROM mini FINALreturns 2 rows whileSELECT count() FROM mini FINALreturns 0, and both become correct afterOPTIMIZE TABLE ... FINAL. Query-timeFINALapplies the zero-row-deletion rule over only the columns the query reads, so reading no columns drops every row.Failed to create any tablereproducer files. Roughly 75 percent of the PP job's runtime is wasted on every nightly. Restarting the server between oracles inci/jobs/sqlancer_pp_job.shrecovers it independently of the upstream fix, and item 4 notes the error must be pinned inClickHouseErrorsonce the fork starts generating that shape.Priorities
LimitRankingcap assertion (server-side)GROUPSframes, negative LIMIT, pipe operators, IEJoin, new statistics types, query condition cache poisoning, text index second wave, Tuple summing engines, sparse columns, comparison-chain rewrites,indexHint, mixed-direction sort keysNullable(Tuple), QBit,AT TIME ZONE, continuous queries and what-if indexesSuggested order (Appendix A): 0a and 0b, then item 1, then item 4 before item 3 (the view-in-join emission is the prerequisite for item 3's strongest positive control, ClickHouse/ClickHouse#111727), then items 2 and 11 together since they share a positive control, and item 15 early despite being P1 because it is S effort, changes no assertion, and lights up every existing pruning, count and FINAL oracle for free.
Method, and how to re-run it
qa_intelligence: merged, non-backport, non-cherry-pick, non-sync PRs in the window. 150new_feature, 58experimental, and the semantics-relevant subset of 468improvementplus 269performance. Both SQL queries are in the doc.src/sqlancer/clickhouse/**/*.javafor every setting name, clause, type and function the inventory names. An item only enters the plan if the sweep shows zero or clearly partial coverage, and each entry names the file that would have to change so the claim stays checkable.Scope discipline
Appendix B lists what was deliberately excluded and why, with volumes: AI functions, WASM UDFs, Web UI and terminal, Keeper, PromQL, Arrow Flight, data lakes, message queues, formats, backup, crash-durability and roughly 80 pure-performance PRs. Data lakes (8 open wrong-results) and message queues (6) are called out as the strongest candidates for a separate plan with an external fixture rather than gaps in this one.
Every one of the 179 referenced PRs and issues was verified via the GitHub API to exist and to use the correct
pullorissuespath.Every item inherits a 9-rule cross-cutting soundness checklist, which is this fork's accumulated false-positive ledger. Both prerequisite fixes are violations of rules that predate the checklist.