@@ -3683,10 +3683,17 @@ func (p *parser) parseSelect() (Select, *parseError) {
36833683
36843684 var sel Select
36853685
3686- if p .eat ("ALL" ) {
3687- // Nothing to do; this is the default.
3688- } else if p .eat ("DISTINCT" ) {
3686+ // Handle AS STRUCT, DISTINCT, and ALL, which can appear in flexible order.
3687+ if p .eat ("AS" , "STRUCT" ) {
3688+ sel .AsStruct = true
3689+ }
3690+ if p .eat ("DISTINCT" ) {
36893691 sel .Distinct = true
3692+ } else if p .eat ("ALL" ) {
3693+ // This is the default, just consume the token.
3694+ }
3695+ if ! sel .AsStruct && p .eat ("AS" , "STRUCT" ) {
3696+ sel .AsStruct = true
36903697 }
36913698
36923699 // Read expressions for the SELECT list.
@@ -4685,6 +4692,17 @@ func (p *parser) parseLit() (Expr, *parseError) {
46854692 return Paren {Expr : e }, nil
46864693 }
46874694
4695+ // Handle ARRAY and STRUCT before generic function handling
4696+ // because they have special syntax (ARRAY can have subqueries, STRUCT can have types)
4697+ if tok .caseEqual ("ARRAY" ) && (p .sniff ("(" ) || p .sniff ("[" ) || p .sniff ("<" )) {
4698+ p .back ()
4699+ return p .parseArrayOrArraySubquery ()
4700+ }
4701+ if tok .caseEqual ("STRUCT" ) && (p .sniff ("(" ) || p .sniff ("<" )) {
4702+ p .back ()
4703+ return p .parseStructLit ()
4704+ }
4705+
46884706 // If the literal was an identifier, and there's an open paren next,
46894707 // this is a function invocation.
46904708 // The `funcs` map is keyed by upper case strings.
@@ -4746,7 +4764,7 @@ func (p *parser) parseLit() (Expr, *parseError) {
47464764 switch {
47474765 case tok .caseEqual ("ARRAY" ) || tok .value == "[" :
47484766 p .back ()
4749- return p .parseArrayLit ()
4767+ return p .parseArrayOrArraySubquery ()
47504768 case tok .caseEqual ("DATE" ):
47514769 if p .sniffTokenType (stringToken ) {
47524770 p .back ()
@@ -4762,10 +4780,11 @@ func (p *parser) parseLit() (Expr, *parseError) {
47624780 p .back ()
47634781 return p .parseJSONLit ()
47644782 }
4783+ case tok .caseEqual ("STRUCT" ):
4784+ p .back ()
4785+ return p .parseStructLit ()
47654786 }
47664787
4767- // TODO: struct literals
4768-
47694788 // Try a parameter.
47704789 // TODO: check character sets.
47714790 if strings .HasPrefix (tok .value , "@" ) {
@@ -4941,6 +4960,67 @@ func (p *parser) parseNullIfExpr() (NullIf, *parseError) {
49414960 return NullIf {Expr : expr , ExprToMatch : exprToMatch }, nil
49424961}
49434962
4963+ func (p * parser ) parseArrayOrArraySubquery () (Expr , * parseError ) {
4964+ // ARRAY can be followed by:
4965+ // - [...] for array literals
4966+ // - (SELECT ...) for array subqueries
4967+ // - <type>[...] for typed array literals
4968+
4969+ if p .sniff ("[" ) {
4970+ // Handle [...] without ARRAY keyword
4971+ return p .parseArrayLit ()
4972+ }
4973+
4974+ if ! p .eat ("ARRAY" ) {
4975+ return nil , p .errorf ("expected ARRAY or [" )
4976+ }
4977+
4978+ // After ARRAY, check what follows
4979+ // Skip any <type> specification if present
4980+ if p .eat ("<" ) {
4981+ // This is a typed array literal ARRAY<type>[...]
4982+ // Skip the type specification
4983+ depth := 1
4984+ for depth > 0 && ! p .done {
4985+ tok := p .next ()
4986+ if tok .err != nil {
4987+ return nil , tok .err
4988+ }
4989+ if tok .value == "<" {
4990+ depth ++
4991+ } else if tok .value == ">" {
4992+ depth --
4993+ }
4994+ }
4995+ }
4996+
4997+ // Now check for [ or (
4998+ if p .eat ("[" ) {
4999+ // It's an array literal ARRAY[...] or ARRAY<type>[...]
5000+ // parseArrayLit expects to be positioned after ARRAY and will consume [...]
5001+ p .back () // Put [ back so parseArrayLit can consume it
5002+ return p .parseArrayLit ()
5003+ } else if p .eat ("(" ) {
5004+ // Check if it's a subquery: ARRAY(SELECT ...)
5005+ if p .sniff ("SELECT" ) {
5006+ // It's an ARRAY subquery
5007+ q , err := p .parseQuery ()
5008+ if err != nil {
5009+ return nil , err
5010+ }
5011+ if err := p .expect (")" ); err != nil {
5012+ return nil , err
5013+ }
5014+ return ArraySubquery {Query : q }, nil
5015+ }
5016+
5017+ // Not supported: ARRAY(expr, expr, ...)
5018+ return nil , p .errorf ("ARRAY(...) expression lists are not supported, use ARRAY[...] instead" )
5019+ }
5020+
5021+ return nil , p .errorf ("expected [ or ( after ARRAY" )
5022+ }
5023+
49445024func (p * parser ) parseArrayLit () (Array , * parseError ) {
49455025 // ARRAY keyword is optional.
49465026 // TODO: If it is present, consume any <T> after it.
@@ -4959,6 +5039,43 @@ func (p *parser) parseArrayLit() (Array, *parseError) {
49595039 return arr , err
49605040}
49615041
5042+ func (p * parser ) parseStructLit () (StructLiteral , * parseError ) {
5043+ if err := p .expect ("STRUCT" ); err != nil {
5044+ return StructLiteral {}, err
5045+ }
5046+
5047+ var sl StructLiteral
5048+
5049+ // Check for typed struct: STRUCT<type1, type2, ...>
5050+ if p .eat ("<" ) {
5051+ for {
5052+ typ , err := p .parseType ()
5053+ if err != nil {
5054+ return StructLiteral {}, err
5055+ }
5056+ sl .FieldTypes = append (sl .FieldTypes , typ )
5057+
5058+ if ! p .eat ("," ) {
5059+ break
5060+ }
5061+ }
5062+ if err := p .expect (">" ); err != nil {
5063+ return StructLiteral {}, err
5064+ }
5065+ }
5066+
5067+ // Parse the field values
5068+ err := p .parseCommaList ("(" , ")" , func (p * parser ) * parseError {
5069+ e , err := p .parseExpr ()
5070+ if err != nil {
5071+ return err
5072+ }
5073+ sl .Fields = append (sl .Fields , e )
5074+ return nil
5075+ })
5076+ return sl , err
5077+ }
5078+
49625079// TODO: There should be exported Parse{Date,Timestamp}Literal package-level funcs
49635080// to support spannertest coercing plain string literals when used in a typed context.
49645081// Those should wrap parseDateLit and parseTimestampLit below.
0 commit comments