Skip to content

EXPLAIN SYNTAX: return a single record and default oneline to 1 - #107925

Closed
groeneai wants to merge 14 commits into
ClickHouse:masterfrom
groeneai:fix-80410-explain-syntax-single-record
Closed

EXPLAIN SYNTAX: return a single record and default oneline to 1#107925
groeneai wants to merge 14 commits into
ClickHouse:masterfrom
groeneai:fix-80410-explain-syntax-single-record

Conversation

@groeneai

@groeneai groeneai commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

Closes: #80410

Changelog category (leave one):

  • Backward Incompatible Change

Changelog entry (a user-readable short description of the changes that goes into CHANGELOG.md):

EXPLAIN SYNTAX now returns the reformatted query as a single String record instead of one record per line. The oneline option now defaults to 1, so the record is rendered on a single physical line. Set oneline = 0 to render that same single record across multiple lines (embedded newlines).

Description

Per the discussion on #80410, EXPLAIN SYNTAX always emits the whole reformatted query as a single String record (not one record per line), so the result is a recoverable single row and is directly usable (for example, SELECT count() FROM (EXPLAIN SYNTAX ...) returns 1). PLAN/PIPELINE/AST keep their per-line tree output.

The single-record shape is unconditional. The oneline option only controls how that one record is rendered: oneline = 1 (the new default) puts the whole query on one physical line; oneline = 0 spreads the same single record across multiple lines with embedded newlines. It does not restore the old N-row output.

This is a backward-incompatible change: existing EXPLAIN SYNTAX consumers see one row instead of N, and the default rendering is single-line. The default flip was explicitly requested by rschu1ze in the PR discussion. The affected stateless .reference files (including .oldanalyzer.reference variants) were regenerated for the new default.

@groeneai

Copy link
Copy Markdown
Collaborator Author

Pre-PR validation gate

# Question Answer
a Deterministic repro? Yes. SELECT count() FROM (EXPLAIN SYNTAX SELECT 1 FROM system.one WHERE 1 IN (0,1,2)) returns 3 (old, one row per line) vs 1 (new, single record), on demand.
b Root cause explained? InterpreterExplainQuery::executeImpl ran the formatted query buffer through fillColumn, which splits on \n and inserts one ColumnString row per line. The SYNTAX kind therefore produced many single-line records. The whole-buffer-as-one-record path already existed behind a flag (used by EXPLAIN PLAN ... json); SYNTAX simply did not set it.
c Fix matches root cause? Yes. Set that single-record flag for the AnalyzedSyntax (SYNTAX) kind so the buffer is inserted as one record instead of split per line. Renamed single_line to single_record (the SYNTAX buffer is multi-line but one record). No new code path.
d Test intent preserved / new tests added? Yes. Affected .reference files were regenerated; for 138/140 the change is a pure row-to-record collapse (verified: each file decodes byte-identically to the original after TSV-unescaping \n). The 2 exceptions still assert the same property they were written for. Added regression test 04338_explain_syntax_single_record asserting one record, embedded newlines, and that oneline still yields a single newline-free record.
e Both directions demonstrated? Yes. New test + a sample of regenerated tests FAIL on the unpatched binary (build id 49b52036) and PASS on the patched binary (build id 82dd3b8a). Full set: 135 changed/added tests pass in new-analyzer mode, 0 failures.
f Fix is general, not a narrow patch? Yes. The change is the requested behavior itself, scoped to the SYNTAX kind (both analyzer and legacy paths set the flag at the start of the case). PLAN/PIPELINE/AST/QUERY TREE intentionally keep one row per line, since their tree output is read/filtered row by row.

Session id: cron:clickhouse-worker-slot-1:20260618-235400

@groeneai

Copy link
Copy Markdown
Collaborator Author

