@@ -81,14 +81,58 @@ func explainLiteral(sb *strings.Builder, n *ast.Literal, indent string, depth in
8181 fmt .Fprintf (sb , "%s ExpressionList\n " , indent )
8282 return
8383 }
84- hasComplexExpr := false
84+ // Check if we should render as Function array
85+ // This happens when:
86+ // 1. Contains non-literal, non-negation expressions OR
87+ // 2. Contains tuples OR
88+ // 3. Contains nested arrays that all have exactly 1 element (homogeneous single-element arrays) OR
89+ // 4. Contains nested arrays with non-literal expressions OR
90+ // 5. Contains nested arrays that are empty or contain tuples/non-literals
91+ shouldUseFunctionArray := false
92+ allAreSingleElementArrays := true
93+ hasNestedArrays := false
94+ nestedArraysNeedFunctionFormat := false
95+
8596 for _ , e := range exprs {
86- if ! isSimpleLiteralOrNegation (e ) {
87- hasComplexExpr = true
88- break
97+ if lit , ok := e .(* ast.Literal ); ok {
98+ if lit .Type == ast .LiteralArray {
99+ hasNestedArrays = true
100+ // Check if this inner array has exactly 1 element
101+ if innerExprs , ok := lit .Value .([]ast.Expression ); ok {
102+ if len (innerExprs ) != 1 {
103+ allAreSingleElementArrays = false
104+ }
105+ // Check if inner array needs Function array format:
106+ // - Contains non-literal expressions OR
107+ // - Contains tuples OR
108+ // - Is empty OR
109+ // - Contains empty arrays
110+ if containsNonLiteralExpressions (innerExprs ) ||
111+ len (innerExprs ) == 0 ||
112+ containsTuples (innerExprs ) ||
113+ containsEmptyArrays (innerExprs ) {
114+ nestedArraysNeedFunctionFormat = true
115+ }
116+ } else {
117+ allAreSingleElementArrays = false
118+ }
119+ } else if lit .Type == ast .LiteralTuple {
120+ // Tuples are complex
121+ shouldUseFunctionArray = true
122+ }
123+ } else if ! isSimpleLiteralOrNegation (e ) {
124+ shouldUseFunctionArray = true
89125 }
90126 }
91- if hasComplexExpr {
127+
128+ // Use Function array when:
129+ // - nested arrays that are ALL single-element
130+ // - nested arrays that need Function format (contain non-literals, tuples, or empty arrays)
131+ if hasNestedArrays && (allAreSingleElementArrays || nestedArraysNeedFunctionFormat ) {
132+ shouldUseFunctionArray = true
133+ }
134+
135+ if shouldUseFunctionArray {
92136 // Render as Function array instead of Literal
93137 fmt .Fprintf (sb , "%sFunction array (children %d)\n " , indent , 1 )
94138 fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , len (exprs ))
@@ -124,6 +168,58 @@ func isSimpleLiteralOrNegation(e ast.Expression) bool {
124168 return false
125169}
126170
171+ // containsOnlyArraysOrTuples checks if a slice of expressions contains
172+ // only array or tuple literals (including empty arrays).
173+ // Returns true if the slice is empty or contains only arrays/tuples.
174+ func containsOnlyArraysOrTuples (exprs []ast.Expression ) bool {
175+ if len (exprs ) == 0 {
176+ return true // empty is considered "only arrays"
177+ }
178+ for _ , e := range exprs {
179+ if lit , ok := e .(* ast.Literal ); ok {
180+ if lit .Type != ast .LiteralArray && lit .Type != ast .LiteralTuple {
181+ return false
182+ }
183+ } else {
184+ return false
185+ }
186+ }
187+ return true
188+ }
189+
190+ // containsNonLiteralExpressions checks if a slice of expressions contains
191+ // any non-literal expressions (identifiers, function calls, etc.)
192+ func containsNonLiteralExpressions (exprs []ast.Expression ) bool {
193+ for _ , e := range exprs {
194+ if _ , ok := e .(* ast.Literal ); ! ok {
195+ return true
196+ }
197+ }
198+ return false
199+ }
200+
201+ // containsTuples checks if a slice of expressions contains any tuple literals
202+ func containsTuples (exprs []ast.Expression ) bool {
203+ for _ , e := range exprs {
204+ if lit , ok := e .(* ast.Literal ); ok && lit .Type == ast .LiteralTuple {
205+ return true
206+ }
207+ }
208+ return false
209+ }
210+
211+ // containsEmptyArrays checks if a slice of expressions contains any empty array literals
212+ func containsEmptyArrays (exprs []ast.Expression ) bool {
213+ for _ , e := range exprs {
214+ if lit , ok := e .(* ast.Literal ); ok && lit .Type == ast .LiteralArray {
215+ if innerExprs , ok := lit .Value .([]ast.Expression ); ok && len (innerExprs ) == 0 {
216+ return true
217+ }
218+ }
219+ }
220+ return false
221+ }
222+
127223func explainBinaryExpr (sb * strings.Builder , n * ast.BinaryExpr , indent string , depth int ) {
128224 // Convert operator to function name
129225 fnName := OperatorToFunction (n .Op )
@@ -303,11 +399,20 @@ func explainAsterisk(sb *strings.Builder, n *ast.Asterisk, indent string) {
303399
304400func explainWithElement (sb * strings.Builder , n * ast.WithElement , indent string , depth int ) {
305401 // For WITH elements, we need to show the underlying expression with the name as alias
402+ // When name is empty, don't show the alias part
306403 switch e := n .Query .(type ) {
307404 case * ast.Literal :
308- fmt .Fprintf (sb , "%sLiteral %s (alias %s)\n " , indent , FormatLiteral (e ), n .Name )
405+ if n .Name != "" {
406+ fmt .Fprintf (sb , "%sLiteral %s (alias %s)\n " , indent , FormatLiteral (e ), n .Name )
407+ } else {
408+ fmt .Fprintf (sb , "%sLiteral %s\n " , indent , FormatLiteral (e ))
409+ }
309410 case * ast.Identifier :
310- fmt .Fprintf (sb , "%sIdentifier %s (alias %s)\n " , indent , e .Name (), n .Name )
411+ if n .Name != "" {
412+ fmt .Fprintf (sb , "%sIdentifier %s (alias %s)\n " , indent , e .Name (), n .Name )
413+ } else {
414+ fmt .Fprintf (sb , "%sIdentifier %s\n " , indent , e .Name ())
415+ }
311416 case * ast.FunctionCall :
312417 explainFunctionCallWithAlias (sb , e , n .Name , indent , depth )
313418 case * ast.BinaryExpr :
@@ -316,19 +421,31 @@ func explainWithElement(sb *strings.Builder, n *ast.WithElement, indent string,
316421 // For || (concat) operator, flatten chained concatenations
317422 if e .Op == "||" {
318423 operands := collectConcatOperands (e )
319- fmt .Fprintf (sb , "%sFunction %s (alias %s) (children %d)\n " , indent , fnName , n .Name , 1 )
424+ if n .Name != "" {
425+ fmt .Fprintf (sb , "%sFunction %s (alias %s) (children %d)\n " , indent , fnName , n .Name , 1 )
426+ } else {
427+ fmt .Fprintf (sb , "%sFunction %s (children %d)\n " , indent , fnName , 1 )
428+ }
320429 fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , len (operands ))
321430 for _ , op := range operands {
322431 Node (sb , op , depth + 2 )
323432 }
324433 } else {
325- fmt .Fprintf (sb , "%sFunction %s (alias %s) (children %d)\n " , indent , fnName , n .Name , 1 )
434+ if n .Name != "" {
435+ fmt .Fprintf (sb , "%sFunction %s (alias %s) (children %d)\n " , indent , fnName , n .Name , 1 )
436+ } else {
437+ fmt .Fprintf (sb , "%sFunction %s (children %d)\n " , indent , fnName , 1 )
438+ }
326439 fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , 2 )
327440 Node (sb , e .Left , depth + 2 )
328441 Node (sb , e .Right , depth + 2 )
329442 }
330443 case * ast.Subquery :
331- fmt .Fprintf (sb , "%sSubquery (alias %s) (children %d)\n " , indent , n .Name , 1 )
444+ if n .Name != "" {
445+ fmt .Fprintf (sb , "%sSubquery (alias %s) (children %d)\n " , indent , n .Name , 1 )
446+ } else {
447+ fmt .Fprintf (sb , "%sSubquery (children %d)\n " , indent , 1 )
448+ }
332449 Node (sb , e .Query , depth + 1 )
333450 default :
334451 // For other types, just output the expression (alias may be lost)
0 commit comments