From 88afb1c97eddbb0daaf82af382352d49f83b3233 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 29 Dec 2025 15:55:21 +0000 Subject: [PATCH 1/2] Remove incorrect UNION ALL simplification in EXPLAIN output The simplifyUnionSelects function was incorrectly collapsing UNION ALL queries when selects had identical expressions but different aliases. ClickHouse's EXPLAIN AST output keeps all SELECT queries in a UNION, so this optimization was incorrect. Fixes test 00592_union_all_different_aliases. --- internal/explain/select.go | 93 +------------------ .../metadata.json | 6 +- 2 files changed, 3 insertions(+), 96 deletions(-) diff --git a/internal/explain/select.go b/internal/explain/select.go index 21a92182f2..789c90aa08 100644 --- a/internal/explain/select.go +++ b/internal/explain/select.go @@ -248,98 +248,9 @@ func countSelectUnionChildren(n *ast.SelectWithUnionQuery) int { return count } -// simplifyUnionSelects implements ClickHouse's UNION ALL optimization: -// When all SELECT queries in a UNION have identical expressions (ignoring aliases) -// but different aliases, only the first SELECT is returned. -// This only applies when ALL columns in ALL SELECTs have explicit aliases. -// If aliases are the same across all SELECTs, or if any column lacks an alias, all are kept. +// simplifyUnionSelects returns all SELECT statements in a UNION. +// ClickHouse does not simplify UNION ALL queries in EXPLAIN AST output. func simplifyUnionSelects(selects []ast.Statement) []ast.Statement { - if len(selects) <= 1 { - return selects - } - - // Check if all are simple SelectQuery with only literal columns - var queries []*ast.SelectQuery - for _, sel := range selects { - sq, ok := sel.(*ast.SelectQuery) - if !ok { - // Not a simple SelectQuery, can't simplify - return selects - } - // Only handle simple SELECT with just columns, no FROM/WHERE/etc. - if sq.From != nil || sq.Where != nil || sq.GroupBy != nil || - sq.Having != nil || sq.OrderBy != nil || len(sq.With) > 0 { - return selects - } - queries = append(queries, sq) - } - - // Check if all have the same number of columns - numCols := len(queries[0].Columns) - for _, q := range queries[1:] { - if len(q.Columns) != numCols { - return selects - } - } - - // Check if columns are all literals with aliases - // and compare expressions (without aliases) and aliases separately - allSameAliases := true - allSameExprs := true - allHaveAliases := true - - for colIdx := 0; colIdx < numCols; colIdx++ { - firstAlias := "" - firstExpr := "" - - for i, q := range queries { - col := q.Columns[colIdx] - alias := "" - exprStr := "" - hasAlias := false - - switch c := col.(type) { - case *ast.AliasedExpr: - alias = c.Alias - hasAlias = c.Alias != "" - // Get string representation of the expression - if lit, ok := c.Expr.(*ast.Literal); ok { - exprStr = fmt.Sprintf("%v", lit.Value) - } else { - // Non-literal expression, can't simplify - return selects - } - case *ast.Literal: - exprStr = fmt.Sprintf("%v", c.Value) - hasAlias = false - default: - // Not a simple literal or aliased literal - return selects - } - - if !hasAlias { - allHaveAliases = false - } - - if i == 0 { - firstAlias = alias - firstExpr = exprStr - } else { - if alias != firstAlias { - allSameAliases = false - } - if exprStr != firstExpr { - allSameExprs = false - } - } - } - } - - // If expressions are the same, all have aliases, but aliases differ, return only first SELECT - if allSameExprs && allHaveAliases && !allSameAliases { - return selects[:1] - } - return selects } diff --git a/parser/testdata/00592_union_all_different_aliases/metadata.json b/parser/testdata/00592_union_all_different_aliases/metadata.json index e9d6e46171..0967ef424b 100644 --- a/parser/testdata/00592_union_all_different_aliases/metadata.json +++ b/parser/testdata/00592_union_all_different_aliases/metadata.json @@ -1,5 +1 @@ -{ - "explain_todo": { - "stmt1": true - } -} +{} From b529339d29e27b9b6cca5fb53e96e625896157bc Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 29 Dec 2025 16:18:31 +0000 Subject: [PATCH 2/2] Remove -v from go test in GitHub workflow --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7039ea41aa..83bd32c8c4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,4 +21,4 @@ jobs: run: go build ./... - name: Test - run: go test -v ./... + run: go test ./...