cc @alexey-milovidov @KochetovNicolai — could you review this? It implements #80410: EXPLAIN SYNTAX now returns the reformatted query as a single multi-line record instead of one record per line. The code change reuses the existing single-record path in InterpreterExplainQuery (previously only used by EXPLAIN PLAN ... json) for the SYNTAX kind; the bulk of the diff is regenerated .reference files plus a regression test.

@alexey-milovidov alexey-milovidov added the can be tested Allows running workflows for external contributors label Jun 19, 2026
@alexey-milovidov

Copy link
Copy Markdown
Member

@groeneai, provide a setting to turn this behavior on/off. Make it one-line by default, but update the tests so that reference files don't change.

@groeneai
groeneai force-pushed the fix-80410-explain-syntax-single-record branch from 3f7a297 to f8c8598 Compare June 19, 2026 03:50
@clickhouse-gh

clickhouse-gh Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Workflow [PR], commit [c838bc5]

Summary:


AI Review

Summary

This PR changes EXPLAIN SYNTAX to always return a single String row, flips oneline to default to 1, and updates the affected docs, source-generated examples, regression coverage, and regenerated references. After checking the current diff against the prior discussion and thread history, I did not find any remaining correctness, compatibility, or evidence gaps that still need action in this PR.

Final Verdict
  • Status: ✅ Approve

@clickhouse-gh clickhouse-gh Bot added the pr-improvement Pull request with some product improvements label Jun 19, 2026
Comment thread src/Interpreters/InterpreterExplainQuery.cpp
@groeneai
groeneai force-pushed the fix-80410-explain-syntax-single-record branch from f8c8598 to 8449e86 Compare June 19, 2026 04:24
@groeneai groeneai changed the title EXPLAIN SYNTAX: return a single multi-line record Add single_record option to EXPLAIN SYNTAX Jun 19, 2026
@groeneai

Copy link
Copy Markdown
Collaborator Author

@alexey-milovidov done. Gated behind an EXPLAIN SYNTAX option single_record (sibling to oneline), off by default, so all reference files are unchanged.

  • Default: EXPLAIN SYNTAX SELECT ... returns one record per line (as before).
  • EXPLAIN SYNTAX single_record = 1 SELECT ... returns one multi-line record.

I made it an EXPLAIN-local option rather than a server setting, matching the existing oneline. Happy to switch it to a query-level setting instead if you prefer.

@groeneai

Copy link
Copy Markdown
Collaborator Author

Pre-PR validation gate

# Question Answer
a Deterministic repro? Yes. SELECT count() FROM (EXPLAIN SYNTAX SELECT 1 FROM system.one WHERE 1 IN (0,1,2)) returns >1 (default, one record per line); the same with EXPLAIN SYNTAX single_record = 1 ... returns 1 (single multi-line record). On demand.
b Root cause explained? Feature, not a bug. InterpreterExplainQuery::executeImpl runs the formatted buffer through fillColumn, which splits on \n into one record per line. The whole-buffer-as-one-record path already existed behind a flag (used by EXPLAIN PLAN ... json). The new single_record SYNTAX option routes the SYNTAX buffer through that path.
c Fix matches root cause / directive? Yes. Gated behind the single_record EXPLAIN SYNTAX option, default false. Default output (and every consuming .reference file) is unchanged, per the request to keep it one-line by default.
d Test intent preserved / new tests added? New test 04338_explain_syntax_single_record asserts both modes: default returns multiple records, single_record = 1 returns exactly one (with embedded newlines; zero newlines when combined with oneline = 1). No existing test was modified or weakened; verified existing EXPLAIN SYNTAX consumer tests still pass unchanged.
e Both directions demonstrated? Yes. Default mode: count() > 1. single_record = 1: count() = 1. Verified on the patched binary (Build ID f998f6d9...) under both analyzers; the new test passes 20/20 with randomization and 1/1 with enable_analyzer=0.
f Fix is general, not a narrow patch? Scoped to EXPLAIN SYNTAX exactly as requested. Other EXPLAIN kinds (PLAN, PIPELINE, AST, QUERY TREE) intentionally keep per-line rows. The in-function flag was renamed single_line -> single_record so the SYNTAX and PLAN json paths share one correctly-named flag.

