@@ -235,6 +235,31 @@ func containsNonLiteralExpressions(exprs []ast.Expression) bool {
235235 return false
236236}
237237
238+ // containsNonLiteralInNested checks if an array or tuple literal contains
239+ // non-literal elements at any nesting level (identifiers, function calls, etc.)
240+ func containsNonLiteralInNested (lit * ast.Literal ) bool {
241+ if lit .Type != ast .LiteralArray && lit .Type != ast .LiteralTuple {
242+ return false
243+ }
244+ exprs , ok := lit .Value .([]ast.Expression )
245+ if ! ok {
246+ return false
247+ }
248+ for _ , e := range exprs {
249+ // Check if this element is a non-literal (identifier, function call, etc.)
250+ if _ , isLit := e .(* ast.Literal ); ! isLit {
251+ return true
252+ }
253+ // Recursively check nested arrays/tuples
254+ if innerLit , ok := e .(* ast.Literal ); ok {
255+ if containsNonLiteralInNested (innerLit ) {
256+ return true
257+ }
258+ }
259+ }
260+ return false
261+ }
262+
238263// containsTuples checks if a slice of expressions contains any tuple literals
239264func containsTuples (exprs []ast.Expression ) bool {
240265 for _ , e := range exprs {
@@ -377,10 +402,23 @@ func explainUnaryExpr(sb *strings.Builder, n *ast.UnaryExpr, indent string, dept
377402 // Convert positive integer to negative
378403 switch val := lit .Value .(type ) {
379404 case int64 :
380- fmt .Fprintf (sb , "%sLiteral Int64_%d\n " , indent , - val )
405+ negVal := - val
406+ // ClickHouse normalizes -0 to UInt64_0
407+ if negVal == 0 {
408+ fmt .Fprintf (sb , "%sLiteral UInt64_0\n " , indent )
409+ } else if negVal > 0 {
410+ fmt .Fprintf (sb , "%sLiteral UInt64_%d\n " , indent , negVal )
411+ } else {
412+ fmt .Fprintf (sb , "%sLiteral Int64_%d\n " , indent , negVal )
413+ }
381414 return
382415 case uint64 :
383- fmt .Fprintf (sb , "%sLiteral Int64_-%d\n " , indent , val )
416+ // ClickHouse normalizes -0 to UInt64_0
417+ if val == 0 {
418+ fmt .Fprintf (sb , "%sLiteral UInt64_0\n " , indent )
419+ } else {
420+ fmt .Fprintf (sb , "%sLiteral Int64_-%d\n " , indent , val )
421+ }
384422 return
385423 }
386424 case ast .LiteralFloat :
@@ -432,11 +470,23 @@ func explainAliasedExpr(sb *strings.Builder, n *ast.AliasedExpr, depth int) {
432470 needsFunctionFormat = true
433471 break
434472 }
473+ // Also check if nested arrays/tuples contain non-literal elements
474+ if lit , ok := expr .(* ast.Literal ); ok {
475+ if containsNonLiteralInNested (lit ) {
476+ needsFunctionFormat = true
477+ break
478+ }
479+ }
435480 }
436481 if needsFunctionFormat {
437482 // Render as Function tuple with alias
438483 fmt .Fprintf (sb , "%sFunction tuple (alias %s) (children %d)\n " , indent , escapeAlias (n .Alias ), 1 )
439- fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , len (exprs ))
484+ // For empty ExpressionList, don't include children count
485+ if len (exprs ) > 0 {
486+ fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , len (exprs ))
487+ } else {
488+ fmt .Fprintf (sb , "%s ExpressionList\n " , indent )
489+ }
440490 for _ , expr := range exprs {
441491 Node (sb , expr , depth + 2 )
442492 }
@@ -463,6 +513,11 @@ func explainAliasedExpr(sb *strings.Builder, n *ast.AliasedExpr, depth int) {
463513 needsFunctionFormat = true
464514 break
465515 }
516+ // Check for function calls - use Function array
517+ if _ , ok := expr .(* ast.FunctionCall ); ok {
518+ needsFunctionFormat = true
519+ break
520+ }
466521 }
467522 if needsFunctionFormat {
468523 // Render as Function array with alias
@@ -577,6 +632,9 @@ func explainAliasedExpr(sb *strings.Builder, n *ast.AliasedExpr, depth int) {
577632 case * ast.CaseExpr :
578633 // CASE expressions with alias
579634 explainCaseExprWithAlias (sb , e , n .Alias , indent , depth )
635+ case * ast.ExistsExpr :
636+ // EXISTS expressions with alias
637+ explainExistsExprWithAlias (sb , e , n .Alias , indent , depth )
580638 default :
581639 // For other types, recursively explain and add alias info
582640 Node (sb , n .Expr , depth )
0 commit comments