From 848ba5469b4e1bdf24e66211725eea8b49cf48b9 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 31 Dec 2025 05:58:05 +0000 Subject: [PATCH 01/24] Fix INTERSECT/EXCEPT operator precedence in parser INTERSECT has higher precedence than EXCEPT in ClickHouse, so: - "a EXCEPT b INTERSECT c" parses as "a EXCEPT (b INTERSECT c)" - "a INTERSECT b EXCEPT c" parses as "(a INTERSECT b) EXCEPT c" EXCEPT is also left-associative, creating binary trees: - "a EXCEPT b EXCEPT c" becomes "((a) EXCEPT b) EXCEPT c" This fixes 10 tests in 02004_intersect_except_operators and 10 tests in 02004_intersect_except_distinct_operators. --- parser/parser.go | 111 +++++++++++++++--- .../metadata.json | 10 -- .../metadata.json | 12 +- 3 files changed, 98 insertions(+), 35 deletions(-) diff --git a/parser/parser.go b/parser/parser.go index 93ac4aa884..adb61f141b 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -260,17 +260,14 @@ func (p *Parser) parseSelectWithUnion() *ast.SelectWithUnionQuery { // Check if this is INTERSECT/EXCEPT that needs SelectIntersectExceptQuery wrapper // Only INTERSECT ALL and EXCEPT ALL are treated like UNION ALL (flattened into ExpressionList) if p.isIntersectExceptWithWrapper() { - intersectExcept := &ast.SelectIntersectExceptQuery{ - Position: p.current.Pos, - } - // Add first item - if firstWasParenthesized { - intersectExcept.Selects = append(intersectExcept.Selects, firstItem) - } else { - intersectExcept.Selects = append(intersectExcept.Selects, firstItem) - } + // Collect all operands and operators first, then apply precedence + // INTERSECT has higher precedence than EXCEPT + + // Start with first operand (statements list) and operators list + stmts := []ast.Statement{firstItem} + var ops []string - // Parse INTERSECT/EXCEPT clauses (those that need wrapper) + // Parse all INTERSECT/EXCEPT clauses and collect them for p.isIntersectExceptWithWrapper() { // Record the operator type var op string @@ -286,9 +283,10 @@ func (p *Parser) parseSelectWithUnion() *ast.SelectWithUnionQuery { op += " DISTINCT" p.nextToken() } - intersectExcept.Operators = append(intersectExcept.Operators, op) + ops = append(ops, op) // Parse the next select + var nextStmt ast.Statement if p.currentIs(token.LPAREN) { p.nextToken() // skip ( nested := p.parseSelectWithUnion() @@ -296,17 +294,21 @@ func (p *Parser) parseSelectWithUnion() *ast.SelectWithUnionQuery { break } p.expect(token.RPAREN) - intersectExcept.Selects = append(intersectExcept.Selects, nested) + nextStmt = nested } else { sel := p.parseSelect() if sel == nil { break } - intersectExcept.Selects = append(intersectExcept.Selects, sel) + nextStmt = sel } + stmts = append(stmts, nextStmt) } - query.Selects = append(query.Selects, intersectExcept) + // Now apply precedence: INTERSECT binds tighter than EXCEPT + result := buildIntersectExceptTree(stmts, ops) + + query.Selects = append(query.Selects, result) return query } @@ -382,6 +384,87 @@ func (p *Parser) isIntersectExceptWithWrapper() bool { return nextTok != token.ALL } +// isIntersectOp checks if the operator is an INTERSECT variant (not EXCEPT) +func isIntersectOp(op string) bool { + return op == "INTERSECT" || op == "INTERSECT DISTINCT" +} + +// buildIntersectExceptTree builds the AST tree respecting operator precedence. +// INTERSECT has higher precedence than EXCEPT, so: +// "a EXCEPT b INTERSECT c" becomes "a EXCEPT (b INTERSECT c)" +// "a INTERSECT b EXCEPT c" becomes "(a INTERSECT b) EXCEPT c" +// +// EXCEPT is left-associative and creates binary trees: +// "a EXCEPT b EXCEPT c" becomes "((a) EXCEPT b) EXCEPT c" +// +// stmts has n elements, ops has n-1 elements where ops[i] is the operator between stmts[i] and stmts[i+1] +func buildIntersectExceptTree(stmts []ast.Statement, ops []string) ast.Statement { + if len(stmts) == 1 { + return stmts[0] + } + + // First pass: group consecutive INTERSECT operations (higher precedence) + // Result will be a list of statements/groups connected by EXCEPT operators + var groups []ast.Statement + var exceptOps []string + + i := 0 + for i < len(stmts) { + // Start a new group with stmts[i] + groupStmts := []ast.Statement{stmts[i]} + var groupOps []string + + // Collect consecutive INTERSECTs - look at the operator AFTER the current statement + for i < len(ops) && isIntersectOp(ops[i]) { + groupOps = append(groupOps, ops[i]) + i++ + groupStmts = append(groupStmts, stmts[i]) + } + + // Create the group + var groupStmt ast.Statement + if len(groupStmts) == 1 { + // Single statement, no grouping needed + groupStmt = groupStmts[0] + } else { + // Multiple statements connected by INTERSECT + groupStmt = &ast.SelectIntersectExceptQuery{ + Selects: groupStmts, + Operators: groupOps, + } + } + groups = append(groups, groupStmt) + + // Check if there's an EXCEPT connecting to the next group + if i < len(ops) && !isIntersectOp(ops[i]) { + exceptOps = append(exceptOps, ops[i]) + i++ // Move past the EXCEPT operator to start next group + } else if i < len(stmts)-1 { + // No more operators but still have stmts - shouldn't happen with valid input + i++ + } else { + // We've processed all statements + break + } + } + + // Now all groups are connected by EXCEPT - build the final tree + if len(groups) == 1 { + return groups[0] + } + + // Build left-associative binary tree for EXCEPT operations + // "a EXCEPT b EXCEPT c" becomes "((a) EXCEPT b) EXCEPT c" + result := groups[0] + for j := 0; j < len(exceptOps); j++ { + result = &ast.SelectIntersectExceptQuery{ + Selects: []ast.Statement{result, groups[j+1]}, + Operators: []string{exceptOps[j]}, + } + } + return result +} + func (p *Parser) parseSelect() *ast.SelectQuery { sel := &ast.SelectQuery{ Position: p.current.Pos, diff --git a/parser/testdata/02004_intersect_except_distinct_operators/metadata.json b/parser/testdata/02004_intersect_except_distinct_operators/metadata.json index e7ce14b155..c80f910d88 100644 --- a/parser/testdata/02004_intersect_except_distinct_operators/metadata.json +++ b/parser/testdata/02004_intersect_except_distinct_operators/metadata.json @@ -1,19 +1,9 @@ { "explain_todo": { - "stmt10": true, - "stmt11": true, - "stmt12": true, - "stmt13": true, - "stmt14": true, - "stmt15": true, - "stmt16": true, - "stmt18": true, "stmt21": true, "stmt22": true, "stmt23": true, - "stmt26": true, "stmt27": true, - "stmt28": true, "stmt31": true, "stmt32": true, "stmt33": true, diff --git a/parser/testdata/02004_intersect_except_operators/metadata.json b/parser/testdata/02004_intersect_except_operators/metadata.json index c931f5643d..a064b0addd 100644 --- a/parser/testdata/02004_intersect_except_operators/metadata.json +++ b/parser/testdata/02004_intersect_except_operators/metadata.json @@ -1,17 +1,9 @@ { "explain_todo": { - "stmt10": true, - "stmt11": true, - "stmt12": true, - "stmt13": true, - "stmt14": true, - "stmt16": true, "stmt19": true, "stmt20": true, "stmt21": true, - "stmt24": true, "stmt25": true, - "stmt26": true, "stmt29": true, "stmt30": true, "stmt31": true, @@ -21,8 +13,6 @@ "stmt36": true, "stmt37": true, "stmt40": true, - "stmt43": true, - "stmt8": true, - "stmt9": true + "stmt43": true } } From 2dae8976f75f334e87a64d5a90706d55ccc2b2d5 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 31 Dec 2025 06:02:12 +0000 Subject: [PATCH 02/24] Add lambda alias support in WITH elements EXPLAIN output When a lambda is defined in a WITH clause like: WITH x -> x + 1 AS lambda SELECT lambda(1) The EXPLAIN AST output now correctly shows the alias: Function lambda (alias lambda) (children 1) This fixes 32 tests across multiple test files including: - 02343_analyzer_lambdas - 02344_analyzer_multiple_aliases_for_expression - 02366_explain_query_tree - 02378_analyzer_projection_names - 02388_analyzer_recursive_lambda - 02389_analyzer_nested_lambda - 03248_invalid_where - 03358_lambda_resolution_segfault_analyzer --- internal/explain/expressions.go | 2 ++ internal/explain/functions.go | 10 +++++++++- .../02343_analyzer_lambdas/metadata.json | 17 +---------------- .../metadata.json | 9 +-------- .../02366_explain_query_tree/metadata.json | 7 +------ .../metadata.json | 2 -- .../metadata.json | 2 +- .../02389_analyzer_nested_lambda/metadata.json | 5 ----- .../testdata/03248_invalid_where/metadata.json | 7 +------ .../metadata.json | 2 +- 10 files changed, 17 insertions(+), 46 deletions(-) diff --git a/internal/explain/expressions.go b/internal/explain/expressions.go index 66fe71efe9..7c9a12262f 100644 --- a/internal/explain/expressions.go +++ b/internal/explain/expressions.go @@ -645,6 +645,8 @@ func explainWithElement(sb *strings.Builder, n *ast.WithElement, indent string, } case *ast.FunctionCall: explainFunctionCallWithAlias(sb, e, n.Name, indent, depth) + case *ast.Lambda: + explainLambdaWithAlias(sb, e, n.Name, indent, depth) case *ast.BinaryExpr: // Binary expressions become functions fnName := OperatorToFunction(e.Op) diff --git a/internal/explain/functions.go b/internal/explain/functions.go index 26c4f74c93..ae04c6afa7 100644 --- a/internal/explain/functions.go +++ b/internal/explain/functions.go @@ -85,8 +85,16 @@ func windowSpecHasContent(w *ast.WindowSpec) bool { } func explainLambda(sb *strings.Builder, n *ast.Lambda, indent string, depth int) { + explainLambdaWithAlias(sb, n, "", indent, depth) +} + +func explainLambdaWithAlias(sb *strings.Builder, n *ast.Lambda, alias string, indent string, depth int) { // Lambda is represented as Function lambda with tuple of params and body - fmt.Fprintf(sb, "%sFunction lambda (children %d)\n", indent, 1) + if alias != "" { + fmt.Fprintf(sb, "%sFunction lambda (alias %s) (children %d)\n", indent, alias, 1) + } else { + fmt.Fprintf(sb, "%sFunction lambda (children %d)\n", indent, 1) + } fmt.Fprintf(sb, "%s ExpressionList (children %d)\n", indent, 2) // Parameters as tuple fmt.Fprintf(sb, "%s Function tuple (children %d)\n", indent, 1) diff --git a/parser/testdata/02343_analyzer_lambdas/metadata.json b/parser/testdata/02343_analyzer_lambdas/metadata.json index 59ef4fd24c..6536e85476 100644 --- a/parser/testdata/02343_analyzer_lambdas/metadata.json +++ b/parser/testdata/02343_analyzer_lambdas/metadata.json @@ -1,28 +1,13 @@ { "explain_todo": { - "stmt10": true, - "stmt13": true, "stmt14": true, - "stmt15": true, "stmt18": true, - "stmt23": true, - "stmt24": true, - "stmt26": true, - "stmt27": true, "stmt31": true, "stmt32": true, "stmt33": true, - "stmt35": true, "stmt37": true, "stmt38": true, - "stmt45": true, "stmt46": true, - "stmt47": true, - "stmt50": true, - "stmt51": true, - "stmt6": true, - "stmt7": true, - "stmt8": true, - "stmt9": true + "stmt47": true } } diff --git a/parser/testdata/02344_analyzer_multiple_aliases_for_expression/metadata.json b/parser/testdata/02344_analyzer_multiple_aliases_for_expression/metadata.json index 8d2abbbde4..0967ef424b 100644 --- a/parser/testdata/02344_analyzer_multiple_aliases_for_expression/metadata.json +++ b/parser/testdata/02344_analyzer_multiple_aliases_for_expression/metadata.json @@ -1,8 +1 @@ -{ - "explain_todo": { - "stmt12": true, - "stmt13": true, - "stmt14": true, - "stmt7": true - } -} +{} diff --git a/parser/testdata/02366_explain_query_tree/metadata.json b/parser/testdata/02366_explain_query_tree/metadata.json index 12e6b4f38d..0967ef424b 100644 --- a/parser/testdata/02366_explain_query_tree/metadata.json +++ b/parser/testdata/02366_explain_query_tree/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt15": true, - "stmt17": true - } -} +{} diff --git a/parser/testdata/02378_analyzer_projection_names/metadata.json b/parser/testdata/02378_analyzer_projection_names/metadata.json index 2112d876d5..c767200be5 100644 --- a/parser/testdata/02378_analyzer_projection_names/metadata.json +++ b/parser/testdata/02378_analyzer_projection_names/metadata.json @@ -5,8 +5,6 @@ "stmt109": true, "stmt113": true, "stmt117": true, - "stmt119": true, - "stmt121": true, "stmt125": true, "stmt133": true, "stmt141": true, diff --git a/parser/testdata/02388_analyzer_recursive_lambda/metadata.json b/parser/testdata/02388_analyzer_recursive_lambda/metadata.json index 47b9f27593..0967ef424b 100644 --- a/parser/testdata/02388_analyzer_recursive_lambda/metadata.json +++ b/parser/testdata/02388_analyzer_recursive_lambda/metadata.json @@ -1 +1 @@ -{"explain_todo":{"stmt2":true,"stmt3":true}} +{} diff --git a/parser/testdata/02389_analyzer_nested_lambda/metadata.json b/parser/testdata/02389_analyzer_nested_lambda/metadata.json index 0332477e32..28a683eda9 100644 --- a/parser/testdata/02389_analyzer_nested_lambda/metadata.json +++ b/parser/testdata/02389_analyzer_nested_lambda/metadata.json @@ -1,10 +1,5 @@ { "explain_todo": { - "stmt21": true, - "stmt23": true, - "stmt52": true, - "stmt54": true, - "stmt56": true, "stmt58": true } } diff --git a/parser/testdata/03248_invalid_where/metadata.json b/parser/testdata/03248_invalid_where/metadata.json index 682bda1cbc..0967ef424b 100644 --- a/parser/testdata/03248_invalid_where/metadata.json +++ b/parser/testdata/03248_invalid_where/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt1": true, - "stmt2": true - } -} +{} diff --git a/parser/testdata/03358_lambda_resolution_segfault_analyzer/metadata.json b/parser/testdata/03358_lambda_resolution_segfault_analyzer/metadata.json index af48d4c110..0967ef424b 100644 --- a/parser/testdata/03358_lambda_resolution_segfault_analyzer/metadata.json +++ b/parser/testdata/03358_lambda_resolution_segfault_analyzer/metadata.json @@ -1 +1 @@ -{"explain_todo":{"stmt2":true}} +{} From 810d6922eff747829a4e83754a0c3e3bfb70cd5e Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 31 Dec 2025 06:09:04 +0000 Subject: [PATCH 03/24] Add lambda alias support in AliasedExpr EXPLAIN output When a lambda has an inline alias like: arrayMap((x -> toString(x)) as lambda, [1,2,3]) The EXPLAIN AST output now correctly shows the alias: Function lambda (alias lambda) (children 1) This fixes 9 more tests across: - 02343_analyzer_lambdas - 02378_analyzer_projection_names - 02389_analyzer_nested_lambda - 03101_analyzer_identifiers_2 --- internal/explain/expressions.go | 3 +++ parser/testdata/02343_analyzer_lambdas/metadata.json | 2 -- .../testdata/02378_analyzer_projection_names/metadata.json | 5 ----- parser/testdata/02389_analyzer_nested_lambda/metadata.json | 6 +----- parser/testdata/03101_analyzer_identifiers_2/metadata.json | 6 +----- 5 files changed, 5 insertions(+), 17 deletions(-) diff --git a/internal/explain/expressions.go b/internal/explain/expressions.go index 7c9a12262f..7aa8c3f97c 100644 --- a/internal/explain/expressions.go +++ b/internal/explain/expressions.go @@ -489,6 +489,9 @@ func explainAliasedExpr(sb *strings.Builder, n *ast.AliasedExpr, depth int) { case *ast.FunctionCall: // Function calls already handle aliases explainFunctionCallWithAlias(sb, e, n.Alias, indent, depth) + case *ast.Lambda: + // Lambda expressions with alias + explainLambdaWithAlias(sb, e, n.Alias, indent, depth) case *ast.Identifier: // Identifiers with alias fmt.Fprintf(sb, "%sIdentifier %s (alias %s)\n", indent, e.Name(), escapeAlias(n.Alias)) diff --git a/parser/testdata/02343_analyzer_lambdas/metadata.json b/parser/testdata/02343_analyzer_lambdas/metadata.json index 6536e85476..840514b0bb 100644 --- a/parser/testdata/02343_analyzer_lambdas/metadata.json +++ b/parser/testdata/02343_analyzer_lambdas/metadata.json @@ -1,7 +1,5 @@ { "explain_todo": { - "stmt14": true, - "stmt18": true, "stmt31": true, "stmt32": true, "stmt33": true, diff --git a/parser/testdata/02378_analyzer_projection_names/metadata.json b/parser/testdata/02378_analyzer_projection_names/metadata.json index c767200be5..f40cb4ffb8 100644 --- a/parser/testdata/02378_analyzer_projection_names/metadata.json +++ b/parser/testdata/02378_analyzer_projection_names/metadata.json @@ -3,11 +3,6 @@ "stmt101": true, "stmt105": true, "stmt109": true, - "stmt113": true, - "stmt117": true, - "stmt125": true, - "stmt133": true, - "stmt141": true, "stmt185": true, "stmt207": true, "stmt215": true, diff --git a/parser/testdata/02389_analyzer_nested_lambda/metadata.json b/parser/testdata/02389_analyzer_nested_lambda/metadata.json index 28a683eda9..0967ef424b 100644 --- a/parser/testdata/02389_analyzer_nested_lambda/metadata.json +++ b/parser/testdata/02389_analyzer_nested_lambda/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt58": true - } -} +{} diff --git a/parser/testdata/03101_analyzer_identifiers_2/metadata.json b/parser/testdata/03101_analyzer_identifiers_2/metadata.json index 95cd2c2b48..0967ef424b 100644 --- a/parser/testdata/03101_analyzer_identifiers_2/metadata.json +++ b/parser/testdata/03101_analyzer_identifiers_2/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt42": true - } -} +{} From 61a44f5b7e01571f483d02f146ad408211ccfc75 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 31 Dec 2025 06:25:21 +0000 Subject: [PATCH 04/24] Fix nested array literal formatting in EXPLAIN output Previously nested arrays with single-element arrays were rendered as Function array format, but they should be Literal format. Conversely, nested arrays containing tuples or empty arrays at any depth should use Function array format. Added recursive checks for empty arrays and tuples at any nesting depth to properly determine the correct EXPLAIN AST format. Fixes 33 test files with updated metadata. --- internal/explain/expressions.go | 73 ++++++++++++++----- .../00040_array_enumerate_uniq/metadata.json | 2 +- .../00343_array_element_generic/metadata.json | 7 +- .../metadata.json | 6 +- .../00500_point_in_polygon/metadata.json | 14 +--- .../metadata.json | 6 +- .../metadata.json | 6 +- .../00666_uniq_complex_types/metadata.json | 2 +- .../00672_arrayDistinct/metadata.json | 2 +- .../00691_array_distinct/metadata.json | 2 +- .../00710_array_enumerate_dense/metadata.json | 2 +- .../metadata.json | 7 +- .../00810_in_operators_segfault/metadata.json | 2 +- parser/testdata/00897_flatten/metadata.json | 2 +- .../00909_arrayEnumerateUniq/metadata.json | 3 - .../metadata.json | 8 +- .../00921_datetime64_basic/metadata.json | 6 +- .../metadata.json | 6 +- parser/testdata/01300_svg/metadata.json | 8 +- parser/testdata/01300_wkt/metadata.json | 6 +- .../01602_array_aggregation/metadata.json | 4 +- .../01763_filter_push_down_bugs/metadata.json | 6 +- .../01798_uniq_theta_sketch/metadata.json | 1 - .../02013_bloom_filter_hasAll/metadata.json | 7 +- .../02374_analyzer_array_join/metadata.json | 6 +- .../metadata.json | 17 +---- .../metadata.json | 4 - .../metadata.json | 2 +- .../02845_arrayShiftRotate/metadata.json | 2 +- .../metadata.json | 9 +-- .../metadata.json | 2 +- .../03240_array_element_or_null/metadata.json | 2 - .../03268_nested_analyzer/metadata.json | 9 +-- .../metadata.json | 6 +- .../testdata/03538_array_except/metadata.json | 1 - 35 files changed, 88 insertions(+), 160 deletions(-) diff --git a/internal/explain/expressions.go b/internal/explain/expressions.go index 7aa8c3f97c..dc436dc0a9 100644 --- a/internal/explain/expressions.go +++ b/internal/explain/expressions.go @@ -114,11 +114,9 @@ func explainLiteral(sb *strings.Builder, n *ast.Literal, indent string, depth in // This happens when: // 1. Contains non-literal, non-negation expressions OR // 2. Contains tuples OR - // 3. Contains nested arrays that all have exactly 1 element (homogeneous single-element arrays) OR - // 4. Contains nested arrays with non-literal expressions OR - // 5. Contains nested arrays that are empty or contain tuples/non-literals + // 3. Contains nested arrays with non-literal expressions OR + // 4. Contains nested arrays that are empty or contain tuples/non-literals shouldUseFunctionArray := false - allAreSingleElementArrays := true hasNestedArrays := false nestedArraysNeedFunctionFormat := false @@ -126,24 +124,18 @@ func explainLiteral(sb *strings.Builder, n *ast.Literal, indent string, depth in if lit, ok := e.(*ast.Literal); ok { if lit.Type == ast.LiteralArray { hasNestedArrays = true - // Check if this inner array has exactly 1 element + // Check if inner array needs Function array format: + // - Contains non-literal expressions OR + // - Contains tuples OR + // - Is empty OR + // - Contains empty arrays if innerExprs, ok := lit.Value.([]ast.Expression); ok { - if len(innerExprs) != 1 { - allAreSingleElementArrays = false - } - // Check if inner array needs Function array format: - // - Contains non-literal expressions OR - // - Contains tuples OR - // - Is empty OR - // - Contains empty arrays if containsNonLiteralExpressions(innerExprs) || len(innerExprs) == 0 || containsTuples(innerExprs) || containsEmptyArrays(innerExprs) { nestedArraysNeedFunctionFormat = true } - } else { - allAreSingleElementArrays = false } } else if lit.Type == ast.LiteralTuple { // Tuples are complex @@ -155,9 +147,17 @@ func explainLiteral(sb *strings.Builder, n *ast.Literal, indent string, depth in } // Use Function array when: - // - nested arrays that are ALL single-element - // - nested arrays that need Function format (contain non-literals, tuples, or empty arrays) - if hasNestedArrays && (allAreSingleElementArrays || nestedArraysNeedFunctionFormat) { + // - nested arrays that need Function format (contain non-literals, tuples, or empty arrays at any depth) + // Note: nested arrays that are ALL single-element should still be Literal format + if hasNestedArrays && nestedArraysNeedFunctionFormat { + shouldUseFunctionArray = true + } + // Also check for empty arrays at any depth within nested arrays + if hasNestedArrays && containsEmptyArraysRecursive(exprs) { + shouldUseFunctionArray = true + } + // Also check for tuples at any depth within nested arrays + if hasNestedArrays && containsTuplesRecursive(exprs) { shouldUseFunctionArray = true } @@ -249,6 +249,43 @@ func containsEmptyArrays(exprs []ast.Expression) bool { return false } +// containsEmptyArraysRecursive checks if any nested array at any depth is empty +func containsEmptyArraysRecursive(exprs []ast.Expression) bool { + for _, e := range exprs { + if lit, ok := e.(*ast.Literal); ok && lit.Type == ast.LiteralArray { + if innerExprs, ok := lit.Value.([]ast.Expression); ok { + if len(innerExprs) == 0 { + return true + } + // Recursively check nested arrays + if containsEmptyArraysRecursive(innerExprs) { + return true + } + } + } + } + return false +} + +// containsTuplesRecursive checks if any nested array contains tuples at any depth +func containsTuplesRecursive(exprs []ast.Expression) bool { + for _, e := range exprs { + if lit, ok := e.(*ast.Literal); ok { + if lit.Type == ast.LiteralTuple { + return true + } + if lit.Type == ast.LiteralArray { + if innerExprs, ok := lit.Value.([]ast.Expression); ok { + if containsTuplesRecursive(innerExprs) { + return true + } + } + } + } + } + return false +} + func explainBinaryExpr(sb *strings.Builder, n *ast.BinaryExpr, indent string, depth int) { // Convert operator to function name fnName := OperatorToFunction(n.Op) diff --git a/parser/testdata/00040_array_enumerate_uniq/metadata.json b/parser/testdata/00040_array_enumerate_uniq/metadata.json index af48d4c110..0967ef424b 100644 --- a/parser/testdata/00040_array_enumerate_uniq/metadata.json +++ b/parser/testdata/00040_array_enumerate_uniq/metadata.json @@ -1 +1 @@ -{"explain_todo":{"stmt2":true}} +{} diff --git a/parser/testdata/00343_array_element_generic/metadata.json b/parser/testdata/00343_array_element_generic/metadata.json index a8cc0be153..0967ef424b 100644 --- a/parser/testdata/00343_array_element_generic/metadata.json +++ b/parser/testdata/00343_array_element_generic/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt18": true, - "stmt19": true - } -} +{} diff --git a/parser/testdata/00461_default_value_of_argument_type/metadata.json b/parser/testdata/00461_default_value_of_argument_type/metadata.json index e9d6e46171..0967ef424b 100644 --- a/parser/testdata/00461_default_value_of_argument_type/metadata.json +++ b/parser/testdata/00461_default_value_of_argument_type/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt1": true - } -} +{} diff --git a/parser/testdata/00500_point_in_polygon/metadata.json b/parser/testdata/00500_point_in_polygon/metadata.json index 228d093b11..0967ef424b 100644 --- a/parser/testdata/00500_point_in_polygon/metadata.json +++ b/parser/testdata/00500_point_in_polygon/metadata.json @@ -1,13 +1 @@ -{ - "explain_todo": { - "stmt58": true, - "stmt59": true, - "stmt60": true, - "stmt61": true, - "stmt62": true, - "stmt63": true, - "stmt64": true, - "stmt66": true, - "stmt67": true - } -} +{} diff --git a/parser/testdata/00500_point_in_polygon_3d_const/metadata.json b/parser/testdata/00500_point_in_polygon_3d_const/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/00500_point_in_polygon_3d_const/metadata.json +++ b/parser/testdata/00500_point_in_polygon_3d_const/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} diff --git a/parser/testdata/00500_point_in_polygon_empty_bound/metadata.json b/parser/testdata/00500_point_in_polygon_empty_bound/metadata.json index 8c6a18d871..0967ef424b 100644 --- a/parser/testdata/00500_point_in_polygon_empty_bound/metadata.json +++ b/parser/testdata/00500_point_in_polygon_empty_bound/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt19": true - } -} +{} diff --git a/parser/testdata/00666_uniq_complex_types/metadata.json b/parser/testdata/00666_uniq_complex_types/metadata.json index f906fff0c1..0967ef424b 100644 --- a/parser/testdata/00666_uniq_complex_types/metadata.json +++ b/parser/testdata/00666_uniq_complex_types/metadata.json @@ -1 +1 @@ -{"explain_todo":{"stmt11":true,"stmt2":true,"stmt20":true}} +{} diff --git a/parser/testdata/00672_arrayDistinct/metadata.json b/parser/testdata/00672_arrayDistinct/metadata.json index 38be741ab9..0967ef424b 100644 --- a/parser/testdata/00672_arrayDistinct/metadata.json +++ b/parser/testdata/00672_arrayDistinct/metadata.json @@ -1 +1 @@ -{"explain_todo":{"stmt13":true}} +{} diff --git a/parser/testdata/00691_array_distinct/metadata.json b/parser/testdata/00691_array_distinct/metadata.json index 2bca590175..0967ef424b 100644 --- a/parser/testdata/00691_array_distinct/metadata.json +++ b/parser/testdata/00691_array_distinct/metadata.json @@ -1 +1 @@ -{"explain_todo":{"stmt2":true,"stmt7":true}} +{} diff --git a/parser/testdata/00710_array_enumerate_dense/metadata.json b/parser/testdata/00710_array_enumerate_dense/metadata.json index af48d4c110..0967ef424b 100644 --- a/parser/testdata/00710_array_enumerate_dense/metadata.json +++ b/parser/testdata/00710_array_enumerate_dense/metadata.json @@ -1 +1 @@ -{"explain_todo":{"stmt2":true}} +{} diff --git a/parser/testdata/00720_combinations_of_aggregate_combinators/metadata.json b/parser/testdata/00720_combinations_of_aggregate_combinators/metadata.json index 04dec16ad7..0967ef424b 100644 --- a/parser/testdata/00720_combinations_of_aggregate_combinators/metadata.json +++ b/parser/testdata/00720_combinations_of_aggregate_combinators/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt1": true, - "stmt5": true - } -} +{} diff --git a/parser/testdata/00810_in_operators_segfault/metadata.json b/parser/testdata/00810_in_operators_segfault/metadata.json index cc2f3624ef..0967ef424b 100644 --- a/parser/testdata/00810_in_operators_segfault/metadata.json +++ b/parser/testdata/00810_in_operators_segfault/metadata.json @@ -1 +1 @@ -{"explain_todo":{"stmt4":true}} +{} diff --git a/parser/testdata/00897_flatten/metadata.json b/parser/testdata/00897_flatten/metadata.json index af48d4c110..0967ef424b 100644 --- a/parser/testdata/00897_flatten/metadata.json +++ b/parser/testdata/00897_flatten/metadata.json @@ -1 +1 @@ -{"explain_todo":{"stmt2":true}} +{} diff --git a/parser/testdata/00909_arrayEnumerateUniq/metadata.json b/parser/testdata/00909_arrayEnumerateUniq/metadata.json index cca3c6d013..86cdcaaf99 100644 --- a/parser/testdata/00909_arrayEnumerateUniq/metadata.json +++ b/parser/testdata/00909_arrayEnumerateUniq/metadata.json @@ -1,11 +1,8 @@ { "explain_todo": { - "stmt144": true, - "stmt155": true, "stmt163": true, "stmt167": true, "stmt171": true, - "stmt177": true, "stmt179": true, "stmt181": true, "stmt183": true, diff --git a/parser/testdata/00918_has_unsufficient_type_check/metadata.json b/parser/testdata/00918_has_unsufficient_type_check/metadata.json index f7c9a031b3..0967ef424b 100644 --- a/parser/testdata/00918_has_unsufficient_type_check/metadata.json +++ b/parser/testdata/00918_has_unsufficient_type_check/metadata.json @@ -1,7 +1 @@ -{ - "explain_todo": { - "stmt1": true, - "stmt2": true, - "stmt3": true - } -} +{} diff --git a/parser/testdata/00921_datetime64_basic/metadata.json b/parser/testdata/00921_datetime64_basic/metadata.json index b698d0f1a2..b65b07d7a6 100644 --- a/parser/testdata/00921_datetime64_basic/metadata.json +++ b/parser/testdata/00921_datetime64_basic/metadata.json @@ -1 +1,5 @@ -{"explain_todo":{"stmt4":true,"stmt8":true}} +{ + "explain_todo": { + "stmt4": true + } +} diff --git a/parser/testdata/00982_array_enumerate_uniq_ranked/metadata.json b/parser/testdata/00982_array_enumerate_uniq_ranked/metadata.json index e9d6e46171..0967ef424b 100644 --- a/parser/testdata/00982_array_enumerate_uniq_ranked/metadata.json +++ b/parser/testdata/00982_array_enumerate_uniq_ranked/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt1": true - } -} +{} diff --git a/parser/testdata/01300_svg/metadata.json b/parser/testdata/01300_svg/metadata.json index fc382c3a82..0967ef424b 100644 --- a/parser/testdata/01300_svg/metadata.json +++ b/parser/testdata/01300_svg/metadata.json @@ -1,7 +1 @@ -{ - "explain_todo": { - "stmt4": true, - "stmt43": true, - "stmt8": true - } -} +{} diff --git a/parser/testdata/01300_wkt/metadata.json b/parser/testdata/01300_wkt/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/01300_wkt/metadata.json +++ b/parser/testdata/01300_wkt/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} diff --git a/parser/testdata/01602_array_aggregation/metadata.json b/parser/testdata/01602_array_aggregation/metadata.json index e142bef2c6..8dae11f1e5 100644 --- a/parser/testdata/01602_array_aggregation/metadata.json +++ b/parser/testdata/01602_array_aggregation/metadata.json @@ -3,8 +3,6 @@ "stmt32": true, "stmt33": true, "stmt34": true, - "stmt35": true, - "stmt6": true, - "stmt8": true + "stmt35": true } } diff --git a/parser/testdata/01763_filter_push_down_bugs/metadata.json b/parser/testdata/01763_filter_push_down_bugs/metadata.json index 3a06a4a1ac..0967ef424b 100644 --- a/parser/testdata/01763_filter_push_down_bugs/metadata.json +++ b/parser/testdata/01763_filter_push_down_bugs/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt5": true - } -} +{} diff --git a/parser/testdata/01798_uniq_theta_sketch/metadata.json b/parser/testdata/01798_uniq_theta_sketch/metadata.json index 0650450927..30faaf592d 100644 --- a/parser/testdata/01798_uniq_theta_sketch/metadata.json +++ b/parser/testdata/01798_uniq_theta_sketch/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt15": true, "stmt64": true } } diff --git a/parser/testdata/02013_bloom_filter_hasAll/metadata.json b/parser/testdata/02013_bloom_filter_hasAll/metadata.json index 6dc0aa1ce2..0967ef424b 100644 --- a/parser/testdata/02013_bloom_filter_hasAll/metadata.json +++ b/parser/testdata/02013_bloom_filter_hasAll/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt17": true, - "stmt7": true - } -} +{} diff --git a/parser/testdata/02374_analyzer_array_join/metadata.json b/parser/testdata/02374_analyzer_array_join/metadata.json index fec152526a..0967ef424b 100644 --- a/parser/testdata/02374_analyzer_array_join/metadata.json +++ b/parser/testdata/02374_analyzer_array_join/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt32": true - } -} +{} diff --git a/parser/testdata/02383_array_signed_const_positive_index/metadata.json b/parser/testdata/02383_array_signed_const_positive_index/metadata.json index a80b1aaaf4..0967ef424b 100644 --- a/parser/testdata/02383_array_signed_const_positive_index/metadata.json +++ b/parser/testdata/02383_array_signed_const_positive_index/metadata.json @@ -1,16 +1 @@ -{ - "explain_todo": { - "stmt1": true, - "stmt10": true, - "stmt13": true, - "stmt14": true, - "stmt17": true, - "stmt18": true, - "stmt2": true, - "stmt21": true, - "stmt22": true, - "stmt5": true, - "stmt6": true, - "stmt9": true - } -} +{} diff --git a/parser/testdata/02423_multidimensional_array_get_data_at/metadata.json b/parser/testdata/02423_multidimensional_array_get_data_at/metadata.json index 629001958f..8b0256d0ad 100644 --- a/parser/testdata/02423_multidimensional_array_get_data_at/metadata.json +++ b/parser/testdata/02423_multidimensional_array_get_data_at/metadata.json @@ -1,10 +1,6 @@ { "explain_todo": { - "stmt1": true, - "stmt3": true, "stmt4": true, - "stmt5": true, - "stmt6": true, "stmt7": true } } diff --git a/parser/testdata/02429_combinators_in_array_reduce/metadata.json b/parser/testdata/02429_combinators_in_array_reduce/metadata.json index b9f2bf602f..0967ef424b 100644 --- a/parser/testdata/02429_combinators_in_array_reduce/metadata.json +++ b/parser/testdata/02429_combinators_in_array_reduce/metadata.json @@ -1 +1 @@ -{"explain_todo":{"stmt2":true,"stmt5":true}} +{} diff --git a/parser/testdata/02845_arrayShiftRotate/metadata.json b/parser/testdata/02845_arrayShiftRotate/metadata.json index 7e77be4952..0967ef424b 100644 --- a/parser/testdata/02845_arrayShiftRotate/metadata.json +++ b/parser/testdata/02845_arrayShiftRotate/metadata.json @@ -1 +1 @@ -{"explain_todo":{"stmt68":true}} +{} diff --git a/parser/testdata/02883_array_scalar_mult_div_modulo/metadata.json b/parser/testdata/02883_array_scalar_mult_div_modulo/metadata.json index daf05a4474..0967ef424b 100644 --- a/parser/testdata/02883_array_scalar_mult_div_modulo/metadata.json +++ b/parser/testdata/02883_array_scalar_mult_div_modulo/metadata.json @@ -1,8 +1 @@ -{ - "explain_todo": { - "stmt10": true, - "stmt11": true, - "stmt8": true, - "stmt9": true - } -} +{} diff --git a/parser/testdata/03216_arrayWithConstant_limits/metadata.json b/parser/testdata/03216_arrayWithConstant_limits/metadata.json index 47b9f27593..0967ef424b 100644 --- a/parser/testdata/03216_arrayWithConstant_limits/metadata.json +++ b/parser/testdata/03216_arrayWithConstant_limits/metadata.json @@ -1 +1 @@ -{"explain_todo":{"stmt2":true,"stmt3":true}} +{} diff --git a/parser/testdata/03240_array_element_or_null/metadata.json b/parser/testdata/03240_array_element_or_null/metadata.json index fca2d22030..60e53ef924 100644 --- a/parser/testdata/03240_array_element_or_null/metadata.json +++ b/parser/testdata/03240_array_element_or_null/metadata.json @@ -1,7 +1,5 @@ { "explain_todo": { - "stmt40": true, - "stmt41": true, "stmt45": true, "stmt47": true } diff --git a/parser/testdata/03268_nested_analyzer/metadata.json b/parser/testdata/03268_nested_analyzer/metadata.json index 83d6471bd9..0967ef424b 100644 --- a/parser/testdata/03268_nested_analyzer/metadata.json +++ b/parser/testdata/03268_nested_analyzer/metadata.json @@ -1,8 +1 @@ -{ - "explain_todo": { - "stmt10": true, - "stmt6": true, - "stmt8": true, - "stmt9": true - } -} +{} diff --git a/parser/testdata/03285_analyzer_array_join_nested/metadata.json b/parser/testdata/03285_analyzer_array_join_nested/metadata.json index 7ad5569408..0967ef424b 100644 --- a/parser/testdata/03285_analyzer_array_join_nested/metadata.json +++ b/parser/testdata/03285_analyzer_array_join_nested/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt9": true - } -} +{} diff --git a/parser/testdata/03538_array_except/metadata.json b/parser/testdata/03538_array_except/metadata.json index 99b2a0c4b1..ad55ed3111 100644 --- a/parser/testdata/03538_array_except/metadata.json +++ b/parser/testdata/03538_array_except/metadata.json @@ -2,7 +2,6 @@ "explain_todo": { "stmt10": true, "stmt11": true, - "stmt21": true, "stmt30": true } } From ec74bfb78e0faf278e05a17d4b66aa7c298db7a3 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 31 Dec 2025 06:33:36 +0000 Subject: [PATCH 05/24] Parse table options after AS clause in CREATE TABLE The CREATE TABLE ... AS other_table ENGINE=... syntax wasn't parsing PARTITION BY, ORDER BY, SAMPLE BY, or SETTINGS clauses after the ENGINE specification. Refactored table options parsing into parseTableOptions function and call it after AS clause ENGINE parsing. Fixes 14 test files with CREATE TABLE AS syntax. --- parser/parser.go | 87 ++++++++++--------- .../00061_storage_buffer/metadata.json | 6 +- .../00157_cache_dictionary/metadata.json | 6 +- .../00643_cast_zookeeper_long/metadata.json | 6 +- .../metadata.json | 2 - .../metadata.json | 9 +- .../metadata.json | 7 +- .../metadata.json | 1 - .../metadata.json | 7 +- .../metadata.json | 6 +- .../metadata.json | 3 +- .../metadata.json | 6 +- .../metadata.json | 3 +- .../metadata.json | 6 +- 14 files changed, 58 insertions(+), 97 deletions(-) diff --git a/parser/parser.go b/parser/parser.go index adb61f141b..a3283e3c0e 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -1686,6 +1686,52 @@ func (p *Parser) parseCreateTable(create *ast.CreateQuery) { } // Parse table options in flexible order (PARTITION BY, ORDER BY, PRIMARY KEY, etc.) + p.parseTableOptions(create) + + // Parse AS SELECT or AS (subquery) or AS table_function() or AS database.table + if p.currentIs(token.AS) { + p.nextToken() + if p.currentIs(token.SELECT) || p.currentIs(token.WITH) || p.currentIs(token.LPAREN) { + // AS SELECT... or AS (SELECT...) INTERSECT ... + create.AsSelect = p.parseSelectWithUnion() + } else if p.currentIs(token.IDENT) || p.current.Token.IsKeyword() { + // AS table_function(...) or AS database.table + name := p.parseIdentifierName() + if p.currentIs(token.DOT) { + // AS database.table - skip the table name + p.nextToken() + p.parseIdentifierName() + } else if p.currentIs(token.LPAREN) { + // AS function(...) - parse as a function call + fn := &ast.FunctionCall{Name: name} + p.nextToken() // skip ( + if !p.currentIs(token.RPAREN) { + fn.Arguments = p.parseExpressionList() + } + if p.currentIs(token.RPAREN) { + p.nextToken() + } + create.AsTableFunction = fn + } + _ = name // Use name for future AS table support + } + } + + // Parse ENGINE after AS (for CREATE TABLE x AS y ENGINE=z syntax) + if create.Engine == nil && p.currentIs(token.ENGINE) { + p.nextToken() + if p.currentIs(token.EQ) { + p.nextToken() + } + create.Engine = p.parseEngineClause() + } + + // Parse table options after AS ... ENGINE (PARTITION BY, ORDER BY, etc.) + p.parseTableOptions(create) +} + +// parseTableOptions parses table options: PARTITION BY, ORDER BY, PRIMARY KEY, SAMPLE BY, TTL, SETTINGS +func (p *Parser) parseTableOptions(create *ast.CreateQuery) { for { switch { case p.currentIs(token.PARTITION): @@ -1793,47 +1839,8 @@ func (p *Parser) parseCreateTable(create *ast.CreateQuery) { p.nextToken() create.Settings = p.parseSettingsList() default: - goto done_table_options - } - } -done_table_options: - - // Parse AS SELECT or AS (subquery) or AS table_function() or AS database.table - if p.currentIs(token.AS) { - p.nextToken() - if p.currentIs(token.SELECT) || p.currentIs(token.WITH) || p.currentIs(token.LPAREN) { - // AS SELECT... or AS (SELECT...) INTERSECT ... - create.AsSelect = p.parseSelectWithUnion() - } else if p.currentIs(token.IDENT) || p.current.Token.IsKeyword() { - // AS table_function(...) or AS database.table - name := p.parseIdentifierName() - if p.currentIs(token.DOT) { - // AS database.table - skip the table name - p.nextToken() - p.parseIdentifierName() - } else if p.currentIs(token.LPAREN) { - // AS function(...) - parse as a function call - fn := &ast.FunctionCall{Name: name} - p.nextToken() // skip ( - if !p.currentIs(token.RPAREN) { - fn.Arguments = p.parseExpressionList() - } - if p.currentIs(token.RPAREN) { - p.nextToken() - } - create.AsTableFunction = fn - } - _ = name // Use name for future AS table support - } - } - - // Parse ENGINE after AS (for CREATE TABLE x AS y ENGINE=z syntax) - if create.Engine == nil && p.currentIs(token.ENGINE) { - p.nextToken() - if p.currentIs(token.EQ) { - p.nextToken() + return } - create.Engine = p.parseEngineClause() } } diff --git a/parser/testdata/00061_storage_buffer/metadata.json b/parser/testdata/00061_storage_buffer/metadata.json index 1295a45747..0967ef424b 100644 --- a/parser/testdata/00061_storage_buffer/metadata.json +++ b/parser/testdata/00061_storage_buffer/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt3": true - } -} +{} diff --git a/parser/testdata/00157_cache_dictionary/metadata.json b/parser/testdata/00157_cache_dictionary/metadata.json index ef58f80315..0967ef424b 100644 --- a/parser/testdata/00157_cache_dictionary/metadata.json +++ b/parser/testdata/00157_cache_dictionary/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt2": true - } -} +{} diff --git a/parser/testdata/00643_cast_zookeeper_long/metadata.json b/parser/testdata/00643_cast_zookeeper_long/metadata.json index 7ad5569408..0967ef424b 100644 --- a/parser/testdata/00643_cast_zookeeper_long/metadata.json +++ b/parser/testdata/00643_cast_zookeeper_long/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt9": true - } -} +{} diff --git a/parser/testdata/01040_distributed_background_insert_batch_inserts/metadata.json b/parser/testdata/01040_distributed_background_insert_batch_inserts/metadata.json index d6b67693c2..187bf0fcb3 100644 --- a/parser/testdata/01040_distributed_background_insert_batch_inserts/metadata.json +++ b/parser/testdata/01040_distributed_background_insert_batch_inserts/metadata.json @@ -1,10 +1,8 @@ { "explain_todo": { "stmt14": true, - "stmt18": true, "stmt22": true, "stmt28": true, - "stmt4": true, "stmt8": true } } diff --git a/parser/testdata/01056_create_table_as_with_sorting_clauses/metadata.json b/parser/testdata/01056_create_table_as_with_sorting_clauses/metadata.json index 9663dfef54..0967ef424b 100644 --- a/parser/testdata/01056_create_table_as_with_sorting_clauses/metadata.json +++ b/parser/testdata/01056_create_table_as_with_sorting_clauses/metadata.json @@ -1,8 +1 @@ -{ - "explain_todo": { - "stmt13": true, - "stmt21": true, - "stmt38": true, - "stmt5": true - } -} +{} diff --git a/parser/testdata/01602_insert_into_table_function_cluster/metadata.json b/parser/testdata/01602_insert_into_table_function_cluster/metadata.json index 7b4ddafa53..0967ef424b 100644 --- a/parser/testdata/01602_insert_into_table_function_cluster/metadata.json +++ b/parser/testdata/01602_insert_into_table_function_cluster/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt3": true, - "stmt4": true - } -} +{} diff --git a/parser/testdata/01644_distributed_async_insert_fsync_smoke/metadata.json b/parser/testdata/01644_distributed_async_insert_fsync_smoke/metadata.json index ccdfb13aa7..6acf335ca3 100644 --- a/parser/testdata/01644_distributed_async_insert_fsync_smoke/metadata.json +++ b/parser/testdata/01644_distributed_async_insert_fsync_smoke/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt13": true, "stmt14": true, "stmt17": true, "stmt6": true, diff --git a/parser/testdata/01684_insert_specify_shard_id/metadata.json b/parser/testdata/01684_insert_specify_shard_id/metadata.json index 0f293987f1..0967ef424b 100644 --- a/parser/testdata/01684_insert_specify_shard_id/metadata.json +++ b/parser/testdata/01684_insert_specify_shard_id/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt5": true, - "stmt6": true - } -} +{} diff --git a/parser/testdata/02481_pk_analysis_with_enum_to_string/metadata.json b/parser/testdata/02481_pk_analysis_with_enum_to_string/metadata.json index ef58f80315..0967ef424b 100644 --- a/parser/testdata/02481_pk_analysis_with_enum_to_string/metadata.json +++ b/parser/testdata/02481_pk_analysis_with_enum_to_string/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt2": true - } -} +{} diff --git a/parser/testdata/03030_system_flush_distributed_settings/metadata.json b/parser/testdata/03030_system_flush_distributed_settings/metadata.json index a9472b2bf5..2c2f7b1753 100644 --- a/parser/testdata/03030_system_flush_distributed_settings/metadata.json +++ b/parser/testdata/03030_system_flush_distributed_settings/metadata.json @@ -2,7 +2,6 @@ "explain_todo": { "stmt10": true, "stmt15": true, - "stmt16": true, - "stmt7": true + "stmt16": true } } diff --git a/parser/testdata/03095_merge_and_buffer_tables/metadata.json b/parser/testdata/03095_merge_and_buffer_tables/metadata.json index 3a06a4a1ac..0967ef424b 100644 --- a/parser/testdata/03095_merge_and_buffer_tables/metadata.json +++ b/parser/testdata/03095_merge_and_buffer_tables/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt5": true - } -} +{} diff --git a/parser/testdata/03100_lwu_22_detach_attach_patches/metadata.json b/parser/testdata/03100_lwu_22_detach_attach_patches/metadata.json index 8653316185..19e8872514 100644 --- a/parser/testdata/03100_lwu_22_detach_attach_patches/metadata.json +++ b/parser/testdata/03100_lwu_22_detach_attach_patches/metadata.json @@ -12,7 +12,6 @@ "stmt28": true, "stmt30": true, "stmt33": true, - "stmt37": true, - "stmt5": true + "stmt37": true } } diff --git a/parser/testdata/03393_max_merge_delayed_streams_for_parallel_write/metadata.json b/parser/testdata/03393_max_merge_delayed_streams_for_parallel_write/metadata.json index ef58f80315..0967ef424b 100644 --- a/parser/testdata/03393_max_merge_delayed_streams_for_parallel_write/metadata.json +++ b/parser/testdata/03393_max_merge_delayed_streams_for_parallel_write/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt2": true - } -} +{} From 7baa9ea7cdbce1c8bb1504b65eb57898b171811e Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 31 Dec 2025 06:42:20 +0000 Subject: [PATCH 06/24] Add YYYY support for EXTRACT and fix alias handling - Added YYYY as an alias for YEAR in EXTRACT field parsing - ExtractExpr now properly uses its Alias field for EXPLAIN output - Added ExtractExpr case in explainAliasedExpr for alias wrapping Fixes 00619_extract test. --- internal/explain/expressions.go | 3 +++ internal/explain/functions.go | 17 +++++++++++++++-- parser/expression.go | 2 +- parser/testdata/00619_extract/metadata.json | 6 +----- .../01095_tpch_like_smoke/metadata.json | 1 - 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/internal/explain/expressions.go b/internal/explain/expressions.go index dc436dc0a9..decb37fb31 100644 --- a/internal/explain/expressions.go +++ b/internal/explain/expressions.go @@ -529,6 +529,9 @@ func explainAliasedExpr(sb *strings.Builder, n *ast.AliasedExpr, depth int) { case *ast.Lambda: // Lambda expressions with alias explainLambdaWithAlias(sb, e, n.Alias, indent, depth) + case *ast.ExtractExpr: + // EXTRACT expressions with alias + explainExtractExprWithAlias(sb, e, n.Alias, indent, depth) case *ast.Identifier: // Identifiers with alias fmt.Fprintf(sb, "%sIdentifier %s (alias %s)\n", indent, e.Name(), escapeAlias(n.Alias)) diff --git a/internal/explain/functions.go b/internal/explain/functions.go index ae04c6afa7..b1e0bed69e 100644 --- a/internal/explain/functions.go +++ b/internal/explain/functions.go @@ -882,10 +882,23 @@ func explainExistsExpr(sb *strings.Builder, n *ast.ExistsExpr, indent string, de } func explainExtractExpr(sb *strings.Builder, n *ast.ExtractExpr, indent string, depth int) { + explainExtractExprWithAlias(sb, n, n.Alias, indent, depth) +} + +func explainExtractExprWithAlias(sb *strings.Builder, n *ast.ExtractExpr, alias string, indent string, depth int) { // EXTRACT is represented as Function toYear, toMonth, etc. // ClickHouse uses specific function names for date/time extraction fnName := extractFieldToFunction(n.Field) - fmt.Fprintf(sb, "%sFunction %s (children %d)\n", indent, fnName, 1) + // Use alias from parameter, or fall back to expression's alias + effectiveAlias := alias + if effectiveAlias == "" { + effectiveAlias = n.Alias + } + if effectiveAlias != "" { + fmt.Fprintf(sb, "%sFunction %s (alias %s) (children %d)\n", indent, fnName, effectiveAlias, 1) + } else { + fmt.Fprintf(sb, "%sFunction %s (children %d)\n", indent, fnName, 1) + } fmt.Fprintf(sb, "%s ExpressionList (children %d)\n", indent, 1) Node(sb, n.From, depth+2) } @@ -897,7 +910,7 @@ func extractFieldToFunction(field string) string { return "toDayOfMonth" case "MONTH": return "toMonth" - case "YEAR": + case "YEAR", "YYYY": return "toYear" case "SECOND": return "toSecond" diff --git a/parser/expression.go b/parser/expression.go index 24a72e890b..636d38983e 100644 --- a/parser/expression.go +++ b/parser/expression.go @@ -1282,7 +1282,7 @@ func (p *Parser) parseExtract() ast.Expression { field := strings.ToUpper(p.current.Value) // Check if it's a known date/time field dateTimeFields := map[string]bool{ - "YEAR": true, "QUARTER": true, "MONTH": true, "WEEK": true, + "YEAR": true, "YYYY": true, "QUARTER": true, "MONTH": true, "WEEK": true, "DAY": true, "DAYOFWEEK": true, "DAYOFYEAR": true, "HOUR": true, "MINUTE": true, "SECOND": true, "TIMEZONE_HOUR": true, "TIMEZONE_MINUTE": true, diff --git a/parser/testdata/00619_extract/metadata.json b/parser/testdata/00619_extract/metadata.json index 62b81668c3..0967ef424b 100644 --- a/parser/testdata/00619_extract/metadata.json +++ b/parser/testdata/00619_extract/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt13": true - } -} +{} diff --git a/parser/testdata/01095_tpch_like_smoke/metadata.json b/parser/testdata/01095_tpch_like_smoke/metadata.json index 39ef68aad9..7a435f68f3 100644 --- a/parser/testdata/01095_tpch_like_smoke/metadata.json +++ b/parser/testdata/01095_tpch_like_smoke/metadata.json @@ -7,7 +7,6 @@ "stmt30": true, "stmt32": true, "stmt34": true, - "stmt36": true, "stmt38": true, "stmt42": true, "stmt46": true, From 0d45aba26538c5a1eefec2611213bd125396c5c8 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 31 Dec 2025 06:47:45 +0000 Subject: [PATCH 07/24] Add implicit NULL in CASE WHEN without ELSE clause CASE expressions without an explicit ELSE clause implicitly return NULL. Update the explain output to always include this implicit NULL value, matching ClickHouse's EXPLAIN AST format. Fixes 4 statements in 4 tests. --- internal/explain/functions.go | 9 +++++---- parser/testdata/00395_nullable/metadata.json | 6 +----- parser/testdata/00688_case_without_else/metadata.json | 2 +- .../metadata.json | 6 +----- .../02901_remove_nullable_crash_analyzer/metadata.json | 6 +----- 5 files changed, 9 insertions(+), 20 deletions(-) diff --git a/internal/explain/functions.go b/internal/explain/functions.go index b1e0bed69e..6e4a767e33 100644 --- a/internal/explain/functions.go +++ b/internal/explain/functions.go @@ -836,10 +836,8 @@ func explainCaseExprWithAlias(sb *strings.Builder, n *ast.CaseExpr, alias string } } else { // CASE WHEN ... form - argCount := len(n.Whens) * 2 - if n.Else != nil { - argCount++ - } + // CASE without ELSE implicitly has NULL as the else value + argCount := len(n.Whens)*2 + 1 // Always add 1 for ELSE (explicit or implicit NULL) if alias != "" { fmt.Fprintf(sb, "%sFunction multiIf (alias %s) (children %d)\n", indent, alias, 1) } else { @@ -852,6 +850,9 @@ func explainCaseExprWithAlias(sb *strings.Builder, n *ast.CaseExpr, alias string } if n.Else != nil { Node(sb, n.Else, depth+2) + } else { + // Implicit NULL when no ELSE clause + fmt.Fprintf(sb, "%s Literal NULL\n", indent) } } } diff --git a/parser/testdata/00395_nullable/metadata.json b/parser/testdata/00395_nullable/metadata.json index 7f83f2ec01..0967ef424b 100644 --- a/parser/testdata/00395_nullable/metadata.json +++ b/parser/testdata/00395_nullable/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt80": true - } -} +{} diff --git a/parser/testdata/00688_case_without_else/metadata.json b/parser/testdata/00688_case_without_else/metadata.json index cc2f3624ef..0967ef424b 100644 --- a/parser/testdata/00688_case_without_else/metadata.json +++ b/parser/testdata/00688_case_without_else/metadata.json @@ -1 +1 @@ -{"explain_todo":{"stmt4":true}} +{} diff --git a/parser/testdata/02346_text_index_function_hasAnyAllTokens/metadata.json b/parser/testdata/02346_text_index_function_hasAnyAllTokens/metadata.json index d352e743d3..0967ef424b 100644 --- a/parser/testdata/02346_text_index_function_hasAnyAllTokens/metadata.json +++ b/parser/testdata/02346_text_index_function_hasAnyAllTokens/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt319": true - } -} +{} diff --git a/parser/testdata/02901_remove_nullable_crash_analyzer/metadata.json b/parser/testdata/02901_remove_nullable_crash_analyzer/metadata.json index ef58f80315..0967ef424b 100644 --- a/parser/testdata/02901_remove_nullable_crash_analyzer/metadata.json +++ b/parser/testdata/02901_remove_nullable_crash_analyzer/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt2": true - } -} +{} From 3142456e257e4e14afed9a516c31a9ff2faa5aa4 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 31 Dec 2025 07:00:12 +0000 Subject: [PATCH 08/24] Fix nested tuple literal formatting in EXPLAIN output When a tuple contains only primitive literals (including nested tuples with primitive literals), it should be rendered as a single Literal Tuple_(...) rather than Function tuple with children. Add containsOnlyPrimitiveLiteralsWithUnary helper that checks if a tuple contains only primitive literals, including handling unary negation of numeric literals (e.g., -0., -123). Fixes 17 statements across 11 tests. --- internal/explain/expressions.go | 12 +++++- internal/explain/functions.go | 40 +++++++++++++++++++ parser/testdata/00132_sets/metadata.json | 1 - parser/testdata/00626_in_syntax/metadata.json | 9 +---- .../00945_bloom_filter_index/metadata.json | 1 - .../01398_in_tuple_func/metadata.json | 6 +-- .../metadata.json | 8 +--- .../01803_untuple_subquery/metadata.json | 6 +-- .../metadata.json | 6 +-- .../testdata/02030_tuple_filter/metadata.json | 2 +- .../02370_analyzer_in_function/metadata.json | 1 - .../02583_map_literal_cast/metadata.json | 7 +--- .../02802_with_cube_with_totals/metadata.json | 6 +-- 13 files changed, 58 insertions(+), 47 deletions(-) diff --git a/internal/explain/expressions.go b/internal/explain/expressions.go index decb37fb31..9f9df6170d 100644 --- a/internal/explain/expressions.go +++ b/internal/explain/expressions.go @@ -65,8 +65,16 @@ func explainLiteral(sb *strings.Builder, n *ast.Literal, indent string, depth in for _, e := range exprs { // Simple literals (numbers, strings, etc.) are OK if lit, isLit := e.(*ast.Literal); isLit { - // Nested tuples/arrays are complex - if lit.Type == ast.LiteralTuple || lit.Type == ast.LiteralArray { + // Nested tuples that contain only primitive literals are OK + if lit.Type == ast.LiteralTuple { + if !containsOnlyPrimitiveLiteralsWithUnary(lit) { + hasComplexExpr = true + break + } + continue + } + // Arrays are always complex in tuple context + if lit.Type == ast.LiteralArray { hasComplexExpr = true break } diff --git a/internal/explain/functions.go b/internal/explain/functions.go index 6e4a767e33..e1e1f27251 100644 --- a/internal/explain/functions.go +++ b/internal/explain/functions.go @@ -322,6 +322,46 @@ func containsOnlyPrimitiveLiterals(lit *ast.Literal) bool { return true } +// containsOnlyPrimitiveLiteralsWithUnary is like containsOnlyPrimitiveLiterals but also handles +// unary negation of numeric literals (e.g., -0., -123) +func containsOnlyPrimitiveLiteralsWithUnary(lit *ast.Literal) bool { + if lit.Type != ast.LiteralTuple { + // Non-tuple literals are primitive + return true + } + exprs, ok := lit.Value.([]ast.Expression) + if !ok { + return false + } + for _, e := range exprs { + // Direct literal + if innerLit, ok := e.(*ast.Literal); ok { + // Recursively check nested tuples + if innerLit.Type == ast.LiteralTuple { + if !containsOnlyPrimitiveLiteralsWithUnary(innerLit) { + return false + } + } + // Arrays inside tuples make it complex + if innerLit.Type == ast.LiteralArray { + return false + } + continue + } + // Unary negation of numeric literal is also primitive + if unary, ok := e.(*ast.UnaryExpr); ok && unary.Op == "-" { + if innerLit, ok := unary.Operand.(*ast.Literal); ok { + if innerLit.Type == ast.LiteralInteger || innerLit.Type == ast.LiteralFloat { + continue + } + } + } + // Non-literal expression in tuple + return false + } + return true +} + // exprToLiteral converts a numeric expression to a literal (handles unary minus) func exprToLiteral(expr ast.Expression) *ast.Literal { if lit, ok := expr.(*ast.Literal); ok { diff --git a/parser/testdata/00132_sets/metadata.json b/parser/testdata/00132_sets/metadata.json index 63148103d5..6c03e47fbc 100644 --- a/parser/testdata/00132_sets/metadata.json +++ b/parser/testdata/00132_sets/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt11": true, "stmt12": true, "stmt6": true, "stmt9": true diff --git a/parser/testdata/00626_in_syntax/metadata.json b/parser/testdata/00626_in_syntax/metadata.json index 39429336f8..0967ef424b 100644 --- a/parser/testdata/00626_in_syntax/metadata.json +++ b/parser/testdata/00626_in_syntax/metadata.json @@ -1,8 +1 @@ -{ - "explain_todo": { - "stmt3": true, - "stmt4": true, - "stmt5": true, - "stmt6": true - } -} +{} diff --git a/parser/testdata/00945_bloom_filter_index/metadata.json b/parser/testdata/00945_bloom_filter_index/metadata.json index 66f0942965..71bff5d186 100644 --- a/parser/testdata/00945_bloom_filter_index/metadata.json +++ b/parser/testdata/00945_bloom_filter_index/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt10": true, "stmt152": true, "stmt19": true, "stmt20": true, diff --git a/parser/testdata/01398_in_tuple_func/metadata.json b/parser/testdata/01398_in_tuple_func/metadata.json index 62b81668c3..0967ef424b 100644 --- a/parser/testdata/01398_in_tuple_func/metadata.json +++ b/parser/testdata/01398_in_tuple_func/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt13": true - } -} +{} diff --git a/parser/testdata/01653_tuple_hamming_distance_2/metadata.json b/parser/testdata/01653_tuple_hamming_distance_2/metadata.json index 685bb7b242..0967ef424b 100644 --- a/parser/testdata/01653_tuple_hamming_distance_2/metadata.json +++ b/parser/testdata/01653_tuple_hamming_distance_2/metadata.json @@ -1,7 +1 @@ -{ - "explain_todo": { - "stmt16": true, - "stmt17": true, - "stmt18": true - } -} +{} diff --git a/parser/testdata/01803_untuple_subquery/metadata.json b/parser/testdata/01803_untuple_subquery/metadata.json index e9d6e46171..0967ef424b 100644 --- a/parser/testdata/01803_untuple_subquery/metadata.json +++ b/parser/testdata/01803_untuple_subquery/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt1": true - } -} +{} diff --git a/parser/testdata/02011_tuple_vector_functions/metadata.json b/parser/testdata/02011_tuple_vector_functions/metadata.json index 91cc72dcb0..0967ef424b 100644 --- a/parser/testdata/02011_tuple_vector_functions/metadata.json +++ b/parser/testdata/02011_tuple_vector_functions/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt90": true - } -} +{} diff --git a/parser/testdata/02030_tuple_filter/metadata.json b/parser/testdata/02030_tuple_filter/metadata.json index 9ac41e809b..0967ef424b 100644 --- a/parser/testdata/02030_tuple_filter/metadata.json +++ b/parser/testdata/02030_tuple_filter/metadata.json @@ -1 +1 @@ -{"explain_todo":{"stmt10":true,"stmt11":true,"stmt13":true}} +{} diff --git a/parser/testdata/02370_analyzer_in_function/metadata.json b/parser/testdata/02370_analyzer_in_function/metadata.json index 2da0074a29..8162ad6436 100644 --- a/parser/testdata/02370_analyzer_in_function/metadata.json +++ b/parser/testdata/02370_analyzer_in_function/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt19": true, "stmt21": true, "stmt9": true } diff --git a/parser/testdata/02583_map_literal_cast/metadata.json b/parser/testdata/02583_map_literal_cast/metadata.json index 0f293987f1..0967ef424b 100644 --- a/parser/testdata/02583_map_literal_cast/metadata.json +++ b/parser/testdata/02583_map_literal_cast/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt5": true, - "stmt6": true - } -} +{} diff --git a/parser/testdata/02802_with_cube_with_totals/metadata.json b/parser/testdata/02802_with_cube_with_totals/metadata.json index e9d6e46171..0967ef424b 100644 --- a/parser/testdata/02802_with_cube_with_totals/metadata.json +++ b/parser/testdata/02802_with_cube_with_totals/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt1": true - } -} +{} From a9600c93c72dad6a93f1906acf2d9545fd64f88f Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 31 Dec 2025 07:07:40 +0000 Subject: [PATCH 09/24] Fix MODIFY COLUMN with only CODEC specification When ALTER TABLE MODIFY COLUMN specifies only a CODEC without a data type (e.g., `MODIFY COLUMN col CODEC(LZ4)`), the parser was incorrectly treating CODEC as the column type. Now correctly recognizes CODEC as a codec specification when no type is present. Fixes 10 statements across 5 tests. --- parser/parser.go | 10 ++++++---- .../00804_test_alter_compression_codecs/metadata.json | 8 +------- .../00804_test_delta_codec_no_type_alter/metadata.json | 6 +----- .../metadata.json | 7 +------ .../00926_adaptive_index_granularity_pk/metadata.json | 6 +----- .../metadata.json | 7 +------ .../metadata.json | 2 +- 7 files changed, 12 insertions(+), 34 deletions(-) diff --git a/parser/parser.go b/parser/parser.go index a3283e3c0e..e06a34f765 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -3065,10 +3065,12 @@ func (p *Parser) parseColumnDeclaration() *ast.ColumnDeclaration { return nil } - // Check if next token is DEFAULT/MATERIALIZED/ALIAS (type omitted) - // These keywords indicate the type is omitted and we go straight to default expression - if p.currentIs(token.DEFAULT) || p.currentIs(token.MATERIALIZED) || p.currentIs(token.ALIAS) { - // Type is omitted, skip to default parsing below + // Check if next token indicates type is omitted + // DEFAULT/MATERIALIZED/ALIAS indicate we go straight to default expression + // CODEC indicates we go straight to codec specification (no type) + isCodec := p.currentIs(token.IDENT) && strings.ToUpper(p.current.Value) == "CODEC" + if p.currentIs(token.DEFAULT) || p.currentIs(token.MATERIALIZED) || p.currentIs(token.ALIAS) || isCodec { + // Type is omitted, skip to parsing below } else { // Parse data type col.Type = p.parseDataType() diff --git a/parser/testdata/00804_test_alter_compression_codecs/metadata.json b/parser/testdata/00804_test_alter_compression_codecs/metadata.json index c4862be04a..0967ef424b 100644 --- a/parser/testdata/00804_test_alter_compression_codecs/metadata.json +++ b/parser/testdata/00804_test_alter_compression_codecs/metadata.json @@ -1,7 +1 @@ -{ - "explain_todo": { - "stmt12": true, - "stmt20": true, - "stmt41": true - } -} +{} diff --git a/parser/testdata/00804_test_delta_codec_no_type_alter/metadata.json b/parser/testdata/00804_test_delta_codec_no_type_alter/metadata.json index dbdbb76d4f..0967ef424b 100644 --- a/parser/testdata/00804_test_delta_codec_no_type_alter/metadata.json +++ b/parser/testdata/00804_test_delta_codec_no_type_alter/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt6": true - } -} +{} diff --git a/parser/testdata/00910_zookeeper_test_alter_compression_codecs_long/metadata.json b/parser/testdata/00910_zookeeper_test_alter_compression_codecs_long/metadata.json index 909e6ec804..0967ef424b 100644 --- a/parser/testdata/00910_zookeeper_test_alter_compression_codecs_long/metadata.json +++ b/parser/testdata/00910_zookeeper_test_alter_compression_codecs_long/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt23": true, - "stmt32": true - } -} +{} diff --git a/parser/testdata/00926_adaptive_index_granularity_pk/metadata.json b/parser/testdata/00926_adaptive_index_granularity_pk/metadata.json index d227d77cb4..0967ef424b 100644 --- a/parser/testdata/00926_adaptive_index_granularity_pk/metadata.json +++ b/parser/testdata/00926_adaptive_index_granularity_pk/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt43": true - } -} +{} diff --git a/parser/testdata/02725_alias_columns_should_not_allow_compression_codec/metadata.json b/parser/testdata/02725_alias_columns_should_not_allow_compression_codec/metadata.json index ef382ce51e..0967ef424b 100644 --- a/parser/testdata/02725_alias_columns_should_not_allow_compression_codec/metadata.json +++ b/parser/testdata/02725_alias_columns_should_not_allow_compression_codec/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt4": true, - "stmt5": true - } -} +{} diff --git a/parser/testdata/03566_inconsistent_formatting_functions_codecs/metadata.json b/parser/testdata/03566_inconsistent_formatting_functions_codecs/metadata.json index af48d4c110..0967ef424b 100644 --- a/parser/testdata/03566_inconsistent_formatting_functions_codecs/metadata.json +++ b/parser/testdata/03566_inconsistent_formatting_functions_codecs/metadata.json @@ -1 +1 @@ -{"explain_todo":{"stmt2":true}} +{} From c39627601747eb0240c3432fba8290b429d036c9 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 31 Dec 2025 07:12:32 +0000 Subject: [PATCH 10/24] Add column TTL expression to EXPLAIN output The Column function was missing handling for column-level TTL expressions. Now properly includes the TTL expression in the ColumnDeclaration's children. Fixes 75 statements across 26 tests. --- internal/explain/explain.go | 6 ++++++ parser/testdata/00933_alter_ttl/metadata.json | 3 --- .../testdata/00933_ttl_formatting/metadata.json | 7 +------ parser/testdata/00933_ttl_simple/metadata.json | 16 +--------------- .../00933_ttl_with_default/metadata.json | 8 +------- .../01006_ttl_with_default_2/metadata.json | 6 +----- .../testdata/01070_alter_with_ttl/metadata.json | 7 +------ .../testdata/01070_materialize_ttl/metadata.json | 3 --- parser/testdata/01070_modify_ttl/metadata.json | 6 ------ .../01070_modify_ttl_recalc_only/metadata.json | 8 +------- .../metadata.json | 2 -- .../metadata.json | 6 +----- .../metadata.json | 6 +----- .../01506_ttl_same_with_order_by/metadata.json | 6 +----- .../01603_remove_column_ttl/metadata.json | 1 - .../02184_storage_add_support_ttl/metadata.json | 15 +-------------- .../metadata.json | 6 +----- parser/testdata/02265_column_ttl/metadata.json | 2 -- .../02296_ttl_non_deterministic/metadata.json | 4 ---- .../metadata.json | 6 +----- .../metadata.json | 6 +----- .../03352_allow_suspicious_ttl/metadata.json | 4 ---- .../03362_default_profiles_context/metadata.json | 7 +------ .../03519_ttl_extended_data_types/metadata.json | 7 +------ .../metadata.json | 1 - .../03642_column_ttl_sparse/metadata.json | 6 +----- .../03701_column_ttl_fully_expired/metadata.json | 3 --- 27 files changed, 22 insertions(+), 136 deletions(-) diff --git a/internal/explain/explain.go b/internal/explain/explain.go index 35209d0e1c..9cf2b8414d 100644 --- a/internal/explain/explain.go +++ b/internal/explain/explain.go @@ -279,6 +279,9 @@ func Column(sb *strings.Builder, col *ast.ColumnDeclaration, depth int) { if col.Default != nil || hasEphemeralDefault { children++ } + if col.TTL != nil { + children++ + } if col.Codec != nil { children++ } @@ -295,6 +298,9 @@ func Column(sb *strings.Builder, col *ast.ColumnDeclaration, depth int) { // EPHEMERAL columns without explicit default value show defaultValueOfTypeName function fmt.Fprintf(sb, "%s Function defaultValueOfTypeName\n", indent) } + if col.TTL != nil { + Node(sb, col.TTL, depth+1) + } if col.Codec != nil { explainCodecExpr(sb, col.Codec, indent+" ", depth+1) } diff --git a/parser/testdata/00933_alter_ttl/metadata.json b/parser/testdata/00933_alter_ttl/metadata.json index a6ab941a27..9a504448b8 100644 --- a/parser/testdata/00933_alter_ttl/metadata.json +++ b/parser/testdata/00933_alter_ttl/metadata.json @@ -1,9 +1,6 @@ { "explain_todo": { "stmt12": true, - "stmt15": true, - "stmt17": true, - "stmt18": true, "stmt4": true } } diff --git a/parser/testdata/00933_ttl_formatting/metadata.json b/parser/testdata/00933_ttl_formatting/metadata.json index bc141058a4..0967ef424b 100644 --- a/parser/testdata/00933_ttl_formatting/metadata.json +++ b/parser/testdata/00933_ttl_formatting/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt2": true, - "stmt3": true - } -} +{} diff --git a/parser/testdata/00933_ttl_simple/metadata.json b/parser/testdata/00933_ttl_simple/metadata.json index da4aef3efc..0967ef424b 100644 --- a/parser/testdata/00933_ttl_simple/metadata.json +++ b/parser/testdata/00933_ttl_simple/metadata.json @@ -1,15 +1 @@ -{ - "explain_todo": { - "stmt19": true, - "stmt39": true, - "stmt4": true, - "stmt45": true, - "stmt51": true, - "stmt57": true, - "stmt64": true, - "stmt65": true, - "stmt66": true, - "stmt67": true, - "stmt68": true - } -} +{} diff --git a/parser/testdata/00933_ttl_with_default/metadata.json b/parser/testdata/00933_ttl_with_default/metadata.json index f6abb39d9f..0967ef424b 100644 --- a/parser/testdata/00933_ttl_with_default/metadata.json +++ b/parser/testdata/00933_ttl_with_default/metadata.json @@ -1,7 +1 @@ -{ - "explain_todo": { - "stmt10": true, - "stmt18": true, - "stmt2": true - } -} +{} diff --git a/parser/testdata/01006_ttl_with_default_2/metadata.json b/parser/testdata/01006_ttl_with_default_2/metadata.json index ef58f80315..0967ef424b 100644 --- a/parser/testdata/01006_ttl_with_default_2/metadata.json +++ b/parser/testdata/01006_ttl_with_default_2/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt2": true - } -} +{} diff --git a/parser/testdata/01070_alter_with_ttl/metadata.json b/parser/testdata/01070_alter_with_ttl/metadata.json index 25122ac4f4..0967ef424b 100644 --- a/parser/testdata/01070_alter_with_ttl/metadata.json +++ b/parser/testdata/01070_alter_with_ttl/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt5": true, - "stmt9": true - } -} +{} diff --git a/parser/testdata/01070_materialize_ttl/metadata.json b/parser/testdata/01070_materialize_ttl/metadata.json index fdf9fafe42..ede6d46fb3 100644 --- a/parser/testdata/01070_materialize_ttl/metadata.json +++ b/parser/testdata/01070_materialize_ttl/metadata.json @@ -6,13 +6,10 @@ "stmt18": true, "stmt20": true, "stmt21": true, - "stmt26": true, "stmt28": true, - "stmt30": true, "stmt31": true, "stmt36": true, "stmt37": true, - "stmt39": true, "stmt40": true, "stmt9": true } diff --git a/parser/testdata/01070_modify_ttl/metadata.json b/parser/testdata/01070_modify_ttl/metadata.json index f818fee1f5..a859f1f406 100644 --- a/parser/testdata/01070_modify_ttl/metadata.json +++ b/parser/testdata/01070_modify_ttl/metadata.json @@ -2,13 +2,7 @@ "explain_todo": { "stmt15": true, "stmt18": true, - "stmt24": true, - "stmt27": true, "stmt33": true, - "stmt36": true, - "stmt42": true, - "stmt47": true, - "stmt48": true, "stmt9": true } } diff --git a/parser/testdata/01070_modify_ttl_recalc_only/metadata.json b/parser/testdata/01070_modify_ttl_recalc_only/metadata.json index 861713c698..56a1a55a2f 100644 --- a/parser/testdata/01070_modify_ttl_recalc_only/metadata.json +++ b/parser/testdata/01070_modify_ttl_recalc_only/metadata.json @@ -3,12 +3,6 @@ "stmt10": true, "stmt19": true, "stmt25": true, - "stmt34": true, - "stmt39": true, - "stmt47": true, - "stmt53": true, - "stmt61": true, - "stmt68": true, - "stmt69": true + "stmt47": true } } diff --git a/parser/testdata/01070_mutations_with_dependencies/metadata.json b/parser/testdata/01070_mutations_with_dependencies/metadata.json index 03f6bec65b..bf2aafed02 100644 --- a/parser/testdata/01070_mutations_with_dependencies/metadata.json +++ b/parser/testdata/01070_mutations_with_dependencies/metadata.json @@ -1,8 +1,6 @@ { "explain_todo": { - "stmt12": true, "stmt21": true, - "stmt23": true, "stmt26": true, "stmt5": true, "stmt6": true diff --git a/parser/testdata/01213_alter_rename_with_default_zookeeper_long/metadata.json b/parser/testdata/01213_alter_rename_with_default_zookeeper_long/metadata.json index 62b81668c3..0967ef424b 100644 --- a/parser/testdata/01213_alter_rename_with_default_zookeeper_long/metadata.json +++ b/parser/testdata/01213_alter_rename_with_default_zookeeper_long/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt13": true - } -} +{} diff --git a/parser/testdata/01413_allow_non_metadata_alters/metadata.json b/parser/testdata/01413_allow_non_metadata_alters/metadata.json index 3a06a4a1ac..0967ef424b 100644 --- a/parser/testdata/01413_allow_non_metadata_alters/metadata.json +++ b/parser/testdata/01413_allow_non_metadata_alters/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt5": true - } -} +{} diff --git a/parser/testdata/01506_ttl_same_with_order_by/metadata.json b/parser/testdata/01506_ttl_same_with_order_by/metadata.json index 5395f06a45..0967ef424b 100644 --- a/parser/testdata/01506_ttl_same_with_order_by/metadata.json +++ b/parser/testdata/01506_ttl_same_with_order_by/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt20": true - } -} +{} diff --git a/parser/testdata/01603_remove_column_ttl/metadata.json b/parser/testdata/01603_remove_column_ttl/metadata.json index 0de7c95587..b563327205 100644 --- a/parser/testdata/01603_remove_column_ttl/metadata.json +++ b/parser/testdata/01603_remove_column_ttl/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt2": true, "stmt7": true } } diff --git a/parser/testdata/02184_storage_add_support_ttl/metadata.json b/parser/testdata/02184_storage_add_support_ttl/metadata.json index 75f8c94056..0967ef424b 100644 --- a/parser/testdata/02184_storage_add_support_ttl/metadata.json +++ b/parser/testdata/02184_storage_add_support_ttl/metadata.json @@ -1,14 +1 @@ -{ - "explain_todo": { - "stmt13": true, - "stmt18": true, - "stmt23": true, - "stmt28": true, - "stmt3": true, - "stmt33": true, - "stmt38": true, - "stmt43": true, - "stmt48": true, - "stmt8": true - } -} +{} diff --git a/parser/testdata/02230_create_table_as_ignore_ttl/metadata.json b/parser/testdata/02230_create_table_as_ignore_ttl/metadata.json index ab9202e88e..0967ef424b 100644 --- a/parser/testdata/02230_create_table_as_ignore_ttl/metadata.json +++ b/parser/testdata/02230_create_table_as_ignore_ttl/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt11": true - } -} +{} diff --git a/parser/testdata/02265_column_ttl/metadata.json b/parser/testdata/02265_column_ttl/metadata.json index df64e7a232..92e84e943a 100644 --- a/parser/testdata/02265_column_ttl/metadata.json +++ b/parser/testdata/02265_column_ttl/metadata.json @@ -1,7 +1,5 @@ { "explain_todo": { - "stmt3": true, - "stmt4": true, "stmt8": true, "stmt9": true } diff --git a/parser/testdata/02296_ttl_non_deterministic/metadata.json b/parser/testdata/02296_ttl_non_deterministic/metadata.json index 38797f1345..d02612666a 100644 --- a/parser/testdata/02296_ttl_non_deterministic/metadata.json +++ b/parser/testdata/02296_ttl_non_deterministic/metadata.json @@ -1,9 +1,5 @@ { "explain_todo": { - "stmt10": true, - "stmt11": true, - "stmt13": true, - "stmt16": true, "stmt5": true, "stmt8": true } diff --git a/parser/testdata/02403_ttl_column_multiple_times/metadata.json b/parser/testdata/02403_ttl_column_multiple_times/metadata.json index ef58f80315..0967ef424b 100644 --- a/parser/testdata/02403_ttl_column_multiple_times/metadata.json +++ b/parser/testdata/02403_ttl_column_multiple_times/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt2": true - } -} +{} diff --git a/parser/testdata/03143_ttl_in_system_parts_columns_table/metadata.json b/parser/testdata/03143_ttl_in_system_parts_columns_table/metadata.json index ef58f80315..0967ef424b 100644 --- a/parser/testdata/03143_ttl_in_system_parts_columns_table/metadata.json +++ b/parser/testdata/03143_ttl_in_system_parts_columns_table/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt2": true - } -} +{} diff --git a/parser/testdata/03352_allow_suspicious_ttl/metadata.json b/parser/testdata/03352_allow_suspicious_ttl/metadata.json index 67ce391069..afaaa4b0a6 100644 --- a/parser/testdata/03352_allow_suspicious_ttl/metadata.json +++ b/parser/testdata/03352_allow_suspicious_ttl/metadata.json @@ -1,9 +1,5 @@ { "explain_todo": { - "stmt12": true, - "stmt14": true, - "stmt16": true, - "stmt18": true, "stmt7": true, "stmt9": true } diff --git a/parser/testdata/03362_default_profiles_context/metadata.json b/parser/testdata/03362_default_profiles_context/metadata.json index 682bda1cbc..0967ef424b 100644 --- a/parser/testdata/03362_default_profiles_context/metadata.json +++ b/parser/testdata/03362_default_profiles_context/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt1": true, - "stmt2": true - } -} +{} diff --git a/parser/testdata/03519_ttl_extended_data_types/metadata.json b/parser/testdata/03519_ttl_extended_data_types/metadata.json index 6b84a8b096..0967ef424b 100644 --- a/parser/testdata/03519_ttl_extended_data_types/metadata.json +++ b/parser/testdata/03519_ttl_extended_data_types/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt18": true, - "stmt26": true - } -} +{} diff --git a/parser/testdata/03571_trying_to_get_name_of_not_a_column_asterisk/metadata.json b/parser/testdata/03571_trying_to_get_name_of_not_a_column_asterisk/metadata.json index c84e30800d..b563327205 100644 --- a/parser/testdata/03571_trying_to_get_name_of_not_a_column_asterisk/metadata.json +++ b/parser/testdata/03571_trying_to_get_name_of_not_a_column_asterisk/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt3": true, "stmt7": true } } diff --git a/parser/testdata/03642_column_ttl_sparse/metadata.json b/parser/testdata/03642_column_ttl_sparse/metadata.json index ef58f80315..0967ef424b 100644 --- a/parser/testdata/03642_column_ttl_sparse/metadata.json +++ b/parser/testdata/03642_column_ttl_sparse/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt2": true - } -} +{} diff --git a/parser/testdata/03701_column_ttl_fully_expired/metadata.json b/parser/testdata/03701_column_ttl_fully_expired/metadata.json index 2978af6902..7974f6a182 100644 --- a/parser/testdata/03701_column_ttl_fully_expired/metadata.json +++ b/parser/testdata/03701_column_ttl_fully_expired/metadata.json @@ -1,8 +1,5 @@ { "explain_todo": { - "stmt11": true, - "stmt19": true, - "stmt2": true, "stmt24": true } } From 4e5e254dfb956a5c6c20ee82346b17050beac1f4 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 31 Dec 2025 07:23:12 +0000 Subject: [PATCH 11/24] Wrap ALTER TABLE MODIFY TTL expression in ExpressionList and TTLElement The MODIFY_TTL alter command's TTL expression should be wrapped in ExpressionList and TTLElement nodes to match ClickHouse's EXPLAIN AST format. Fixes 32 statements across 14 tests. --- internal/explain/statements.go | 5 ++++- parser/testdata/00933_alter_ttl/metadata.json | 7 +------ .../testdata/00976_ttl_with_old_parts/metadata.json | 6 +----- parser/testdata/01070_materialize_ttl/metadata.json | 4 ---- parser/testdata/01070_modify_ttl/metadata.json | 9 +-------- .../01070_modify_ttl_recalc_only/metadata.json | 9 +-------- .../01070_mutations_with_dependencies/metadata.json | 1 - .../metadata.json | 1 - parser/testdata/01652_ttl_old_syntax/metadata.json | 6 +----- .../metadata.json | 12 +----------- .../02296_ttl_non_deterministic/metadata.json | 7 +------ .../02484_substitute_udf_storage_args/metadata.json | 3 +-- .../testdata/02697_alter_dependencies/metadata.json | 6 +----- .../03282_block_number_otehr_mutations/metadata.json | 6 +----- .../03352_allow_suspicious_ttl/metadata.json | 7 +------ 15 files changed, 15 insertions(+), 74 deletions(-) diff --git a/internal/explain/statements.go b/internal/explain/statements.go index 83cb63511a..bf8a521a17 100644 --- a/internal/explain/statements.go +++ b/internal/explain/statements.go @@ -1053,7 +1053,10 @@ func explainAlterCommand(sb *strings.Builder, cmd *ast.AlterCommand, indent stri } case ast.AlterModifyTTL: if cmd.TTL != nil && cmd.TTL.Expression != nil { - Node(sb, cmd.TTL.Expression, depth+1) + // TTL is wrapped in ExpressionList and TTLElement + fmt.Fprintf(sb, "%s ExpressionList (children 1)\n", indent) + fmt.Fprintf(sb, "%s TTLElement (children 1)\n", indent) + Node(sb, cmd.TTL.Expression, depth+3) } case ast.AlterModifySetting: fmt.Fprintf(sb, "%s Set\n", indent) diff --git a/parser/testdata/00933_alter_ttl/metadata.json b/parser/testdata/00933_alter_ttl/metadata.json index 9a504448b8..0967ef424b 100644 --- a/parser/testdata/00933_alter_ttl/metadata.json +++ b/parser/testdata/00933_alter_ttl/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt12": true, - "stmt4": true - } -} +{} diff --git a/parser/testdata/00976_ttl_with_old_parts/metadata.json b/parser/testdata/00976_ttl_with_old_parts/metadata.json index b563327205..0967ef424b 100644 --- a/parser/testdata/00976_ttl_with_old_parts/metadata.json +++ b/parser/testdata/00976_ttl_with_old_parts/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt7": true - } -} +{} diff --git a/parser/testdata/01070_materialize_ttl/metadata.json b/parser/testdata/01070_materialize_ttl/metadata.json index ede6d46fb3..d8562cd921 100644 --- a/parser/testdata/01070_materialize_ttl/metadata.json +++ b/parser/testdata/01070_materialize_ttl/metadata.json @@ -1,14 +1,10 @@ { "explain_todo": { - "stmt10": true, "stmt12": true, - "stmt17": true, "stmt18": true, - "stmt20": true, "stmt21": true, "stmt28": true, "stmt31": true, - "stmt36": true, "stmt37": true, "stmt40": true, "stmt9": true diff --git a/parser/testdata/01070_modify_ttl/metadata.json b/parser/testdata/01070_modify_ttl/metadata.json index a859f1f406..0967ef424b 100644 --- a/parser/testdata/01070_modify_ttl/metadata.json +++ b/parser/testdata/01070_modify_ttl/metadata.json @@ -1,8 +1 @@ -{ - "explain_todo": { - "stmt15": true, - "stmt18": true, - "stmt33": true, - "stmt9": true - } -} +{} diff --git a/parser/testdata/01070_modify_ttl_recalc_only/metadata.json b/parser/testdata/01070_modify_ttl_recalc_only/metadata.json index 56a1a55a2f..0967ef424b 100644 --- a/parser/testdata/01070_modify_ttl_recalc_only/metadata.json +++ b/parser/testdata/01070_modify_ttl_recalc_only/metadata.json @@ -1,8 +1 @@ -{ - "explain_todo": { - "stmt10": true, - "stmt19": true, - "stmt25": true, - "stmt47": true - } -} +{} diff --git a/parser/testdata/01070_mutations_with_dependencies/metadata.json b/parser/testdata/01070_mutations_with_dependencies/metadata.json index bf2aafed02..b367731225 100644 --- a/parser/testdata/01070_mutations_with_dependencies/metadata.json +++ b/parser/testdata/01070_mutations_with_dependencies/metadata.json @@ -2,7 +2,6 @@ "explain_todo": { "stmt21": true, "stmt26": true, - "stmt5": true, "stmt6": true } } diff --git a/parser/testdata/01378_alter_rename_with_ttl_zookeeper/metadata.json b/parser/testdata/01378_alter_rename_with_ttl_zookeeper/metadata.json index 08a237ec55..7ad5569408 100644 --- a/parser/testdata/01378_alter_rename_with_ttl_zookeeper/metadata.json +++ b/parser/testdata/01378_alter_rename_with_ttl_zookeeper/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt6": true, "stmt9": true } } diff --git a/parser/testdata/01652_ttl_old_syntax/metadata.json b/parser/testdata/01652_ttl_old_syntax/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/01652_ttl_old_syntax/metadata.json +++ b/parser/testdata/01652_ttl_old_syntax/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} diff --git a/parser/testdata/02265_per_table_ttl_mutation_on_change/metadata.json b/parser/testdata/02265_per_table_ttl_mutation_on_change/metadata.json index 6ee95645a9..0967ef424b 100644 --- a/parser/testdata/02265_per_table_ttl_mutation_on_change/metadata.json +++ b/parser/testdata/02265_per_table_ttl_mutation_on_change/metadata.json @@ -1,11 +1 @@ -{ - "explain_todo": { - "stmt10": true, - "stmt12": true, - "stmt14": true, - "stmt16": true, - "stmt4": true, - "stmt6": true, - "stmt8": true - } -} +{} diff --git a/parser/testdata/02296_ttl_non_deterministic/metadata.json b/parser/testdata/02296_ttl_non_deterministic/metadata.json index d02612666a..0967ef424b 100644 --- a/parser/testdata/02296_ttl_non_deterministic/metadata.json +++ b/parser/testdata/02296_ttl_non_deterministic/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt5": true, - "stmt8": true - } -} +{} diff --git a/parser/testdata/02484_substitute_udf_storage_args/metadata.json b/parser/testdata/02484_substitute_udf_storage_args/metadata.json index 0bb678734a..74d1fd2782 100644 --- a/parser/testdata/02484_substitute_udf_storage_args/metadata.json +++ b/parser/testdata/02484_substitute_udf_storage_args/metadata.json @@ -1,7 +1,6 @@ { "explain_todo": { "stmt10": true, - "stmt13": true, - "stmt16": true + "stmt13": true } } diff --git a/parser/testdata/02697_alter_dependencies/metadata.json b/parser/testdata/02697_alter_dependencies/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/02697_alter_dependencies/metadata.json +++ b/parser/testdata/02697_alter_dependencies/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} diff --git a/parser/testdata/03282_block_number_otehr_mutations/metadata.json b/parser/testdata/03282_block_number_otehr_mutations/metadata.json index 0438c9b85f..0967ef424b 100644 --- a/parser/testdata/03282_block_number_otehr_mutations/metadata.json +++ b/parser/testdata/03282_block_number_otehr_mutations/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt15": true - } -} +{} diff --git a/parser/testdata/03352_allow_suspicious_ttl/metadata.json b/parser/testdata/03352_allow_suspicious_ttl/metadata.json index afaaa4b0a6..0967ef424b 100644 --- a/parser/testdata/03352_allow_suspicious_ttl/metadata.json +++ b/parser/testdata/03352_allow_suspicious_ttl/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt7": true, - "stmt9": true - } -} +{} From a899fb69cd7be45506d8c95a0f774581a92cf46a Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 31 Dec 2025 07:35:24 +0000 Subject: [PATCH 12/24] Add GROUPING SETS support for EXPLAIN AST output Each grouping set element in GROUPING SETS clause needs to be wrapped in an ExpressionList in the EXPLAIN output. Added GroupingSets flag to SelectQuery AST to track when GROUPING SETS is used, and updated the explain code to output the wrapper when needed. Fixes 66 statements across 25 tests. --- ast/ast.go | 1 + internal/explain/select.go | 8 +++++++- parser/parser.go | 1 + .../testdata/01883_grouping_sets_crash/metadata.json | 1 - parser/testdata/01883_with_grouping_sets/metadata.json | 3 --- parser/testdata/02293_grouping_function/metadata.json | 10 +--------- parser/testdata/02343_group_by_use_nulls/metadata.json | 8 +------- .../02343_group_by_use_nulls_distributed/metadata.json | 7 +------ .../metadata.json | 1 - .../metadata.json | 6 +----- .../02534_analyzer_grouping_function/metadata.json | 9 +-------- .../02535_analyzer_group_by_use_nulls/metadata.json | 9 +-------- .../metadata.json | 7 +------ parser/testdata/02579_fill_empty_chunk/metadata.json | 6 +----- .../02579_fill_empty_chunk_analyzer/metadata.json | 6 +----- .../02835_fuzz_remove_redundant_sorting/metadata.json | 6 +----- parser/testdata/02917_transform_tsan/metadata.json | 6 +----- .../testdata/02932_group_by_null_fuzzer/metadata.json | 7 +------ .../metadata.json | 7 +------ .../02992_analyzer_group_by_const/metadata.json | 6 +----- .../metadata.json | 10 +--------- .../metadata.json | 6 +----- .../metadata.json | 3 +-- .../metadata.json | 10 +--------- .../testdata/03259_grouping_sets_aliases/metadata.json | 6 +----- .../testdata/03358_block_structure_match/metadata.json | 6 +----- .../03392_crash_group_by_use_nulls/metadata.json | 4 +--- .../metadata.json | 6 +----- 28 files changed, 31 insertions(+), 135 deletions(-) diff --git a/ast/ast.go b/ast/ast.go index 349d96ef75..4747fcbf73 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -64,6 +64,7 @@ type SelectQuery struct { PreWhere Expression `json:"prewhere,omitempty"` Where Expression `json:"where,omitempty"` GroupBy []Expression `json:"group_by,omitempty"` + GroupingSets bool `json:"grouping_sets,omitempty"` // true if GROUP BY uses GROUPING SETS WithRollup bool `json:"with_rollup,omitempty"` WithCube bool `json:"with_cube,omitempty"` WithTotals bool `json:"with_totals,omitempty"` diff --git a/internal/explain/select.go b/internal/explain/select.go index eb727de271..41541adfe0 100644 --- a/internal/explain/select.go +++ b/internal/explain/select.go @@ -100,7 +100,13 @@ func explainSelectQuery(sb *strings.Builder, n *ast.SelectQuery, indent string, if len(n.GroupBy) > 0 { fmt.Fprintf(sb, "%s ExpressionList (children %d)\n", indent, len(n.GroupBy)) for _, g := range n.GroupBy { - Node(sb, g, depth+2) + if n.GroupingSets { + // Each grouping set is wrapped in an ExpressionList + fmt.Fprintf(sb, "%s ExpressionList (children 1)\n", indent) + Node(sb, g, depth+3) + } else { + Node(sb, g, depth+2) + } } } // HAVING diff --git a/parser/parser.go b/parser/parser.go index e06a34f765..998a3d284b 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -534,6 +534,7 @@ func (p *Parser) parseSelect() *ast.SelectQuery { p.nextToken() // skip GROUPING p.nextToken() // skip SETS sel.GroupBy = p.parseGroupingSets() + sel.GroupingSets = true } else if p.currentIs(token.ROLLUP) && p.peekIs(token.LPAREN) { // ROLLUP(a, b, c) p.nextToken() // skip ROLLUP diff --git a/parser/testdata/01883_grouping_sets_crash/metadata.json b/parser/testdata/01883_grouping_sets_crash/metadata.json index f6006d38d7..516b488196 100644 --- a/parser/testdata/01883_grouping_sets_crash/metadata.json +++ b/parser/testdata/01883_grouping_sets_crash/metadata.json @@ -3,7 +3,6 @@ "stmt10": true, "stmt11": true, "stmt12": true, - "stmt13": true, "stmt14": true, "stmt4": true, "stmt6": true, diff --git a/parser/testdata/01883_with_grouping_sets/metadata.json b/parser/testdata/01883_with_grouping_sets/metadata.json index 5aea666c0b..27dc5556b2 100644 --- a/parser/testdata/01883_with_grouping_sets/metadata.json +++ b/parser/testdata/01883_with_grouping_sets/metadata.json @@ -3,9 +3,6 @@ "stmt10": true, "stmt11": true, "stmt12": true, - "stmt14": true, - "stmt15": true, - "stmt4": true, "stmt6": true, "stmt7": true, "stmt8": true, diff --git a/parser/testdata/02293_grouping_function/metadata.json b/parser/testdata/02293_grouping_function/metadata.json index 5835d389f1..b563327205 100644 --- a/parser/testdata/02293_grouping_function/metadata.json +++ b/parser/testdata/02293_grouping_function/metadata.json @@ -1,13 +1,5 @@ { "explain_todo": { - "stmt10": true, - "stmt2": true, - "stmt3": true, - "stmt4": true, - "stmt5": true, - "stmt6": true, - "stmt7": true, - "stmt8": true, - "stmt9": true + "stmt7": true } } diff --git a/parser/testdata/02343_group_by_use_nulls/metadata.json b/parser/testdata/02343_group_by_use_nulls/metadata.json index 2a5c198ffd..0967ef424b 100644 --- a/parser/testdata/02343_group_by_use_nulls/metadata.json +++ b/parser/testdata/02343_group_by_use_nulls/metadata.json @@ -1,7 +1 @@ -{ - "explain_todo": { - "stmt10": true, - "stmt6": true, - "stmt7": true - } -} +{} diff --git a/parser/testdata/02343_group_by_use_nulls_distributed/metadata.json b/parser/testdata/02343_group_by_use_nulls_distributed/metadata.json index ff0eba6904..0967ef424b 100644 --- a/parser/testdata/02343_group_by_use_nulls_distributed/metadata.json +++ b/parser/testdata/02343_group_by_use_nulls_distributed/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt6": true, - "stmt7": true - } -} +{} diff --git a/parser/testdata/02481_analyzer_optimize_grouping_sets_keys/metadata.json b/parser/testdata/02481_analyzer_optimize_grouping_sets_keys/metadata.json index 39429336f8..19830977ac 100644 --- a/parser/testdata/02481_analyzer_optimize_grouping_sets_keys/metadata.json +++ b/parser/testdata/02481_analyzer_optimize_grouping_sets_keys/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt3": true, "stmt4": true, "stmt5": true, "stmt6": true diff --git a/parser/testdata/02521_grouping_sets_plus_memory_efficient_aggr/metadata.json b/parser/testdata/02521_grouping_sets_plus_memory_efficient_aggr/metadata.json index ef58f80315..0967ef424b 100644 --- a/parser/testdata/02521_grouping_sets_plus_memory_efficient_aggr/metadata.json +++ b/parser/testdata/02521_grouping_sets_plus_memory_efficient_aggr/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt2": true - } -} +{} diff --git a/parser/testdata/02534_analyzer_grouping_function/metadata.json b/parser/testdata/02534_analyzer_grouping_function/metadata.json index b024a9978b..0967ef424b 100644 --- a/parser/testdata/02534_analyzer_grouping_function/metadata.json +++ b/parser/testdata/02534_analyzer_grouping_function/metadata.json @@ -1,8 +1 @@ -{ - "explain_todo": { - "stmt11": true, - "stmt12": true, - "stmt13": true, - "stmt14": true - } -} +{} diff --git a/parser/testdata/02535_analyzer_group_by_use_nulls/metadata.json b/parser/testdata/02535_analyzer_group_by_use_nulls/metadata.json index 554b434097..0967ef424b 100644 --- a/parser/testdata/02535_analyzer_group_by_use_nulls/metadata.json +++ b/parser/testdata/02535_analyzer_group_by_use_nulls/metadata.json @@ -1,8 +1 @@ -{ - "explain_todo": { - "stmt12": true, - "stmt16": true, - "stmt8": true, - "stmt9": true - } -} +{} diff --git a/parser/testdata/02541_analyzer_grouping_sets_crash_fix/metadata.json b/parser/testdata/02541_analyzer_grouping_sets_crash_fix/metadata.json index bc141058a4..0967ef424b 100644 --- a/parser/testdata/02541_analyzer_grouping_sets_crash_fix/metadata.json +++ b/parser/testdata/02541_analyzer_grouping_sets_crash_fix/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt2": true, - "stmt3": true - } -} +{} diff --git a/parser/testdata/02579_fill_empty_chunk/metadata.json b/parser/testdata/02579_fill_empty_chunk/metadata.json index 1295a45747..0967ef424b 100644 --- a/parser/testdata/02579_fill_empty_chunk/metadata.json +++ b/parser/testdata/02579_fill_empty_chunk/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt3": true - } -} +{} diff --git a/parser/testdata/02579_fill_empty_chunk_analyzer/metadata.json b/parser/testdata/02579_fill_empty_chunk_analyzer/metadata.json index 1295a45747..0967ef424b 100644 --- a/parser/testdata/02579_fill_empty_chunk_analyzer/metadata.json +++ b/parser/testdata/02579_fill_empty_chunk_analyzer/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt3": true - } -} +{} diff --git a/parser/testdata/02835_fuzz_remove_redundant_sorting/metadata.json b/parser/testdata/02835_fuzz_remove_redundant_sorting/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/02835_fuzz_remove_redundant_sorting/metadata.json +++ b/parser/testdata/02835_fuzz_remove_redundant_sorting/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} diff --git a/parser/testdata/02917_transform_tsan/metadata.json b/parser/testdata/02917_transform_tsan/metadata.json index e9d6e46171..0967ef424b 100644 --- a/parser/testdata/02917_transform_tsan/metadata.json +++ b/parser/testdata/02917_transform_tsan/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt1": true - } -} +{} diff --git a/parser/testdata/02932_group_by_null_fuzzer/metadata.json b/parser/testdata/02932_group_by_null_fuzzer/metadata.json index 9a8cc69c0b..0967ef424b 100644 --- a/parser/testdata/02932_group_by_null_fuzzer/metadata.json +++ b/parser/testdata/02932_group_by_null_fuzzer/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt2": true, - "stmt4": true - } -} +{} diff --git a/parser/testdata/02962_analyzer_resolve_group_by_on_shards/metadata.json b/parser/testdata/02962_analyzer_resolve_group_by_on_shards/metadata.json index 682bda1cbc..0967ef424b 100644 --- a/parser/testdata/02962_analyzer_resolve_group_by_on_shards/metadata.json +++ b/parser/testdata/02962_analyzer_resolve_group_by_on_shards/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt1": true, - "stmt2": true - } -} +{} diff --git a/parser/testdata/02992_analyzer_group_by_const/metadata.json b/parser/testdata/02992_analyzer_group_by_const/metadata.json index b563327205..0967ef424b 100644 --- a/parser/testdata/02992_analyzer_group_by_const/metadata.json +++ b/parser/testdata/02992_analyzer_group_by_const/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt7": true - } -} +{} diff --git a/parser/testdata/03013_group_by_use_nulls_with_materialize_and_analyzer/metadata.json b/parser/testdata/03013_group_by_use_nulls_with_materialize_and_analyzer/metadata.json index 0b3b120536..0967ef424b 100644 --- a/parser/testdata/03013_group_by_use_nulls_with_materialize_and_analyzer/metadata.json +++ b/parser/testdata/03013_group_by_use_nulls_with_materialize_and_analyzer/metadata.json @@ -1,9 +1 @@ -{ - "explain_todo": { - "stmt5": true, - "stmt6": true, - "stmt7": true, - "stmt8": true, - "stmt9": true - } -} +{} diff --git a/parser/testdata/03023_group_by_use_nulls_analyzer_crashes/metadata.json b/parser/testdata/03023_group_by_use_nulls_analyzer_crashes/metadata.json index 4a30edb046..ab9202e88e 100644 --- a/parser/testdata/03023_group_by_use_nulls_analyzer_crashes/metadata.json +++ b/parser/testdata/03023_group_by_use_nulls_analyzer_crashes/metadata.json @@ -1,9 +1,5 @@ { "explain_todo": { - "stmt11": true, - "stmt14": true, - "stmt15": true, - "stmt4": true, - "stmt5": true + "stmt11": true } } diff --git a/parser/testdata/03150_grouping_sets_use_nulls_pushdown/metadata.json b/parser/testdata/03150_grouping_sets_use_nulls_pushdown/metadata.json index 25308949f8..109ad8bb5d 100644 --- a/parser/testdata/03150_grouping_sets_use_nulls_pushdown/metadata.json +++ b/parser/testdata/03150_grouping_sets_use_nulls_pushdown/metadata.json @@ -5,7 +5,6 @@ "stmt5": true, "stmt6": true, "stmt7": true, - "stmt8": true, - "stmt9": true + "stmt8": true } } diff --git a/parser/testdata/03231_dynamic_variant_in_order_by_group_by/metadata.json b/parser/testdata/03231_dynamic_variant_in_order_by_group_by/metadata.json index b6ab32c03b..8eb3175658 100644 --- a/parser/testdata/03231_dynamic_variant_in_order_by_group_by/metadata.json +++ b/parser/testdata/03231_dynamic_variant_in_order_by_group_by/metadata.json @@ -1,14 +1,6 @@ { "explain_todo": { - "stmt101": true, - "stmt115": true, - "stmt126": true, "stmt17": true, - "stmt37": true, - "stmt48": true, - "stmt62": true, - "stmt73": true, - "stmt8": true, - "stmt90": true + "stmt8": true } } diff --git a/parser/testdata/03259_grouping_sets_aliases/metadata.json b/parser/testdata/03259_grouping_sets_aliases/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/03259_grouping_sets_aliases/metadata.json +++ b/parser/testdata/03259_grouping_sets_aliases/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} diff --git a/parser/testdata/03358_block_structure_match/metadata.json b/parser/testdata/03358_block_structure_match/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/03358_block_structure_match/metadata.json +++ b/parser/testdata/03358_block_structure_match/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} diff --git a/parser/testdata/03392_crash_group_by_use_nulls/metadata.json b/parser/testdata/03392_crash_group_by_use_nulls/metadata.json index f7c9a031b3..e9d6e46171 100644 --- a/parser/testdata/03392_crash_group_by_use_nulls/metadata.json +++ b/parser/testdata/03392_crash_group_by_use_nulls/metadata.json @@ -1,7 +1,5 @@ { "explain_todo": { - "stmt1": true, - "stmt2": true, - "stmt3": true + "stmt1": true } } diff --git a/parser/testdata/03749_table_function_argument_asterisk/metadata.json b/parser/testdata/03749_table_function_argument_asterisk/metadata.json index 3a06a4a1ac..0967ef424b 100644 --- a/parser/testdata/03749_table_function_argument_asterisk/metadata.json +++ b/parser/testdata/03749_table_function_argument_asterisk/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt5": true - } -} +{} From 5effbea4cc1e9fea133c3c92885a5d49a6fedf22 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 31 Dec 2025 07:45:00 +0000 Subject: [PATCH 13/24] Fix FORMAT clause handling in EXPLAIN statement output When EXPLAIN wraps a SELECT query with FORMAT clause, the FORMAT identifier should be a child of the Explain node, not the inner SelectWithUnionQuery. Updated explainExplainQuery to extract the format from the inner SelectQuery and output it as a sibling. Fixes 17 statements across 13 tests. --- internal/explain/statements.go | 24 ++++++++++++++++++- parser/testdata/01470_explain/metadata.json | 6 +---- .../metadata.json | 6 +---- .../metadata.json | 6 +---- .../metadata.json | 9 +------ .../metadata.json | 1 - .../02707_skip_index_with_in/metadata.json | 2 +- .../metadata.json | 7 +----- .../metadata.json | 6 +---- .../metadata.json | 6 +---- .../metadata.json | 6 +---- .../metadata.json | 1 - .../metadata.json | 6 +---- .../metadata.json | 6 +---- 14 files changed, 34 insertions(+), 58 deletions(-) diff --git a/internal/explain/statements.go b/internal/explain/statements.go index bf8a521a17..1ae59e551b 100644 --- a/internal/explain/statements.go +++ b/internal/explain/statements.go @@ -613,11 +613,30 @@ func explainExplainQuery(sb *strings.Builder, n *ast.ExplainQuery, indent string } return } - // Count children: settings (if present) + statement + + // Check if inner statement has FORMAT clause - this should be output as child of Explain + var format *ast.Identifier + if swu, ok := n.Statement.(*ast.SelectWithUnionQuery); ok { + for _, sel := range swu.Selects { + if sq, ok := sel.(*ast.SelectQuery); ok && sq.Format != nil { + format = sq.Format + // Temporarily nil out the format so it's not output by SelectWithUnionQuery + sq.Format = nil + defer func() { sq.Format = format }() + break + } + } + } + + // Count children: settings (if present) + statement + format (if present) children := 1 if n.HasSettings { children++ } + if format != nil { + children++ + } + // At top level (depth 0), ClickHouse outputs "Explain EXPLAIN " // Nested in subqueries, it outputs "Explain " if depth == 0 { @@ -629,6 +648,9 @@ func explainExplainQuery(sb *strings.Builder, n *ast.ExplainQuery, indent string fmt.Fprintf(sb, "%s Set\n", indent) } Node(sb, n.Statement, depth+1) + if format != nil { + fmt.Fprintf(sb, "%s Identifier %s\n", indent, format.Parts[len(format.Parts)-1]) + } } func explainShowQuery(sb *strings.Builder, n *ast.ShowQuery, indent string) { diff --git a/parser/testdata/01470_explain/metadata.json b/parser/testdata/01470_explain/metadata.json index e9d6e46171..0967ef424b 100644 --- a/parser/testdata/01470_explain/metadata.json +++ b/parser/testdata/01470_explain/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt1": true - } -} +{} diff --git a/parser/testdata/02271_fix_column_matcher_and_column_transformer/metadata.json b/parser/testdata/02271_fix_column_matcher_and_column_transformer/metadata.json index b563327205..0967ef424b 100644 --- a/parser/testdata/02271_fix_column_matcher_and_column_transformer/metadata.json +++ b/parser/testdata/02271_fix_column_matcher_and_column_transformer/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt7": true - } -} +{} diff --git a/parser/testdata/02421_exponential_join_rewrite_21557/metadata.json b/parser/testdata/02421_exponential_join_rewrite_21557/metadata.json index abe45ba24a..0967ef424b 100644 --- a/parser/testdata/02421_exponential_join_rewrite_21557/metadata.json +++ b/parser/testdata/02421_exponential_join_rewrite_21557/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt27": true - } -} +{} diff --git a/parser/testdata/02678_explain_pipeline_graph_with_projection/metadata.json b/parser/testdata/02678_explain_pipeline_graph_with_projection/metadata.json index 2dda3f42fa..0967ef424b 100644 --- a/parser/testdata/02678_explain_pipeline_graph_with_projection/metadata.json +++ b/parser/testdata/02678_explain_pipeline_graph_with_projection/metadata.json @@ -1,8 +1 @@ -{ - "explain_todo": { - "stmt4": true, - "stmt5": true, - "stmt6": true, - "stmt7": true - } -} +{} diff --git a/parser/testdata/02704_storage_merge_explain_graph_crash/metadata.json b/parser/testdata/02704_storage_merge_explain_graph_crash/metadata.json index ec09c7e10e..c45b7602ba 100644 --- a/parser/testdata/02704_storage_merge_explain_graph_crash/metadata.json +++ b/parser/testdata/02704_storage_merge_explain_graph_crash/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt11": true, "stmt12": true } } diff --git a/parser/testdata/02707_skip_index_with_in/metadata.json b/parser/testdata/02707_skip_index_with_in/metadata.json index cc2f3624ef..0967ef424b 100644 --- a/parser/testdata/02707_skip_index_with_in/metadata.json +++ b/parser/testdata/02707_skip_index_with_in/metadata.json @@ -1 +1 @@ -{"explain_todo":{"stmt4":true}} +{} diff --git a/parser/testdata/02780_final_streams_data_skipping_index/metadata.json b/parser/testdata/02780_final_streams_data_skipping_index/metadata.json index f6d9f2395b..0967ef424b 100644 --- a/parser/testdata/02780_final_streams_data_skipping_index/metadata.json +++ b/parser/testdata/02780_final_streams_data_skipping_index/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt7": true, - "stmt8": true - } -} +{} diff --git a/parser/testdata/02788_fix_logical_error_in_sorting/metadata.json b/parser/testdata/02788_fix_logical_error_in_sorting/metadata.json index c45b7602ba..0967ef424b 100644 --- a/parser/testdata/02788_fix_logical_error_in_sorting/metadata.json +++ b/parser/testdata/02788_fix_logical_error_in_sorting/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt12": true - } -} +{} diff --git a/parser/testdata/03023_group_by_use_nulls_analyzer_crashes/metadata.json b/parser/testdata/03023_group_by_use_nulls_analyzer_crashes/metadata.json index ab9202e88e..0967ef424b 100644 --- a/parser/testdata/03023_group_by_use_nulls_analyzer_crashes/metadata.json +++ b/parser/testdata/03023_group_by_use_nulls_analyzer_crashes/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt11": true - } -} +{} diff --git a/parser/testdata/03031_read_in_order_optimization_with_virtual_row_explain/metadata.json b/parser/testdata/03031_read_in_order_optimization_with_virtual_row_explain/metadata.json index 342b3ff5b4..0967ef424b 100644 --- a/parser/testdata/03031_read_in_order_optimization_with_virtual_row_explain/metadata.json +++ b/parser/testdata/03031_read_in_order_optimization_with_virtual_row_explain/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt8": true - } -} +{} diff --git a/parser/testdata/03176_check_timeout_in_index_analysis/metadata.json b/parser/testdata/03176_check_timeout_in_index_analysis/metadata.json index 8b0256d0ad..b563327205 100644 --- a/parser/testdata/03176_check_timeout_in_index_analysis/metadata.json +++ b/parser/testdata/03176_check_timeout_in_index_analysis/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt4": true, "stmt7": true } } diff --git a/parser/testdata/03289_explain_syntax_statistics/metadata.json b/parser/testdata/03289_explain_syntax_statistics/metadata.json index 3a06a4a1ac..0967ef424b 100644 --- a/parser/testdata/03289_explain_syntax_statistics/metadata.json +++ b/parser/testdata/03289_explain_syntax_statistics/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt5": true - } -} +{} diff --git a/parser/testdata/03611_point_in_polygon_key_condition_bug/metadata.json b/parser/testdata/03611_point_in_polygon_key_condition_bug/metadata.json index 1295a45747..0967ef424b 100644 --- a/parser/testdata/03611_point_in_polygon_key_condition_bug/metadata.json +++ b/parser/testdata/03611_point_in_polygon_key_condition_bug/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt3": true - } -} +{} From 7ff6679f6be977e3910783b3d5d41eccefbb3cc2 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 31 Dec 2025 07:56:51 +0000 Subject: [PATCH 14/24] Fix large string list handling in IN expressions Remove incorrect maxStringTupleSize limit that prevented large string lists in IN expressions from being combined into a single Tuple literal. ClickHouse EXPLAIN AST always outputs IN lists of strings as a single Literal Tuple_(...) regardless of size. Fixes 5 tests. --- internal/explain/functions.go | 71 ++++--------------- .../metadata.json | 6 +- .../metadata.json | 6 +- .../metadata.json | 6 +- .../metadata.json | 6 +- .../03535_system_formats/metadata.json | 6 +- 6 files changed, 17 insertions(+), 84 deletions(-) diff --git a/internal/explain/functions.go b/internal/explain/functions.go index e1e1f27251..e53dda965b 100644 --- a/internal/explain/functions.go +++ b/internal/explain/functions.go @@ -419,12 +419,9 @@ func explainInExpr(sb *strings.Builder, n *ast.InExpr, indent string, depth int) // Determine if the IN list should be combined into a single tuple literal // This happens when we have multiple literals of compatible types: // - All numeric literals/expressions (integers/floats, including unary minus) - // - All string literals (only for small lists, max 10 items) + // - All string literals // - All tuple literals that contain only primitive literals (recursively) canBeTupleLiteral := false - // Only combine strings into tuple for small lists (up to 10 items) - // Large string lists are kept as separate children in ClickHouse EXPLAIN AST - const maxStringTupleSize = 10 if n.Query == nil && len(n.List) > 1 { allNumeric := true allStrings := true @@ -457,9 +454,8 @@ func explainInExpr(sb *strings.Builder, n *ast.InExpr, indent string, depth int) break } } - // For strings, only combine if list is small enough // For tuples, only combine if all contain primitive literals - canBeTupleLiteral = allNumeric || (allStrings && len(n.List) <= maxStringTupleSize) || (allTuples && allTuplesArePrimitive) + canBeTupleLiteral = allNumeric || allStrings || (allTuples && allTuplesArePrimitive) } // Count arguments: expr + list items or subquery @@ -479,21 +475,8 @@ func explainInExpr(sb *strings.Builder, n *ast.InExpr, indent string, depth int) argCount += len(n.List) } } else { - // Check if all items are string literals (large list case - no wrapper) - allStringLiterals := true - for _, item := range n.List { - if lit, ok := item.(*ast.Literal); !ok || lit.Type != ast.LiteralString { - allStringLiterals = false - break - } - } - if allStringLiterals { - // Large string list - separate children - argCount += len(n.List) - } else { - // Non-string items get wrapped in a single Function tuple - argCount++ - } + // Non-string items get wrapped in a single Function tuple + argCount++ } } fmt.Fprintf(sb, "%s ExpressionList (children %d)\n", indent, argCount) @@ -540,26 +523,11 @@ func explainInExpr(sb *strings.Builder, n *ast.InExpr, indent string, depth int) explainTupleInInList(sb, item.(*ast.Literal), indent+" ", depth+4) } } else { - // Check if all items are string literals (large list case) - allStringLiterals := true + // Wrap non-literal/non-tuple list items in Function tuple + fmt.Fprintf(sb, "%s Function tuple (children %d)\n", indent, 1) + fmt.Fprintf(sb, "%s ExpressionList (children %d)\n", indent, len(n.List)) for _, item := range n.List { - if lit, ok := item.(*ast.Literal); !ok || lit.Type != ast.LiteralString { - allStringLiterals = false - break - } - } - if allStringLiterals { - // Large string list - output as separate children (no tuple wrapper) - for _, item := range n.List { - Node(sb, item, depth+2) - } - } else { - // Wrap non-literal/non-tuple list items in Function tuple - fmt.Fprintf(sb, "%s Function tuple (children %d)\n", indent, 1) - fmt.Fprintf(sb, "%s ExpressionList (children %d)\n", indent, len(n.List)) - for _, item := range n.List { - Node(sb, item, depth+4) - } + Node(sb, item, depth+4) } } } @@ -705,26 +673,11 @@ func explainInExprWithAlias(sb *strings.Builder, n *ast.InExpr, alias string, in explainTupleInInList(sb, item.(*ast.Literal), indent+" ", depth+4) } } else { - // Check if all items are string literals (large list case) - allStringLiterals := true + // Wrap non-literal/non-tuple list items in Function tuple + fmt.Fprintf(sb, "%s Function tuple (children %d)\n", indent, 1) + fmt.Fprintf(sb, "%s ExpressionList (children %d)\n", indent, len(n.List)) for _, item := range n.List { - if lit, ok := item.(*ast.Literal); !ok || lit.Type != ast.LiteralString { - allStringLiterals = false - break - } - } - if allStringLiterals { - // Large string list - output as separate children (no tuple wrapper) - for _, item := range n.List { - Node(sb, item, depth+2) - } - } else { - // Wrap non-literal/non-tuple list items in Function tuple - fmt.Fprintf(sb, "%s Function tuple (children %d)\n", indent, 1) - fmt.Fprintf(sb, "%s ExpressionList (children %d)\n", indent, len(n.List)) - for _, item := range n.List { - Node(sb, item, depth+4) - } + Node(sb, item, depth+4) } } } diff --git a/parser/testdata/02414_all_new_table_functions_must_be_documented/metadata.json b/parser/testdata/02414_all_new_table_functions_must_be_documented/metadata.json index e9d6e46171..0967ef424b 100644 --- a/parser/testdata/02414_all_new_table_functions_must_be_documented/metadata.json +++ b/parser/testdata/02414_all_new_table_functions_must_be_documented/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt1": true - } -} +{} diff --git a/parser/testdata/02415_all_new_functions_must_be_documented/metadata.json b/parser/testdata/02415_all_new_functions_must_be_documented/metadata.json index e9d6e46171..0967ef424b 100644 --- a/parser/testdata/02415_all_new_functions_must_be_documented/metadata.json +++ b/parser/testdata/02415_all_new_functions_must_be_documented/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt1": true - } -} +{} diff --git a/parser/testdata/02415_all_new_functions_must_have_version_information/metadata.json b/parser/testdata/02415_all_new_functions_must_have_version_information/metadata.json index e9d6e46171..0967ef424b 100644 --- a/parser/testdata/02415_all_new_functions_must_have_version_information/metadata.json +++ b/parser/testdata/02415_all_new_functions_must_have_version_information/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt1": true - } -} +{} diff --git a/parser/testdata/02992_all_columns_should_have_comment/metadata.json b/parser/testdata/02992_all_columns_should_have_comment/metadata.json index ef58f80315..0967ef424b 100644 --- a/parser/testdata/02992_all_columns_should_have_comment/metadata.json +++ b/parser/testdata/02992_all_columns_should_have_comment/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt2": true - } -} +{} diff --git a/parser/testdata/03535_system_formats/metadata.json b/parser/testdata/03535_system_formats/metadata.json index e9d6e46171..0967ef424b 100644 --- a/parser/testdata/03535_system_formats/metadata.json +++ b/parser/testdata/03535_system_formats/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt1": true - } -} +{} From 259d66316e62c291d807c7a20f24e8a843fe2deb Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 31 Dec 2025 08:09:21 +0000 Subject: [PATCH 15/24] Fix GROUPING SETS tuple unwrapping in EXPLAIN output When outputting GROUPING SETS elements, unwrap tuple literals to output their elements directly with correct child counts instead of wrapping in ExpressionList(children 1) and outputting as Function tuple. Fixes tests for GROUPING SETS queries across 12 test files. --- internal/explain/select.go | 19 +++++++++++++++++-- .../metadata.json | 6 +----- .../02304_grouping_set_order_by/metadata.json | 6 +----- .../metadata.json | 8 +------- .../metadata.json | 11 +---------- .../metadata.json | 6 +----- .../metadata.json | 8 +------- .../metadata.json | 6 +----- .../metadata.json | 11 +---------- parser/testdata/03168_cld2_tsan/metadata.json | 6 +----- .../metadata.json | 6 +----- .../metadata.json | 2 +- .../metadata.json | 8 +------- 13 files changed, 29 insertions(+), 74 deletions(-) diff --git a/internal/explain/select.go b/internal/explain/select.go index 41541adfe0..b37cc62a6e 100644 --- a/internal/explain/select.go +++ b/internal/explain/select.go @@ -102,8 +102,23 @@ func explainSelectQuery(sb *strings.Builder, n *ast.SelectQuery, indent string, for _, g := range n.GroupBy { if n.GroupingSets { // Each grouping set is wrapped in an ExpressionList - fmt.Fprintf(sb, "%s ExpressionList (children 1)\n", indent) - Node(sb, g, depth+3) + // but we need to unwrap tuples and output elements directly + if lit, ok := g.(*ast.Literal); ok && lit.Type == ast.LiteralTuple { + if elements, ok := lit.Value.([]ast.Expression); ok { + fmt.Fprintf(sb, "%s ExpressionList (children %d)\n", indent, len(elements)) + for _, elem := range elements { + Node(sb, elem, depth+3) + } + } else { + // Fallback for unexpected tuple value type + fmt.Fprintf(sb, "%s ExpressionList (children 1)\n", indent) + Node(sb, g, depth+3) + } + } else { + // Single expression grouping set + fmt.Fprintf(sb, "%s ExpressionList (children 1)\n", indent) + Node(sb, g, depth+3) + } } else { Node(sb, g, depth+2) } diff --git a/parser/testdata/01710_aggregate_projection_with_grouping_set/metadata.json b/parser/testdata/01710_aggregate_projection_with_grouping_set/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/01710_aggregate_projection_with_grouping_set/metadata.json +++ b/parser/testdata/01710_aggregate_projection_with_grouping_set/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} diff --git a/parser/testdata/02304_grouping_set_order_by/metadata.json b/parser/testdata/02304_grouping_set_order_by/metadata.json index e9d6e46171..0967ef424b 100644 --- a/parser/testdata/02304_grouping_set_order_by/metadata.json +++ b/parser/testdata/02304_grouping_set_order_by/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt1": true - } -} +{} diff --git a/parser/testdata/02481_analyzer_optimize_grouping_sets_keys/metadata.json b/parser/testdata/02481_analyzer_optimize_grouping_sets_keys/metadata.json index 19830977ac..0967ef424b 100644 --- a/parser/testdata/02481_analyzer_optimize_grouping_sets_keys/metadata.json +++ b/parser/testdata/02481_analyzer_optimize_grouping_sets_keys/metadata.json @@ -1,7 +1 @@ -{ - "explain_todo": { - "stmt4": true, - "stmt5": true, - "stmt6": true - } -} +{} diff --git a/parser/testdata/02554_fix_grouping_sets_predicate_push_down/metadata.json b/parser/testdata/02554_fix_grouping_sets_predicate_push_down/metadata.json index 0a3175509f..0967ef424b 100644 --- a/parser/testdata/02554_fix_grouping_sets_predicate_push_down/metadata.json +++ b/parser/testdata/02554_fix_grouping_sets_predicate_push_down/metadata.json @@ -1,10 +1 @@ -{ - "explain_todo": { - "stmt10": true, - "stmt13": true, - "stmt16": true, - "stmt17": true, - "stmt6": true, - "stmt9": true - } -} +{} diff --git a/parser/testdata/02705_grouping_keys_equal_keys/metadata.json b/parser/testdata/02705_grouping_keys_equal_keys/metadata.json index e9d6e46171..0967ef424b 100644 --- a/parser/testdata/02705_grouping_keys_equal_keys/metadata.json +++ b/parser/testdata/02705_grouping_keys_equal_keys/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt1": true - } -} +{} diff --git a/parser/testdata/03014_group_by_use_nulls_injective_functions_and_analyzer/metadata.json b/parser/testdata/03014_group_by_use_nulls_injective_functions_and_analyzer/metadata.json index fffcb7d38b..0967ef424b 100644 --- a/parser/testdata/03014_group_by_use_nulls_injective_functions_and_analyzer/metadata.json +++ b/parser/testdata/03014_group_by_use_nulls_injective_functions_and_analyzer/metadata.json @@ -1,7 +1 @@ -{ - "explain_todo": { - "stmt2": true, - "stmt3": true, - "stmt4": true - } -} +{} diff --git a/parser/testdata/03023_analyzer_optimize_group_by_function_keys_with_nulls/metadata.json b/parser/testdata/03023_analyzer_optimize_group_by_function_keys_with_nulls/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/03023_analyzer_optimize_group_by_function_keys_with_nulls/metadata.json +++ b/parser/testdata/03023_analyzer_optimize_group_by_function_keys_with_nulls/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} diff --git a/parser/testdata/03150_grouping_sets_use_nulls_pushdown/metadata.json b/parser/testdata/03150_grouping_sets_use_nulls_pushdown/metadata.json index 109ad8bb5d..0967ef424b 100644 --- a/parser/testdata/03150_grouping_sets_use_nulls_pushdown/metadata.json +++ b/parser/testdata/03150_grouping_sets_use_nulls_pushdown/metadata.json @@ -1,10 +1 @@ -{ - "explain_todo": { - "stmt10": true, - "stmt11": true, - "stmt5": true, - "stmt6": true, - "stmt7": true, - "stmt8": true - } -} +{} diff --git a/parser/testdata/03168_cld2_tsan/metadata.json b/parser/testdata/03168_cld2_tsan/metadata.json index e9d6e46171..0967ef424b 100644 --- a/parser/testdata/03168_cld2_tsan/metadata.json +++ b/parser/testdata/03168_cld2_tsan/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt1": true - } -} +{} diff --git a/parser/testdata/03228_dynamic_serializations_uninitialized_value/metadata.json b/parser/testdata/03228_dynamic_serializations_uninitialized_value/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/03228_dynamic_serializations_uninitialized_value/metadata.json +++ b/parser/testdata/03228_dynamic_serializations_uninitialized_value/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} diff --git a/parser/testdata/03305_mergine_aggregated_filter_push_down/metadata.json b/parser/testdata/03305_mergine_aggregated_filter_push_down/metadata.json index d281969467..0967ef424b 100644 --- a/parser/testdata/03305_mergine_aggregated_filter_push_down/metadata.json +++ b/parser/testdata/03305_mergine_aggregated_filter_push_down/metadata.json @@ -1 +1 @@ -{"explain_todo":{"stmt10":true,"stmt11":true,"stmt15":true,"stmt16":true,"stmt8":true,"stmt9":true}} +{} diff --git a/parser/testdata/03447_grouping_sets_analyzer_const_columns/metadata.json b/parser/testdata/03447_grouping_sets_analyzer_const_columns/metadata.json index d5e9483c45..0967ef424b 100644 --- a/parser/testdata/03447_grouping_sets_analyzer_const_columns/metadata.json +++ b/parser/testdata/03447_grouping_sets_analyzer_const_columns/metadata.json @@ -1,7 +1 @@ -{ - "explain_todo": { - "stmt3": true, - "stmt5": true, - "stmt7": true - } -} +{} From 4ff9272b64d26140d410d9a4c5f82bc67bb6ed22 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 31 Dec 2025 08:25:41 +0000 Subject: [PATCH 16/24] Fix GROUPING SETS tuple unwrapping and add TOP clause support - Fixed GROUPING SETS handling to unwrap tuple literals and output elements directly with correct child counts - Added TOP clause support to SELECT parser (use MUL_PREC to stop at *) - Added TOP clause output to EXPLAIN AST at end of SelectQuery - Updated 3 GROUPING SETS tests that now pass The TOP fix prevents `SELECT TOP 5 * FROM t` from being misparsed as `TOP (5 * FROM t)` where * was treated as multiplication. --- internal/explain/select.go | 8 ++++++++ parser/parser.go | 3 ++- parser/testdata/01883_grouping_sets_crash/metadata.json | 9 +-------- parser/testdata/01883_with_grouping_sets/metadata.json | 6 ------ .../metadata.json | 6 +----- 5 files changed, 12 insertions(+), 20 deletions(-) diff --git a/internal/explain/select.go b/internal/explain/select.go index b37cc62a6e..99b1a83423 100644 --- a/internal/explain/select.go +++ b/internal/explain/select.go @@ -181,6 +181,10 @@ func explainSelectQuery(sb *strings.Builder, n *ast.SelectQuery, indent string, if len(n.Settings) > 0 && !n.SettingsAfterFormat { fmt.Fprintf(sb, "%s Set\n", indent) } + // TOP clause is output at the end + if n.Top != nil { + Node(sb, n.Top, depth+1) + } } func explainOrderByElement(sb *strings.Builder, n *ast.OrderByElement, indent string, depth int) { @@ -355,5 +359,9 @@ func countSelectQueryChildren(n *ast.SelectQuery) int { if len(n.Settings) > 0 && !n.SettingsAfterFormat { count++ } + // TOP clause + if n.Top != nil { + count++ + } return count } diff --git a/parser/parser.go b/parser/parser.go index 998a3d284b..e94f7af8e8 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -492,7 +492,8 @@ func (p *Parser) parseSelect() *ast.SelectQuery { // Handle TOP if p.currentIs(token.TOP) { p.nextToken() - sel.Top = p.parseExpression(LOWEST) + // Use MUL_PREC to stop at * (which would be parsed as column selector, not multiplication) + sel.Top = p.parseExpression(MUL_PREC) } // Parse column list diff --git a/parser/testdata/01883_grouping_sets_crash/metadata.json b/parser/testdata/01883_grouping_sets_crash/metadata.json index 516b488196..dbdbb76d4f 100644 --- a/parser/testdata/01883_grouping_sets_crash/metadata.json +++ b/parser/testdata/01883_grouping_sets_crash/metadata.json @@ -1,12 +1,5 @@ { "explain_todo": { - "stmt10": true, - "stmt11": true, - "stmt12": true, - "stmt14": true, - "stmt4": true, - "stmt6": true, - "stmt8": true, - "stmt9": true + "stmt6": true } } diff --git a/parser/testdata/01883_with_grouping_sets/metadata.json b/parser/testdata/01883_with_grouping_sets/metadata.json index 27dc5556b2..7ad5569408 100644 --- a/parser/testdata/01883_with_grouping_sets/metadata.json +++ b/parser/testdata/01883_with_grouping_sets/metadata.json @@ -1,11 +1,5 @@ { "explain_todo": { - "stmt10": true, - "stmt11": true, - "stmt12": true, - "stmt6": true, - "stmt7": true, - "stmt8": true, "stmt9": true } } diff --git a/parser/testdata/02313_group_by_modifiers_with_non_default_types/metadata.json b/parser/testdata/02313_group_by_modifiers_with_non_default_types/metadata.json index dbdbb76d4f..0967ef424b 100644 --- a/parser/testdata/02313_group_by_modifiers_with_non_default_types/metadata.json +++ b/parser/testdata/02313_group_by_modifiers_with_non_default_types/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt6": true - } -} +{} From 3adff40eb0a26c43c9734c1d23713625e138548b Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 31 Dec 2025 08:32:42 +0000 Subject: [PATCH 17/24] Update metadata: TOP clause test now passes 00834_limit_with_constant_expressions stmt16 (SELECT TOP) now passes after the TOP clause parsing and EXPLAIN support added in previous commit. --- .../00834_limit_with_constant_expressions/metadata.json | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/parser/testdata/00834_limit_with_constant_expressions/metadata.json b/parser/testdata/00834_limit_with_constant_expressions/metadata.json index 7b4455cd5f..0967ef424b 100644 --- a/parser/testdata/00834_limit_with_constant_expressions/metadata.json +++ b/parser/testdata/00834_limit_with_constant_expressions/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt16": true - } -} +{} From 42938980c7b15fee175671e119ee06daa6446565 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 31 Dec 2025 08:39:49 +0000 Subject: [PATCH 18/24] Support join strictness after type (RIGHT ANTI JOIN) ClickHouse allows join strictness modifiers (ANTI, SEMI, ANY, ALL, ASOF) either before or after the join type. This fix adds support for parsing strictness after the type, enabling queries like: - RIGHT ANTI JOIN - LEFT SEMI JOIN etc. 10 tests now pass with this fix. --- parser/parser.go | 21 +++++++++++++++++++ .../02724_mutliple_storage_join/metadata.json | 7 +------ .../02769_compare_functions_nan/metadata.json | 6 +----- .../metadata.json | 6 +----- .../metadata.json | 9 +------- .../metadata.json | 5 +---- .../metadata.json | 2 +- .../03580_join_runtime_filter/metadata.json | 4 +--- .../metadata.json | 7 +------ .../metadata.json | 6 +----- .../metadata.json | 15 +------------ 11 files changed, 31 insertions(+), 57 deletions(-) diff --git a/parser/parser.go b/parser/parser.go index e94f7af8e8..71b635262c 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -1004,6 +1004,27 @@ func (p *Parser) parseTableElementWithJoin() *ast.TablesInSelectQueryElement { join.Type = ast.JoinInner } + // Parse strictness after type if not already parsed (e.g., RIGHT ANTI JOIN) + if join.Strictness == "" { + switch p.current.Token { + case token.ANY: + join.Strictness = ast.JoinStrictAny + p.nextToken() + case token.ALL: + join.Strictness = ast.JoinStrictAll + p.nextToken() + case token.ASOF: + join.Strictness = ast.JoinStrictAsof + p.nextToken() + case token.SEMI: + join.Strictness = ast.JoinStrictSemi + p.nextToken() + case token.ANTI: + join.Strictness = ast.JoinStrictAnti + p.nextToken() + } + } + if !p.expect(token.JOIN) { return nil } diff --git a/parser/testdata/02724_mutliple_storage_join/metadata.json b/parser/testdata/02724_mutliple_storage_join/metadata.json index f6d9f2395b..0967ef424b 100644 --- a/parser/testdata/02724_mutliple_storage_join/metadata.json +++ b/parser/testdata/02724_mutliple_storage_join/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt7": true, - "stmt8": true - } -} +{} diff --git a/parser/testdata/02769_compare_functions_nan/metadata.json b/parser/testdata/02769_compare_functions_nan/metadata.json index 7974f6a182..0967ef424b 100644 --- a/parser/testdata/02769_compare_functions_nan/metadata.json +++ b/parser/testdata/02769_compare_functions_nan/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt24": true - } -} +{} diff --git a/parser/testdata/03015_aggregator_empty_data_multiple_blocks/metadata.json b/parser/testdata/03015_aggregator_empty_data_multiple_blocks/metadata.json index 1295a45747..0967ef424b 100644 --- a/parser/testdata/03015_aggregator_empty_data_multiple_blocks/metadata.json +++ b/parser/testdata/03015_aggregator_empty_data_multiple_blocks/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt3": true - } -} +{} diff --git a/parser/testdata/03211_convert_outer_join_to_inner_join_anti_join/metadata.json b/parser/testdata/03211_convert_outer_join_to_inner_join_anti_join/metadata.json index 762730d42a..0967ef424b 100644 --- a/parser/testdata/03211_convert_outer_join_to_inner_join_anti_join/metadata.json +++ b/parser/testdata/03211_convert_outer_join_to_inner_join_anti_join/metadata.json @@ -1,8 +1 @@ -{ - "explain_todo": { - "stmt10": true, - "stmt13": true, - "stmt16": true, - "stmt8": true - } -} +{} diff --git a/parser/testdata/03214_join_on_tuple_comparison_elimination_bug/metadata.json b/parser/testdata/03214_join_on_tuple_comparison_elimination_bug/metadata.json index 612a5b7592..342b3ff5b4 100644 --- a/parser/testdata/03214_join_on_tuple_comparison_elimination_bug/metadata.json +++ b/parser/testdata/03214_join_on_tuple_comparison_elimination_bug/metadata.json @@ -1,8 +1,5 @@ { "explain_todo": { - "stmt10": true, - "stmt7": true, - "stmt8": true, - "stmt9": true + "stmt8": true } } diff --git a/parser/testdata/03402_concurrent_right_full_join/metadata.json b/parser/testdata/03402_concurrent_right_full_join/metadata.json index 040cedf646..0967ef424b 100644 --- a/parser/testdata/03402_concurrent_right_full_join/metadata.json +++ b/parser/testdata/03402_concurrent_right_full_join/metadata.json @@ -1 +1 @@ -{"explain_todo":{"stmt24":true}} +{} diff --git a/parser/testdata/03580_join_runtime_filter/metadata.json b/parser/testdata/03580_join_runtime_filter/metadata.json index 0c28d09e0c..5cf734c28d 100644 --- a/parser/testdata/03580_join_runtime_filter/metadata.json +++ b/parser/testdata/03580_join_runtime_filter/metadata.json @@ -4,8 +4,6 @@ "stmt28": true, "stmt30": true, "stmt32": true, - "stmt33": true, - "stmt34": true, - "stmt35": true + "stmt34": true } } diff --git a/parser/testdata/03623_convert_any_join_to_semi_or_anti_2/metadata.json b/parser/testdata/03623_convert_any_join_to_semi_or_anti_2/metadata.json index 92e84e943a..0967ef424b 100644 --- a/parser/testdata/03623_convert_any_join_to_semi_or_anti_2/metadata.json +++ b/parser/testdata/03623_convert_any_join_to_semi_or_anti_2/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt8": true, - "stmt9": true - } -} +{} diff --git a/parser/testdata/03708_analyzer_convert_any_outer_to_inner_2/metadata.json b/parser/testdata/03708_analyzer_convert_any_outer_to_inner_2/metadata.json index 5e95da978c..c45b7602ba 100644 --- a/parser/testdata/03708_analyzer_convert_any_outer_to_inner_2/metadata.json +++ b/parser/testdata/03708_analyzer_convert_any_outer_to_inner_2/metadata.json @@ -1,9 +1,5 @@ { "explain_todo": { - "stmt10": true, - "stmt11": true, - "stmt12": true, - "stmt8": true, - "stmt9": true + "stmt12": true } } diff --git a/parser/testdata/03733_anti_join_runtime_filter_3/metadata.json b/parser/testdata/03733_anti_join_runtime_filter_3/metadata.json index 61557fb286..0967ef424b 100644 --- a/parser/testdata/03733_anti_join_runtime_filter_3/metadata.json +++ b/parser/testdata/03733_anti_join_runtime_filter_3/metadata.json @@ -1,14 +1 @@ -{ - "explain_todo": { - "stmt14": true, - "stmt15": true, - "stmt17": true, - "stmt18": true, - "stmt20": true, - "stmt21": true, - "stmt23": true, - "stmt24": true, - "stmt27": true, - "stmt28": true - } -} +{} From d57311ff3cdec02334cc25303ec0aacaf858a05a Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 31 Dec 2025 08:43:55 +0000 Subject: [PATCH 19/24] Support column definitions in CREATE VIEW statements Add parsing of column list after view name in CREATE VIEW, e.g.: CREATE VIEW v (x UInt64) AS SELECT * FROM table This enables views to specify column types for the view columns. 14 tests now pass with this fix. --- parser/parser.go | 17 +++++++++++++++++ .../testdata/01124_view_bad_types/metadata.json | 6 +----- .../01798_uniq_theta_sketch/metadata.json | 6 +----- .../02184_default_table_engine/metadata.json | 2 -- .../testdata/02242_join_rocksdb/metadata.json | 9 +-------- .../metadata.json | 3 +-- .../metadata.json | 6 +----- .../metadata.json | 6 +----- .../02842_truncate_database/metadata.json | 5 ----- .../testdata/02916_set_formatting/metadata.json | 6 +----- parser/testdata/02968_url_args/metadata.json | 9 +-------- .../02982_create_mv_inner_extra/metadata.json | 1 - .../03010_view_prewhere_in/metadata.json | 6 +----- .../metadata.json | 6 +----- .../metadata.json | 7 +------ 15 files changed, 28 insertions(+), 67 deletions(-) diff --git a/parser/parser.go b/parser/parser.go index 71b635262c..c30388d48f 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -1927,6 +1927,23 @@ func (p *Parser) parseCreateView(create *ast.CreateQuery) { } } + // Parse column definitions (e.g., CREATE VIEW v (x UInt64) AS SELECT ...) + if p.currentIs(token.LPAREN) { + p.nextToken() + for !p.currentIs(token.RPAREN) && !p.currentIs(token.EOF) { + col := p.parseColumnDeclaration() + if col != nil { + create.Columns = append(create.Columns, col) + } + if p.currentIs(token.COMMA) { + p.nextToken() + } else { + break + } + } + p.expect(token.RPAREN) + } + // Handle ON CLUSTER if p.currentIs(token.ON) { p.nextToken() diff --git a/parser/testdata/01124_view_bad_types/metadata.json b/parser/testdata/01124_view_bad_types/metadata.json index 3a06a4a1ac..0967ef424b 100644 --- a/parser/testdata/01124_view_bad_types/metadata.json +++ b/parser/testdata/01124_view_bad_types/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt5": true - } -} +{} diff --git a/parser/testdata/01798_uniq_theta_sketch/metadata.json b/parser/testdata/01798_uniq_theta_sketch/metadata.json index 30faaf592d..0967ef424b 100644 --- a/parser/testdata/01798_uniq_theta_sketch/metadata.json +++ b/parser/testdata/01798_uniq_theta_sketch/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt64": true - } -} +{} diff --git a/parser/testdata/02184_default_table_engine/metadata.json b/parser/testdata/02184_default_table_engine/metadata.json index 62efe4ca41..319dd860f8 100644 --- a/parser/testdata/02184_default_table_engine/metadata.json +++ b/parser/testdata/02184_default_table_engine/metadata.json @@ -3,8 +3,6 @@ "stmt107": true, "stmt114": true, "stmt26": true, - "stmt36": true, - "stmt37": true, "stmt46": true, "stmt56": true, "stmt61": true, diff --git a/parser/testdata/02242_join_rocksdb/metadata.json b/parser/testdata/02242_join_rocksdb/metadata.json index 713ed400fd..0967ef424b 100644 --- a/parser/testdata/02242_join_rocksdb/metadata.json +++ b/parser/testdata/02242_join_rocksdb/metadata.json @@ -1,8 +1 @@ -{ - "explain_todo": { - "stmt16": true, - "stmt18": true, - "stmt39": true, - "stmt40": true - } -} +{} diff --git a/parser/testdata/02291_dictionary_scalar_subquery_reload/metadata.json b/parser/testdata/02291_dictionary_scalar_subquery_reload/metadata.json index 3a352d68aa..f4c74e32be 100644 --- a/parser/testdata/02291_dictionary_scalar_subquery_reload/metadata.json +++ b/parser/testdata/02291_dictionary_scalar_subquery_reload/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt10": true, - "stmt4": true + "stmt10": true } } diff --git a/parser/testdata/02501_limits_on_result_for_view/metadata.json b/parser/testdata/02501_limits_on_result_for_view/metadata.json index dbdbb76d4f..0967ef424b 100644 --- a/parser/testdata/02501_limits_on_result_for_view/metadata.json +++ b/parser/testdata/02501_limits_on_result_for_view/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt6": true - } -} +{} diff --git a/parser/testdata/02797_aggregator_huge_mem_usage_bug/metadata.json b/parser/testdata/02797_aggregator_huge_mem_usage_bug/metadata.json index ef58f80315..0967ef424b 100644 --- a/parser/testdata/02797_aggregator_huge_mem_usage_bug/metadata.json +++ b/parser/testdata/02797_aggregator_huge_mem_usage_bug/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt2": true - } -} +{} diff --git a/parser/testdata/02842_truncate_database/metadata.json b/parser/testdata/02842_truncate_database/metadata.json index ea9a0ddfed..857cf4b2dc 100644 --- a/parser/testdata/02842_truncate_database/metadata.json +++ b/parser/testdata/02842_truncate_database/metadata.json @@ -1,10 +1,5 @@ { "explain_todo": { - "stmt16": true, - "stmt17": true, - "stmt18": true, - "stmt19": true, - "stmt20": true, "stmt32": true, "stmt33": true, "stmt43": true diff --git a/parser/testdata/02916_set_formatting/metadata.json b/parser/testdata/02916_set_formatting/metadata.json index dbdbb76d4f..0967ef424b 100644 --- a/parser/testdata/02916_set_formatting/metadata.json +++ b/parser/testdata/02916_set_formatting/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt6": true - } -} +{} diff --git a/parser/testdata/02968_url_args/metadata.json b/parser/testdata/02968_url_args/metadata.json index 7ba6cd1a5d..0967ef424b 100644 --- a/parser/testdata/02968_url_args/metadata.json +++ b/parser/testdata/02968_url_args/metadata.json @@ -1,8 +1 @@ -{ - "explain_todo": { - "stmt11": true, - "stmt13": true, - "stmt15": true, - "stmt9": true - } -} +{} diff --git a/parser/testdata/02982_create_mv_inner_extra/metadata.json b/parser/testdata/02982_create_mv_inner_extra/metadata.json index 5e95da978c..daf05a4474 100644 --- a/parser/testdata/02982_create_mv_inner_extra/metadata.json +++ b/parser/testdata/02982_create_mv_inner_extra/metadata.json @@ -2,7 +2,6 @@ "explain_todo": { "stmt10": true, "stmt11": true, - "stmt12": true, "stmt8": true, "stmt9": true } diff --git a/parser/testdata/03010_view_prewhere_in/metadata.json b/parser/testdata/03010_view_prewhere_in/metadata.json index ef58f80315..0967ef424b 100644 --- a/parser/testdata/03010_view_prewhere_in/metadata.json +++ b/parser/testdata/03010_view_prewhere_in/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt2": true - } -} +{} diff --git a/parser/testdata/03074_analyzer_alias_column_in_view/metadata.json b/parser/testdata/03074_analyzer_alias_column_in_view/metadata.json index ef58f80315..0967ef424b 100644 --- a/parser/testdata/03074_analyzer_alias_column_in_view/metadata.json +++ b/parser/testdata/03074_analyzer_alias_column_in_view/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt2": true - } -} +{} diff --git a/parser/testdata/03243_create_or_replace_view_dependency_check/metadata.json b/parser/testdata/03243_create_or_replace_view_dependency_check/metadata.json index d02612666a..0967ef424b 100644 --- a/parser/testdata/03243_create_or_replace_view_dependency_check/metadata.json +++ b/parser/testdata/03243_create_or_replace_view_dependency_check/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt5": true, - "stmt8": true - } -} +{} From cf878e59c07da075f4c568c83f64d871a693c5d1 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 31 Dec 2025 08:47:56 +0000 Subject: [PATCH 20/24] Add ORDER BY and table options support for MATERIALIZED VIEW Parse table options (ORDER BY, PRIMARY KEY, etc.) after ENGINE for materialized views. Fixes 26 tests including stmt2 in test 03667. --- parser/parser.go | 3 +++ .../metadata.json | 8 +------- parser/testdata/02131_mv_many_chunks_bug/metadata.json | 6 +----- parser/testdata/02146_mv_non_phys/metadata.json | 6 +----- .../metadata.json | 6 +----- parser/testdata/02184_default_table_engine/metadata.json | 1 - parser/testdata/02324_map_combinator_bug/metadata.json | 6 +----- .../02518_delete_on_materialized_view/metadata.json | 1 - .../02560_analyzer_materialized_view/metadata.json | 6 +----- .../02912_ingestion_mv_deduplication/metadata.json | 8 +------- .../metadata.json | 7 +------ .../03008_deduplication_cases_from_docs/metadata.json | 7 +------ .../metadata.json | 8 +------- .../metadata.json | 1 - .../03094_virtual_column_table_name/metadata.json | 6 +----- parser/testdata/03105_table_aliases_in_mv/metadata.json | 6 +----- .../metadata.json | 6 +----- .../03143_parallel_replicas_mat_view_bug/metadata.json | 6 +----- parser/testdata/03161_create_table_as_mv/metadata.json | 6 +----- .../03167_transactions_are_really_disabled/metadata.json | 6 +----- .../metadata.json | 6 +----- .../03282_materialized_views_ignore_errors/metadata.json | 6 +----- .../03321_inner_materialized_view_nested/metadata.json | 1 - .../03357_check_contraints_null_syntax/metadata.json | 6 +----- .../metadata.json | 1 - .../03667_drop_inner_table_size_limits/metadata.json | 6 +----- 26 files changed, 23 insertions(+), 113 deletions(-) diff --git a/parser/parser.go b/parser/parser.go index c30388d48f..0606c05da6 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -1973,6 +1973,9 @@ func (p *Parser) parseCreateView(create *ast.CreateQuery) { create.Engine = p.parseEngineClause() } + // Parse table options (ORDER BY, PRIMARY KEY, etc.) for materialized views + p.parseTableOptions(create) + // Parse POPULATE (for materialized views) if p.currentIs(token.POPULATE) { create.Populate = true diff --git a/parser/testdata/02124_insert_deduplication_token_materialized_views/metadata.json b/parser/testdata/02124_insert_deduplication_token_materialized_views/metadata.json index 4f593ff9c6..0967ef424b 100644 --- a/parser/testdata/02124_insert_deduplication_token_materialized_views/metadata.json +++ b/parser/testdata/02124_insert_deduplication_token_materialized_views/metadata.json @@ -1,7 +1 @@ -{ - "explain_todo": { - "stmt10": true, - "stmt8": true, - "stmt9": true - } -} +{} diff --git a/parser/testdata/02131_mv_many_chunks_bug/metadata.json b/parser/testdata/02131_mv_many_chunks_bug/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/02131_mv_many_chunks_bug/metadata.json +++ b/parser/testdata/02131_mv_many_chunks_bug/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} diff --git a/parser/testdata/02146_mv_non_phys/metadata.json b/parser/testdata/02146_mv_non_phys/metadata.json index ef58f80315..0967ef424b 100644 --- a/parser/testdata/02146_mv_non_phys/metadata.json +++ b/parser/testdata/02146_mv_non_phys/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt2": true - } -} +{} diff --git a/parser/testdata/02164_materialized_view_support_virtual_column/metadata.json b/parser/testdata/02164_materialized_view_support_virtual_column/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/02164_materialized_view_support_virtual_column/metadata.json +++ b/parser/testdata/02164_materialized_view_support_virtual_column/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} diff --git a/parser/testdata/02184_default_table_engine/metadata.json b/parser/testdata/02184_default_table_engine/metadata.json index 319dd860f8..64ab9858cf 100644 --- a/parser/testdata/02184_default_table_engine/metadata.json +++ b/parser/testdata/02184_default_table_engine/metadata.json @@ -3,7 +3,6 @@ "stmt107": true, "stmt114": true, "stmt26": true, - "stmt46": true, "stmt56": true, "stmt61": true, "stmt69": true, diff --git a/parser/testdata/02324_map_combinator_bug/metadata.json b/parser/testdata/02324_map_combinator_bug/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/02324_map_combinator_bug/metadata.json +++ b/parser/testdata/02324_map_combinator_bug/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} diff --git a/parser/testdata/02518_delete_on_materialized_view/metadata.json b/parser/testdata/02518_delete_on_materialized_view/metadata.json index f3773105ca..ff0eba6904 100644 --- a/parser/testdata/02518_delete_on_materialized_view/metadata.json +++ b/parser/testdata/02518_delete_on_materialized_view/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt4": true, "stmt6": true, "stmt7": true } diff --git a/parser/testdata/02560_analyzer_materialized_view/metadata.json b/parser/testdata/02560_analyzer_materialized_view/metadata.json index 3a06a4a1ac..0967ef424b 100644 --- a/parser/testdata/02560_analyzer_materialized_view/metadata.json +++ b/parser/testdata/02560_analyzer_materialized_view/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt5": true - } -} +{} diff --git a/parser/testdata/02912_ingestion_mv_deduplication/metadata.json b/parser/testdata/02912_ingestion_mv_deduplication/metadata.json index c5ac9fc15b..0967ef424b 100644 --- a/parser/testdata/02912_ingestion_mv_deduplication/metadata.json +++ b/parser/testdata/02912_ingestion_mv_deduplication/metadata.json @@ -1,7 +1 @@ -{ - "explain_todo": { - "stmt17": true, - "stmt29": true, - "stmt5": true - } -} +{} diff --git a/parser/testdata/02943_create_query_interpreter_sample_block_fix/metadata.json b/parser/testdata/02943_create_query_interpreter_sample_block_fix/metadata.json index 8606858586..0967ef424b 100644 --- a/parser/testdata/02943_create_query_interpreter_sample_block_fix/metadata.json +++ b/parser/testdata/02943_create_query_interpreter_sample_block_fix/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt16": true, - "stmt4": true - } -} +{} diff --git a/parser/testdata/03008_deduplication_cases_from_docs/metadata.json b/parser/testdata/03008_deduplication_cases_from_docs/metadata.json index 1334c74e46..0967ef424b 100644 --- a/parser/testdata/03008_deduplication_cases_from_docs/metadata.json +++ b/parser/testdata/03008_deduplication_cases_from_docs/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt27": true, - "stmt68": true - } -} +{} diff --git a/parser/testdata/03008_deduplication_insert_into_partitioned_table/metadata.json b/parser/testdata/03008_deduplication_insert_into_partitioned_table/metadata.json index 15f208b34f..0967ef424b 100644 --- a/parser/testdata/03008_deduplication_insert_into_partitioned_table/metadata.json +++ b/parser/testdata/03008_deduplication_insert_into_partitioned_table/metadata.json @@ -1,7 +1 @@ -{ - "explain_todo": { - "stmt18": true, - "stmt30": true, - "stmt6": true - } -} +{} diff --git a/parser/testdata/03008_deduplication_remote_insert_select/metadata.json b/parser/testdata/03008_deduplication_remote_insert_select/metadata.json index b6a0ad05da..7ad5569408 100644 --- a/parser/testdata/03008_deduplication_remote_insert_select/metadata.json +++ b/parser/testdata/03008_deduplication_remote_insert_select/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt14": true, "stmt9": true } } diff --git a/parser/testdata/03094_virtual_column_table_name/metadata.json b/parser/testdata/03094_virtual_column_table_name/metadata.json index d05a7b54b6..0967ef424b 100644 --- a/parser/testdata/03094_virtual_column_table_name/metadata.json +++ b/parser/testdata/03094_virtual_column_table_name/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt60": true - } -} +{} diff --git a/parser/testdata/03105_table_aliases_in_mv/metadata.json b/parser/testdata/03105_table_aliases_in_mv/metadata.json index 342b3ff5b4..0967ef424b 100644 --- a/parser/testdata/03105_table_aliases_in_mv/metadata.json +++ b/parser/testdata/03105_table_aliases_in_mv/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt8": true - } -} +{} diff --git a/parser/testdata/03107_ill_formed_select_in_materialized_view/metadata.json b/parser/testdata/03107_ill_formed_select_in_materialized_view/metadata.json index b563327205..0967ef424b 100644 --- a/parser/testdata/03107_ill_formed_select_in_materialized_view/metadata.json +++ b/parser/testdata/03107_ill_formed_select_in_materialized_view/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt7": true - } -} +{} diff --git a/parser/testdata/03143_parallel_replicas_mat_view_bug/metadata.json b/parser/testdata/03143_parallel_replicas_mat_view_bug/metadata.json index dbdbb76d4f..0967ef424b 100644 --- a/parser/testdata/03143_parallel_replicas_mat_view_bug/metadata.json +++ b/parser/testdata/03143_parallel_replicas_mat_view_bug/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt6": true - } -} +{} diff --git a/parser/testdata/03161_create_table_as_mv/metadata.json b/parser/testdata/03161_create_table_as_mv/metadata.json index f4c74e32be..0967ef424b 100644 --- a/parser/testdata/03161_create_table_as_mv/metadata.json +++ b/parser/testdata/03161_create_table_as_mv/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt10": true - } -} +{} diff --git a/parser/testdata/03167_transactions_are_really_disabled/metadata.json b/parser/testdata/03167_transactions_are_really_disabled/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/03167_transactions_are_really_disabled/metadata.json +++ b/parser/testdata/03167_transactions_are_really_disabled/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} diff --git a/parser/testdata/03263_analyzer_materialized_view_cte_nested/metadata.json b/parser/testdata/03263_analyzer_materialized_view_cte_nested/metadata.json index 3a06a4a1ac..0967ef424b 100644 --- a/parser/testdata/03263_analyzer_materialized_view_cte_nested/metadata.json +++ b/parser/testdata/03263_analyzer_materialized_view_cte_nested/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt5": true - } -} +{} diff --git a/parser/testdata/03282_materialized_views_ignore_errors/metadata.json b/parser/testdata/03282_materialized_views_ignore_errors/metadata.json index dbdbb76d4f..0967ef424b 100644 --- a/parser/testdata/03282_materialized_views_ignore_errors/metadata.json +++ b/parser/testdata/03282_materialized_views_ignore_errors/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt6": true - } -} +{} diff --git a/parser/testdata/03321_inner_materialized_view_nested/metadata.json b/parser/testdata/03321_inner_materialized_view_nested/metadata.json index 15d79beb93..3a06a4a1ac 100644 --- a/parser/testdata/03321_inner_materialized_view_nested/metadata.json +++ b/parser/testdata/03321_inner_materialized_view_nested/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt11": true, "stmt5": true } } diff --git a/parser/testdata/03357_check_contraints_null_syntax/metadata.json b/parser/testdata/03357_check_contraints_null_syntax/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/03357_check_contraints_null_syntax/metadata.json +++ b/parser/testdata/03357_check_contraints_null_syntax/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} diff --git a/parser/testdata/03460_alter_materialized_view_on_cluster/metadata.json b/parser/testdata/03460_alter_materialized_view_on_cluster/metadata.json index 943b275814..dbdbb76d4f 100644 --- a/parser/testdata/03460_alter_materialized_view_on_cluster/metadata.json +++ b/parser/testdata/03460_alter_materialized_view_on_cluster/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt4": true, "stmt6": true } } diff --git a/parser/testdata/03667_drop_inner_table_size_limits/metadata.json b/parser/testdata/03667_drop_inner_table_size_limits/metadata.json index ef58f80315..0967ef424b 100644 --- a/parser/testdata/03667_drop_inner_table_size_limits/metadata.json +++ b/parser/testdata/03667_drop_inner_table_size_limits/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt2": true - } -} +{} From 6aaa618dec58eb5c72fa41aec6a9f2d1ed1ae75a Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 31 Dec 2025 08:57:20 +0000 Subject: [PATCH 21/24] Fix empty tuple and WITH clause expression parsing 1. Fix WITH clause to only treat ( as subquery when followed by SELECT/WITH Previously (SELECT...) AS name was parsed even for empty () or expressions 2. Fix empty tuple EXPLAIN output to use Function tuple format Empty tuples should output "Function tuple (children 1)" with ExpressionList rather than "Literal Tuple_()" Fixes 41 tests including materialized views and WITH clause tests. --- internal/explain/expressions.go | 22 ++++++++++++++++--- parser/parser.go | 4 ++-- .../metadata.json | 4 +--- .../metadata.json | 6 +---- .../metadata.json | 7 +----- .../00172_constexprs_in_set/metadata.json | 6 +---- .../00175_partition_by_ignore/metadata.json | 7 +----- .../metadata.json | 6 +---- .../metadata.json | 6 +---- .../00687_insert_into_mv/metadata.json | 8 +------ .../metadata.json | 6 +---- .../00752_low_cardinality_mv_1/metadata.json | 6 +---- .../00752_low_cardinality_mv_2/metadata.json | 6 +---- .../metadata.json | 3 +-- .../metadata.json | 6 +---- .../00945_bloom_filter_index/metadata.json | 6 +---- .../metadata.json | 6 +---- .../01153_attach_mv_uuid/metadata.json | 3 +-- .../metadata.json | 1 - .../01161_information_schema/metadata.json | 6 +---- .../metadata.json | 12 +--------- .../01504_view_type_conversion/metadata.json | 7 +----- .../metadata.json | 6 +---- .../metadata.json | 6 +---- .../01907_multiple_aliases/metadata.json | 6 +---- .../02096_rename_atomic_hang/metadata.json | 3 +-- .../metadata.json | 2 -- .../02343_analyzer_lambdas/metadata.json | 6 +---- .../metadata.json | 2 -- .../metadata.json | 6 +---- .../testdata/02833_tuple_concat/metadata.json | 9 +------- .../02841_with_clause_resolve/metadata.json | 7 +----- .../metadata.json | 6 +---- .../metadata.json | 1 - .../metadata.json | 7 +----- .../metadata.json | 6 +---- .../metadata.json | 3 --- .../metadata.json | 6 +---- .../metadata.json | 6 +---- .../metadata.json | 16 +------------- .../metadata.json | 6 +---- 41 files changed, 55 insertions(+), 199 deletions(-) diff --git a/internal/explain/expressions.go b/internal/explain/expressions.go index 9f9df6170d..3d96a1e78a 100644 --- a/internal/explain/expressions.go +++ b/internal/explain/expressions.go @@ -422,14 +422,18 @@ func explainAliasedExpr(sb *strings.Builder, n *ast.AliasedExpr, depth int) { // Check if this is a tuple with complex expressions that should be rendered as Function tuple if e.Type == ast.LiteralTuple { if exprs, ok := e.Value.([]ast.Expression); ok { - hasComplexExpr := false + needsFunctionFormat := false + // Empty tuples always use Function tuple format + if len(exprs) == 0 { + needsFunctionFormat = true + } for _, expr := range exprs { if _, isLit := expr.(*ast.Literal); !isLit { - hasComplexExpr = true + needsFunctionFormat = true break } } - if hasComplexExpr { + if needsFunctionFormat { // Render as Function tuple with alias fmt.Fprintf(sb, "%sFunction tuple (alias %s) (children %d)\n", indent, escapeAlias(n.Alias), 1) fmt.Fprintf(sb, "%s ExpressionList (children %d)\n", indent, len(exprs)) @@ -683,6 +687,18 @@ func explainWithElement(sb *strings.Builder, n *ast.WithElement, indent string, // When name is empty, don't show the alias part switch e := n.Query.(type) { case *ast.Literal: + // Empty tuples should be rendered as Function tuple, not Literal + if e.Type == ast.LiteralTuple { + if exprs, ok := e.Value.([]ast.Expression); ok && len(exprs) == 0 { + if n.Name != "" { + fmt.Fprintf(sb, "%sFunction tuple (alias %s) (children %d)\n", indent, n.Name, 1) + } else { + fmt.Fprintf(sb, "%sFunction tuple (children %d)\n", indent, 1) + } + fmt.Fprintf(sb, "%s ExpressionList\n", indent) + return + } + } if n.Name != "" { fmt.Fprintf(sb, "%sLiteral %s (alias %s)\n", indent, FormatLiteral(e), n.Name) } else { diff --git a/parser/parser.go b/parser/parser.go index 0606c05da6..0b1f591357 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -819,8 +819,8 @@ func (p *Parser) parseWithClause() []ast.Expression { elem.Name = name elem.Query = &ast.Identifier{Position: pos, Parts: []string{name}} } - } else if p.currentIs(token.LPAREN) { - // Subquery: (SELECT ...) AS name + } else if p.currentIs(token.LPAREN) && (p.peekIs(token.SELECT) || p.peekIs(token.WITH)) { + // Subquery: (SELECT ...) AS name or (WITH ... SELECT ...) AS name // In this syntax, the alias goes on the Subquery, not on WithElement p.nextToken() subquery := p.parseSelectWithUnion() diff --git a/parser/testdata/00101_materialized_views_and_insert_without_explicit_database/metadata.json b/parser/testdata/00101_materialized_views_and_insert_without_explicit_database/metadata.json index 30cf38cc7b..63effae13a 100644 --- a/parser/testdata/00101_materialized_views_and_insert_without_explicit_database/metadata.json +++ b/parser/testdata/00101_materialized_views_and_insert_without_explicit_database/metadata.json @@ -3,8 +3,6 @@ "stmt35": true, "stmt36": true, "stmt37": true, - "stmt38": true, - "stmt6": true, - "stmt7": true + "stmt38": true } } diff --git a/parser/testdata/00148_summing_merge_tree_aggregate_function/metadata.json b/parser/testdata/00148_summing_merge_tree_aggregate_function/metadata.json index ca4ce64f93..0967ef424b 100644 --- a/parser/testdata/00148_summing_merge_tree_aggregate_function/metadata.json +++ b/parser/testdata/00148_summing_merge_tree_aggregate_function/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt78": true - } -} +{} diff --git a/parser/testdata/00165_jit_aggregate_functions/metadata.json b/parser/testdata/00165_jit_aggregate_functions/metadata.json index 8888e2e3ae..0967ef424b 100644 --- a/parser/testdata/00165_jit_aggregate_functions/metadata.json +++ b/parser/testdata/00165_jit_aggregate_functions/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt10": true, - "stmt16": true - } -} +{} diff --git a/parser/testdata/00172_constexprs_in_set/metadata.json b/parser/testdata/00172_constexprs_in_set/metadata.json index b563327205..0967ef424b 100644 --- a/parser/testdata/00172_constexprs_in_set/metadata.json +++ b/parser/testdata/00172_constexprs_in_set/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt7": true - } -} +{} diff --git a/parser/testdata/00175_partition_by_ignore/metadata.json b/parser/testdata/00175_partition_by_ignore/metadata.json index 0f293987f1..0967ef424b 100644 --- a/parser/testdata/00175_partition_by_ignore/metadata.json +++ b/parser/testdata/00175_partition_by_ignore/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt5": true, - "stmt6": true - } -} +{} diff --git a/parser/testdata/00542_materialized_view_and_time_zone_tag/metadata.json b/parser/testdata/00542_materialized_view_and_time_zone_tag/metadata.json index dbdbb76d4f..0967ef424b 100644 --- a/parser/testdata/00542_materialized_view_and_time_zone_tag/metadata.json +++ b/parser/testdata/00542_materialized_view_and_time_zone_tag/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt6": true - } -} +{} diff --git a/parser/testdata/00610_materialized_view_forward_alter_partition_statements/metadata.json b/parser/testdata/00610_materialized_view_forward_alter_partition_statements/metadata.json index 3a06a4a1ac..0967ef424b 100644 --- a/parser/testdata/00610_materialized_view_forward_alter_partition_statements/metadata.json +++ b/parser/testdata/00610_materialized_view_forward_alter_partition_statements/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt5": true - } -} +{} diff --git a/parser/testdata/00687_insert_into_mv/metadata.json b/parser/testdata/00687_insert_into_mv/metadata.json index bd1b4cdd81..0967ef424b 100644 --- a/parser/testdata/00687_insert_into_mv/metadata.json +++ b/parser/testdata/00687_insert_into_mv/metadata.json @@ -1,7 +1 @@ -{ - "explain_todo": { - "stmt6": true, - "stmt7": true, - "stmt8": true - } -} +{} diff --git a/parser/testdata/00751_default_databasename_for_view/metadata.json b/parser/testdata/00751_default_databasename_for_view/metadata.json index f4c74e32be..0967ef424b 100644 --- a/parser/testdata/00751_default_databasename_for_view/metadata.json +++ b/parser/testdata/00751_default_databasename_for_view/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt10": true - } -} +{} diff --git a/parser/testdata/00752_low_cardinality_mv_1/metadata.json b/parser/testdata/00752_low_cardinality_mv_1/metadata.json index dbdbb76d4f..0967ef424b 100644 --- a/parser/testdata/00752_low_cardinality_mv_1/metadata.json +++ b/parser/testdata/00752_low_cardinality_mv_1/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt6": true - } -} +{} diff --git a/parser/testdata/00752_low_cardinality_mv_2/metadata.json b/parser/testdata/00752_low_cardinality_mv_2/metadata.json index b563327205..0967ef424b 100644 --- a/parser/testdata/00752_low_cardinality_mv_2/metadata.json +++ b/parser/testdata/00752_low_cardinality_mv_2/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt7": true - } -} +{} diff --git a/parser/testdata/00753_system_columns_and_system_tables_long/metadata.json b/parser/testdata/00753_system_columns_and_system_tables_long/metadata.json index e285916386..6eea4ac173 100644 --- a/parser/testdata/00753_system_columns_and_system_tables_long/metadata.json +++ b/parser/testdata/00753_system_columns_and_system_tables_long/metadata.json @@ -1,7 +1,6 @@ { "explain_todo": { "stmt3": true, - "stmt74": true, - "stmt76": true + "stmt74": true } } diff --git a/parser/testdata/00916_create_or_replace_view/metadata.json b/parser/testdata/00916_create_or_replace_view/metadata.json index ef58f80315..0967ef424b 100644 --- a/parser/testdata/00916_create_or_replace_view/metadata.json +++ b/parser/testdata/00916_create_or_replace_view/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt2": true - } -} +{} diff --git a/parser/testdata/00945_bloom_filter_index/metadata.json b/parser/testdata/00945_bloom_filter_index/metadata.json index 71bff5d186..7c0763ffaa 100644 --- a/parser/testdata/00945_bloom_filter_index/metadata.json +++ b/parser/testdata/00945_bloom_filter_index/metadata.json @@ -1,9 +1,5 @@ { "explain_todo": { - "stmt152": true, - "stmt19": true, - "stmt20": true, - "stmt21": true, - "stmt22": true + "stmt152": true } } diff --git a/parser/testdata/01046_materialized_view_with_join_over_distributed/metadata.json b/parser/testdata/01046_materialized_view_with_join_over_distributed/metadata.json index b563327205..0967ef424b 100644 --- a/parser/testdata/01046_materialized_view_with_join_over_distributed/metadata.json +++ b/parser/testdata/01046_materialized_view_with_join_over_distributed/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt7": true - } -} +{} diff --git a/parser/testdata/01153_attach_mv_uuid/metadata.json b/parser/testdata/01153_attach_mv_uuid/metadata.json index 02e33f6cbe..d3de3d16d5 100644 --- a/parser/testdata/01153_attach_mv_uuid/metadata.json +++ b/parser/testdata/01153_attach_mv_uuid/metadata.json @@ -3,7 +3,6 @@ "stmt16": true, "stmt26": true, "stmt27": true, - "stmt37": true, - "stmt5": true + "stmt37": true } } diff --git a/parser/testdata/01155_rename_move_materialized_view/metadata.json b/parser/testdata/01155_rename_move_materialized_view/metadata.json index 53382836cd..9afaf3adfa 100644 --- a/parser/testdata/01155_rename_move_materialized_view/metadata.json +++ b/parser/testdata/01155_rename_move_materialized_view/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt11": true, "stmt13": true, "stmt16": true, "stmt20": true, diff --git a/parser/testdata/01161_information_schema/metadata.json b/parser/testdata/01161_information_schema/metadata.json index ab9202e88e..0967ef424b 100644 --- a/parser/testdata/01161_information_schema/metadata.json +++ b/parser/testdata/01161_information_schema/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt11": true - } -} +{} diff --git a/parser/testdata/01332_join_type_syntax_position/metadata.json b/parser/testdata/01332_join_type_syntax_position/metadata.json index 83c1dfd8a9..0967ef424b 100644 --- a/parser/testdata/01332_join_type_syntax_position/metadata.json +++ b/parser/testdata/01332_join_type_syntax_position/metadata.json @@ -1,11 +1 @@ -{ - "explain_todo": { - "stmt10": true, - "stmt3": true, - "stmt4": true, - "stmt5": true, - "stmt6": true, - "stmt7": true, - "stmt8": true - } -} +{} diff --git a/parser/testdata/01504_view_type_conversion/metadata.json b/parser/testdata/01504_view_type_conversion/metadata.json index f5dd12602b..0967ef424b 100644 --- a/parser/testdata/01504_view_type_conversion/metadata.json +++ b/parser/testdata/01504_view_type_conversion/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt2": true, - "stmt5": true - } -} +{} diff --git a/parser/testdata/01549_low_cardinality_materialized_view/metadata.json b/parser/testdata/01549_low_cardinality_materialized_view/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/01549_low_cardinality_materialized_view/metadata.json +++ b/parser/testdata/01549_low_cardinality_materialized_view/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} diff --git a/parser/testdata/01549_low_cardinality_mv_fuzz/metadata.json b/parser/testdata/01549_low_cardinality_mv_fuzz/metadata.json index 3a06a4a1ac..0967ef424b 100644 --- a/parser/testdata/01549_low_cardinality_mv_fuzz/metadata.json +++ b/parser/testdata/01549_low_cardinality_mv_fuzz/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt5": true - } -} +{} diff --git a/parser/testdata/01907_multiple_aliases/metadata.json b/parser/testdata/01907_multiple_aliases/metadata.json index 3a06a4a1ac..0967ef424b 100644 --- a/parser/testdata/01907_multiple_aliases/metadata.json +++ b/parser/testdata/01907_multiple_aliases/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt5": true - } -} +{} diff --git a/parser/testdata/02096_rename_atomic_hang/metadata.json b/parser/testdata/02096_rename_atomic_hang/metadata.json index 24c397911d..d4d1d99f95 100644 --- a/parser/testdata/02096_rename_atomic_hang/metadata.json +++ b/parser/testdata/02096_rename_atomic_hang/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt14": true, - "stmt8": true + "stmt14": true } } diff --git a/parser/testdata/02116_tuple_element_analyzer/metadata.json b/parser/testdata/02116_tuple_element_analyzer/metadata.json index 50155ebc65..5452d4a529 100644 --- a/parser/testdata/02116_tuple_element_analyzer/metadata.json +++ b/parser/testdata/02116_tuple_element_analyzer/metadata.json @@ -1,7 +1,5 @@ { "explain_todo": { - "stmt28": true, - "stmt29": true, "stmt30": true, "stmt31": true } diff --git a/parser/testdata/02343_analyzer_lambdas/metadata.json b/parser/testdata/02343_analyzer_lambdas/metadata.json index 840514b0bb..06afe672c2 100644 --- a/parser/testdata/02343_analyzer_lambdas/metadata.json +++ b/parser/testdata/02343_analyzer_lambdas/metadata.json @@ -2,10 +2,6 @@ "explain_todo": { "stmt31": true, "stmt32": true, - "stmt33": true, - "stmt37": true, - "stmt38": true, - "stmt46": true, - "stmt47": true + "stmt33": true } } diff --git a/parser/testdata/02385_analyzer_aliases_compound_expression/metadata.json b/parser/testdata/02385_analyzer_aliases_compound_expression/metadata.json index 3b61d1417e..15223e732d 100644 --- a/parser/testdata/02385_analyzer_aliases_compound_expression/metadata.json +++ b/parser/testdata/02385_analyzer_aliases_compound_expression/metadata.json @@ -1,8 +1,6 @@ { "explain_todo": { "stmt11": true, - "stmt4": true, - "stmt5": true, "stmt9": true } } diff --git a/parser/testdata/02695_logical_optimizer_alias_bug/metadata.json b/parser/testdata/02695_logical_optimizer_alias_bug/metadata.json index ef58f80315..0967ef424b 100644 --- a/parser/testdata/02695_logical_optimizer_alias_bug/metadata.json +++ b/parser/testdata/02695_logical_optimizer_alias_bug/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt2": true - } -} +{} diff --git a/parser/testdata/02833_tuple_concat/metadata.json b/parser/testdata/02833_tuple_concat/metadata.json index 6a991c37ba..0967ef424b 100644 --- a/parser/testdata/02833_tuple_concat/metadata.json +++ b/parser/testdata/02833_tuple_concat/metadata.json @@ -1,8 +1 @@ -{ - "explain_todo": { - "stmt10": true, - "stmt11": true, - "stmt5": true, - "stmt9": true - } -} +{} diff --git a/parser/testdata/02841_with_clause_resolve/metadata.json b/parser/testdata/02841_with_clause_resolve/metadata.json index bc141058a4..0967ef424b 100644 --- a/parser/testdata/02841_with_clause_resolve/metadata.json +++ b/parser/testdata/02841_with_clause_resolve/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt2": true, - "stmt3": true - } -} +{} diff --git a/parser/testdata/02923_cte_equality_disjunction/metadata.json b/parser/testdata/02923_cte_equality_disjunction/metadata.json index ef58f80315..0967ef424b 100644 --- a/parser/testdata/02923_cte_equality_disjunction/metadata.json +++ b/parser/testdata/02923_cte_equality_disjunction/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt2": true - } -} +{} diff --git a/parser/testdata/03022_alter_materialized_view_query_has_inner_table/metadata.json b/parser/testdata/03022_alter_materialized_view_query_has_inner_table/metadata.json index 05aa6dfc72..342b3ff5b4 100644 --- a/parser/testdata/03022_alter_materialized_view_query_has_inner_table/metadata.json +++ b/parser/testdata/03022_alter_materialized_view_query_has_inner_table/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt4": true, "stmt8": true } } diff --git a/parser/testdata/03035_materialized_primary_key/metadata.json b/parser/testdata/03035_materialized_primary_key/metadata.json index 6bf8d5b80a..0967ef424b 100644 --- a/parser/testdata/03035_materialized_primary_key/metadata.json +++ b/parser/testdata/03035_materialized_primary_key/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt5": true, - "stmt7": true - } -} +{} diff --git a/parser/testdata/03174_split_parts_ranges_into_intersecting_and_non_intersecting_final_and_read-in-order_bug/metadata.json b/parser/testdata/03174_split_parts_ranges_into_intersecting_and_non_intersecting_final_and_read-in-order_bug/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/03174_split_parts_ranges_into_intersecting_and_non_intersecting_final_and_read-in-order_bug/metadata.json +++ b/parser/testdata/03174_split_parts_ranges_into_intersecting_and_non_intersecting_final_and_read-in-order_bug/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} diff --git a/parser/testdata/03201_analyzer_resolve_in_parent_scope/metadata.json b/parser/testdata/03201_analyzer_resolve_in_parent_scope/metadata.json index 7d6fbb092b..60106a3b25 100644 --- a/parser/testdata/03201_analyzer_resolve_in_parent_scope/metadata.json +++ b/parser/testdata/03201_analyzer_resolve_in_parent_scope/metadata.json @@ -1,9 +1,6 @@ { "explain_todo": { - "stmt11": true, - "stmt2": true, "stmt3": true, - "stmt5": true, "stmt9": true } } diff --git a/parser/testdata/03314_analyzer_resolve_in_parent_scope_3/metadata.json b/parser/testdata/03314_analyzer_resolve_in_parent_scope_3/metadata.json index ef58f80315..0967ef424b 100644 --- a/parser/testdata/03314_analyzer_resolve_in_parent_scope_3/metadata.json +++ b/parser/testdata/03314_analyzer_resolve_in_parent_scope_3/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt2": true - } -} +{} diff --git a/parser/testdata/03359_analyzer_rewrite_view_query/metadata.json b/parser/testdata/03359_analyzer_rewrite_view_query/metadata.json index ef58f80315..0967ef424b 100644 --- a/parser/testdata/03359_analyzer_rewrite_view_query/metadata.json +++ b/parser/testdata/03359_analyzer_rewrite_view_query/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt2": true - } -} +{} diff --git a/parser/testdata/03566_analyzer_single_with_scope/metadata.json b/parser/testdata/03566_analyzer_single_with_scope/metadata.json index 42fc006fd0..0967ef424b 100644 --- a/parser/testdata/03566_analyzer_single_with_scope/metadata.json +++ b/parser/testdata/03566_analyzer_single_with_scope/metadata.json @@ -1,15 +1 @@ -{ - "explain_todo": { - "stmt11": true, - "stmt12": true, - "stmt13": true, - "stmt14": true, - "stmt15": true, - "stmt3": true, - "stmt4": true, - "stmt5": true, - "stmt6": true, - "stmt7": true, - "stmt8": true - } -} +{} diff --git a/parser/testdata/03714_empty_tuple_reverse_function/metadata.json b/parser/testdata/03714_empty_tuple_reverse_function/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/03714_empty_tuple_reverse_function/metadata.json +++ b/parser/testdata/03714_empty_tuple_reverse_function/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} From 78070a7e79f0e457e1e684c01a8b6649a27fc21c Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 31 Dec 2025 09:05:50 +0000 Subject: [PATCH 22/24] Add SETTINGS support for ALTER TABLE statements - Added Settings field to AlterQuery struct in ast/ast.go - Parse SETTINGS clause after ALTER commands in parser/parser.go - Output Set child in explainAlterQuery when Settings are present This fixes ~90 tests that use ALTER TABLE with SETTINGS clause like: ALTER TABLE t ADD COLUMN c String SETTINGS alter_sync = 2 --- ast/ast.go | 1 + internal/explain/statements.go | 8 ++++++++ parser/parser.go | 6 ++++++ parser/testdata/00806_alter_update/metadata.json | 6 +----- .../testdata/00955_test_final_mark/metadata.json | 5 +---- .../metadata.json | 1 - .../metadata.json | 9 +-------- .../metadata.json | 1 - .../metadata.json | 7 +------ .../01414_mutations_and_errors/metadata.json | 7 +------ .../metadata.json | 7 +------ .../testdata/01475_mutation_with_if/metadata.json | 10 +--------- .../metadata.json | 6 +----- .../metadata.json | 6 +----- .../01648_mutations_and_escaping/metadata.json | 6 +----- .../metadata.json | 3 +-- .../01701_if_tuple_segfault/metadata.json | 8 +------- .../metadata.json | 6 +----- .../metadata.json | 6 +----- .../01710_projection_mutation/metadata.json | 6 +----- .../metadata.json | 6 +----- .../metadata.json | 6 +----- .../metadata.json | 6 +----- .../metadata.json | 3 +-- .../02129_add_column_add_ttl/metadata.json | 2 -- .../02131_materialize_column_cast/metadata.json | 1 - .../02251_alter_enum_nested_struct/metadata.json | 6 +----- .../metadata.json | 5 ----- .../metadata.json | 4 ---- .../02346_text_index_bug47393/metadata.json | 6 +----- .../02352_lightweight_delete/metadata.json | 1 - .../metadata.json | 3 +-- .../metadata.json | 7 +------ .../02436_system_zookeeper_context/metadata.json | 6 +----- .../metadata.json | 1 - .../02448_clone_replica_lost_part/metadata.json | 1 - .../02456_alter-nullable-column-bag/metadata.json | 6 +----- .../metadata.json | 9 +-------- .../metadata.json | 3 +-- .../metadata.json | 8 +------- .../metadata.json | 6 +----- .../metadata.json | 1 - .../02516_projections_with_rollup/metadata.json | 7 +------ .../metadata.json | 1 - .../02538_alter_rename_sequence/metadata.json | 9 +-------- .../metadata.json | 3 --- .../metadata.json | 14 +------------- .../metadata.json | 9 +-------- .../metadata.json | 2 -- .../metadata.json | 8 +------- .../metadata.json | 6 +----- .../metadata.json | 3 +-- .../metadata.json | 1 - .../metadata.json | 6 +----- .../metadata.json | 6 +----- .../metadata.json | 6 +----- .../metadata.json | 7 +------ .../metadata.json | 6 +----- .../metadata.json | 6 +----- .../metadata.json | 1 - .../metadata.json | 3 +-- .../metadata.json | 6 +----- .../03001_data_version_column/metadata.json | 6 +----- .../metadata.json | 9 +-------- .../metadata.json | 9 +-------- .../metadata.json | 9 +-------- .../metadata.json | 5 +---- .../metadata.json | 5 +---- .../03047_on_fly_mutations_events/metadata.json | 2 -- .../metadata.json | 2 -- .../metadata.json | 7 +------ .../metadata.json | 3 +-- .../03100_lwu_44_missing_default/metadata.json | 2 -- .../metadata.json | 7 +------ .../03169_modify_column_data_loss/metadata.json | 6 +----- .../metadata.json | 7 +------ .../03268_empty_tuple_update/metadata.json | 6 +----- .../metadata.json | 4 +--- .../metadata.json | 6 +----- .../metadata.json | 6 +----- .../metadata.json | 6 +----- .../metadata.json | 1 - .../metadata.json | 6 +----- .../metadata.json | 2 -- .../metadata.json | 15 +-------------- .../03625_prewhere-and-default-bug/metadata.json | 6 +----- .../03636_storage_alias_basic/metadata.json | 1 - .../03673_columns_description_cache/metadata.json | 1 - .../03721_statistics_alter_type_bug/metadata.json | 7 +------ .../metadata.json | 6 +----- .../metadata.json | 6 +----- .../metadata.json | 6 +----- .../metadata.json | 6 +----- 93 files changed, 83 insertions(+), 409 deletions(-) diff --git a/ast/ast.go b/ast/ast.go index 4747fcbf73..c69df6f960 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -504,6 +504,7 @@ type AlterQuery struct { Table string `json:"table"` Commands []*AlterCommand `json:"commands"` OnCluster string `json:"on_cluster,omitempty"` + Settings []*SettingExpr `json:"settings,omitempty"` } func (a *AlterQuery) Pos() token.Position { return a.Position } diff --git a/internal/explain/statements.go b/internal/explain/statements.go index 1ae59e551b..cf7b187357 100644 --- a/internal/explain/statements.go +++ b/internal/explain/statements.go @@ -993,6 +993,11 @@ func explainAlterQuery(sb *strings.Builder, n *ast.AlterQuery, indent string, de children := 2 // ExpressionList + Identifier for table if n.Database != "" { children = 3 // ExpressionList + Identifier for database + Identifier for table + } + if len(n.Settings) > 0 { + children++ // Add Set child for SETTINGS + } + if n.Database != "" { fmt.Fprintf(sb, "%sAlterQuery %s %s (children %d)\n", indent, n.Database, n.Table, children) } else { fmt.Fprintf(sb, "%sAlterQuery %s (children %d)\n", indent, n.Table, children) @@ -1006,6 +1011,9 @@ func explainAlterQuery(sb *strings.Builder, n *ast.AlterQuery, indent string, de fmt.Fprintf(sb, "%s Identifier %s\n", indent, n.Database) } fmt.Fprintf(sb, "%s Identifier %s\n", indent, n.Table) + if len(n.Settings) > 0 { + fmt.Fprintf(sb, "%s Set\n", indent) + } } func explainAlterCommand(sb *strings.Builder, cmd *ast.AlterCommand, indent string, depth int) { diff --git a/parser/parser.go b/parser/parser.go index 0b1f591357..bdd6bbc125 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -3842,6 +3842,12 @@ func (p *Parser) parseAlter() *ast.AlterQuery { p.nextToken() } + // Parse SETTINGS clause + if p.currentIs(token.SETTINGS) { + p.nextToken() + alter.Settings = p.parseSettingsList() + } + return alter } diff --git a/parser/testdata/00806_alter_update/metadata.json b/parser/testdata/00806_alter_update/metadata.json index dbdbb76d4f..0967ef424b 100644 --- a/parser/testdata/00806_alter_update/metadata.json +++ b/parser/testdata/00806_alter_update/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt6": true - } -} +{} diff --git a/parser/testdata/00955_test_final_mark/metadata.json b/parser/testdata/00955_test_final_mark/metadata.json index f18e4d9975..b330691357 100644 --- a/parser/testdata/00955_test_final_mark/metadata.json +++ b/parser/testdata/00955_test_final_mark/metadata.json @@ -1,8 +1,5 @@ { "explain_todo": { - "stmt20": true, - "stmt21": true, - "stmt26": true, - "stmt53": true + "stmt26": true } } diff --git a/parser/testdata/00988_constraints_replication_zookeeper_long/metadata.json b/parser/testdata/00988_constraints_replication_zookeeper_long/metadata.json index a5216843cc..e80c16c5c9 100644 --- a/parser/testdata/00988_constraints_replication_zookeeper_long/metadata.json +++ b/parser/testdata/00988_constraints_replication_zookeeper_long/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt10": true, "stmt13": true, "stmt14": true } diff --git a/parser/testdata/01049_zookeeper_synchronous_mutations_long/metadata.json b/parser/testdata/01049_zookeeper_synchronous_mutations_long/metadata.json index 316285e34a..0967ef424b 100644 --- a/parser/testdata/01049_zookeeper_synchronous_mutations_long/metadata.json +++ b/parser/testdata/01049_zookeeper_synchronous_mutations_long/metadata.json @@ -1,8 +1 @@ -{ - "explain_todo": { - "stmt10": true, - "stmt18": true, - "stmt20": true, - "stmt8": true - } -} +{} diff --git a/parser/testdata/01201_drop_column_compact_part_replicated_zookeeper_long/metadata.json b/parser/testdata/01201_drop_column_compact_part_replicated_zookeeper_long/metadata.json index c02898f6b6..05747ff9e9 100644 --- a/parser/testdata/01201_drop_column_compact_part_replicated_zookeeper_long/metadata.json +++ b/parser/testdata/01201_drop_column_compact_part_replicated_zookeeper_long/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt12": true, "stmt6": true, "stmt7": true, "stmt8": true, diff --git a/parser/testdata/01267_alter_default_key_columns_zookeeper_long/metadata.json b/parser/testdata/01267_alter_default_key_columns_zookeeper_long/metadata.json index ec09c7e10e..0967ef424b 100644 --- a/parser/testdata/01267_alter_default_key_columns_zookeeper_long/metadata.json +++ b/parser/testdata/01267_alter_default_key_columns_zookeeper_long/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt11": true, - "stmt12": true - } -} +{} diff --git a/parser/testdata/01414_mutations_and_errors/metadata.json b/parser/testdata/01414_mutations_and_errors/metadata.json index ff0eba6904..0967ef424b 100644 --- a/parser/testdata/01414_mutations_and_errors/metadata.json +++ b/parser/testdata/01414_mutations_and_errors/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt6": true, - "stmt7": true - } -} +{} diff --git a/parser/testdata/01471_calculate_ttl_during_merge/metadata.json b/parser/testdata/01471_calculate_ttl_during_merge/metadata.json index c246313af9..0967ef424b 100644 --- a/parser/testdata/01471_calculate_ttl_during_merge/metadata.json +++ b/parser/testdata/01471_calculate_ttl_during_merge/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt11": true, - "stmt7": true - } -} +{} diff --git a/parser/testdata/01475_mutation_with_if/metadata.json b/parser/testdata/01475_mutation_with_if/metadata.json index 465d713219..0967ef424b 100644 --- a/parser/testdata/01475_mutation_with_if/metadata.json +++ b/parser/testdata/01475_mutation_with_if/metadata.json @@ -1,9 +1 @@ -{ - "explain_todo": { - "stmt11": true, - "stmt15": true, - "stmt17": true, - "stmt20": true, - "stmt4": true - } -} +{} diff --git a/parser/testdata/01511_alter_version_versioned_collapsing_merge_tree_zookeeper/metadata.json b/parser/testdata/01511_alter_version_versioned_collapsing_merge_tree_zookeeper/metadata.json index 7ad5569408..0967ef424b 100644 --- a/parser/testdata/01511_alter_version_versioned_collapsing_merge_tree_zookeeper/metadata.json +++ b/parser/testdata/01511_alter_version_versioned_collapsing_merge_tree_zookeeper/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt9": true - } -} +{} diff --git a/parser/testdata/01586_replicated_mutations_empty_partition/metadata.json b/parser/testdata/01586_replicated_mutations_empty_partition/metadata.json index ab9202e88e..0967ef424b 100644 --- a/parser/testdata/01586_replicated_mutations_empty_partition/metadata.json +++ b/parser/testdata/01586_replicated_mutations_empty_partition/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt11": true - } -} +{} diff --git a/parser/testdata/01648_mutations_and_escaping/metadata.json b/parser/testdata/01648_mutations_and_escaping/metadata.json index 7ad5569408..0967ef424b 100644 --- a/parser/testdata/01648_mutations_and_escaping/metadata.json +++ b/parser/testdata/01648_mutations_and_escaping/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt9": true - } -} +{} diff --git a/parser/testdata/01650_fetch_patition_with_macro_in_zk_path_long/metadata.json b/parser/testdata/01650_fetch_patition_with_macro_in_zk_path_long/metadata.json index 92efb02376..dbdbb76d4f 100644 --- a/parser/testdata/01650_fetch_patition_with_macro_in_zk_path_long/metadata.json +++ b/parser/testdata/01650_fetch_patition_with_macro_in_zk_path_long/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt6": true, - "stmt8": true + "stmt6": true } } diff --git a/parser/testdata/01701_if_tuple_segfault/metadata.json b/parser/testdata/01701_if_tuple_segfault/metadata.json index 661bded8e9..0967ef424b 100644 --- a/parser/testdata/01701_if_tuple_segfault/metadata.json +++ b/parser/testdata/01701_if_tuple_segfault/metadata.json @@ -1,7 +1 @@ -{ - "explain_todo": { - "stmt7": true, - "stmt8": true, - "stmt9": true - } -} +{} diff --git a/parser/testdata/01710_aggregate_projection_with_hashing/metadata.json b/parser/testdata/01710_aggregate_projection_with_hashing/metadata.json index dbdbb76d4f..0967ef424b 100644 --- a/parser/testdata/01710_aggregate_projection_with_hashing/metadata.json +++ b/parser/testdata/01710_aggregate_projection_with_hashing/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt6": true - } -} +{} diff --git a/parser/testdata/01710_projection_materialize_with_missing_columns/metadata.json b/parser/testdata/01710_projection_materialize_with_missing_columns/metadata.json index dbdbb76d4f..0967ef424b 100644 --- a/parser/testdata/01710_projection_materialize_with_missing_columns/metadata.json +++ b/parser/testdata/01710_projection_materialize_with_missing_columns/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt6": true - } -} +{} diff --git a/parser/testdata/01710_projection_mutation/metadata.json b/parser/testdata/01710_projection_mutation/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/01710_projection_mutation/metadata.json +++ b/parser/testdata/01710_projection_mutation/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} diff --git a/parser/testdata/01710_projection_optimize_materialize/metadata.json b/parser/testdata/01710_projection_optimize_materialize/metadata.json index dbdbb76d4f..0967ef424b 100644 --- a/parser/testdata/01710_projection_optimize_materialize/metadata.json +++ b/parser/testdata/01710_projection_optimize_materialize/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt6": true - } -} +{} diff --git a/parser/testdata/01710_projection_vertical_merges/metadata.json b/parser/testdata/01710_projection_vertical_merges/metadata.json index dbdbb76d4f..0967ef424b 100644 --- a/parser/testdata/01710_projection_vertical_merges/metadata.json +++ b/parser/testdata/01710_projection_vertical_merges/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt6": true - } -} +{} diff --git a/parser/testdata/01747_alter_partition_key_enum_zookeeper_long/metadata.json b/parser/testdata/01747_alter_partition_key_enum_zookeeper_long/metadata.json index ca584b3e28..0967ef424b 100644 --- a/parser/testdata/01747_alter_partition_key_enum_zookeeper_long/metadata.json +++ b/parser/testdata/01747_alter_partition_key_enum_zookeeper_long/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt17": true - } -} +{} diff --git a/parser/testdata/02028_system_data_skipping_indices_size/metadata.json b/parser/testdata/02028_system_data_skipping_indices_size/metadata.json index ff0eba6904..dbdbb76d4f 100644 --- a/parser/testdata/02028_system_data_skipping_indices_size/metadata.json +++ b/parser/testdata/02028_system_data_skipping_indices_size/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt6": true, - "stmt7": true + "stmt6": true } } diff --git a/parser/testdata/02129_add_column_add_ttl/metadata.json b/parser/testdata/02129_add_column_add_ttl/metadata.json index d94e324dee..6dc0aa1ce2 100644 --- a/parser/testdata/02129_add_column_add_ttl/metadata.json +++ b/parser/testdata/02129_add_column_add_ttl/metadata.json @@ -1,8 +1,6 @@ { "explain_todo": { - "stmt15": true, "stmt17": true, - "stmt5": true, "stmt7": true } } diff --git a/parser/testdata/02131_materialize_column_cast/metadata.json b/parser/testdata/02131_materialize_column_cast/metadata.json index 184c8b6f0c..15d79beb93 100644 --- a/parser/testdata/02131_materialize_column_cast/metadata.json +++ b/parser/testdata/02131_materialize_column_cast/metadata.json @@ -1,7 +1,6 @@ { "explain_todo": { "stmt11": true, - "stmt12": true, "stmt5": true } } diff --git a/parser/testdata/02251_alter_enum_nested_struct/metadata.json b/parser/testdata/02251_alter_enum_nested_struct/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/02251_alter_enum_nested_struct/metadata.json +++ b/parser/testdata/02251_alter_enum_nested_struct/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} diff --git a/parser/testdata/02319_lightweight_delete_on_merge_tree/metadata.json b/parser/testdata/02319_lightweight_delete_on_merge_tree/metadata.json index 5a98c71a6f..9103ba5f40 100644 --- a/parser/testdata/02319_lightweight_delete_on_merge_tree/metadata.json +++ b/parser/testdata/02319_lightweight_delete_on_merge_tree/metadata.json @@ -4,15 +4,10 @@ "stmt16": true, "stmt26": true, "stmt30": true, - "stmt34": true, - "stmt35": true, - "stmt36": true, "stmt45": true, "stmt52": true, - "stmt56": true, "stmt57": true, "stmt6": true, - "stmt65": true, "stmt67": true, "stmt72": true, "stmt74": true diff --git a/parser/testdata/02319_lightweight_delete_on_merge_tree_compact_parts/metadata.json b/parser/testdata/02319_lightweight_delete_on_merge_tree_compact_parts/metadata.json index fd6529c982..9849199b47 100644 --- a/parser/testdata/02319_lightweight_delete_on_merge_tree_compact_parts/metadata.json +++ b/parser/testdata/02319_lightweight_delete_on_merge_tree_compact_parts/metadata.json @@ -4,12 +4,8 @@ "stmt19": true, "stmt31": true, "stmt35": true, - "stmt39": true, - "stmt40": true, - "stmt41": true, "stmt50": true, "stmt57": true, - "stmt61": true, "stmt62": true, "stmt7": true } diff --git a/parser/testdata/02346_text_index_bug47393/metadata.json b/parser/testdata/02346_text_index_bug47393/metadata.json index dbdbb76d4f..0967ef424b 100644 --- a/parser/testdata/02346_text_index_bug47393/metadata.json +++ b/parser/testdata/02346_text_index_bug47393/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt6": true - } -} +{} diff --git a/parser/testdata/02352_lightweight_delete/metadata.json b/parser/testdata/02352_lightweight_delete/metadata.json index 2e37f85aea..7cece2367e 100644 --- a/parser/testdata/02352_lightweight_delete/metadata.json +++ b/parser/testdata/02352_lightweight_delete/metadata.json @@ -2,7 +2,6 @@ "explain_todo": { "stmt14": true, "stmt19": true, - "stmt24": true, "stmt29": true, "stmt34": true, "stmt39": true, diff --git a/parser/testdata/02354_vector_search_postfiltering_bug/metadata.json b/parser/testdata/02354_vector_search_postfiltering_bug/metadata.json index ef382ce51e..b65b07d7a6 100644 --- a/parser/testdata/02354_vector_search_postfiltering_bug/metadata.json +++ b/parser/testdata/02354_vector_search_postfiltering_bug/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt4": true, - "stmt5": true + "stmt4": true } } diff --git a/parser/testdata/02371_select_projection_normal_agg/metadata.json b/parser/testdata/02371_select_projection_normal_agg/metadata.json index 54590bc988..0967ef424b 100644 --- a/parser/testdata/02371_select_projection_normal_agg/metadata.json +++ b/parser/testdata/02371_select_projection_normal_agg/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt11": true, - "stmt13": true - } -} +{} diff --git a/parser/testdata/02436_system_zookeeper_context/metadata.json b/parser/testdata/02436_system_zookeeper_context/metadata.json index 3a06a4a1ac..0967ef424b 100644 --- a/parser/testdata/02436_system_zookeeper_context/metadata.json +++ b/parser/testdata/02436_system_zookeeper_context/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt5": true - } -} +{} diff --git a/parser/testdata/02441_alter_delete_and_drop_column/metadata.json b/parser/testdata/02441_alter_delete_and_drop_column/metadata.json index 84f57deaf2..25122ac4f4 100644 --- a/parser/testdata/02441_alter_delete_and_drop_column/metadata.json +++ b/parser/testdata/02441_alter_delete_and_drop_column/metadata.json @@ -1,7 +1,6 @@ { "explain_todo": { "stmt5": true, - "stmt7": true, "stmt9": true } } diff --git a/parser/testdata/02448_clone_replica_lost_part/metadata.json b/parser/testdata/02448_clone_replica_lost_part/metadata.json index 4ecdbbd83a..7f83f2ec01 100644 --- a/parser/testdata/02448_clone_replica_lost_part/metadata.json +++ b/parser/testdata/02448_clone_replica_lost_part/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt51": true, "stmt80": true } } diff --git a/parser/testdata/02456_alter-nullable-column-bag/metadata.json b/parser/testdata/02456_alter-nullable-column-bag/metadata.json index b563327205..0967ef424b 100644 --- a/parser/testdata/02456_alter-nullable-column-bag/metadata.json +++ b/parser/testdata/02456_alter-nullable-column-bag/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt7": true - } -} +{} diff --git a/parser/testdata/02461_alter_update_respect_part_column_type_bug/metadata.json b/parser/testdata/02461_alter_update_respect_part_column_type_bug/metadata.json index 063b99afba..0967ef424b 100644 --- a/parser/testdata/02461_alter_update_respect_part_column_type_bug/metadata.json +++ b/parser/testdata/02461_alter_update_respect_part_column_type_bug/metadata.json @@ -1,8 +1 @@ -{ - "explain_todo": { - "stmt15": true, - "stmt40": true, - "stmt48": true, - "stmt7": true - } -} +{} diff --git a/parser/testdata/02478_projection_and_alter_low_cardinality/metadata.json b/parser/testdata/02478_projection_and_alter_low_cardinality/metadata.json index f5dd12602b..ef58f80315 100644 --- a/parser/testdata/02478_projection_and_alter_low_cardinality/metadata.json +++ b/parser/testdata/02478_projection_and_alter_low_cardinality/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt2": true, - "stmt5": true + "stmt2": true } } diff --git a/parser/testdata/02478_projection_with_group_by_alter/metadata.json b/parser/testdata/02478_projection_with_group_by_alter/metadata.json index abf21b100d..0967ef424b 100644 --- a/parser/testdata/02478_projection_with_group_by_alter/metadata.json +++ b/parser/testdata/02478_projection_with_group_by_alter/metadata.json @@ -1,7 +1 @@ -{ - "explain_todo": { - "stmt11": true, - "stmt15": true, - "stmt7": true - } -} +{} diff --git a/parser/testdata/02481_low_cardinality_with_short_circuit_functins_mutations/metadata.json b/parser/testdata/02481_low_cardinality_with_short_circuit_functins_mutations/metadata.json index 1295a45747..0967ef424b 100644 --- a/parser/testdata/02481_low_cardinality_with_short_circuit_functins_mutations/metadata.json +++ b/parser/testdata/02481_low_cardinality_with_short_circuit_functins_mutations/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt3": true - } -} +{} diff --git a/parser/testdata/02494_query_cache_eligible_queries/metadata.json b/parser/testdata/02494_query_cache_eligible_queries/metadata.json index dbd52b6142..edf04afbb9 100644 --- a/parser/testdata/02494_query_cache_eligible_queries/metadata.json +++ b/parser/testdata/02494_query_cache_eligible_queries/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt11": true, "stmt17": true, "stmt23": true, "stmt25": true, diff --git a/parser/testdata/02516_projections_with_rollup/metadata.json b/parser/testdata/02516_projections_with_rollup/metadata.json index a56c7cdb0b..0967ef424b 100644 --- a/parser/testdata/02516_projections_with_rollup/metadata.json +++ b/parser/testdata/02516_projections_with_rollup/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt10": true, - "stmt12": true - } -} +{} diff --git a/parser/testdata/02521_lightweight_delete_and_ttl/metadata.json b/parser/testdata/02521_lightweight_delete_and_ttl/metadata.json index d04e936e77..47f980edf9 100644 --- a/parser/testdata/02521_lightweight_delete_and_ttl/metadata.json +++ b/parser/testdata/02521_lightweight_delete_and_ttl/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt12": true, "stmt15": true, "stmt18": true, "stmt5": true, diff --git a/parser/testdata/02538_alter_rename_sequence/metadata.json b/parser/testdata/02538_alter_rename_sequence/metadata.json index d0820085d8..0967ef424b 100644 --- a/parser/testdata/02538_alter_rename_sequence/metadata.json +++ b/parser/testdata/02538_alter_rename_sequence/metadata.json @@ -1,8 +1 @@ -{ - "explain_todo": { - "stmt10": true, - "stmt16": true, - "stmt21": true, - "stmt5": true - } -} +{} diff --git a/parser/testdata/02581_share_big_sets_between_multiple_mutations_tasks_long/metadata.json b/parser/testdata/02581_share_big_sets_between_multiple_mutations_tasks_long/metadata.json index 5d56c00740..e91f8984c2 100644 --- a/parser/testdata/02581_share_big_sets_between_multiple_mutations_tasks_long/metadata.json +++ b/parser/testdata/02581_share_big_sets_between_multiple_mutations_tasks_long/metadata.json @@ -1,9 +1,6 @@ { "explain_todo": { - "stmt10": true, - "stmt11": true, "stmt12": true, - "stmt13": true, "stmt16": true, "stmt2": true } diff --git a/parser/testdata/02581_share_big_sets_between_mutation_tasks/metadata.json b/parser/testdata/02581_share_big_sets_between_mutation_tasks/metadata.json index 93a8bcd4dc..0967ef424b 100644 --- a/parser/testdata/02581_share_big_sets_between_mutation_tasks/metadata.json +++ b/parser/testdata/02581_share_big_sets_between_mutation_tasks/metadata.json @@ -1,13 +1 @@ -{ - "explain_todo": { - "stmt10": true, - "stmt12": true, - "stmt14": true, - "stmt16": true, - "stmt18": true, - "stmt20": true, - "stmt22": true, - "stmt24": true, - "stmt8": true - } -} +{} diff --git a/parser/testdata/02581_share_big_sets_between_mutation_tasks_long/metadata.json b/parser/testdata/02581_share_big_sets_between_mutation_tasks_long/metadata.json index d42586add1..ef58f80315 100644 --- a/parser/testdata/02581_share_big_sets_between_mutation_tasks_long/metadata.json +++ b/parser/testdata/02581_share_big_sets_between_mutation_tasks_long/metadata.json @@ -1,12 +1,5 @@ { "explain_todo": { - "stmt11": true, - "stmt13": true, - "stmt15": true, - "stmt17": true, - "stmt19": true, - "stmt2": true, - "stmt21": true, - "stmt9": true + "stmt2": true } } diff --git a/parser/testdata/02581_share_big_sets_between_mutation_tasks_with_storage_set/metadata.json b/parser/testdata/02581_share_big_sets_between_mutation_tasks_with_storage_set/metadata.json index 7515e2a4b1..ef58f80315 100644 --- a/parser/testdata/02581_share_big_sets_between_mutation_tasks_with_storage_set/metadata.json +++ b/parser/testdata/02581_share_big_sets_between_mutation_tasks_with_storage_set/metadata.json @@ -1,7 +1,5 @@ { "explain_todo": { - "stmt11": true, - "stmt14": true, "stmt2": true } } diff --git a/parser/testdata/02597_column_update_tricky_expression_and_replication/metadata.json b/parser/testdata/02597_column_update_tricky_expression_and_replication/metadata.json index 1dbeaea9b6..342b3ff5b4 100644 --- a/parser/testdata/02597_column_update_tricky_expression_and_replication/metadata.json +++ b/parser/testdata/02597_column_update_tricky_expression_and_replication/metadata.json @@ -1,11 +1,5 @@ { "explain_todo": { - "stmt10": true, - "stmt4": true, - "stmt5": true, - "stmt6": true, - "stmt7": true, - "stmt8": true, - "stmt9": true + "stmt8": true } } diff --git a/parser/testdata/02691_drop_column_with_projections_replicated/metadata.json b/parser/testdata/02691_drop_column_with_projections_replicated/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/02691_drop_column_with_projections_replicated/metadata.json +++ b/parser/testdata/02691_drop_column_with_projections_replicated/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} diff --git a/parser/testdata/02796_projection_date_filter_on_view/metadata.json b/parser/testdata/02796_projection_date_filter_on_view/metadata.json index ef382ce51e..b65b07d7a6 100644 --- a/parser/testdata/02796_projection_date_filter_on_view/metadata.json +++ b/parser/testdata/02796_projection_date_filter_on_view/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt4": true, - "stmt5": true + "stmt4": true } } diff --git a/parser/testdata/02842_mutations_replace_non_deterministic/metadata.json b/parser/testdata/02842_mutations_replace_non_deterministic/metadata.json index a24e4c0691..7389add715 100644 --- a/parser/testdata/02842_mutations_replace_non_deterministic/metadata.json +++ b/parser/testdata/02842_mutations_replace_non_deterministic/metadata.json @@ -1,7 +1,6 @@ { "explain_todo": { "stmt28": true, - "stmt36": true, "stmt41": true, "stmt42": true } diff --git a/parser/testdata/02842_vertical_merge_after_add_drop_column/metadata.json b/parser/testdata/02842_vertical_merge_after_add_drop_column/metadata.json index dbdbb76d4f..0967ef424b 100644 --- a/parser/testdata/02842_vertical_merge_after_add_drop_column/metadata.json +++ b/parser/testdata/02842_vertical_merge_after_add_drop_column/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt6": true - } -} +{} diff --git a/parser/testdata/02882_replicated_fetch_checksums_doesnt_match/metadata.json b/parser/testdata/02882_replicated_fetch_checksums_doesnt_match/metadata.json index 7ad5569408..0967ef424b 100644 --- a/parser/testdata/02882_replicated_fetch_checksums_doesnt_match/metadata.json +++ b/parser/testdata/02882_replicated_fetch_checksums_doesnt_match/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt9": true - } -} +{} diff --git a/parser/testdata/02891_alter_update_adaptive_granularity/metadata.json b/parser/testdata/02891_alter_update_adaptive_granularity/metadata.json index 1295a45747..0967ef424b 100644 --- a/parser/testdata/02891_alter_update_adaptive_granularity/metadata.json +++ b/parser/testdata/02891_alter_update_adaptive_granularity/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt3": true - } -} +{} diff --git a/parser/testdata/02919_segfault_nullable_materialized_update/metadata.json b/parser/testdata/02919_segfault_nullable_materialized_update/metadata.json index 6bf8d5b80a..0967ef424b 100644 --- a/parser/testdata/02919_segfault_nullable_materialized_update/metadata.json +++ b/parser/testdata/02919_segfault_nullable_materialized_update/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt5": true, - "stmt7": true - } -} +{} diff --git a/parser/testdata/02920_alter_column_of_projections/metadata.json b/parser/testdata/02920_alter_column_of_projections/metadata.json index c45b7602ba..0967ef424b 100644 --- a/parser/testdata/02920_alter_column_of_projections/metadata.json +++ b/parser/testdata/02920_alter_column_of_projections/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt12": true - } -} +{} diff --git a/parser/testdata/02920_rename_column_of_skip_indices/metadata.json b/parser/testdata/02920_rename_column_of_skip_indices/metadata.json index 7ad5569408..0967ef424b 100644 --- a/parser/testdata/02920_rename_column_of_skip_indices/metadata.json +++ b/parser/testdata/02920_rename_column_of_skip_indices/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt9": true - } -} +{} diff --git a/parser/testdata/02932_query_settings_max_size_drop/metadata.json b/parser/testdata/02932_query_settings_max_size_drop/metadata.json index 9fa46e35fb..e8ebb227c0 100644 --- a/parser/testdata/02932_query_settings_max_size_drop/metadata.json +++ b/parser/testdata/02932_query_settings_max_size_drop/metadata.json @@ -2,7 +2,6 @@ "explain_todo": { "stmt10": true, "stmt2": true, - "stmt5": true, "stmt9": true } } diff --git a/parser/testdata/02932_query_settings_max_size_drop_rmt/metadata.json b/parser/testdata/02932_query_settings_max_size_drop_rmt/metadata.json index 25122ac4f4..3a06a4a1ac 100644 --- a/parser/testdata/02932_query_settings_max_size_drop_rmt/metadata.json +++ b/parser/testdata/02932_query_settings_max_size_drop_rmt/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt5": true, - "stmt9": true + "stmt5": true } } diff --git a/parser/testdata/02941_projections_external_aggregation/metadata.json b/parser/testdata/02941_projections_external_aggregation/metadata.json index 7b4455cd5f..0967ef424b 100644 --- a/parser/testdata/02941_projections_external_aggregation/metadata.json +++ b/parser/testdata/02941_projections_external_aggregation/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt16": true - } -} +{} diff --git a/parser/testdata/03001_data_version_column/metadata.json b/parser/testdata/03001_data_version_column/metadata.json index dbdbb76d4f..0967ef424b 100644 --- a/parser/testdata/03001_data_version_column/metadata.json +++ b/parser/testdata/03001_data_version_column/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt6": true - } -} +{} diff --git a/parser/testdata/03040_dynamic_type_alters_1_compact_merge_tree/metadata.json b/parser/testdata/03040_dynamic_type_alters_1_compact_merge_tree/metadata.json index 3dd4c40b17..0967ef424b 100644 --- a/parser/testdata/03040_dynamic_type_alters_1_compact_merge_tree/metadata.json +++ b/parser/testdata/03040_dynamic_type_alters_1_compact_merge_tree/metadata.json @@ -1,8 +1 @@ -{ - "explain_todo": { - "stmt20": true, - "stmt28": true, - "stmt36": true, - "stmt9": true - } -} +{} diff --git a/parser/testdata/03040_dynamic_type_alters_1_memory/metadata.json b/parser/testdata/03040_dynamic_type_alters_1_memory/metadata.json index 3dd4c40b17..0967ef424b 100644 --- a/parser/testdata/03040_dynamic_type_alters_1_memory/metadata.json +++ b/parser/testdata/03040_dynamic_type_alters_1_memory/metadata.json @@ -1,8 +1 @@ -{ - "explain_todo": { - "stmt20": true, - "stmt28": true, - "stmt36": true, - "stmt9": true - } -} +{} diff --git a/parser/testdata/03040_dynamic_type_alters_1_wide_merge_tree/metadata.json b/parser/testdata/03040_dynamic_type_alters_1_wide_merge_tree/metadata.json index 3dd4c40b17..0967ef424b 100644 --- a/parser/testdata/03040_dynamic_type_alters_1_wide_merge_tree/metadata.json +++ b/parser/testdata/03040_dynamic_type_alters_1_wide_merge_tree/metadata.json @@ -1,8 +1 @@ -{ - "explain_todo": { - "stmt20": true, - "stmt28": true, - "stmt36": true, - "stmt9": true - } -} +{} diff --git a/parser/testdata/03040_dynamic_type_alters_2_compact_merge_tree/metadata.json b/parser/testdata/03040_dynamic_type_alters_2_compact_merge_tree/metadata.json index c7d61335bb..87fa61cc2d 100644 --- a/parser/testdata/03040_dynamic_type_alters_2_compact_merge_tree/metadata.json +++ b/parser/testdata/03040_dynamic_type_alters_2_compact_merge_tree/metadata.json @@ -1,9 +1,6 @@ { "explain_todo": { - "stmt20": true, "stmt24": true, - "stmt28": true, - "stmt30": true, - "stmt9": true + "stmt30": true } } diff --git a/parser/testdata/03040_dynamic_type_alters_2_wide_merge_tree/metadata.json b/parser/testdata/03040_dynamic_type_alters_2_wide_merge_tree/metadata.json index 54a3d3c1df..2da8c35726 100644 --- a/parser/testdata/03040_dynamic_type_alters_2_wide_merge_tree/metadata.json +++ b/parser/testdata/03040_dynamic_type_alters_2_wide_merge_tree/metadata.json @@ -1,9 +1,6 @@ { "explain_todo": { - "stmt21": true, "stmt25": true, - "stmt30": true, - "stmt32": true, - "stmt9": true + "stmt32": true } } diff --git a/parser/testdata/03047_on_fly_mutations_events/metadata.json b/parser/testdata/03047_on_fly_mutations_events/metadata.json index 7f674aae32..2ef6a38008 100644 --- a/parser/testdata/03047_on_fly_mutations_events/metadata.json +++ b/parser/testdata/03047_on_fly_mutations_events/metadata.json @@ -1,8 +1,6 @@ { "explain_todo": { - "stmt12": true, "stmt15": true, - "stmt19": true, "stmt8": true, "stmt9": true } diff --git a/parser/testdata/03047_on_fly_mutations_non_deterministic_replace/metadata.json b/parser/testdata/03047_on_fly_mutations_non_deterministic_replace/metadata.json index 37668fba8c..0c54d3781a 100644 --- a/parser/testdata/03047_on_fly_mutations_non_deterministic_replace/metadata.json +++ b/parser/testdata/03047_on_fly_mutations_non_deterministic_replace/metadata.json @@ -1,8 +1,6 @@ { "explain_todo": { - "stmt21": true, "stmt36": true, - "stmt49": true, "stmt55": true, "stmt58": true } diff --git a/parser/testdata/03096_update_non_indexed_columns/metadata.json b/parser/testdata/03096_update_non_indexed_columns/metadata.json index 92efb02376..0967ef424b 100644 --- a/parser/testdata/03096_update_non_indexed_columns/metadata.json +++ b/parser/testdata/03096_update_non_indexed_columns/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt6": true, - "stmt8": true - } -} +{} diff --git a/parser/testdata/03100_lwu_27_update_after_on_fly_mutations/metadata.json b/parser/testdata/03100_lwu_27_update_after_on_fly_mutations/metadata.json index 4f593ff9c6..2cf11720b5 100644 --- a/parser/testdata/03100_lwu_27_update_after_on_fly_mutations/metadata.json +++ b/parser/testdata/03100_lwu_27_update_after_on_fly_mutations/metadata.json @@ -1,7 +1,6 @@ { "explain_todo": { "stmt10": true, - "stmt8": true, - "stmt9": true + "stmt8": true } } diff --git a/parser/testdata/03100_lwu_44_missing_default/metadata.json b/parser/testdata/03100_lwu_44_missing_default/metadata.json index 527e00e289..8162ad6436 100644 --- a/parser/testdata/03100_lwu_44_missing_default/metadata.json +++ b/parser/testdata/03100_lwu_44_missing_default/metadata.json @@ -1,8 +1,6 @@ { "explain_todo": { - "stmt10": true, "stmt21": true, - "stmt22": true, "stmt9": true } } diff --git a/parser/testdata/03129_update_nested_materialized_column_check/metadata.json b/parser/testdata/03129_update_nested_materialized_column_check/metadata.json index 6bf8d5b80a..0967ef424b 100644 --- a/parser/testdata/03129_update_nested_materialized_column_check/metadata.json +++ b/parser/testdata/03129_update_nested_materialized_column_check/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt5": true, - "stmt7": true - } -} +{} diff --git a/parser/testdata/03169_modify_column_data_loss/metadata.json b/parser/testdata/03169_modify_column_data_loss/metadata.json index 342b3ff5b4..0967ef424b 100644 --- a/parser/testdata/03169_modify_column_data_loss/metadata.json +++ b/parser/testdata/03169_modify_column_data_loss/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt8": true - } -} +{} diff --git a/parser/testdata/03205_parallel_replicas_alter_select_ubsan/metadata.json b/parser/testdata/03205_parallel_replicas_alter_select_ubsan/metadata.json index f6d9f2395b..0967ef424b 100644 --- a/parser/testdata/03205_parallel_replicas_alter_select_ubsan/metadata.json +++ b/parser/testdata/03205_parallel_replicas_alter_select_ubsan/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt7": true, - "stmt8": true - } -} +{} diff --git a/parser/testdata/03268_empty_tuple_update/metadata.json b/parser/testdata/03268_empty_tuple_update/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/03268_empty_tuple_update/metadata.json +++ b/parser/testdata/03268_empty_tuple_update/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} diff --git a/parser/testdata/03285_materialize_ttl_only_drop_parts/metadata.json b/parser/testdata/03285_materialize_ttl_only_drop_parts/metadata.json index 2419c457e5..69b463d035 100644 --- a/parser/testdata/03285_materialize_ttl_only_drop_parts/metadata.json +++ b/parser/testdata/03285_materialize_ttl_only_drop_parts/metadata.json @@ -1,9 +1,7 @@ { "explain_todo": { "stmt10": true, - "stmt13": true, "stmt14": true, - "stmt5": true, - "stmt9": true + "stmt5": true } } diff --git a/parser/testdata/03381_lazy_materialization_limit_offset/metadata.json b/parser/testdata/03381_lazy_materialization_limit_offset/metadata.json index 3a06a4a1ac..0967ef424b 100644 --- a/parser/testdata/03381_lazy_materialization_limit_offset/metadata.json +++ b/parser/testdata/03381_lazy_materialization_limit_offset/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt5": true - } -} +{} diff --git a/parser/testdata/03401_normal_projection_with_part_offset/metadata.json b/parser/testdata/03401_normal_projection_with_part_offset/metadata.json index f4c74e32be..0967ef424b 100644 --- a/parser/testdata/03401_normal_projection_with_part_offset/metadata.json +++ b/parser/testdata/03401_normal_projection_with_part_offset/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt10": true - } -} +{} diff --git a/parser/testdata/03401_normal_projection_with_part_offset_no_sorting/metadata.json b/parser/testdata/03401_normal_projection_with_part_offset_no_sorting/metadata.json index f4c74e32be..0967ef424b 100644 --- a/parser/testdata/03401_normal_projection_with_part_offset_no_sorting/metadata.json +++ b/parser/testdata/03401_normal_projection_with_part_offset_no_sorting/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt10": true - } -} +{} diff --git a/parser/testdata/03442_lightweight_deletes_on_fly/metadata.json b/parser/testdata/03442_lightweight_deletes_on_fly/metadata.json index 63ef8ced26..e3f4c45da5 100644 --- a/parser/testdata/03442_lightweight_deletes_on_fly/metadata.json +++ b/parser/testdata/03442_lightweight_deletes_on_fly/metadata.json @@ -1,7 +1,6 @@ { "explain_todo": { "stmt13": true, - "stmt15": true, "stmt16": true, "stmt7": true, "stmt8": true diff --git a/parser/testdata/03522_alter_modify_column_and_materialize_projection/metadata.json b/parser/testdata/03522_alter_modify_column_and_materialize_projection/metadata.json index dbdbb76d4f..0967ef424b 100644 --- a/parser/testdata/03522_alter_modify_column_and_materialize_projection/metadata.json +++ b/parser/testdata/03522_alter_modify_column_and_materialize_projection/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt6": true - } -} +{} diff --git a/parser/testdata/03593_backup_with_broken_projection/metadata.json b/parser/testdata/03593_backup_with_broken_projection/metadata.json index a4f8773303..3a06a4a1ac 100644 --- a/parser/testdata/03593_backup_with_broken_projection/metadata.json +++ b/parser/testdata/03593_backup_with_broken_projection/metadata.json @@ -1,7 +1,5 @@ { "explain_todo": { - "stmt3": true, - "stmt4": true, "stmt5": true } } diff --git a/parser/testdata/03596_alter_update_column_with_subcolumn_used_in_materialized_expression/metadata.json b/parser/testdata/03596_alter_update_column_with_subcolumn_used_in_materialized_expression/metadata.json index c3335fbf65..0967ef424b 100644 --- a/parser/testdata/03596_alter_update_column_with_subcolumn_used_in_materialized_expression/metadata.json +++ b/parser/testdata/03596_alter_update_column_with_subcolumn_used_in_materialized_expression/metadata.json @@ -1,14 +1 @@ -{ - "explain_todo": { - "stmt14": true, - "stmt16": true, - "stmt22": true, - "stmt28": true, - "stmt30": true, - "stmt37": true, - "stmt39": true, - "stmt45": true, - "stmt5": true, - "stmt7": true - } -} +{} diff --git a/parser/testdata/03625_prewhere-and-default-bug/metadata.json b/parser/testdata/03625_prewhere-and-default-bug/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/03625_prewhere-and-default-bug/metadata.json +++ b/parser/testdata/03625_prewhere-and-default-bug/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} diff --git a/parser/testdata/03636_storage_alias_basic/metadata.json b/parser/testdata/03636_storage_alias_basic/metadata.json index 7f91686195..f778b3ba0e 100644 --- a/parser/testdata/03636_storage_alias_basic/metadata.json +++ b/parser/testdata/03636_storage_alias_basic/metadata.json @@ -1,7 +1,6 @@ { "explain_todo": { "stmt32": true, - "stmt52": true, "stmt55": true } } diff --git a/parser/testdata/03673_columns_description_cache/metadata.json b/parser/testdata/03673_columns_description_cache/metadata.json index 40d03a3c09..9238486a6e 100644 --- a/parser/testdata/03673_columns_description_cache/metadata.json +++ b/parser/testdata/03673_columns_description_cache/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt12": true, "stmt17": true, "stmt18": true } diff --git a/parser/testdata/03721_statistics_alter_type_bug/metadata.json b/parser/testdata/03721_statistics_alter_type_bug/metadata.json index 5e06643b76..0967ef424b 100644 --- a/parser/testdata/03721_statistics_alter_type_bug/metadata.json +++ b/parser/testdata/03721_statistics_alter_type_bug/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt12": true, - "stmt6": true - } -} +{} diff --git a/parser/testdata/03732_json_duplicated_path_in_dynamic_paths_and_shared_data_bug/metadata.json b/parser/testdata/03732_json_duplicated_path_in_dynamic_paths_and_shared_data_bug/metadata.json index 3a06a4a1ac..0967ef424b 100644 --- a/parser/testdata/03732_json_duplicated_path_in_dynamic_paths_and_shared_data_bug/metadata.json +++ b/parser/testdata/03732_json_duplicated_path_in_dynamic_paths_and_shared_data_bug/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt5": true - } -} +{} diff --git a/parser/testdata/03741_subcolumns_of_materialized_columns_in_mutation/metadata.json b/parser/testdata/03741_subcolumns_of_materialized_columns_in_mutation/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/03741_subcolumns_of_materialized_columns_in_mutation/metadata.json +++ b/parser/testdata/03741_subcolumns_of_materialized_columns_in_mutation/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} diff --git a/parser/testdata/03742_lazy_materialization_of_array_after_alter_add_column/metadata.json b/parser/testdata/03742_lazy_materialization_of_array_after_alter_add_column/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/03742_lazy_materialization_of_array_after_alter_add_column/metadata.json +++ b/parser/testdata/03742_lazy_materialization_of_array_after_alter_add_column/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} diff --git a/parser/testdata/03745_fix_dynamic_structure_in_compact_part/metadata.json b/parser/testdata/03745_fix_dynamic_structure_in_compact_part/metadata.json index b65b07d7a6..0967ef424b 100644 --- a/parser/testdata/03745_fix_dynamic_structure_in_compact_part/metadata.json +++ b/parser/testdata/03745_fix_dynamic_structure_in_compact_part/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt4": true - } -} +{} From acb8bb2e8ae2b40fd24571c72e5da6f46cca7a3c Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 31 Dec 2025 09:21:13 +0000 Subject: [PATCH 23/24] Fix empty lambda parameter list EXPLAIN output When a lambda has no parameters (e.g., `() -> expr`), ClickHouse outputs just `ExpressionList` without the `(children N)` suffix. Previously we were outputting `ExpressionList (children 0)` which didn't match the expected format. Fixes 5 tests related to user-defined functions with empty lambda args. --- internal/explain/functions.go | 11 ++++++++--- .../metadata.json | 6 +----- .../metadata.json | 2 +- .../metadata.json | 9 +-------- .../metadata.json | 5 +---- parser/testdata/03215_udf_with_union/metadata.json | 6 +----- 6 files changed, 13 insertions(+), 26 deletions(-) diff --git a/internal/explain/functions.go b/internal/explain/functions.go index e53dda965b..c4cbea74d5 100644 --- a/internal/explain/functions.go +++ b/internal/explain/functions.go @@ -98,9 +98,14 @@ func explainLambdaWithAlias(sb *strings.Builder, n *ast.Lambda, alias string, in fmt.Fprintf(sb, "%s ExpressionList (children %d)\n", indent, 2) // Parameters as tuple fmt.Fprintf(sb, "%s Function tuple (children %d)\n", indent, 1) - fmt.Fprintf(sb, "%s ExpressionList (children %d)\n", indent, len(n.Parameters)) - for _, p := range n.Parameters { - fmt.Fprintf(sb, "%s Identifier %s\n", indent, p) + // When there are no parameters, ClickHouse omits the (children N) part + if len(n.Parameters) > 0 { + fmt.Fprintf(sb, "%s ExpressionList (children %d)\n", indent, len(n.Parameters)) + for _, p := range n.Parameters { + fmt.Fprintf(sb, "%s Identifier %s\n", indent, p) + } + } else { + fmt.Fprintf(sb, "%s ExpressionList\n", indent) } // Body Node(sb, n.Body, depth+2) diff --git a/parser/testdata/02103_sql_user_defined_functions_composition/metadata.json b/parser/testdata/02103_sql_user_defined_functions_composition/metadata.json index ef58f80315..0967ef424b 100644 --- a/parser/testdata/02103_sql_user_defined_functions_composition/metadata.json +++ b/parser/testdata/02103_sql_user_defined_functions_composition/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt2": true - } -} +{} diff --git a/parser/testdata/02126_identity_user_defined_function/metadata.json b/parser/testdata/02126_identity_user_defined_function/metadata.json index a5700aa3f1..0967ef424b 100644 --- a/parser/testdata/02126_identity_user_defined_function/metadata.json +++ b/parser/testdata/02126_identity_user_defined_function/metadata.json @@ -1 +1 @@ -{"explain_todo":{"stmt5":true,"stmt7":true}} +{} diff --git a/parser/testdata/02148_sql_user_defined_function_subquery/metadata.json b/parser/testdata/02148_sql_user_defined_function_subquery/metadata.json index 34aad7f209..0967ef424b 100644 --- a/parser/testdata/02148_sql_user_defined_function_subquery/metadata.json +++ b/parser/testdata/02148_sql_user_defined_function_subquery/metadata.json @@ -1,8 +1 @@ -{ - "explain_todo": { - "stmt17": true, - "stmt19": true, - "stmt2": true, - "stmt4": true - } -} +{} diff --git a/parser/testdata/02354_vector_search_reference_vector_types/metadata.json b/parser/testdata/02354_vector_search_reference_vector_types/metadata.json index 74e8ec22a2..ab9202e88e 100644 --- a/parser/testdata/02354_vector_search_reference_vector_types/metadata.json +++ b/parser/testdata/02354_vector_search_reference_vector_types/metadata.json @@ -1,8 +1,5 @@ { "explain_todo": { - "stmt11": true, - "stmt14": true, - "stmt16": true, - "stmt18": true + "stmt11": true } } diff --git a/parser/testdata/03215_udf_with_union/metadata.json b/parser/testdata/03215_udf_with_union/metadata.json index ef58f80315..0967ef424b 100644 --- a/parser/testdata/03215_udf_with_union/metadata.json +++ b/parser/testdata/03215_udf_with_union/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt2": true - } -} +{} From c983b1a36b3e2bf9fe77d127d222b4c445ec997a Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 31 Dec 2025 09:30:13 +0000 Subject: [PATCH 24/24] Fix WITH FILL STEP output format in ORDER BY When ORDER BY has WITH fill step N (without FROM/TO), ClickHouse outputs the step value directly as a Literal child of OrderByElement, not wrapped in a FillModifier node. Previously we used FillModifier for step-only cases, but ClickHouse only uses FillModifier when FROM/TO contain complex expressions. Fixes 19+ statements across 6 tests related to WITH FILL. --- internal/explain/select.go | 7 +++---- parser/testdata/00995_order_by_with_fill/metadata.json | 1 - .../metadata.json | 6 +----- .../01868_order_by_fill_with_datetime64/metadata.json | 7 +------ parser/testdata/02112_with_fill_interval/metadata.json | 9 ++++++++- .../02730_with_fill_by_sorting_prefix/metadata.json | 5 +---- parser/testdata/03366_with_fill_dag/metadata.json | 1 - 7 files changed, 14 insertions(+), 22 deletions(-) diff --git a/internal/explain/select.go b/internal/explain/select.go index 99b1a83423..06651fa6d3 100644 --- a/internal/explain/select.go +++ b/internal/explain/select.go @@ -194,10 +194,9 @@ func explainOrderByElement(sb *strings.Builder, n *ast.OrderByElement, indent st hasFromOrTo := n.FillFrom != nil || n.FillTo != nil hasComplexFillExpr := hasFromOrTo && (isComplexExpr(n.FillFrom) || isComplexExpr(n.FillTo)) - // Use FillModifier when: - // 1. Only STEP is present (no FROM/TO), or - // 2. FROM/TO contain complex expressions (not simple literals) - useFillModifier := n.WithFill && ((n.FillStep != nil && !hasFromOrTo) || hasComplexFillExpr) + // Use FillModifier when FROM/TO contain complex expressions (not simple literals) + // When only STEP is present, output it directly as a child (no FillModifier) + useFillModifier := n.WithFill && hasComplexFillExpr if useFillModifier { // Use FillModifier wrapper diff --git a/parser/testdata/00995_order_by_with_fill/metadata.json b/parser/testdata/00995_order_by_with_fill/metadata.json index c307142bf5..1a80004277 100644 --- a/parser/testdata/00995_order_by_with_fill/metadata.json +++ b/parser/testdata/00995_order_by_with_fill/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt16": true, "stmt19": true, "stmt6": true, "stmt8": true, diff --git a/parser/testdata/01034_with_fill_and_push_down_predicate/metadata.json b/parser/testdata/01034_with_fill_and_push_down_predicate/metadata.json index e9d6e46171..0967ef424b 100644 --- a/parser/testdata/01034_with_fill_and_push_down_predicate/metadata.json +++ b/parser/testdata/01034_with_fill_and_push_down_predicate/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt1": true - } -} +{} diff --git a/parser/testdata/01868_order_by_fill_with_datetime64/metadata.json b/parser/testdata/01868_order_by_fill_with_datetime64/metadata.json index 682bda1cbc..0967ef424b 100644 --- a/parser/testdata/01868_order_by_fill_with_datetime64/metadata.json +++ b/parser/testdata/01868_order_by_fill_with_datetime64/metadata.json @@ -1,6 +1 @@ -{ - "explain_todo": { - "stmt1": true, - "stmt2": true - } -} +{} diff --git a/parser/testdata/02112_with_fill_interval/metadata.json b/parser/testdata/02112_with_fill_interval/metadata.json index b50f055109..b123819252 100644 --- a/parser/testdata/02112_with_fill_interval/metadata.json +++ b/parser/testdata/02112_with_fill_interval/metadata.json @@ -1 +1,8 @@ -{"explain_todo":{"stmt10":true,"stmt12":true,"stmt14":true,"stmt15":true,"stmt17":true,"stmt19":true,"stmt21":true,"stmt23":true,"stmt24":true,"stmt31":true,"stmt33":true,"stmt35":true,"stmt37":true,"stmt39":true,"stmt41":true,"stmt43":true,"stmt50":true,"stmt52":true,"stmt8":true}} +{ + "explain_todo": { + "stmt14": true, + "stmt23": true, + "stmt50": true, + "stmt52": true + } +} diff --git a/parser/testdata/02730_with_fill_by_sorting_prefix/metadata.json b/parser/testdata/02730_with_fill_by_sorting_prefix/metadata.json index 21e49f8743..10d115b1ef 100644 --- a/parser/testdata/02730_with_fill_by_sorting_prefix/metadata.json +++ b/parser/testdata/02730_with_fill_by_sorting_prefix/metadata.json @@ -1,7 +1,5 @@ { "explain_todo": { - "stmt13": true, - "stmt19": true, "stmt20": true, "stmt21": true, "stmt22": true, @@ -14,7 +12,6 @@ "stmt29": true, "stmt30": true, "stmt31": true, - "stmt32": true, - "stmt6": true + "stmt32": true } } diff --git a/parser/testdata/03366_with_fill_dag/metadata.json b/parser/testdata/03366_with_fill_dag/metadata.json index 682bda1cbc..ef58f80315 100644 --- a/parser/testdata/03366_with_fill_dag/metadata.json +++ b/parser/testdata/03366_with_fill_dag/metadata.json @@ -1,6 +1,5 @@ { "explain_todo": { - "stmt1": true, "stmt2": true } }