Session id: cron:clickhouse-worker-slot-0:20260619-040100

Comment thread tests/queries/0_stateless/04338_explain_syntax_single_record.sql Outdated
@groeneai
groeneai force-pushed the fix-80410-explain-syntax-single-record branch from 8449e86 to 8b5ed2b Compare June 19, 2026 05:27
@groeneai

Copy link
Copy Markdown
Collaborator Author

CI fully finished on head 8b5ed2b9e9ac (the setting-gated redesign + no-random-settings tag drop). Triage of every non-green check:

  • Fast test: SUCCESS — the EXPLAIN SYNTAX consumer tests (04319-04337 optimize_limit_by/optimize_function_keys) that failed on the prior commit f8c85981 (the unconditional single-record approach) now pass. The behavior is gated behind the new single_record option, default off, so no .reference files change.
  • Stateless tests (amd_msan, WasmEdge, parallel, 1/2): FAILURE03518_alter_logical_race, a known flaky test (7 unrelated PRs in 7 days, 0 master, passes on rerun). It is @alexey-milovidov's deliberately-racy ALTER test from Add a test about a race condition in ALTERs #80416; the failure is a CPU-contention timing artifact, not an engine bug. Unrelated to this PR (which touches only src/Interpreters/InterpreterExplainQuery.cpp + docs + the new test).
  • Stress test (arm_asan_ubsan): FAILURELogical error: Not-ready Set is passed as the second argument for function 'in' (STID 0250-4e52), a chronic trunk bug tracked separately (6 master + 18 distinct PRs in 30d). Not caused by this PR.
  • BuzzHouse (amd_tsan): FAILURE — generic fuzzer timeout, tracked separately (Web UI: hide ", +Shift to run all" hint for a single query #107817).
  • CH Inc sync / Mergeable Check / PR: FAILURE — aggregator roll-ups reflecting the reds above; no independent failure.

No PR-caused failures. All reds are pre-existing flaky/trunk signatures unrelated to the EXPLAIN SYNTAX change.

@cv4g

cv4g commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

@groeneai Could you add one top-level output-format test for this as well? The existing subquery checks cover the row shape through viewExplain, but a direct FORMAT JSONEachRow case would make the user-visible behavior explicit. For example:

EXPLAIN SYNTAX single_record = 1 SELECT 1 FROM system.one WHERE 1 IN (0, 1, 2) FORMAT JSONEachRow;

with a reference like:

{"explain":"SELECT 1\nFROM system.one\nWHERE in(1, (0, 1, 2))"}

This asserts that single_record = 1 produces one result row containing escaped line feeds, rather than several rows.

@groeneai

Copy link
Copy Markdown
Collaborator Author

@cv4g Added a top-level FORMAT JSONEachRow case to 04338_explain_syntax_single_record (commit ebff1a0):

EXPLAIN SYNTAX single_record = 1 SELECT 1 FROM system.one WHERE dummy = 0 FORMAT JSONEachRow;
-- {"explain":"SELECT 1\nFROM system.one\nWHERE equals(dummy, 0)"}
EXPLAIN SYNTAX SELECT 1 FROM system.one WHERE dummy = 0 FORMAT JSONEachRow;
-- {"explain":"SELECT 1"} / {"explain":"FROM system.one"} / {"explain":"WHERE equals(dummy, 0)"}

This asserts directly that single_record = 1 returns one JSON row with \n-escaped line feeds, while the default returns one row per line.

One change from your example: the predicate is dummy = 0 instead of 1 IN (0, 1, 2). The old analyzer constant-folds 1 IN (0, 1, 2) away, so that exact text would differ between analyzers, and the test no longer carries no-random-settings (CI randomizes enable_analyzer). dummy = 0 is kept by both analyzers, so the reference is stable. Verified 50/50 with randomization, 30/30 with enable_analyzer=0, 50/50 randomization + enable_analyzer=0.

@groeneai

Copy link
Copy Markdown
Collaborator Author
Pre-PR validation gate (click to expand) — top-level JSONEachRow test add
# Question Answer
a Deterministic repro? Yes. clickhouse local -q "EXPLAIN SYNTAX single_record = 1 SELECT 1 FROM system.one WHERE dummy = 0 FORMAT JSONEachRow" deterministically returns one JSON row with \n-escaped newlines; without single_record it returns three rows.
b Root cause explained? N/A (no bug). This is an additive test requested by @cv4g to make the user-visible row shape explicit at the top level (existing assertions go through SELECT count() FROM (EXPLAIN SYNTAX ...) subqueries).
c Fix matches root cause? N/A (test coverage add, no code change). InterpreterExplainQuery.cpp and docs are unchanged from the reviewed PR.
d Test intent preserved / new tests added? Yes. All existing assertions are kept unchanged; two new top-level FORMAT JSONEachRow cases are appended (single_record=1 -> one row; default -> one row per line).
e Both directions demonstrated? Yes. single_record=1 -> exactly one JSON row containing \n; default -> three JSON rows, one per line. Both captured in the reference.
f Fix is general across code paths? N/A (no code bug).
g Fix generalizes across inputs? N/A (test-coverage add, not a code bug). Note: dummy = 0 chosen over 1 IN (0,1,2) because the old analyzer folds the latter away, which would make the exact-text reference analyzer-dependent; dummy = 0 is stable under randomized enable_analyzer.
h Backward compatible? N/A (test-only; no setting/format/validation change).
i Invariants and contracts preserved? N/A (test-only).

Validation: 50/50 with randomization, 30/30 with enable_analyzer=0, 50/50 randomization + enable_analyzer=0. Verified on a current-master binary (build id 023b1a2d, version 26.7.1.1, git hash 4c5ba5a) that use_lightweight_primary_key_index_analysis (added to master since the original PR) does not affect EXPLAIN SYNTAX output.

Session id: cron:clickhouse-worker-slot-1:20260630-164700

@groeneai

groeneai commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator Author

CI finish ledger — ebff1a0

Every failure below has an owner (a fixing PR). Only CH Inc sync is exempt. This PR adds an opt-in single_record display option to EXPLAIN SYNTAX (default off, zero reference churn), so it cannot cause any of the server-side/CI failures below.

Check / test Reason Owner / fixing PR
AST fuzzer (amd_debug) / Block structure mismatch (STID 0993-27f0) chronic trunk AST-fuzzer LOGICAL_ERROR (20 master / 176 PRs / 243 hits, 30d); UnionStep/IntersectOrExceptStep constant-fold #107719 (ours, open)
Stress test (arm_debug) / Inconsistent KeyCondition behavior (STID 5182-2f27) chronic trunk KeyCondition monotonicity canary (0 master / 21 PRs / 29 hits, 30d) #108011 (external, open)
Upgrade check (amd_release) / Error message in clickhouse-server.log benign background-mutation FUNCTION_THROW_IF_VALUE_IS_NON_ZERO left by stress tests, retried after upgrade restart (chronic; 34 such hits/7d across many PRs) #108651 (ours, open)
Mergeable Check / PR aggregator roll-ups of the reds above (derivative)
CH Inc sync private fork-sync mirror CH Inc sync (private, not actionable)

No PR-caused failures.

Session id: cron:our-pr-ci-monitor:20260701-000000

@rschu1ze

rschu1ze commented Jul 5, 2026

Copy link
Copy Markdown
Member

How is this different from existing SELECT EXPLAIN option oneline?

@groeneai

groeneai commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator Author

@rschu1ze They are orthogonal.

  • oneline reformats the SQL onto a single physical line (no line feeds). It happens to yield one row because there are no \n left to split on, but the multi-line pretty-printing is lost.
  • single_record keeps the multi-line pretty-printed text (with embedded \n) and returns it as one record, instead of splitting on \n into one row per line.

Same query with FORMAT JSONEachRow:

-- default (both off): N rows, one line each
{"explain":"SELECT 1"}
{"explain":"FROM system.one"}
{"explain":"WHERE in(1, (0, 1, 2))"}

-- oneline = 1: one row, but the query is squashed onto one line
{"explain":"SELECT 1 FROM system.one WHERE in(1, (0, 1, 2))"}

-- single_record = 1: one row, multi-line formatting preserved
{"explain":"SELECT 1\nFROM system.one\nWHERE in(1, (0, 1, 2))"}

-- single_record = 1, oneline = 1: one row, no newlines
{"explain":"SELECT 1 FROM system.one WHERE in(1, (0, 1, 2))"}

In short: oneline controls line wrapping of the SQL; single_record controls the result shape (1 row vs N rows) while keeping the readable multi-line form. They compose. oneline does not satisfy #80410 because it collapses the whole query onto one line, whereas the request is to keep the multi-line reformatted query but return it as a single record.

@rschu1ze

rschu1ze commented Jul 6, 2026

Copy link
Copy Markdown
Member

We are over-complicating this. We should rather keep EXPLAIN SYNTAX simple and dumb and its defaults reasonable.

@groeneai Do not introduce single_record. Instead, make oneline = 1 the default behavior. It should return one single multi-line record.

@groeneai

groeneai commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator Author

@rschu1ze Understood, simpler is better. One thing to align before I rework, because it collides with an earlier directive on this PR.

@alexey-milovidov asked (2026-06-19) to gate the single-multi-line-record behavior behind a setting, keep it off by default, and specifically so that no .reference files change. That is why this PR added the opt-in single_record and touched zero references.

Your ask is the opposite: make it the default and drop the extra option. Making a single multi-line record the default is a behavior change for EXPLAIN SYNTAX as a query source (SELECT count() FROM (EXPLAIN SYNTAX ...), line-filtering consumers) and will churn ~140 .reference files.

Also note oneline today squashes the query onto one physical line (drops the pretty-printing), so oneline = 1 does not by itself produce a multi-line record; repurposing it would change its meaning.

Which do you both want?

  1. Default ON (drop single_record, single multi-line record becomes the default, accept the ~140 reference updates), or
  2. alexey-milovidov's earlier gated/off-by-default approach (this PR as-is).

Happy to implement either immediately once you agree.

@rschu1ze

rschu1ze commented Jul 7, 2026

Copy link
Copy Markdown
Member

I want option 1.: Default ON (drop single_record, single multi-line record becomes the default, accept the ~140 reference updates).

@groeneai

groeneai commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator Author

@rschu1ze Ack, proceeding with option 1: dropping single_record, making the single multi-line record the default for EXPLAIN SYNTAX, and regenerating the affected reference files. oneline stays as-is (it squashes onto one physical line, different semantics).

@alexey-milovidov this reverses your 2026-06-19 request to gate it behind a setting with default off. If you disagree with defaulting it on, say so before I push the rework.

EXPLAIN SYNTAX now returns the reformatted query as one multi-line record
instead of one record per line, so the output is directly copy-pasteable
(issue ClickHouse#80410). PLAN/PIPELINE/AST keep their per-line tree output.

Regenerated the affected stateless .reference files (row-per-line to
single-record collapse) and updated 04338_explain_syntax_single_record
to assert the new default behavior.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
EXPLAIN SYNTAX now emits a single physical line by default (oneline=1).
The 02428_parameterized_view test is tagged `long`, so the earlier
reference regeneration (which ran with --no-long) missed it. Its lone
EXPLAIN SYNTAX output line was still in the old multi-line escaped form.
Regenerated to the single-line form; verified the full test passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@groeneai

groeneai commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator Author

Fixed a further oneline=1 reference regression: 02428_parameterized_view (tagged long, so it was skipped by the earlier --no-long reference regeneration). Its single EXPLAIN SYNTAX output line was still in the old multi-line escaped form; regenerated to the single-line form and verified the full test passes locally.

Comprehensive re-check: ran all 142 tests that use EXPLAIN SYNTAX against the oneline=1 binary and scanned every corresponding .reference — this was the only remaining stale one. The optimizer-test batch reported failing in the coverage 1/3 job (01029/01622/01623/... ) passes with the current references; those coverage-job reds were the coverage-region-quality instrumentation issue, not reference staleness.

…default

The oneline=1 EXPLAIN SYNTAX default (f3f2035) collapses multi-line
reformatted queries to a single physical line. Prior slots regenerated the
default .reference files but not the .oldanalyzer.reference variants used by
the old-analyzer CI jobs, causing Stateless coverage-job failures on 3e03fa6.

Regenerated all 28 stale .oldanalyzer.reference files (whitespace-insensitive
content identical to the old form; pure multi-line -> single-line reformat).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@groeneai

groeneai commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator Author

Regenerated the .oldanalyzer.reference variants that the oneline=1 default flip left stale (commit 0bd67ed). Prior fixes updated the default .reference files but not the .oldanalyzer.reference files consumed by the old-analyzer CI jobs, which is what the coverage-job result differs failures on 3e03fa6 were. 28 files, all pure multi-line to single-line reformat (whitespace-insensitive content identical, verified token-by-token). All affected tests pass locally against an old-analyzer server.

Comment thread tests/queries/0_stateless/02428_parameterized_view.sh Outdated
long drops these tests from every --no-long sweep (LLVM coverage etc.),
not just flaky-check. That side effect already bit this PR: 02428 was
skipped during the oneline=1 reference regeneration pass, so its stale
reference survived a CI round. The actual problem is only flaky-check's
per-run TOO_LONG gate, so no-flaky-check is the targeted tag.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment thread docs/en/sql-reference/statements/explain.md
@groeneai groeneai changed the title EXPLAIN SYNTAX: return a single multi-line record EXPLAIN SYNTAX: return a single record and default oneline to 1 Jul 8, 2026
@groeneai

groeneai commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator Author

CI finish ledger — 86e0df5

Every failure below has an owner (fixing PR or full-effort fix task). Only CH Inc sync is exempt.

Check / test Reason Owner / fixing PR
AST fuzzer (amd_debug, targeted) + (targeted, old_compatibility) / Block structure mismatch in UnionStep (STID 0993-27f0) chronic trunk logical error (14 master hits + ~12 unrelated PRs / 30d; this PR only touches EXPLAIN SYNTAX + test references, cannot produce a UnionStep block mismatch) #107719 (ours, open)
Performance Comparison (arm_release, master_head, 5/6) perf report-build noise (unstable queries; not PR-caused) a fix task is moved to pending (investigating at full effort; fixing-PR link to follow here)
Mergeable Check / PR rollup of the above owned via #107719 + the perf fix task

Session id: cron:our-pr-ci-monitor:20260708-110000

…yntax-single-record

# Conflicts:
#	tests/queries/0_stateless/02226_analyzer_or_like_combine.oldanalyzer.reference
#	tests/queries/0_stateless/02226_analyzer_or_like_combine.reference
@groeneai

Copy link
Copy Markdown
Collaborator Author

Merged master into the branch to resolve the conflict (head ce0c536). The only conflict was 02226_analyzer_or_like_combine (default + oldanalyzer references): master's optimize_or_like_chain rework and this PR's oneline = 1 EXPLAIN SYNTAX default both touched those files. Resolution: took master's references, then regenerated them against the merged binary so the EXPLAIN SYNTAX output is single-line; token-set comparison confirms every QUERY TREE node and SELECT result row is identical to master, only the EXPLAIN SYNTAX rendering collapses to one line. No submodule drift vs master.

@clickhouse-gh clickhouse-gh Bot added pr-backward-incompatible Pull request with backwards incompatible changes and removed pr-improvement Pull request with some product improvements labels Jul 13, 2026
@groeneai

Copy link
Copy Markdown
Collaborator Author

CI finish ledger — ce0c536

Every failure below has an owner: a fixing PR (ours), or the private sync (exempt).

Check / test Reason Owner / fixing PR
Stateless (amd_debug/amd_msan WasmEdge/amd_tsan/amd_tsan s3, sequential) / 02346_text_index_bug108519_qcc_skip_index flaky (randomized materialize_statistics_on_insert=True) #110260 (ours, merged 2026-07-13 15:05Z); this build predated it, merged master @ 2899fb4 to pick it up
Stateless (amd_tsan s3, sequential) / Scraping system tables infra (minio_audit_logs dump timeout on s3 configs) a fix task is moved to pending (investigating; fixing-PR link to follow here)
CH Inc sync - CH Inc sync (private, not actionable)

Session id: cron:our-pr-ci-monitor:20260713-183000

@groeneai

Copy link
Copy Markdown
Collaborator Author

Correction to the ledger above: the Scraping system tables / minio_audit_logs dump-timeout line has an existing fixing PR owner — #110099 (ours, open, info-only follow-up to merged #109837), not a new fix task.

Comment thread src/Interpreters/InterpreterExplainQuery.cpp
The oneline setting now defaults to 1, so EXPLAIN SYNTAX prints the reformatted
query on one physical line. The convert_query_to_cnf and optimize_syntax_fuse_functions
docstring examples intentionally show multi-line output, so opt them into oneline = 0.
The fuse example also used FORMAT TSV, which escapes the embedded newlines; switch it
to FORMAT TSVRaw so the shown multi-line block stays literal.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@clickhouse-gh

clickhouse-gh Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

LLVM Coverage Report

Metric Baseline Current Δ
Lines 85.80% 85.90% +0.10%
Functions 92.70% 92.70% +0.00%
Branches 78.00% 78.10% +0.10%

Changed lines: Changed C/C++ lines covered: 34/34 (100.00%) · Uncovered code

Full report · Diff report

@groeneai

Copy link
Copy Markdown
Collaborator Author

CI finish ledger — c838bc5

CI is fully green on this head (the docstring-example fix for the oneline=1 default). No failed checks, no failed tests. Only CH Inc sync is exempt.

Check / test Reason Owner / fixing PR
(no failures)
Sync CH Inc sync (private, not actionable)

Session id: cron:our-pr-ci-monitor:20260714-093000

@alexey-milovidov alexey-milovidov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not what I asked for.

I asked to output a pretty-printed query (multi-line) in a single result record.

@alexey-milovidov

Copy link
Copy Markdown
Member

This PR looks wasted due to conflicting requests. I will open another one.

@alexey-milovidov alexey-milovidov added the wasted Discussion went in a wrong direction label Jul 14, 2026
@alexey-milovidov

Copy link
Copy Markdown
Member

@rschu1ze

How is this different from existing SELECT EXPLAIN option oneline?

One-line controls pretty-printing query over multiple lines, while the single-record option fixes the idiosyncrasy about returning a single result value split into multiple records.

@groeneai

Copy link
Copy Markdown
Collaborator Author

@alexey-milovidov Understood, and agreed. The single-record shape was the right part; the default should have kept the multi-line pretty-printed rendering in that one record, not defaulted to oneline=1 (which is the orthogonal, pre-existing pretty-print toggle). Sorry for the churn from the conflicting guidance across the thread. Leaving this closed for your replacement PR; happy to help there if useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

can be tested Allows running workflows for external contributors pr-backward-incompatible Pull request with backwards incompatible changes wasted Discussion went in a wrong direction

Projects

None yet

Development

Successfully merging this pull request may close these issues.

EXPLAIN SYNTAX should return a single multi-line record instead of many single-line records

4 participants