1515package ast
1616
1717import (
18+ "strings"
19+
1820 "github.com/cockroachdb/errors"
1921
2022 vitess "github.com/dolthub/vitess/go/vt/sqlparser"
@@ -24,13 +26,117 @@ import (
2426)
2527
2628// nodeAliasedTableExpr handles *tree.AliasedTableExpr nodes.
27- func nodeAliasedTableExpr (ctx * Context , node * tree.AliasedTableExpr ) (* vitess.AliasedTableExpr , error ) {
28- if node .Ordinality {
29- return nil , errors .Errorf ("ordinality is not yet supported" )
30- }
29+ func nodeAliasedTableExpr (ctx * Context , node * tree.AliasedTableExpr ) (vitess.TableExpr , error ) {
3130 if node .IndexFlags != nil {
3231 return nil , errors .Errorf ("index flags are not yet supported" )
3332 }
33+
34+ // Handle RowsFromExpr specially - it can have WITH ORDINALITY and column aliases
35+ if rowsFrom , ok := node .Expr .(* tree.RowsFromExpr ); ok {
36+ // Handle multi-argument UNNEST specially: UNNEST(arr1, arr2, ...)
37+ // is syntactic sugar for ROWS FROM(unnest(arr1), unnest(arr2), ...)
38+ // We need to detect this case and expand it to use RowsFromExpr.
39+ if len (rowsFrom .Items ) == 1 {
40+ if funcExpr , ok := rowsFrom .Items [0 ].(* tree.FuncExpr ); ok {
41+ funcName := funcExpr .Func .String ()
42+ if strings .EqualFold (funcName , "unnest" ) && len (funcExpr .Exprs ) > 1 {
43+ // Expand multi-arg UNNEST into separate unnest calls
44+ selectExprs := make (vitess.SelectExprs , len (funcExpr .Exprs ))
45+ for i , arg := range funcExpr .Exprs {
46+ argExpr , err := nodeExpr (ctx , arg )
47+ if err != nil {
48+ return nil , err
49+ }
50+ selectExprs [i ] = & vitess.AliasedExpr {
51+ Expr : & vitess.FuncExpr {
52+ Name : vitess .NewColIdent ("unnest" ),
53+ Exprs : vitess.SelectExprs {& vitess.AliasedExpr {Expr : argExpr }},
54+ },
55+ }
56+ }
57+
58+ var columns vitess.Columns
59+ if len (node .As .Cols ) > 0 {
60+ columns = make (vitess.Columns , len (node .As .Cols ))
61+ for i := range node .As .Cols {
62+ columns [i ] = vitess .NewColIdent (string (node .As .Cols [i ]))
63+ }
64+ }
65+
66+ return & vitess.RowsFromExpr {
67+ Exprs : selectExprs ,
68+ WithOrdinality : node .Ordinality ,
69+ Alias : vitess .NewTableIdent (string (node .As .Alias )),
70+ Columns : columns ,
71+ }, nil
72+ }
73+ }
74+ }
75+
76+ // For single functions or non-multi-arg-UNNEST cases, use the existing
77+ // subquery-based approach that works with the table function infrastructure.
78+ // Only WITH ORDINALITY requires the new RowsFromExpr approach.
79+ if node .Ordinality {
80+ // Use RowsFromExpr for WITH ORDINALITY support
81+ selectExprs := make (vitess.SelectExprs , len (rowsFrom .Items ))
82+ for i , item := range rowsFrom .Items {
83+ expr , err := nodeExpr (ctx , item )
84+ if err != nil {
85+ return nil , err
86+ }
87+ selectExprs [i ] = & vitess.AliasedExpr {Expr : expr }
88+ }
89+
90+ var columns vitess.Columns
91+ if len (node .As .Cols ) > 0 {
92+ columns = make (vitess.Columns , len (node .As .Cols ))
93+ for i := range node .As .Cols {
94+ columns [i ] = vitess .NewColIdent (string (node .As .Cols [i ]))
95+ }
96+ }
97+
98+ return & vitess.RowsFromExpr {
99+ Exprs : selectExprs ,
100+ WithOrdinality : node .Ordinality ,
101+ Alias : vitess .NewTableIdent (string (node .As .Alias )),
102+ Columns : columns ,
103+ }, nil
104+ }
105+
106+ // For non-ordinality cases, fall through to use the existing
107+ // table function infrastructure via nodeTableExpr
108+ tableExpr , err := nodeTableExpr (ctx , rowsFrom )
109+ if err != nil {
110+ return nil , err
111+ }
112+
113+ // Wrap in a subquery as the original code did
114+ subquery := & vitess.Subquery {
115+ Select : & vitess.Select {
116+ From : vitess.TableExprs {tableExpr },
117+ },
118+ }
119+
120+ if len (node .As .Cols ) > 0 {
121+ columns := make ([]vitess.ColIdent , len (node .As .Cols ))
122+ for i := range node .As .Cols {
123+ columns [i ] = vitess .NewColIdent (string (node .As .Cols [i ]))
124+ }
125+ subquery .Columns = columns
126+ }
127+
128+ return & vitess.AliasedTableExpr {
129+ Expr : subquery ,
130+ As : vitess .NewTableIdent (string (node .As .Alias )),
131+ Lateral : node .Lateral ,
132+ }, nil
133+ }
134+
135+ // For non-RowsFromExpr expressions, ordinality is not yet supported
136+ if node .Ordinality {
137+ return nil , errors .Errorf ("ordinality is only supported for ROWS FROM expressions" )
138+ }
139+
34140 var aliasExpr vitess.SimpleTableExpr
35141 var authInfo vitess.AuthInformation
36142
@@ -92,27 +198,6 @@ func nodeAliasedTableExpr(ctx *Context, node *tree.AliasedTableExpr) (*vitess.Al
92198 Select : selectStmt ,
93199 }
94200
95- if len (node .As .Cols ) > 0 {
96- columns := make ([]vitess.ColIdent , len (node .As .Cols ))
97- for i := range node .As .Cols {
98- columns [i ] = vitess .NewColIdent (string (node .As .Cols [i ]))
99- }
100- subquery .Columns = columns
101- }
102- aliasExpr = subquery
103- case * tree.RowsFromExpr :
104- tableExpr , err := nodeTableExpr (ctx , expr )
105- if err != nil {
106- return nil , err
107- }
108-
109- // TODO: this should be represented as a table function more directly
110- subquery := & vitess.Subquery {
111- Select : & vitess.Select {
112- From : vitess.TableExprs {tableExpr },
113- },
114- }
115-
116201 if len (node .As .Cols ) > 0 {
117202 columns := make ([]vitess.ColIdent , len (node .As .Cols ))
118203 for i := range node .As .Cols {
0 commit comments