From 4b7c949c5737269754b5e741cfad23d0a5f4c1df Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Sat, 28 Sep 2024 16:05:09 +0900 Subject: [PATCH 01/22] Implement BracedNewConstructor --- ast/ast.go | 188 +++++++++++++++++++++++++++++++++++++++++++++++++++++ parser.go | 67 +++++++++++++++++++ 2 files changed, 255 insertions(+) diff --git a/ast/ast.go b/ast/ast.go index 2dbdfff2..bf7a76fa 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -1511,6 +1511,194 @@ type JSONLiteral struct { Value *StringLiteral } +// NewConstructorArg +// +// {{Expr | sql}} {{Alias | sqlOpt}} +type NewConstructorArg struct { + // pos = Expr.pos + // (Alias ?? Expr).end + + Expr Expr + Alias *AsAlias // optional, "AS" is required +} + +// NewConstructor +// +// NEW {{TypeName | sql}} ({{Args | sqlJoin ", "}}) +type NewConstructor struct { + // pos = New + // end = Rparen + 1 + + New token.Pos + TypeName *Path + + Args []*NewConstructorArg + + Rparen token.Pos +} + +func (n *NewConstructor) Pos() token.Pos { + return n.New +} + +func (n *NewConstructor) End() token.Pos { + return n.Rparen + 1 +} + +func (n *NewConstructor) SQL() string { + return "NEW " + n.TypeName.SQL() +} + +func (*NewConstructor) isExpr() {} + +// BracedNewConstructor +// +// NEW {{.TypeName | sql}} {{"{"}}{{"}"}} +type BracedNewConstructor struct { + // pos = New + // end = Rbrace + 1 + + New token.Pos + TypeName *Path + Body *BracedConstructor +} + +func (b *BracedNewConstructor) isExpr() {} + +func (b *BracedNewConstructor) Pos() token.Pos { + return b.New +} + +func (b *BracedNewConstructor) End() token.Pos { + return b.Body.End() +} + +func (b *BracedNewConstructor) SQL() string { + return "NEW " + b.TypeName.SQL() + b.Body.SQL() +} + +func (*BracedNewConstructor) isBracedConstructorFieldValue() {} + +// BracedConstructor +// +// {{"{"}}{{.Fields | sqlJoin ", "}}{{"}"}} +type BracedConstructor struct { + // pos = Lbrace + // end = Rbrace + 1 + + Lbrace, Rbrace token.Pos + + Fields []*BracedConstructorField +} + +func (*BracedConstructor) isExpr() {} + +func (b *BracedConstructor) isBracedConstructorFieldValue() {} + +func (b *BracedConstructor) Pos() token.Pos { + return b.Lbrace +} + +func (b *BracedConstructor) End() token.Pos { + return b.Rbrace + 1 +} + +func (b *BracedConstructor) SQL() string { + var fieldsStr string + for i, field := range b.Fields { + if i > 0 { + fieldsStr += ", " + } + fieldsStr += field.SQL() + } + return "{" + fieldsStr + "}" +} + +// BracedConstructorField +// +// {{.Name | sql}} {{.Value | sql}} +type BracedConstructorField struct { + // pos = Name.pos + // end = Value.end + + Name *Ident + Value BracedConstructorFieldValue +} + +func (b *BracedConstructorField) Pos() token.Pos { + return b.Name.Pos() +} + +func (b *BracedConstructorField) End() token.Pos { + return b.Value.End() +} + +func (b *BracedConstructorField) SQL() string { + return b.Name.SQL() + " " + b.Value.SQL() +} + +type BracedConstructorFieldValue interface { + Node + isBracedConstructorFieldValue() +} + +// BracedConstructorFieldValueExpr +// +// : {{.Expr | sql}} +type BracedConstructorFieldValueExpr struct { + Colon token.Pos + Expr Expr +} + +func (b *BracedConstructorFieldValueExpr) Pos() token.Pos { + return b.Colon +} + +func (b *BracedConstructorFieldValueExpr) End() token.Pos { + return b.Expr.End() +} + +func (b *BracedConstructorFieldValueExpr) SQL() string { + return ": " + b.Expr.SQL() +} + +func (*BracedConstructorFieldValueExpr) isBracedConstructorFieldValue() {} + +// BracedConstructorFieldValueBracedConstructors +// +// : [{{.Constructors | sqlJoin ", "}}] +type BracedConstructorFieldValueBracedConstructors struct { + // pos = Colon + // end = Rbrack + 1 + + Colon token.Pos + Rbrack token.Pos + Constructors []*BracedConstructor +} + +func (b *BracedConstructorFieldValueBracedConstructors) Pos() token.Pos { + return b.Colon +} + +func (b *BracedConstructorFieldValueBracedConstructors) End() token.Pos { + return b.Rbrack + 1 +} + +func (b *BracedConstructorFieldValueBracedConstructors) SQL() string { + var sql string + sql += ": [" + for i, constructor := range b.Constructors { + if i > 0 { + sql += ", " + } + sql += constructor.SQL() + } + sql += "]" + return sql +} + +func (b *BracedConstructorFieldValueBracedConstructors) isBracedConstructorFieldValue() {} + // ================================================================================ // // Type diff --git a/parser.go b/parser.go index 0d004854..e798a17e 100644 --- a/parser.go +++ b/parser.go @@ -1427,6 +1427,11 @@ func (p *Parser) parseLit() ast.Expr { return p.parseSimpleArrayLiteral() case "(": return p.parseParenExpr() + case "NEW": + return p.parseNewConstructors() + // In parser level, it is a valid ast.Expr, but it is semantically valid only in ast.BracedConstructorFieldExpr. + case "{": + return p.parseBracedConstructor() case token.TokenIdent: id := p.Token switch { @@ -2099,6 +2104,68 @@ func (p *Parser) parseStructTypeFields() (fields []*ast.StructField, gt token.Po return } +func (p *Parser) parseNewConstructor(newPos token.Pos, path []*ast.Ident) *ast.NewConstructor { + return nil +} + +func (p *Parser) parseBracedNewConstructorField() *ast.BracedConstructorField { + name := p.parseIdent() + var fieldValue ast.BracedConstructorFieldValue + switch p.Token.Kind { + case ":": + colon := p.expect(":").Pos + expr := p.parseExpr() + fieldValue = &ast.BracedConstructorFieldValueExpr{Colon: colon, Expr: expr} + case "{": + fieldValue = p.parseBracedConstructor() + } + return &ast.BracedConstructorField{Name: name, Value: fieldValue} +} + +func (p *Parser) parseBracedConstructor() *ast.BracedConstructor { + lbrace := p.expect("{").Pos + var fields []*ast.BracedConstructorField + for { + if p.Token.Kind == "}" { + break + } + if p.Token.Kind == token.TokenIdent { + fields = append(fields, p.parseBracedNewConstructorField()) + } + if p.Token.Kind == "," { + p.nextToken() + } + } + rbrace := p.expect("}").Pos + return &ast.BracedConstructor{ + Lbrace: lbrace, + Rbrace: rbrace, + Fields: fields, + } +} +func (p *Parser) parseBracedNewConstructor(newPos token.Pos, path []*ast.Ident) *ast.BracedNewConstructor { + body := p.parseBracedConstructor() + return &ast.BracedNewConstructor{ + New: newPos, + TypeName: &ast.Path{Idents: path}, + Body: body, + } +} + +func (p *Parser) parseNewConstructors() ast.Expr { + newPos := p.expect("NEW").Pos + path := p.parseIdentOrPath() + switch p.Token.Kind { + case "(": + return p.parseNewConstructor(newPos, path) + case "{": + return p.parseBracedNewConstructor(newPos, path) + default: + p.panicfAtToken(&p.Token, `expect '{' or '(', but %v`, p.Token.Kind) + } + return nil +} + func (p *Parser) parseFieldType() *ast.StructField { lexer := p.Lexer.Clone() // Try to parse as "x INT64" case. From 1972ee7067c7e8c05063b8873a193e7325b9ece3 Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Sat, 28 Sep 2024 17:27:58 +0900 Subject: [PATCH 02/22] Clean up NEW operator implementation --- ast/ast.go | 208 ++++++++++---------------------------- ast/pos.go | 48 +++++++++ ast/sql.go | 46 +++++++++ parser.go | 33 +++++- tools/gen-ast-pos/main.go | 3 + 5 files changed, 180 insertions(+), 158 deletions(-) diff --git a/ast/ast.go b/ast/ast.go index bf7a76fa..d879dd46 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -150,38 +150,41 @@ type Expr interface { isExpr() } -func (BinaryExpr) isExpr() {} -func (UnaryExpr) isExpr() {} -func (InExpr) isExpr() {} -func (IsNullExpr) isExpr() {} -func (IsBoolExpr) isExpr() {} -func (BetweenExpr) isExpr() {} -func (SelectorExpr) isExpr() {} -func (IndexExpr) isExpr() {} -func (CallExpr) isExpr() {} -func (CountStarExpr) isExpr() {} -func (CastExpr) isExpr() {} -func (ExtractExpr) isExpr() {} -func (CaseExpr) isExpr() {} -func (ParenExpr) isExpr() {} -func (ScalarSubQuery) isExpr() {} -func (ArraySubQuery) isExpr() {} -func (ExistsSubQuery) isExpr() {} -func (Param) isExpr() {} -func (Ident) isExpr() {} -func (Path) isExpr() {} -func (ArrayLiteral) isExpr() {} -func (StructLiteral) isExpr() {} -func (NullLiteral) isExpr() {} -func (BoolLiteral) isExpr() {} -func (IntLiteral) isExpr() {} -func (FloatLiteral) isExpr() {} -func (StringLiteral) isExpr() {} -func (BytesLiteral) isExpr() {} -func (DateLiteral) isExpr() {} -func (TimestampLiteral) isExpr() {} -func (NumericLiteral) isExpr() {} -func (JSONLiteral) isExpr() {} +func (BinaryExpr) isExpr() {} +func (UnaryExpr) isExpr() {} +func (InExpr) isExpr() {} +func (IsNullExpr) isExpr() {} +func (IsBoolExpr) isExpr() {} +func (BetweenExpr) isExpr() {} +func (SelectorExpr) isExpr() {} +func (IndexExpr) isExpr() {} +func (CallExpr) isExpr() {} +func (CountStarExpr) isExpr() {} +func (CastExpr) isExpr() {} +func (ExtractExpr) isExpr() {} +func (CaseExpr) isExpr() {} +func (ParenExpr) isExpr() {} +func (ScalarSubQuery) isExpr() {} +func (ArraySubQuery) isExpr() {} +func (ExistsSubQuery) isExpr() {} +func (Param) isExpr() {} +func (Ident) isExpr() {} +func (Path) isExpr() {} +func (ArrayLiteral) isExpr() {} +func (StructLiteral) isExpr() {} +func (NullLiteral) isExpr() {} +func (BoolLiteral) isExpr() {} +func (IntLiteral) isExpr() {} +func (FloatLiteral) isExpr() {} +func (StringLiteral) isExpr() {} +func (BytesLiteral) isExpr() {} +func (DateLiteral) isExpr() {} +func (TimestampLiteral) isExpr() {} +func (NumericLiteral) isExpr() {} +func (JSONLiteral) isExpr() {} +func (*NewConstructor) isExpr() {} +func (*BracedNewConstructor) isExpr() {} +func (*BracedConstructor) isExpr() {} // Arg represents argument of function call. type Arg interface { @@ -1511,18 +1514,18 @@ type JSONLiteral struct { Value *StringLiteral } -// NewConstructorArg +// NewConstructorArg represents a single argument in NEW constructor. // // {{Expr | sql}} {{Alias | sqlOpt}} type NewConstructorArg struct { // pos = Expr.pos - // (Alias ?? Expr).end + // end = (Alias ?? Expr).end Expr Expr - Alias *AsAlias // optional, "AS" is required + Alias *AsAlias // optional } -// NewConstructor +// NewConstructor represents NEW operator which creates a protocol buffer using a parenthesized list of arguments. // // NEW {{TypeName | sql}} ({{Args | sqlJoin ", "}}) type NewConstructor struct { @@ -1537,49 +1540,21 @@ type NewConstructor struct { Rparen token.Pos } -func (n *NewConstructor) Pos() token.Pos { - return n.New -} - -func (n *NewConstructor) End() token.Pos { - return n.Rparen + 1 -} - -func (n *NewConstructor) SQL() string { - return "NEW " + n.TypeName.SQL() -} - -func (*NewConstructor) isExpr() {} - -// BracedNewConstructor +// BracedNewConstructor represents NEW operator which creates a protocol buffer using a map constructor. // // NEW {{.TypeName | sql}} {{"{"}}{{"}"}} type BracedNewConstructor struct { // pos = New - // end = Rbrace + 1 + // end = Body.end + + New token.Pos - New token.Pos TypeName *Path Body *BracedConstructor } -func (b *BracedNewConstructor) isExpr() {} - -func (b *BracedNewConstructor) Pos() token.Pos { - return b.New -} - -func (b *BracedNewConstructor) End() token.Pos { - return b.Body.End() -} - -func (b *BracedNewConstructor) SQL() string { - return "NEW " + b.TypeName.SQL() + b.Body.SQL() -} - -func (*BracedNewConstructor) isBracedConstructorFieldValue() {} - -// BracedConstructor +// BracedConstructor represents a single map constructor which is used in BracedNewConstructor. +// Actually, it is a top level Expr in syntax, but it is not permitted semantically in other place. // // {{"{"}}{{.Fields | sqlJoin ", "}}{{"}"}} type BracedConstructor struct { @@ -1591,30 +1566,7 @@ type BracedConstructor struct { Fields []*BracedConstructorField } -func (*BracedConstructor) isExpr() {} - -func (b *BracedConstructor) isBracedConstructorFieldValue() {} - -func (b *BracedConstructor) Pos() token.Pos { - return b.Lbrace -} - -func (b *BracedConstructor) End() token.Pos { - return b.Rbrace + 1 -} - -func (b *BracedConstructor) SQL() string { - var fieldsStr string - for i, field := range b.Fields { - if i > 0 { - fieldsStr += ", " - } - fieldsStr += field.SQL() - } - return "{" + fieldsStr + "}" -} - -// BracedConstructorField +// BracedConstructorField represents a single field in BracedConstructor. // // {{.Name | sql}} {{.Value | sql}} type BracedConstructorField struct { @@ -1625,80 +1577,26 @@ type BracedConstructorField struct { Value BracedConstructorFieldValue } -func (b *BracedConstructorField) Pos() token.Pos { - return b.Name.Pos() -} - -func (b *BracedConstructorField) End() token.Pos { - return b.Value.End() -} - -func (b *BracedConstructorField) SQL() string { - return b.Name.SQL() + " " + b.Value.SQL() -} - type BracedConstructorFieldValue interface { Node isBracedConstructorFieldValue() } -// BracedConstructorFieldValueExpr -// -// : {{.Expr | sql}} -type BracedConstructorFieldValueExpr struct { - Colon token.Pos - Expr Expr -} - -func (b *BracedConstructorFieldValueExpr) Pos() token.Pos { - return b.Colon -} - -func (b *BracedConstructorFieldValueExpr) End() token.Pos { - return b.Expr.End() -} - -func (b *BracedConstructorFieldValueExpr) SQL() string { - return ": " + b.Expr.SQL() -} - +func (*BracedConstructor) isBracedConstructorFieldValue() {} func (*BracedConstructorFieldValueExpr) isBracedConstructorFieldValue() {} -// BracedConstructorFieldValueBracedConstructors +// BracedConstructorFieldValueExpr represents a field value node. // -// : [{{.Constructors | sqlJoin ", "}}] -type BracedConstructorFieldValueBracedConstructors struct { +// : {{.Expr | sql}} +type BracedConstructorFieldValueExpr struct { // pos = Colon - // end = Rbrack + 1 - - Colon token.Pos - Rbrack token.Pos - Constructors []*BracedConstructor -} - -func (b *BracedConstructorFieldValueBracedConstructors) Pos() token.Pos { - return b.Colon -} + // end = Expr.end -func (b *BracedConstructorFieldValueBracedConstructors) End() token.Pos { - return b.Rbrack + 1 -} + Colon token.Pos -func (b *BracedConstructorFieldValueBracedConstructors) SQL() string { - var sql string - sql += ": [" - for i, constructor := range b.Constructors { - if i > 0 { - sql += ", " - } - sql += constructor.SQL() - } - sql += "]" - return sql + Expr Expr } -func (b *BracedConstructorFieldValueBracedConstructors) isBracedConstructorFieldValue() {} - // ================================================================================ // // Type diff --git a/ast/pos.go b/ast/pos.go index f2875632..d88e98f2 100644 --- a/ast/pos.go +++ b/ast/pos.go @@ -662,6 +662,54 @@ func (j *JSONLiteral) End() token.Pos { return nodeEnd(wrapNode(j.Value)) } +func (n *NewConstructorArg) Pos() token.Pos { + return nodePos(wrapNode(n.Expr)) +} + +func (n *NewConstructorArg) End() token.Pos { + return nodeEnd(nodeChoice(wrapNode(n.Alias), wrapNode(n.Expr))) +} + +func (n *NewConstructor) Pos() token.Pos { + return n.New +} + +func (n *NewConstructor) End() token.Pos { + return posAdd(n.Rparen, 1) +} + +func (b *BracedNewConstructor) Pos() token.Pos { + return b.New +} + +func (b *BracedNewConstructor) End() token.Pos { + return nodeEnd(wrapNode(b.Body)) +} + +func (b *BracedConstructor) Pos() token.Pos { + return b.Lbrace +} + +func (b *BracedConstructor) End() token.Pos { + return posAdd(b.Rbrace, 1) +} + +func (b *BracedConstructorField) Pos() token.Pos { + return nodePos(wrapNode(b.Name)) +} + +func (b *BracedConstructorField) End() token.Pos { + return nodeEnd(wrapNode(b.Value)) +} + +func (b *BracedConstructorFieldValueExpr) Pos() token.Pos { + return b.Colon +} + +func (b *BracedConstructorFieldValueExpr) End() token.Pos { + return nodeEnd(wrapNode(b.Expr)) +} + func (s *SimpleType) Pos() token.Pos { return s.NamePos } diff --git a/ast/sql.go b/ast/sql.go index dd38f0bc..34bb2b12 100644 --- a/ast/sql.go +++ b/ast/sql.go @@ -681,6 +681,52 @@ func (t *JSONLiteral) SQL() string { return "JSON " + t.Value.SQL() } +func (n *NewConstructorArg) SQL() string { + if n.Alias != nil { + return n.Expr.SQL() + " " + n.Alias.SQL() + } + return n.Expr.SQL() +} + +func (n *NewConstructor) SQL() string { + var sql string + sql += "NEW " + n.TypeName.SQL() + "(" + for i, arg := range n.Args { + if i > 0 { + sql += ", " + } + sql += arg.SQL() + } + sql += ")" + return sql +} + +func (b *BracedNewConstructor) SQL() string { + return "NEW " + b.TypeName.SQL() + " " + b.Body.SQL() +} + +func (b *BracedConstructor) SQL() string { + var str string + str += "{" + for i, field := range b.Fields { + if i > 0 { + str += ", " + } + str += field.SQL() + } + str += "}" + return str +} + +func (b *BracedConstructorField) SQL() string { + if _, ok := b.Value.(*BracedConstructorFieldValueExpr); ok { + return b.Name.SQL() + b.Value.SQL() + } + return b.Name.SQL() + " " + b.Value.SQL() +} + +func (b *BracedConstructorFieldValueExpr) SQL() string { return ": " + b.Expr.SQL() } + // ================================================================================ // // Type diff --git a/parser.go b/parser.go index e798a17e..272537a6 100644 --- a/parser.go +++ b/parser.go @@ -2105,7 +2105,33 @@ func (p *Parser) parseStructTypeFields() (fields []*ast.StructField, gt token.Po } func (p *Parser) parseNewConstructor(newPos token.Pos, path []*ast.Ident) *ast.NewConstructor { - return nil + p.expect("(") + + var args []*ast.NewConstructorArg + for { + if p.Token.Kind == ")" { + break + } + expr := p.parseExpr() + var alias *ast.AsAlias + if p.Token.Kind == "AS" { + alias = p.tryParseAsAlias() + } + args = append(args, &ast.NewConstructorArg{ + Expr: expr, + Alias: alias, + }) + if p.Token.Kind == "," { + p.nextToken() + } + } + rparen := p.expect(")").Pos + return &ast.NewConstructor{ + New: newPos, + TypeName: &ast.Path{Idents: path}, + Args: args, + Rparen: rparen, + } } func (p *Parser) parseBracedNewConstructorField() *ast.BracedConstructorField { @@ -2129,9 +2155,10 @@ func (p *Parser) parseBracedConstructor() *ast.BracedConstructor { if p.Token.Kind == "}" { break } - if p.Token.Kind == token.TokenIdent { - fields = append(fields, p.parseBracedNewConstructorField()) + if p.Token.Kind != token.TokenIdent { + p.panicfAtToken(&p.Token, "expect , but %v", p.Token.Kind) } + fields = append(fields, p.parseBracedNewConstructorField()) if p.Token.Kind == "," { p.nextToken() } diff --git a/tools/gen-ast-pos/main.go b/tools/gen-ast-pos/main.go index 3bfa6f44..1041e3ca 100644 --- a/tools/gen-ast-pos/main.go +++ b/tools/gen-ast-pos/main.go @@ -102,6 +102,9 @@ func main() { for _, node := range nodes { x := string(unicode.ToLower(rune(node.name[0]))) + if node.posExpr == nil || node.endExpr == nil { + log.Fatalf("pos/end is not defined: node %s", node.name) + } fmt.Fprintln(&buffer) fmt.Fprintf(&buffer, "func (%s *%s) Pos() token.Pos {\n", x, node.name) From 72d2a44c6c34fa75f683ca9c2ac802b5a9955052 Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Sat, 28 Sep 2024 17:28:39 +0900 Subject: [PATCH 03/22] Add testdata for NEW operators --- .../input/expr/braced_new_constructor.sql | 17 ++ testdata/input/expr/new_constructor.sql | 1 + .../expr/braced_new_constructor.sql.txt | 271 ++++++++++++++++++ testdata/result/expr/new_constructor.sql.txt | 66 +++++ 4 files changed, 355 insertions(+) create mode 100644 testdata/input/expr/braced_new_constructor.sql create mode 100644 testdata/input/expr/new_constructor.sql create mode 100644 testdata/result/expr/braced_new_constructor.sql.txt create mode 100644 testdata/result/expr/new_constructor.sql.txt diff --git a/testdata/input/expr/braced_new_constructor.sql b/testdata/input/expr/braced_new_constructor.sql new file mode 100644 index 00000000..28cf679d --- /dev/null +++ b/testdata/input/expr/braced_new_constructor.sql @@ -0,0 +1,17 @@ +-- Example from https://cloud.google.com/spanner/docs/reference/standard-sql/operators#new_operator +NEW Universe { + name: "Sol" + closest_planets: ["Mercury", "Venus", "Earth" ] + star { + radius_miles: 432690 + age: 4603000000 + } + constellations: [{ + name: "Libra" + index: 0 + }, { + name: "Scorpio" + index: 1 + }] + all_planets: (SELECT planets FROM SolTable) +} \ No newline at end of file diff --git a/testdata/input/expr/new_constructor.sql b/testdata/input/expr/new_constructor.sql new file mode 100644 index 00000000..c1c8f9e9 --- /dev/null +++ b/testdata/input/expr/new_constructor.sql @@ -0,0 +1 @@ +NEW googlesql.examples.music.Chart(key AS rank, name AS chart_name) \ No newline at end of file diff --git a/testdata/result/expr/braced_new_constructor.sql.txt b/testdata/result/expr/braced_new_constructor.sql.txt new file mode 100644 index 00000000..596789e4 --- /dev/null +++ b/testdata/result/expr/braced_new_constructor.sql.txt @@ -0,0 +1,271 @@ +--- braced_new_constructor.sql +-- Example from https://cloud.google.com/spanner/docs/reference/standard-sql/operators#new_operator +NEW Universe { + name: "Sol" + closest_planets: ["Mercury", "Venus", "Earth" ] + star { + radius_miles: 432690 + age: 4603000000 + } + constellations: [{ + name: "Libra" + index: 0 + }, { + name: "Scorpio" + index: 1 + }] + all_planets: (SELECT planets FROM SolTable) +} +--- AST +&ast.BracedNewConstructor{ + New: 100, + TypeName: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 104, + NameEnd: 112, + Name: "Universe", + }, + }, + }, + Body: &ast.BracedConstructor{ + Lbrace: 113, + Rbrace: 380, + Fields: []*ast.BracedConstructorField{ + &ast.BracedConstructorField{ + Name: &ast.Ident{ + NamePos: 117, + NameEnd: 121, + Name: "name", + }, + Value: &ast.BracedConstructorFieldValueExpr{ + Colon: 121, + Expr: &ast.StringLiteral{ + ValuePos: 123, + ValueEnd: 128, + Value: "Sol", + }, + }, + }, + &ast.BracedConstructorField{ + Name: &ast.Ident{ + NamePos: 131, + NameEnd: 146, + Name: "closest_planets", + }, + Value: &ast.BracedConstructorFieldValueExpr{ + Colon: 146, + Expr: &ast.ArrayLiteral{ + Array: 0, + Lbrack: 148, + Rbrack: 177, + Type: nil, + Values: []ast.Expr{ + &ast.StringLiteral{ + ValuePos: 149, + ValueEnd: 158, + Value: "Mercury", + }, + &ast.StringLiteral{ + ValuePos: 160, + ValueEnd: 167, + Value: "Venus", + }, + &ast.StringLiteral{ + ValuePos: 169, + ValueEnd: 176, + Value: "Earth", + }, + }, + }, + }, + }, + &ast.BracedConstructorField{ + Name: &ast.Ident{ + NamePos: 181, + NameEnd: 185, + Name: "star", + }, + Value: &ast.BracedConstructor{ + Lbrace: 186, + Rbrace: 235, + Fields: []*ast.BracedConstructorField{ + &ast.BracedConstructorField{ + Name: &ast.Ident{ + NamePos: 192, + NameEnd: 204, + Name: "radius_miles", + }, + Value: &ast.BracedConstructorFieldValueExpr{ + Colon: 204, + Expr: &ast.IntLiteral{ + ValuePos: 206, + ValueEnd: 212, + Base: 10, + Value: "432690", + }, + }, + }, + &ast.BracedConstructorField{ + Name: &ast.Ident{ + NamePos: 217, + NameEnd: 220, + Name: "age", + }, + Value: &ast.BracedConstructorFieldValueExpr{ + Colon: 220, + Expr: &ast.IntLiteral{ + ValuePos: 222, + ValueEnd: 232, + Base: 10, + Value: "4603000000", + }, + }, + }, + }, + }, + }, + &ast.BracedConstructorField{ + Name: &ast.Ident{ + NamePos: 239, + NameEnd: 253, + Name: "constellations", + }, + Value: &ast.BracedConstructorFieldValueExpr{ + Colon: 253, + Expr: &ast.ArrayLiteral{ + Array: 0, + Lbrack: 255, + Rbrack: 332, + Type: nil, + Values: []ast.Expr{ + &ast.BracedConstructor{ + Lbrace: 256, + Rbrace: 291, + Fields: []*ast.BracedConstructorField{ + &ast.BracedConstructorField{ + Name: &ast.Ident{ + NamePos: 262, + NameEnd: 266, + Name: "name", + }, + Value: &ast.BracedConstructorFieldValueExpr{ + Colon: 266, + Expr: &ast.StringLiteral{ + ValuePos: 268, + ValueEnd: 275, + Value: "Libra", + }, + }, + }, + &ast.BracedConstructorField{ + Name: &ast.Ident{ + NamePos: 280, + NameEnd: 285, + Name: "index", + }, + Value: &ast.BracedConstructorFieldValueExpr{ + Colon: 285, + Expr: &ast.IntLiteral{ + ValuePos: 287, + ValueEnd: 288, + Base: 10, + Value: "0", + }, + }, + }, + }, + }, + &ast.BracedConstructor{ + Lbrace: 294, + Rbrace: 331, + Fields: []*ast.BracedConstructorField{ + &ast.BracedConstructorField{ + Name: &ast.Ident{ + NamePos: 300, + NameEnd: 304, + Name: "name", + }, + Value: &ast.BracedConstructorFieldValueExpr{ + Colon: 304, + Expr: &ast.StringLiteral{ + ValuePos: 306, + ValueEnd: 315, + Value: "Scorpio", + }, + }, + }, + &ast.BracedConstructorField{ + Name: &ast.Ident{ + NamePos: 320, + NameEnd: 325, + Name: "index", + }, + Value: &ast.BracedConstructorFieldValueExpr{ + Colon: 325, + Expr: &ast.IntLiteral{ + ValuePos: 327, + ValueEnd: 328, + Base: 10, + Value: "1", + }, + }, + }, + }, + }, + }, + }, + }, + }, + &ast.BracedConstructorField{ + Name: &ast.Ident{ + NamePos: 336, + NameEnd: 347, + Name: "all_planets", + }, + Value: &ast.BracedConstructorFieldValueExpr{ + Colon: 347, + Expr: &ast.ScalarSubQuery{ + Lparen: 349, + Rparen: 378, + Query: &ast.Select{ + Select: 350, + Distinct: false, + AsStruct: false, + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.Ident{ + NamePos: 357, + NameEnd: 364, + Name: "planets", + }, + }, + }, + From: &ast.From{ + From: 365, + Source: &ast.TableName{ + Table: &ast.Ident{ + NamePos: 370, + NameEnd: 378, + Name: "SolTable", + }, + Hint: (*ast.Hint)(nil), + As: (*ast.AsAlias)(nil), + Sample: (*ast.TableSample)(nil), + }, + }, + Where: (*ast.Where)(nil), + GroupBy: (*ast.GroupBy)(nil), + Having: (*ast.Having)(nil), + OrderBy: (*ast.OrderBy)(nil), + Limit: (*ast.Limit)(nil), + }, + }, + }, + }, + }, + }, +} + +--- SQL +NEW Universe {name: "Sol", closest_planets: ARRAY["Mercury", "Venus", "Earth"], star {radius_miles: 432690, age: 4603000000}, constellations: ARRAY[{name: "Libra", index: 0}, {name: "Scorpio", index: 1}], all_planets: (SELECT planets FROM SolTable)} diff --git a/testdata/result/expr/new_constructor.sql.txt b/testdata/result/expr/new_constructor.sql.txt new file mode 100644 index 00000000..0b442016 --- /dev/null +++ b/testdata/result/expr/new_constructor.sql.txt @@ -0,0 +1,66 @@ +--- new_constructor.sql +NEW googlesql.examples.music.Chart(key AS rank, name AS chart_name) +--- AST +&ast.NewConstructor{ + New: 0, + TypeName: &ast.Path{ + Idents: []*ast.Ident{ + &ast.Ident{ + NamePos: 4, + NameEnd: 13, + Name: "googlesql", + }, + &ast.Ident{ + NamePos: 14, + NameEnd: 22, + Name: "examples", + }, + &ast.Ident{ + NamePos: 23, + NameEnd: 28, + Name: "music", + }, + &ast.Ident{ + NamePos: 29, + NameEnd: 34, + Name: "Chart", + }, + }, + }, + Args: []*ast.NewConstructorArg{ + &ast.NewConstructorArg{ + Expr: &ast.Ident{ + NamePos: 35, + NameEnd: 38, + Name: "key", + }, + Alias: &ast.AsAlias{ + As: -1, + Alias: &ast.Ident{ + NamePos: 42, + NameEnd: 46, + Name: "rank", + }, + }, + }, + &ast.NewConstructorArg{ + Expr: &ast.Ident{ + NamePos: 48, + NameEnd: 52, + Name: "name", + }, + Alias: &ast.AsAlias{ + As: -1, + Alias: &ast.Ident{ + NamePos: 56, + NameEnd: 66, + Name: "chart_name", + }, + }, + }, + }, + Rparen: 66, +} + +--- SQL +NEW googlesql.examples.music.Chart(key AS rank, name AS chart_name) From df9755fe45a6e59de9d1cf0b7847fc9b057e8774 Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Sat, 28 Sep 2024 17:40:06 +0900 Subject: [PATCH 04/22] Fix receiver of isExpr --- ast/ast.go | 70 +++++++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/ast/ast.go b/ast/ast.go index d879dd46..07245137 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -150,41 +150,41 @@ type Expr interface { isExpr() } -func (BinaryExpr) isExpr() {} -func (UnaryExpr) isExpr() {} -func (InExpr) isExpr() {} -func (IsNullExpr) isExpr() {} -func (IsBoolExpr) isExpr() {} -func (BetweenExpr) isExpr() {} -func (SelectorExpr) isExpr() {} -func (IndexExpr) isExpr() {} -func (CallExpr) isExpr() {} -func (CountStarExpr) isExpr() {} -func (CastExpr) isExpr() {} -func (ExtractExpr) isExpr() {} -func (CaseExpr) isExpr() {} -func (ParenExpr) isExpr() {} -func (ScalarSubQuery) isExpr() {} -func (ArraySubQuery) isExpr() {} -func (ExistsSubQuery) isExpr() {} -func (Param) isExpr() {} -func (Ident) isExpr() {} -func (Path) isExpr() {} -func (ArrayLiteral) isExpr() {} -func (StructLiteral) isExpr() {} -func (NullLiteral) isExpr() {} -func (BoolLiteral) isExpr() {} -func (IntLiteral) isExpr() {} -func (FloatLiteral) isExpr() {} -func (StringLiteral) isExpr() {} -func (BytesLiteral) isExpr() {} -func (DateLiteral) isExpr() {} -func (TimestampLiteral) isExpr() {} -func (NumericLiteral) isExpr() {} -func (JSONLiteral) isExpr() {} -func (*NewConstructor) isExpr() {} -func (*BracedNewConstructor) isExpr() {} -func (*BracedConstructor) isExpr() {} +func (BinaryExpr) isExpr() {} +func (UnaryExpr) isExpr() {} +func (InExpr) isExpr() {} +func (IsNullExpr) isExpr() {} +func (IsBoolExpr) isExpr() {} +func (BetweenExpr) isExpr() {} +func (SelectorExpr) isExpr() {} +func (IndexExpr) isExpr() {} +func (CallExpr) isExpr() {} +func (CountStarExpr) isExpr() {} +func (CastExpr) isExpr() {} +func (ExtractExpr) isExpr() {} +func (CaseExpr) isExpr() {} +func (ParenExpr) isExpr() {} +func (ScalarSubQuery) isExpr() {} +func (ArraySubQuery) isExpr() {} +func (ExistsSubQuery) isExpr() {} +func (Param) isExpr() {} +func (Ident) isExpr() {} +func (Path) isExpr() {} +func (ArrayLiteral) isExpr() {} +func (StructLiteral) isExpr() {} +func (NullLiteral) isExpr() {} +func (BoolLiteral) isExpr() {} +func (IntLiteral) isExpr() {} +func (FloatLiteral) isExpr() {} +func (StringLiteral) isExpr() {} +func (BytesLiteral) isExpr() {} +func (DateLiteral) isExpr() {} +func (TimestampLiteral) isExpr() {} +func (NumericLiteral) isExpr() {} +func (JSONLiteral) isExpr() {} +func (NewConstructor) isExpr() {} +func (BracedNewConstructor) isExpr() {} +func (BracedConstructor) isExpr() {} // Arg represents argument of function call. type Arg interface { From 8d2b00af35e16e9a3485d64e9ae349122818ca3e Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Tue, 1 Oct 2024 12:55:25 +0900 Subject: [PATCH 05/22] Fix to use NamedType --- ast/ast.go | 12 +++++----- ast/sql.go | 4 ++-- parser.go | 24 ++++++++++--------- .../expr/braced_new_constructor.sql.txt | 14 +++++------ testdata/result/expr/new_constructor.sql.txt | 6 ++--- 5 files changed, 31 insertions(+), 29 deletions(-) diff --git a/ast/ast.go b/ast/ast.go index 07245137..27c4e519 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -1527,13 +1527,13 @@ type NewConstructorArg struct { // NewConstructor represents NEW operator which creates a protocol buffer using a parenthesized list of arguments. // -// NEW {{TypeName | sql}} ({{Args | sqlJoin ", "}}) +// NEW {{.Type | sql}} ({{.Args | sqlJoin ", "}}) type NewConstructor struct { // pos = New // end = Rparen + 1 - New token.Pos - TypeName *Path + New token.Pos + Type *NamedType Args []*NewConstructorArg @@ -1542,15 +1542,15 @@ type NewConstructor struct { // BracedNewConstructor represents NEW operator which creates a protocol buffer using a map constructor. // -// NEW {{.TypeName | sql}} {{"{"}}{{"}"}} +// NEW {{.Type | sql}} {{"{"}}{{"}"}} type BracedNewConstructor struct { // pos = New // end = Body.end New token.Pos - TypeName *Path - Body *BracedConstructor + Type *NamedType + Body *BracedConstructor } // BracedConstructor represents a single map constructor which is used in BracedNewConstructor. diff --git a/ast/sql.go b/ast/sql.go index 34bb2b12..3d93ff38 100644 --- a/ast/sql.go +++ b/ast/sql.go @@ -690,7 +690,7 @@ func (n *NewConstructorArg) SQL() string { func (n *NewConstructor) SQL() string { var sql string - sql += "NEW " + n.TypeName.SQL() + "(" + sql += "NEW " + n.Type.SQL() + "(" for i, arg := range n.Args { if i > 0 { sql += ", " @@ -702,7 +702,7 @@ func (n *NewConstructor) SQL() string { } func (b *BracedNewConstructor) SQL() string { - return "NEW " + b.TypeName.SQL() + " " + b.Body.SQL() + return "NEW " + b.Type.SQL() + " " + b.Body.SQL() } func (b *BracedConstructor) SQL() string { diff --git a/parser.go b/parser.go index 272537a6..21372851 100644 --- a/parser.go +++ b/parser.go @@ -2104,7 +2104,7 @@ func (p *Parser) parseStructTypeFields() (fields []*ast.StructField, gt token.Po return } -func (p *Parser) parseNewConstructor(newPos token.Pos, path []*ast.Ident) *ast.NewConstructor { +func (p *Parser) parseNewConstructor(newPos token.Pos, namedType *ast.NamedType) *ast.NewConstructor { p.expect("(") var args []*ast.NewConstructorArg @@ -2127,10 +2127,10 @@ func (p *Parser) parseNewConstructor(newPos token.Pos, path []*ast.Ident) *ast.N } rparen := p.expect(")").Pos return &ast.NewConstructor{ - New: newPos, - TypeName: &ast.Path{Idents: path}, - Args: args, - Rparen: rparen, + New: newPos, + Type: namedType, + Args: args, + Rparen: rparen, } } @@ -2170,23 +2170,25 @@ func (p *Parser) parseBracedConstructor() *ast.BracedConstructor { Fields: fields, } } -func (p *Parser) parseBracedNewConstructor(newPos token.Pos, path []*ast.Ident) *ast.BracedNewConstructor { + +func (p *Parser) parseBracedNewConstructor(newPos token.Pos, namedType *ast.NamedType) *ast.BracedNewConstructor { body := p.parseBracedConstructor() return &ast.BracedNewConstructor{ - New: newPos, - TypeName: &ast.Path{Idents: path}, - Body: body, + New: newPos, + Type: namedType, + Body: body, } } func (p *Parser) parseNewConstructors() ast.Expr { newPos := p.expect("NEW").Pos path := p.parseIdentOrPath() + namedType := &ast.NamedType{Path: path} switch p.Token.Kind { case "(": - return p.parseNewConstructor(newPos, path) + return p.parseNewConstructor(newPos, namedType) case "{": - return p.parseBracedNewConstructor(newPos, path) + return p.parseBracedNewConstructor(newPos, namedType) default: p.panicfAtToken(&p.Token, `expect '{' or '(', but %v`, p.Token.Kind) } diff --git a/testdata/result/expr/braced_new_constructor.sql.txt b/testdata/result/expr/braced_new_constructor.sql.txt index 596789e4..18d206e3 100644 --- a/testdata/result/expr/braced_new_constructor.sql.txt +++ b/testdata/result/expr/braced_new_constructor.sql.txt @@ -18,9 +18,9 @@ NEW Universe { } --- AST &ast.BracedNewConstructor{ - New: 100, - TypeName: &ast.Path{ - Idents: []*ast.Ident{ + New: 100, + Type: &ast.NamedType{ + Path: []*ast.Ident{ &ast.Ident{ NamePos: 104, NameEnd: 112, @@ -56,7 +56,7 @@ NEW Universe { Value: &ast.BracedConstructorFieldValueExpr{ Colon: 146, Expr: &ast.ArrayLiteral{ - Array: 0, + Array: -1, Lbrack: 148, Rbrack: 177, Type: nil, @@ -134,7 +134,7 @@ NEW Universe { Value: &ast.BracedConstructorFieldValueExpr{ Colon: 253, Expr: &ast.ArrayLiteral{ - Array: 0, + Array: -1, Lbrack: 255, Rbrack: 332, Type: nil, @@ -231,7 +231,7 @@ NEW Universe { Query: &ast.Select{ Select: 350, Distinct: false, - AsStruct: false, + As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ Expr: &ast.Ident{ @@ -268,4 +268,4 @@ NEW Universe { } --- SQL -NEW Universe {name: "Sol", closest_planets: ARRAY["Mercury", "Venus", "Earth"], star {radius_miles: 432690, age: 4603000000}, constellations: ARRAY[{name: "Libra", index: 0}, {name: "Scorpio", index: 1}], all_planets: (SELECT planets FROM SolTable)} +NEW Universe {name: "Sol", closest_planets: ["Mercury", "Venus", "Earth"], star {radius_miles: 432690, age: 4603000000}, constellations: [{name: "Libra", index: 0}, {name: "Scorpio", index: 1}], all_planets: (SELECT planets FROM SolTable)} diff --git a/testdata/result/expr/new_constructor.sql.txt b/testdata/result/expr/new_constructor.sql.txt index 0b442016..de222c2d 100644 --- a/testdata/result/expr/new_constructor.sql.txt +++ b/testdata/result/expr/new_constructor.sql.txt @@ -2,9 +2,9 @@ NEW googlesql.examples.music.Chart(key AS rank, name AS chart_name) --- AST &ast.NewConstructor{ - New: 0, - TypeName: &ast.Path{ - Idents: []*ast.Ident{ + New: 0, + Type: &ast.NamedType{ + Path: []*ast.Ident{ &ast.Ident{ NamePos: 4, NameEnd: 13, From becd674edd6c5c123cb80be441542fb9e579e5a6 Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Tue, 1 Oct 2024 13:05:53 +0900 Subject: [PATCH 06/22] Update to use p.parseNamedType() --- parser.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/parser.go b/parser.go index 21372851..1dda7e83 100644 --- a/parser.go +++ b/parser.go @@ -2182,8 +2182,7 @@ func (p *Parser) parseBracedNewConstructor(newPos token.Pos, namedType *ast.Name func (p *Parser) parseNewConstructors() ast.Expr { newPos := p.expect("NEW").Pos - path := p.parseIdentOrPath() - namedType := &ast.NamedType{Path: path} + namedType := p.parseNamedType() switch p.Token.Kind { case "(": return p.parseNewConstructor(newPos, namedType) From b3141e1a7f182bf690789fbffd6cc80ead5ab593 Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Tue, 15 Oct 2024 21:39:45 +0900 Subject: [PATCH 07/22] Refactor SQL() using helper functions --- ast/sql.go | 35 ++++++++--------------------------- 1 file changed, 8 insertions(+), 27 deletions(-) diff --git a/ast/sql.go b/ast/sql.go index 3d93ff38..cb72d9f1 100644 --- a/ast/sql.go +++ b/ast/sql.go @@ -682,23 +682,11 @@ func (t *JSONLiteral) SQL() string { } func (n *NewConstructorArg) SQL() string { - if n.Alias != nil { - return n.Expr.SQL() + " " + n.Alias.SQL() - } - return n.Expr.SQL() + return n.Expr.SQL() + sqlOpt(" ", n.Alias, "") } func (n *NewConstructor) SQL() string { - var sql string - sql += "NEW " + n.Type.SQL() + "(" - for i, arg := range n.Args { - if i > 0 { - sql += ", " - } - sql += arg.SQL() - } - sql += ")" - return sql + return "NEW " + n.Type.SQL() + "(" + sqlJoin(n.Args, ", ") + ")" } func (b *BracedNewConstructor) SQL() string { @@ -706,23 +694,16 @@ func (b *BracedNewConstructor) SQL() string { } func (b *BracedConstructor) SQL() string { - var str string - str += "{" - for i, field := range b.Fields { - if i > 0 { - str += ", " - } - str += field.SQL() - } - str += "}" - return str + return "{" + sqlJoin(b.Fields, ", ") + "}" } func (b *BracedConstructorField) SQL() string { - if _, ok := b.Value.(*BracedConstructorFieldValueExpr); ok { - return b.Name.SQL() + b.Value.SQL() + if _, ok := b.Value.(*BracedConstructor); ok { + // Name {...} + return b.Name.SQL() + " " + b.Value.SQL() } - return b.Name.SQL() + " " + b.Value.SQL() + // Name: value + return b.Name.SQL() + b.Value.SQL() } func (b *BracedConstructorFieldValueExpr) SQL() string { return ": " + b.Expr.SQL() } From 3db71b8e4377771577d528ce2434139373c3ccce Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Tue, 15 Oct 2024 21:45:36 +0900 Subject: [PATCH 08/22] Add NEW constructor section in ast --- ast/ast.go | 22 ++++++++++++++-------- ast/sql.go | 6 ++++++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/ast/ast.go b/ast/ast.go index 27c4e519..f80268db 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -1514,6 +1514,20 @@ type JSONLiteral struct { Value *StringLiteral } +// ================================================================================ +// +// NEW constructors +// +// ================================================================================ + +type BracedConstructorFieldValue interface { + Node + isBracedConstructorFieldValue() +} + +func (*BracedConstructor) isBracedConstructorFieldValue() {} +func (*BracedConstructorFieldValueExpr) isBracedConstructorFieldValue() {} + // NewConstructorArg represents a single argument in NEW constructor. // // {{Expr | sql}} {{Alias | sqlOpt}} @@ -1577,14 +1591,6 @@ type BracedConstructorField struct { Value BracedConstructorFieldValue } -type BracedConstructorFieldValue interface { - Node - isBracedConstructorFieldValue() -} - -func (*BracedConstructor) isBracedConstructorFieldValue() {} -func (*BracedConstructorFieldValueExpr) isBracedConstructorFieldValue() {} - // BracedConstructorFieldValueExpr represents a field value node. // // : {{.Expr | sql}} diff --git a/ast/sql.go b/ast/sql.go index cb72d9f1..0d75a1e1 100644 --- a/ast/sql.go +++ b/ast/sql.go @@ -681,6 +681,12 @@ func (t *JSONLiteral) SQL() string { return "JSON " + t.Value.SQL() } +// ================================================================================ +// +// NEW constructors +// +// ================================================================================ + func (n *NewConstructorArg) SQL() string { return n.Expr.SQL() + sqlOpt(" ", n.Alias, "") } From 67ea3268191538ca7dd7e4548125f1d60b3088a1 Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Tue, 15 Oct 2024 22:37:14 +0900 Subject: [PATCH 09/22] Fix comments --- ast/ast.go | 1 + 1 file changed, 1 insertion(+) diff --git a/ast/ast.go b/ast/ast.go index f80268db..3e56f809 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -1520,6 +1520,7 @@ type JSONLiteral struct { // // ================================================================================ +// BracedConstructorFieldValue represents value part of fields in BracedNewConstructor. type BracedConstructorFieldValue interface { Node isBracedConstructorFieldValue() From bf06b5001231f3c76f4c484f1790f33fb5739d2c Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Sat, 19 Oct 2024 16:58:40 +0900 Subject: [PATCH 10/22] Update parser implementation of NEW constructors --- parser.go | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/parser.go b/parser.go index 1dda7e83..d806d792 100644 --- a/parser.go +++ b/parser.go @@ -2104,27 +2104,29 @@ func (p *Parser) parseStructTypeFields() (fields []*ast.StructField, gt token.Po return } +func (p *Parser) parseNewConstructorArg() *ast.NewConstructorArg { + expr := p.parseExpr() + var alias *ast.AsAlias + + // Whole "AS alias" is optional, but "AS" keyword can't be omitted. + if p.Token.Kind == "AS" { + alias = p.tryParseAsAlias() + } + + return &ast.NewConstructorArg{ + Expr: expr, + Alias: alias, + } +} func (p *Parser) parseNewConstructor(newPos token.Pos, namedType *ast.NamedType) *ast.NewConstructor { p.expect("(") + // Args can be empty like `NEW pkg.TypeName ()`. var args []*ast.NewConstructorArg - for { - if p.Token.Kind == ")" { - break - } - expr := p.parseExpr() - var alias *ast.AsAlias - if p.Token.Kind == "AS" { - alias = p.tryParseAsAlias() - } - args = append(args, &ast.NewConstructorArg{ - Expr: expr, - Alias: alias, - }) - if p.Token.Kind == "," { - p.nextToken() - } + if p.Token.Kind != ")" { + args = parseCommaSeparatedList(p, p.parseNewConstructorArg) } + rparen := p.expect(")").Pos return &ast.NewConstructor{ New: newPos, @@ -2150,20 +2152,27 @@ func (p *Parser) parseBracedNewConstructorField() *ast.BracedConstructorField { func (p *Parser) parseBracedConstructor() *ast.BracedConstructor { lbrace := p.expect("{").Pos + + // Braced constructor permits empty. var fields []*ast.BracedConstructorField for { if p.Token.Kind == "}" { break } + if p.Token.Kind != token.TokenIdent { p.panicfAtToken(&p.Token, "expect , but %v", p.Token.Kind) } fields = append(fields, p.parseBracedNewConstructorField()) + + // It is an optional comma. if p.Token.Kind == "," { p.nextToken() } } + rbrace := p.expect("}").Pos + return &ast.BracedConstructor{ Lbrace: lbrace, Rbrace: rbrace, @@ -2183,6 +2192,7 @@ func (p *Parser) parseBracedNewConstructor(newPos token.Pos, namedType *ast.Name func (p *Parser) parseNewConstructors() ast.Expr { newPos := p.expect("NEW").Pos namedType := p.parseNamedType() + switch p.Token.Kind { case "(": return p.parseNewConstructor(newPos, namedType) From fc608f3de05b495cc47b0a9ec2d7327812bb40db Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Sat, 19 Oct 2024 16:59:16 +0900 Subject: [PATCH 11/22] Do go test --update --- .../expr/braced_new_constructor_empty.sql | 1 + .../expr/braced_new_constructor_oneliner.sql | 1 + testdata/input/expr/new_constructor_empty.sql | 1 + .../expr/braced_new_constructor_empty.sql.txt | 23 ++++++ .../braced_new_constructor_oneliner.sql.txt | 72 +++++++++++++++++++ .../result/expr/new_constructor_empty.sql.txt | 36 ++++++++++ 6 files changed, 134 insertions(+) create mode 100644 testdata/input/expr/braced_new_constructor_empty.sql create mode 100644 testdata/input/expr/braced_new_constructor_oneliner.sql create mode 100644 testdata/input/expr/new_constructor_empty.sql create mode 100644 testdata/result/expr/braced_new_constructor_empty.sql.txt create mode 100644 testdata/result/expr/braced_new_constructor_oneliner.sql.txt create mode 100644 testdata/result/expr/new_constructor_empty.sql.txt diff --git a/testdata/input/expr/braced_new_constructor_empty.sql b/testdata/input/expr/braced_new_constructor_empty.sql new file mode 100644 index 00000000..d3d99104 --- /dev/null +++ b/testdata/input/expr/braced_new_constructor_empty.sql @@ -0,0 +1 @@ +NEW Universe {} \ No newline at end of file diff --git a/testdata/input/expr/braced_new_constructor_oneliner.sql b/testdata/input/expr/braced_new_constructor_oneliner.sql new file mode 100644 index 00000000..a3902848 --- /dev/null +++ b/testdata/input/expr/braced_new_constructor_oneliner.sql @@ -0,0 +1 @@ +NEW Universe {name: "Sol", closest_planets: ["Mercury", "Venus", "Earth" ]} \ No newline at end of file diff --git a/testdata/input/expr/new_constructor_empty.sql b/testdata/input/expr/new_constructor_empty.sql new file mode 100644 index 00000000..87bd24b3 --- /dev/null +++ b/testdata/input/expr/new_constructor_empty.sql @@ -0,0 +1 @@ +NEW googlesql.examples.music.Chart() diff --git a/testdata/result/expr/braced_new_constructor_empty.sql.txt b/testdata/result/expr/braced_new_constructor_empty.sql.txt new file mode 100644 index 00000000..60878f90 --- /dev/null +++ b/testdata/result/expr/braced_new_constructor_empty.sql.txt @@ -0,0 +1,23 @@ +--- braced_new_constructor_empty.sql +NEW Universe {} +--- AST +&ast.BracedNewConstructor{ + New: 0, + Type: &ast.NamedType{ + Path: []*ast.Ident{ + &ast.Ident{ + NamePos: 4, + NameEnd: 12, + Name: "Universe", + }, + }, + }, + Body: &ast.BracedConstructor{ + Lbrace: 13, + Rbrace: 14, + Fields: []*ast.BracedConstructorField(nil), + }, +} + +--- SQL +NEW Universe {} diff --git a/testdata/result/expr/braced_new_constructor_oneliner.sql.txt b/testdata/result/expr/braced_new_constructor_oneliner.sql.txt new file mode 100644 index 00000000..5b49efed --- /dev/null +++ b/testdata/result/expr/braced_new_constructor_oneliner.sql.txt @@ -0,0 +1,72 @@ +--- braced_new_constructor_oneliner.sql +NEW Universe {name: "Sol", closest_planets: ["Mercury", "Venus", "Earth" ]} +--- AST +&ast.BracedNewConstructor{ + New: 0, + Type: &ast.NamedType{ + Path: []*ast.Ident{ + &ast.Ident{ + NamePos: 4, + NameEnd: 12, + Name: "Universe", + }, + }, + }, + Body: &ast.BracedConstructor{ + Lbrace: 13, + Rbrace: 74, + Fields: []*ast.BracedConstructorField{ + &ast.BracedConstructorField{ + Name: &ast.Ident{ + NamePos: 14, + NameEnd: 18, + Name: "name", + }, + Value: &ast.BracedConstructorFieldValueExpr{ + Colon: 18, + Expr: &ast.StringLiteral{ + ValuePos: 20, + ValueEnd: 25, + Value: "Sol", + }, + }, + }, + &ast.BracedConstructorField{ + Name: &ast.Ident{ + NamePos: 27, + NameEnd: 42, + Name: "closest_planets", + }, + Value: &ast.BracedConstructorFieldValueExpr{ + Colon: 42, + Expr: &ast.ArrayLiteral{ + Array: 0, + Lbrack: 44, + Rbrack: 73, + Type: nil, + Values: []ast.Expr{ + &ast.StringLiteral{ + ValuePos: 45, + ValueEnd: 54, + Value: "Mercury", + }, + &ast.StringLiteral{ + ValuePos: 56, + ValueEnd: 63, + Value: "Venus", + }, + &ast.StringLiteral{ + ValuePos: 65, + ValueEnd: 72, + Value: "Earth", + }, + }, + }, + }, + }, + }, + }, +} + +--- SQL +NEW Universe {name: "Sol", closest_planets: ARRAY["Mercury", "Venus", "Earth"]} diff --git a/testdata/result/expr/new_constructor_empty.sql.txt b/testdata/result/expr/new_constructor_empty.sql.txt new file mode 100644 index 00000000..11db9262 --- /dev/null +++ b/testdata/result/expr/new_constructor_empty.sql.txt @@ -0,0 +1,36 @@ +--- new_constructor_empty.sql +NEW googlesql.examples.music.Chart() + +--- AST +&ast.NewConstructor{ + New: 0, + Type: &ast.NamedType{ + Path: []*ast.Ident{ + &ast.Ident{ + NamePos: 4, + NameEnd: 13, + Name: "googlesql", + }, + &ast.Ident{ + NamePos: 14, + NameEnd: 22, + Name: "examples", + }, + &ast.Ident{ + NamePos: 23, + NameEnd: 28, + Name: "music", + }, + &ast.Ident{ + NamePos: 29, + NameEnd: 34, + Name: "Chart", + }, + }, + }, + Args: []*ast.NewConstructorArg(nil), + Rparen: 35, +} + +--- SQL +NEW googlesql.examples.music.Chart() From 8b37f43550f850d2920f8ccb1f9d4c3900ce57fd Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Sat, 19 Oct 2024 17:23:47 +0900 Subject: [PATCH 12/22] Fix code placement --- parser.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parser.go b/parser.go index d806d792..586dfcdd 100644 --- a/parser.go +++ b/parser.go @@ -2106,9 +2106,9 @@ func (p *Parser) parseStructTypeFields() (fields []*ast.StructField, gt token.Po func (p *Parser) parseNewConstructorArg() *ast.NewConstructorArg { expr := p.parseExpr() - var alias *ast.AsAlias // Whole "AS alias" is optional, but "AS" keyword can't be omitted. + var alias *ast.AsAlias if p.Token.Kind == "AS" { alias = p.tryParseAsAlias() } From e9d5f86233cf147a35036663f31b2dfd5bfad11b Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Sat, 19 Oct 2024 21:24:08 +0900 Subject: [PATCH 13/22] Do go test --update --- testdata/result/expr/braced_new_constructor_oneliner.sql.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testdata/result/expr/braced_new_constructor_oneliner.sql.txt b/testdata/result/expr/braced_new_constructor_oneliner.sql.txt index 5b49efed..cc34fbeb 100644 --- a/testdata/result/expr/braced_new_constructor_oneliner.sql.txt +++ b/testdata/result/expr/braced_new_constructor_oneliner.sql.txt @@ -40,7 +40,7 @@ NEW Universe {name: "Sol", closest_planets: ["Mercury", "Venus", "Earth" ]} Value: &ast.BracedConstructorFieldValueExpr{ Colon: 42, Expr: &ast.ArrayLiteral{ - Array: 0, + Array: -1, Lbrack: 44, Rbrack: 73, Type: nil, @@ -69,4 +69,4 @@ NEW Universe {name: "Sol", closest_planets: ["Mercury", "Venus", "Earth" ]} } --- SQL -NEW Universe {name: "Sol", closest_planets: ARRAY["Mercury", "Venus", "Earth"]} +NEW Universe {name: "Sol", closest_planets: ["Mercury", "Venus", "Earth"]} From ed0bd6b5f25ce27bcf5b15ea655a54e5e20f4cdf Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Sun, 27 Oct 2024 00:09:47 +0900 Subject: [PATCH 14/22] Separate StructLiteral to TupleStructLiteral, TypelessStructLiteral, TypedStructLiteral --- ast/ast.go | 120 ++++++++++++------ ast/ast_test.go | 2 +- ast/pos.go | 32 ++++- ast/sql.go | 37 +++--- parser.go | 66 +++++++--- testdata/result/dml/insert_select.sql.txt | 10 +- .../query/select_array_with_struct.sql.txt | 10 +- testdata/result/query/select_cast.sql.txt | 12 +- .../query/select_from_implicit_unnest.sql.txt | 3 +- .../result/query/select_literals_all.sql.txt | 51 ++++---- .../query/select_literals_struct.sql.txt | 108 ++++++++-------- .../query/select_struct_compare_eq.sql.txt | 65 +++++----- ...ct_tablesample_with_unnest_invalid.sql.txt | 10 +- .../query/select_with_field_path.sql.txt | 18 +-- .../result/statement/insert_select.sql.txt | 10 +- .../select_array_with_struct.sql.txt | 10 +- testdata/result/statement/select_cast.sql.txt | 12 +- .../select_from_implicit_unnest.sql.txt | 3 +- .../statement/select_literals_all.sql.txt | 51 ++++---- .../statement/select_literals_struct.sql.txt | 108 ++++++++-------- .../select_struct_compare_eq.sql.txt | 65 +++++----- ...ct_tablesample_with_unnest_invalid.sql.txt | 10 +- .../statement/select_with_field_path.sql.txt | 18 +-- 23 files changed, 447 insertions(+), 384 deletions(-) diff --git a/ast/ast.go b/ast/ast.go index 3e56f809..037f538d 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -150,41 +150,43 @@ type Expr interface { isExpr() } -func (BinaryExpr) isExpr() {} -func (UnaryExpr) isExpr() {} -func (InExpr) isExpr() {} -func (IsNullExpr) isExpr() {} -func (IsBoolExpr) isExpr() {} -func (BetweenExpr) isExpr() {} -func (SelectorExpr) isExpr() {} -func (IndexExpr) isExpr() {} -func (CallExpr) isExpr() {} -func (CountStarExpr) isExpr() {} -func (CastExpr) isExpr() {} -func (ExtractExpr) isExpr() {} -func (CaseExpr) isExpr() {} -func (ParenExpr) isExpr() {} -func (ScalarSubQuery) isExpr() {} -func (ArraySubQuery) isExpr() {} -func (ExistsSubQuery) isExpr() {} -func (Param) isExpr() {} -func (Ident) isExpr() {} -func (Path) isExpr() {} -func (ArrayLiteral) isExpr() {} -func (StructLiteral) isExpr() {} -func (NullLiteral) isExpr() {} -func (BoolLiteral) isExpr() {} -func (IntLiteral) isExpr() {} -func (FloatLiteral) isExpr() {} -func (StringLiteral) isExpr() {} -func (BytesLiteral) isExpr() {} -func (DateLiteral) isExpr() {} -func (TimestampLiteral) isExpr() {} -func (NumericLiteral) isExpr() {} -func (JSONLiteral) isExpr() {} -func (NewConstructor) isExpr() {} -func (BracedNewConstructor) isExpr() {} -func (BracedConstructor) isExpr() {} +func (BinaryExpr) isExpr() {} +func (UnaryExpr) isExpr() {} +func (InExpr) isExpr() {} +func (IsNullExpr) isExpr() {} +func (IsBoolExpr) isExpr() {} +func (BetweenExpr) isExpr() {} +func (SelectorExpr) isExpr() {} +func (IndexExpr) isExpr() {} +func (CallExpr) isExpr() {} +func (CountStarExpr) isExpr() {} +func (CastExpr) isExpr() {} +func (ExtractExpr) isExpr() {} +func (CaseExpr) isExpr() {} +func (ParenExpr) isExpr() {} +func (ScalarSubQuery) isExpr() {} +func (ArraySubQuery) isExpr() {} +func (ExistsSubQuery) isExpr() {} +func (Param) isExpr() {} +func (Ident) isExpr() {} +func (Path) isExpr() {} +func (ArrayLiteral) isExpr() {} +func (TupleStructLiteral) isExpr() {} +func (TypelessStructLiteral) isExpr() {} +func (TypedStructLiteral) isExpr() {} +func (NullLiteral) isExpr() {} +func (BoolLiteral) isExpr() {} +func (IntLiteral) isExpr() {} +func (FloatLiteral) isExpr() {} +func (StringLiteral) isExpr() {} +func (BytesLiteral) isExpr() {} +func (DateLiteral) isExpr() {} +func (TimestampLiteral) isExpr() {} +func (NumericLiteral) isExpr() {} +func (JSONLiteral) isExpr() {} +func (NewConstructor) isExpr() {} +func (BracedNewConstructor) isExpr() {} +func (BracedConstructor) isExpr() {} // Arg represents argument of function call. type Arg interface { @@ -1379,18 +1381,52 @@ type ArrayLiteral struct { Values []Expr } -// StructLiteral is struct literal node. +// TupleStructLiteral is tuple syntax struct literal node. // -// STRUCT{{if not (isnil .Fields)}}<{{.Fields | sqlJoin ","}}>{{end}}({{.Values | sqlJoin ","}}) -type StructLiteral struct { - // pos = Struct || Lparen +// ({{.Values | sqlJoin ","}}) +type TupleStructLiteral struct { + // pos = Lparen // end = Rparen + 1 - Struct token.Pos // position of "STRUCT" Lparen, Rparen token.Pos // position of "(" and ")" - // NOTE: Distinguish nil from len(Fields) == 0 case. - // nil means type is not specified, or empty slice means this struct has 0 fields. + Values []Expr // len(Values) > 1 +} + +// TypelessStructLiteral is typeless struct literal node. +// +// STRUCT({{.Values | sqlJoin ","}}) +type TypelessStructLiteral struct { + // pos = Struct + // end = Rparen + 1 + + Struct token.Pos // position of "STRUCT" + Rparen token.Pos // position of ")" + + Values []*TypelessStructValue +} + +// TypelessStructValue is value with optional name in typeless struct literal. +// +// {{.Expr | sql}}{{if .Name}} AS {{.Name | sql}}{{end}} +type TypelessStructValue struct { + // pos = Expr.pos + // end = (Name ?? Expr).end + + Expr Expr + Name *Ident // optional +} + +// TypedStructLiteral is typed struct literal node. +// +// STRUCT<{{.Fields | sqlJoin ","}}>({{.Values | sqlJoin ","}}) +type TypedStructLiteral struct { + // pos = Struct + // end = Rparen + 1 + + Struct token.Pos // position of "STRUCT" + Rparen token.Pos // position of "(" and ")" + Fields []*StructField Values []Expr } diff --git a/ast/ast_test.go b/ast/ast_test.go index 338cd95c..cc8ee6d3 100644 --- a/ast/ast_test.go +++ b/ast/ast_test.go @@ -87,7 +87,7 @@ func TestExpr(t *testing.T) { Expr(&Ident{}).isExpr() Expr(&Path{}).isExpr() Expr(&ArrayLiteral{}).isExpr() - Expr(&StructLiteral{}).isExpr() + Expr(&TypedStructLiteral{}).isExpr() Expr(&NullLiteral{}).isExpr() Expr(&BoolLiteral{}).isExpr() Expr(&IntLiteral{}).isExpr() diff --git a/ast/pos.go b/ast/pos.go index d88e98f2..b7220932 100644 --- a/ast/pos.go +++ b/ast/pos.go @@ -574,12 +574,36 @@ func (a *ArrayLiteral) End() token.Pos { return posAdd(a.Rbrack, 1) } -func (s *StructLiteral) Pos() token.Pos { - return posChoice(s.Struct, s.Lparen) +func (t *TupleStructLiteral) Pos() token.Pos { + return t.Lparen } -func (s *StructLiteral) End() token.Pos { - return posAdd(s.Rparen, 1) +func (t *TupleStructLiteral) End() token.Pos { + return posAdd(t.Rparen, 1) +} + +func (t *TypelessStructLiteral) Pos() token.Pos { + return t.Struct +} + +func (t *TypelessStructLiteral) End() token.Pos { + return posAdd(t.Rparen, 1) +} + +func (t *TypelessStructValue) Pos() token.Pos { + return nodePos(wrapNode(t.Expr)) +} + +func (t *TypelessStructValue) End() token.Pos { + return nodeEnd(nodeChoice(wrapNode(t.Name), wrapNode(t.Expr))) +} + +func (t *TypedStructLiteral) Pos() token.Pos { + return t.Struct +} + +func (t *TypedStructLiteral) End() token.Pos { + return posAdd(t.Rparen, 1) } func (n *NullLiteral) Pos() token.Pos { diff --git a/ast/sql.go b/ast/sql.go index 0d75a1e1..71df8579 100644 --- a/ast/sql.go +++ b/ast/sql.go @@ -76,7 +76,7 @@ const ( func exprPrec(e Expr) prec { switch e := e.(type) { - case *CallExpr, *CountStarExpr, *CastExpr, *ExtractExpr, *CaseExpr, *ParenExpr, *ScalarSubQuery, *ArraySubQuery, *ExistsSubQuery, *Param, *Ident, *Path, *ArrayLiteral, *StructLiteral, *NullLiteral, *BoolLiteral, *IntLiteral, *FloatLiteral, *StringLiteral, *BytesLiteral, *DateLiteral, *TimestampLiteral, *NumericLiteral: + case *CallExpr, *CountStarExpr, *CastExpr, *ExtractExpr, *CaseExpr, *ParenExpr, *ScalarSubQuery, *ArraySubQuery, *ExistsSubQuery, *Param, *Ident, *Path, *ArrayLiteral, *TupleStructLiteral, *TypedStructLiteral, *TypelessStructLiteral, *NullLiteral, *BoolLiteral, *IntLiteral, *FloatLiteral, *StringLiteral, *BytesLiteral, *DateLiteral, *TimestampLiteral, *NumericLiteral: return precLit case *IndexExpr, *SelectorExpr: return precSelector @@ -614,27 +614,20 @@ func (a *ArrayLiteral) SQL() string { "[" + sqlJoin(a.Values, ", ") + "]" } -func (s *StructLiteral) SQL() string { - sql := "STRUCT" - if s.Fields != nil { - sql += "<" - for i, f := range s.Fields { - if i != 0 { - sql += ", " - } - sql += f.SQL() - } - sql += ">" - } - sql += "(" - for i, v := range s.Values { - if i != 0 { - sql += ", " - } - sql += v.SQL() - } - sql += ")" - return sql +func (s *TupleStructLiteral) SQL() string { + return "(" + sqlJoin(s.Values, ", ") + ")" +} + +func (s *TypelessStructLiteral) SQL() string { + return strOpt(!s.Struct.Invalid(), "STRUCT") + "(" + sqlJoin(s.Values, ", ") + ")" +} + +func (s *TypelessStructValue) SQL() string { + return s.Expr.SQL() + sqlOpt(" AS ", s.Name, "") +} + +func (s *TypedStructLiteral) SQL() string { + return "STRUCT<" + sqlJoin(s.Fields, ", ") + ">(" + sqlJoin(s.Values, ", ") + ")" } func (*NullLiteral) SQL() string { diff --git a/parser.go b/parser.go index 586dfcdd..0bc3f53b 100644 --- a/parser.go +++ b/parser.go @@ -1803,22 +1803,35 @@ func (p *Parser) parseParenExpr() ast.Expr { } if p.Token.Kind != "," { - p.panicfAtToken(&paren, "cannot parse (...) as expression, struct literal or subquery") + p.panicfAtToken(&paren, "cannot parse (...) as expression, typeless struct literal or subquery") } - values := []ast.Expr{expr} - for p.Token.Kind == "," { - p.nextToken() - values = append(values, p.parseExpr()) - } + p.expect(",") + + values := append([]ast.Expr{expr}, parseCommaSeparatedList(p, p.parseExpr)...) rparen := p.expect(")").Pos - return &ast.StructLiteral{ + + return &ast.TupleStructLiteral{ Lparen: paren.Pos, Rparen: rparen, Values: values, } } +func (p *Parser) parseTypelessStructField() *ast.TypelessStructValue { + expr := p.parseExpr() + if p.Token.Kind != "AS" { + return &ast.TypelessStructValue{Expr: expr} + } + + p.nextToken() + ident := p.parseIdent() + return &ast.TypelessStructValue{ + Expr: expr, + Name: ident, + } +} + func (p *Parser) parseArrayLiteralOrSubQuery() ast.Expr { pos := p.expect("ARRAY").Pos @@ -1875,24 +1888,34 @@ func (p *Parser) parseArrayLiteralBody() (values []ast.Expr, lbrack, rbrack toke return } -func (p *Parser) parseStructLiteral() *ast.StructLiteral { +func (p *Parser) parseStructLiteral() ast.Expr { + // tuple struct syntax is handled in parseParenExpr. pos := p.expect("STRUCT").Pos - fields, _ := p.parseStructTypeFields() - lparen := p.expect("(").Pos + fields, gt := p.tryParseStructTypeFields() + p.expect("(") + + if gt.Invalid() { + // typeless + var values []*ast.TypelessStructValue + if p.Token.Kind != ")" { + values = parseCommaSeparatedList(p, p.parseTypelessStructField) + } + rparen := p.expect(")").Pos + return &ast.TypelessStructLiteral{ + Struct: pos, + Rparen: rparen, + Values: values, + } + } + + // typed var values []ast.Expr if p.Token.Kind != ")" { - for p.Token.Kind != token.TokenEOF { - values = append(values, p.parseExpr()) - if p.Token.Kind != "," { - break - } - p.nextToken() - } + values = parseCommaSeparatedList(p, p.parseExpr) } rparen := p.expect(")").Pos - return &ast.StructLiteral{ + return &ast.TypedStructLiteral{ Struct: pos, - Lparen: lparen, Rparen: rparen, Fields: fields, Values: values, @@ -2060,7 +2083,7 @@ func (p *Parser) parseArrayType() *ast.ArrayType { func (p *Parser) parseStructType() *ast.StructType { pos := p.expect("STRUCT").Pos - fields, gt := p.parseStructTypeFields() + fields, gt := p.tryParseStructTypeFields() if fields == nil { p.panicfAtToken(&p.Token, "expected token: <, <>, but: %s", p.Token.Kind) } @@ -2071,7 +2094,8 @@ func (p *Parser) parseStructType() *ast.StructType { } } -func (p *Parser) parseStructTypeFields() (fields []*ast.StructField, gt token.Pos) { +func (p *Parser) tryParseStructTypeFields() (fields []*ast.StructField, gt token.Pos) { + gt = token.InvalidPos if p.Token.Kind != "<" && p.Token.Kind != "<>" { return } diff --git a/testdata/result/dml/insert_select.sql.txt b/testdata/result/dml/insert_select.sql.txt index cc71ca16..6afe8c7c 100644 --- a/testdata/result/dml/insert_select.sql.txt +++ b/testdata/result/dml/insert_select.sql.txt @@ -43,11 +43,9 @@ select * from unnest([(1, 2), (3, 4)]) Rbrack: 58, Type: nil, Values: []ast.Expr{ - &ast.StructLiteral{ - Struct: 0, + &ast.TupleStructLiteral{ Lparen: 44, Rparen: 49, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 45, @@ -63,11 +61,9 @@ select * from unnest([(1, 2), (3, 4)]) }, }, }, - &ast.StructLiteral{ - Struct: 0, + &ast.TupleStructLiteral{ Lparen: 52, Rparen: 57, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 53, @@ -101,4 +97,4 @@ select * from unnest([(1, 2), (3, 4)]) } --- SQL -INSERT INTO foo (foo, bar) SELECT * FROM UNNEST([STRUCT(1, 2), STRUCT(3, 4)]) +INSERT INTO foo (foo, bar) SELECT * FROM UNNEST([(1, 2), (3, 4)]) diff --git a/testdata/result/query/select_array_with_struct.sql.txt b/testdata/result/query/select_array_with_struct.sql.txt index 28c893b2..32f645d4 100644 --- a/testdata/result/query/select_array_with_struct.sql.txt +++ b/testdata/result/query/select_array_with_struct.sql.txt @@ -55,11 +55,9 @@ FROM }, }, Values: []ast.Expr{ - &ast.StructLiteral{ - Struct: 0, + &ast.TupleStructLiteral{ Lparen: 58, Rparen: 67, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 59, @@ -74,11 +72,9 @@ FROM }, }, }, - &ast.StructLiteral{ - Struct: 0, + &ast.TupleStructLiteral{ Lparen: 70, Rparen: 79, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 71, @@ -110,4 +106,4 @@ FROM } --- SQL -SELECT * FROM UNNEST(ARRAY>[STRUCT(1, "foo"), STRUCT(3, "bar")]) +SELECT * FROM UNNEST(ARRAY>[(1, "foo"), (3, "bar")]) diff --git a/testdata/result/query/select_cast.sql.txt b/testdata/result/query/select_cast.sql.txt index d5f6fb96..d104b8e8 100644 --- a/testdata/result/query/select_cast.sql.txt +++ b/testdata/result/query/select_cast.sql.txt @@ -52,18 +52,14 @@ limit cast(1 as INT64) offset cast(@foo as INT64) Cast: 47, Rparen: 147, Safe: false, - Expr: &ast.StructLiteral{ - Struct: 0, + Expr: &ast.TupleStructLiteral{ Lparen: 52, Rparen: 84, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ - &ast.StructLiteral{ + &ast.TypelessStructLiteral{ Struct: 53, - Lparen: 59, Rparen: 60, - Fields: []*ast.StructField(nil), - Values: []ast.Expr(nil), + Values: []*ast.TypelessStructValue(nil), }, &ast.IntLiteral{ ValuePos: 63, @@ -300,4 +296,4 @@ limit cast(1 as INT64) offset cast(@foo as INT64) } --- SQL -SELECT CAST(1 AS INT64), CAST(0.1 AS FLOAT32), CAST(STRUCT(STRUCT(), 1, [2, 3], ["4", "5"]) AS STRUCT, x INT64, y ARRAY, z ARRAY>) FROM x TABLESAMPLE BERNOULLI (CAST(0.1 AS FLOAT64) PERCENT), y TABLESAMPLE BERNOULLI (CAST(1 AS INT64) ROWS), z TABLESAMPLE BERNOULLI (CAST(@param AS INT64) ROWS) LIMIT CAST(1 AS INT64) OFFSET CAST(@foo AS INT64) +SELECT CAST(1 AS INT64), CAST(0.1 AS FLOAT32), CAST((STRUCT(), 1, [2, 3], ["4", "5"]) AS STRUCT, x INT64, y ARRAY, z ARRAY>) FROM x TABLESAMPLE BERNOULLI (CAST(0.1 AS FLOAT64) PERCENT), y TABLESAMPLE BERNOULLI (CAST(1 AS INT64) ROWS), z TABLESAMPLE BERNOULLI (CAST(@param AS INT64) ROWS) LIMIT CAST(1 AS INT64) OFFSET CAST(@foo AS INT64) diff --git a/testdata/result/query/select_from_implicit_unnest.sql.txt b/testdata/result/query/select_from_implicit_unnest.sql.txt index 6cea9889..e29c72a3 100644 --- a/testdata/result/query/select_from_implicit_unnest.sql.txt +++ b/testdata/result/query/select_from_implicit_unnest.sql.txt @@ -41,9 +41,8 @@ FROM UNNEST([STRUCT>(["foo"])]) AS t, Rbrack: 61, Type: nil, Values: []ast.Expr{ - &ast.StructLiteral{ + &ast.TypedStructLiteral{ Struct: 27, - Lparen: 52, Rparen: 60, Fields: []*ast.StructField{ &ast.StructField{ diff --git a/testdata/result/query/select_literals_all.sql.txt b/testdata/result/query/select_literals_all.sql.txt index 3e35cc34..f92e62d1 100644 --- a/testdata/result/query/select_literals_all.sql.txt +++ b/testdata/result/query/select_literals_all.sql.txt @@ -392,29 +392,36 @@ lines''', As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ - Expr: &ast.StructLiteral{ + Expr: &ast.TypelessStructLiteral{ Struct: 467, - Lparen: 473, Rparen: 481, - Fields: []*ast.StructField(nil), - Values: []ast.Expr{ - &ast.IntLiteral{ - ValuePos: 474, - ValueEnd: 475, - Base: 10, - Value: "1", + Values: []*ast.TypelessStructValue{ + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 474, + ValueEnd: 475, + Base: 10, + Value: "1", + }, + Name: (*ast.Ident)(nil), }, - &ast.IntLiteral{ - ValuePos: 477, - ValueEnd: 478, - Base: 10, - Value: "2", + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 477, + ValueEnd: 478, + Base: 10, + Value: "2", + }, + Name: (*ast.Ident)(nil), }, - &ast.IntLiteral{ - ValuePos: 480, - ValueEnd: 481, - Base: 10, - Value: "3", + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 480, + ValueEnd: 481, + Base: 10, + Value: "3", + }, + Name: (*ast.Ident)(nil), }, }, }, @@ -439,11 +446,9 @@ lines''', As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ - Expr: &ast.StructLiteral{ - Struct: 0, + Expr: &ast.TupleStructLiteral{ Lparen: 500, Rparen: 508, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 501, @@ -635,4 +640,4 @@ lines''', } --- SQL -SELECT "abc", "it\'s", "it\'s", "Title: \"Boy\"", "abc", "it\'s", "Title:\"Boy\"", "two\nlines", "why\?", "abc+", "abc+", "abc+", "f\\(abc,(.*),def\\)", B"abc", B"abc", B"abc", B"abc+", B"abc+", B"abc", 123, 0xABC, -123, -0xABC, 123.456e-67, .1E4, 58., 4e2, [1, 2, 3], ["x", "y", "xy"], ARRAY[1, 2, 3], ARRAY["x", "y", "xy"], ARRAY[], ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, 3)), DATE "2014-09-27", DATE("2014-09-27"), TIMESTAMP "2014-09-27 12:30:00.45-08", TIMESTAMP "2014-09-27 12:30:00.45 America/Los_Angeles", TIMESTAMP "2014-09-27", TIMESTAMP("2014-09-27"), JSON "1", JSON "[1, 2]", JSON "{}", NUMERIC "0", NUMERIC "0", TRUE, FALSE +SELECT "abc", "it\'s", "it\'s", "Title: \"Boy\"", "abc", "it\'s", "Title:\"Boy\"", "two\nlines", "why\?", "abc+", "abc+", "abc+", "f\\(abc,(.*),def\\)", B"abc", B"abc", B"abc", B"abc+", B"abc+", B"abc", 123, 0xABC, -123, -0xABC, 123.456e-67, .1E4, 58., 4e2, [1, 2, 3], ["x", "y", "xy"], ARRAY[1, 2, 3], ARRAY["x", "y", "xy"], ARRAY[], ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT (1, 2, 3)), DATE "2014-09-27", DATE("2014-09-27"), TIMESTAMP "2014-09-27 12:30:00.45-08", TIMESTAMP "2014-09-27 12:30:00.45 America/Los_Angeles", TIMESTAMP "2014-09-27", TIMESTAMP("2014-09-27"), JSON "1", JSON "[1, 2]", JSON "{}", NUMERIC "0", NUMERIC "0", TRUE, FALSE diff --git a/testdata/result/query/select_literals_struct.sql.txt b/testdata/result/query/select_literals_struct.sql.txt index 802fb1e0..272a9b5d 100644 --- a/testdata/result/query/select_literals_struct.sql.txt +++ b/testdata/result/query/select_literals_struct.sql.txt @@ -28,29 +28,36 @@ SELECT As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ - Expr: &ast.StructLiteral{ + Expr: &ast.TypelessStructLiteral{ Struct: 22, - Lparen: 28, Rparen: 36, - Fields: []*ast.StructField(nil), - Values: []ast.Expr{ - &ast.IntLiteral{ - ValuePos: 29, - ValueEnd: 30, - Base: 10, - Value: "1", + Values: []*ast.TypelessStructValue{ + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 29, + ValueEnd: 30, + Base: 10, + Value: "1", + }, + Name: (*ast.Ident)(nil), }, - &ast.IntLiteral{ - ValuePos: 32, - ValueEnd: 33, - Base: 10, - Value: "2", + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 32, + ValueEnd: 33, + Base: 10, + Value: "2", + }, + Name: (*ast.Ident)(nil), }, - &ast.IntLiteral{ - ValuePos: 35, - ValueEnd: 36, - Base: 10, - Value: "3", + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 35, + ValueEnd: 36, + Base: 10, + Value: "3", + }, + Name: (*ast.Ident)(nil), }, }, }, @@ -75,27 +82,34 @@ SELECT As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ - Expr: &ast.StructLiteral{ + Expr: &ast.TypelessStructLiteral{ Struct: 55, - Lparen: 61, Rparen: 72, - Fields: []*ast.StructField(nil), - Values: []ast.Expr{ - &ast.IntLiteral{ - ValuePos: 62, - ValueEnd: 63, - Base: 10, - Value: "1", + Values: []*ast.TypelessStructValue{ + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 62, + ValueEnd: 63, + Base: 10, + Value: "1", + }, + Name: (*ast.Ident)(nil), }, - &ast.IntLiteral{ - ValuePos: 65, - ValueEnd: 66, - Base: 10, - Value: "2", + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 65, + ValueEnd: 66, + Base: 10, + Value: "2", + }, + Name: (*ast.Ident)(nil), }, - &ast.BoolLiteral{ - ValuePos: 68, - Value: true, + &ast.TypelessStructValue{ + Expr: &ast.BoolLiteral{ + ValuePos: 68, + Value: true, + }, + Name: (*ast.Ident)(nil), }, }, }, @@ -120,9 +134,8 @@ SELECT As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ - Expr: &ast.StructLiteral{ + Expr: &ast.TypedStructLiteral{ Struct: 91, - Lparen: 124, Rparen: 132, Fields: []*ast.StructField{ &ast.StructField{ @@ -201,9 +214,8 @@ SELECT As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ - Expr: &ast.StructLiteral{ + Expr: &ast.TypedStructLiteral{ Struct: 151, - Lparen: 178, Rparen: 186, Fields: []*ast.StructField{ &ast.StructField{ @@ -270,9 +282,8 @@ SELECT As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ - Expr: &ast.StructLiteral{ + Expr: &ast.TypedStructLiteral{ Struct: 205, - Lparen: 234, Rparen: 242, Fields: []*ast.StructField{ &ast.StructField{ @@ -343,11 +354,9 @@ SELECT As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ - Expr: &ast.StructLiteral{ - Struct: 0, + Expr: &ast.TupleStructLiteral{ Lparen: 261, Rparen: 269, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 262, @@ -390,9 +399,8 @@ SELECT As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ - Expr: &ast.StructLiteral{ + Expr: &ast.TypedStructLiteral{ Struct: 288, - Lparen: 296, Rparen: 297, Fields: []*ast.StructField{}, Values: []ast.Expr(nil), @@ -419,11 +427,9 @@ SELECT As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ - Expr: &ast.StructLiteral{ - Struct: 0, + Expr: &ast.TupleStructLiteral{ Lparen: 317, Rparen: 322, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 318, @@ -461,4 +467,4 @@ SELECT } --- SQL -SELECT ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, TRUE)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT<>()), EXISTS(SELECT STRUCT(1, 2)) +SELECT ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, TRUE)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT (1, 2, 3)), ARRAY(SELECT STRUCT<>()), EXISTS(SELECT (1, 2)) diff --git a/testdata/result/query/select_struct_compare_eq.sql.txt b/testdata/result/query/select_struct_compare_eq.sql.txt index 0ecdcbf5..ca4bcf5a 100644 --- a/testdata/result/query/select_struct_compare_eq.sql.txt +++ b/testdata/result/query/select_struct_compare_eq.sql.txt @@ -40,9 +40,8 @@ SELECT ARRAY( As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ - Expr: &ast.StructLiteral{ + Expr: &ast.TypedStructLiteral{ Struct: 48, - Lparen: 81, Rparen: 89, Fields: []*ast.StructField{ &ast.StructField{ @@ -129,37 +128,45 @@ SELECT ARRAY( NameEnd: 106, Name: "S", }, - Right: &ast.StructLiteral{ + Right: &ast.TypelessStructLiteral{ Struct: 109, - Lparen: 115, Rparen: 131, - Fields: []*ast.StructField(nil), - Values: []ast.Expr{ - &ast.StructLiteral{ - Struct: 116, - Lparen: 122, - Rparen: 130, - Fields: []*ast.StructField(nil), - Values: []ast.Expr{ - &ast.IntLiteral{ - ValuePos: 123, - ValueEnd: 124, - Base: 10, - Value: "1", - }, - &ast.IntLiteral{ - ValuePos: 126, - ValueEnd: 127, - Base: 10, - Value: "2", - }, - &ast.IntLiteral{ - ValuePos: 129, - ValueEnd: 130, - Base: 10, - Value: "3", + Values: []*ast.TypelessStructValue{ + &ast.TypelessStructValue{ + Expr: &ast.TypelessStructLiteral{ + Struct: 116, + Rparen: 130, + Values: []*ast.TypelessStructValue{ + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 123, + ValueEnd: 124, + Base: 10, + Value: "1", + }, + Name: (*ast.Ident)(nil), + }, + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 126, + ValueEnd: 127, + Base: 10, + Value: "2", + }, + Name: (*ast.Ident)(nil), + }, + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 129, + ValueEnd: 130, + Base: 10, + Value: "3", + }, + Name: (*ast.Ident)(nil), + }, }, }, + Name: (*ast.Ident)(nil), }, }, }, diff --git a/testdata/result/query/select_tablesample_with_unnest_invalid.sql.txt b/testdata/result/query/select_tablesample_with_unnest_invalid.sql.txt index 397274f3..44d34a87 100644 --- a/testdata/result/query/select_tablesample_with_unnest_invalid.sql.txt +++ b/testdata/result/query/select_tablesample_with_unnest_invalid.sql.txt @@ -55,11 +55,9 @@ FROM }, }, Values: []ast.Expr{ - &ast.StructLiteral{ - Struct: 0, + &ast.TupleStructLiteral{ Lparen: 58, Rparen: 67, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 59, @@ -74,11 +72,9 @@ FROM }, }, }, - &ast.StructLiteral{ - Struct: 0, + &ast.TupleStructLiteral{ Lparen: 70, Rparen: 79, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 71, @@ -124,4 +120,4 @@ FROM } --- SQL -SELECT * FROM UNNEST(ARRAY>[STRUCT(1, "foo"), STRUCT(3, "bar")]) TABLESAMPLE BERNOULLI (90 PERCENT) +SELECT * FROM UNNEST(ARRAY>[(1, "foo"), (3, "bar")]) TABLESAMPLE BERNOULLI (90 PERCENT) diff --git a/testdata/result/query/select_with_field_path.sql.txt b/testdata/result/query/select_with_field_path.sql.txt index e977ad18..3b8d53c2 100644 --- a/testdata/result/query/select_with_field_path.sql.txt +++ b/testdata/result/query/select_with_field_path.sql.txt @@ -212,11 +212,9 @@ WHERE A.z.a = 2 }, }, Values: []ast.Expr{ - &ast.StructLiteral{ - Struct: 0, + &ast.TupleStructLiteral{ Lparen: 206, Rparen: 223, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 207, @@ -229,11 +227,9 @@ WHERE A.z.a = 2 ValueEnd: 215, Value: "foo", }, - &ast.StructLiteral{ - Struct: 0, + &ast.TupleStructLiteral{ Lparen: 217, Rparen: 222, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 218, @@ -251,11 +247,9 @@ WHERE A.z.a = 2 }, }, }, - &ast.StructLiteral{ - Struct: 0, + &ast.TupleStructLiteral{ Lparen: 226, Rparen: 243, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 227, @@ -268,11 +262,9 @@ WHERE A.z.a = 2 ValueEnd: 235, Value: "bar", }, - &ast.StructLiteral{ - Struct: 0, + &ast.TupleStructLiteral{ Lparen: 237, Rparen: 242, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 238, @@ -357,4 +349,4 @@ WHERE A.z.a = 2 } --- SQL -SELECT A.x, A.y, A.z.a, A.z.b FROM UNNEST(ARRAY(SELECT AS STRUCT x, y, z FROM UNNEST(ARRAY>>[STRUCT(1, "foo", STRUCT(2, 3)), STRUCT(3, "bar", STRUCT(4, 5))]))) AS A WHERE A.z.a = 2 +SELECT A.x, A.y, A.z.a, A.z.b FROM UNNEST(ARRAY(SELECT AS STRUCT x, y, z FROM UNNEST(ARRAY>>[(1, "foo", (2, 3)), (3, "bar", (4, 5))]))) AS A WHERE A.z.a = 2 diff --git a/testdata/result/statement/insert_select.sql.txt b/testdata/result/statement/insert_select.sql.txt index cc71ca16..6afe8c7c 100644 --- a/testdata/result/statement/insert_select.sql.txt +++ b/testdata/result/statement/insert_select.sql.txt @@ -43,11 +43,9 @@ select * from unnest([(1, 2), (3, 4)]) Rbrack: 58, Type: nil, Values: []ast.Expr{ - &ast.StructLiteral{ - Struct: 0, + &ast.TupleStructLiteral{ Lparen: 44, Rparen: 49, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 45, @@ -63,11 +61,9 @@ select * from unnest([(1, 2), (3, 4)]) }, }, }, - &ast.StructLiteral{ - Struct: 0, + &ast.TupleStructLiteral{ Lparen: 52, Rparen: 57, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 53, @@ -101,4 +97,4 @@ select * from unnest([(1, 2), (3, 4)]) } --- SQL -INSERT INTO foo (foo, bar) SELECT * FROM UNNEST([STRUCT(1, 2), STRUCT(3, 4)]) +INSERT INTO foo (foo, bar) SELECT * FROM UNNEST([(1, 2), (3, 4)]) diff --git a/testdata/result/statement/select_array_with_struct.sql.txt b/testdata/result/statement/select_array_with_struct.sql.txt index 28c893b2..32f645d4 100644 --- a/testdata/result/statement/select_array_with_struct.sql.txt +++ b/testdata/result/statement/select_array_with_struct.sql.txt @@ -55,11 +55,9 @@ FROM }, }, Values: []ast.Expr{ - &ast.StructLiteral{ - Struct: 0, + &ast.TupleStructLiteral{ Lparen: 58, Rparen: 67, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 59, @@ -74,11 +72,9 @@ FROM }, }, }, - &ast.StructLiteral{ - Struct: 0, + &ast.TupleStructLiteral{ Lparen: 70, Rparen: 79, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 71, @@ -110,4 +106,4 @@ FROM } --- SQL -SELECT * FROM UNNEST(ARRAY>[STRUCT(1, "foo"), STRUCT(3, "bar")]) +SELECT * FROM UNNEST(ARRAY>[(1, "foo"), (3, "bar")]) diff --git a/testdata/result/statement/select_cast.sql.txt b/testdata/result/statement/select_cast.sql.txt index d5f6fb96..d104b8e8 100644 --- a/testdata/result/statement/select_cast.sql.txt +++ b/testdata/result/statement/select_cast.sql.txt @@ -52,18 +52,14 @@ limit cast(1 as INT64) offset cast(@foo as INT64) Cast: 47, Rparen: 147, Safe: false, - Expr: &ast.StructLiteral{ - Struct: 0, + Expr: &ast.TupleStructLiteral{ Lparen: 52, Rparen: 84, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ - &ast.StructLiteral{ + &ast.TypelessStructLiteral{ Struct: 53, - Lparen: 59, Rparen: 60, - Fields: []*ast.StructField(nil), - Values: []ast.Expr(nil), + Values: []*ast.TypelessStructValue(nil), }, &ast.IntLiteral{ ValuePos: 63, @@ -300,4 +296,4 @@ limit cast(1 as INT64) offset cast(@foo as INT64) } --- SQL -SELECT CAST(1 AS INT64), CAST(0.1 AS FLOAT32), CAST(STRUCT(STRUCT(), 1, [2, 3], ["4", "5"]) AS STRUCT, x INT64, y ARRAY, z ARRAY>) FROM x TABLESAMPLE BERNOULLI (CAST(0.1 AS FLOAT64) PERCENT), y TABLESAMPLE BERNOULLI (CAST(1 AS INT64) ROWS), z TABLESAMPLE BERNOULLI (CAST(@param AS INT64) ROWS) LIMIT CAST(1 AS INT64) OFFSET CAST(@foo AS INT64) +SELECT CAST(1 AS INT64), CAST(0.1 AS FLOAT32), CAST((STRUCT(), 1, [2, 3], ["4", "5"]) AS STRUCT, x INT64, y ARRAY, z ARRAY>) FROM x TABLESAMPLE BERNOULLI (CAST(0.1 AS FLOAT64) PERCENT), y TABLESAMPLE BERNOULLI (CAST(1 AS INT64) ROWS), z TABLESAMPLE BERNOULLI (CAST(@param AS INT64) ROWS) LIMIT CAST(1 AS INT64) OFFSET CAST(@foo AS INT64) diff --git a/testdata/result/statement/select_from_implicit_unnest.sql.txt b/testdata/result/statement/select_from_implicit_unnest.sql.txt index 6cea9889..e29c72a3 100644 --- a/testdata/result/statement/select_from_implicit_unnest.sql.txt +++ b/testdata/result/statement/select_from_implicit_unnest.sql.txt @@ -41,9 +41,8 @@ FROM UNNEST([STRUCT>(["foo"])]) AS t, Rbrack: 61, Type: nil, Values: []ast.Expr{ - &ast.StructLiteral{ + &ast.TypedStructLiteral{ Struct: 27, - Lparen: 52, Rparen: 60, Fields: []*ast.StructField{ &ast.StructField{ diff --git a/testdata/result/statement/select_literals_all.sql.txt b/testdata/result/statement/select_literals_all.sql.txt index 3e35cc34..f92e62d1 100644 --- a/testdata/result/statement/select_literals_all.sql.txt +++ b/testdata/result/statement/select_literals_all.sql.txt @@ -392,29 +392,36 @@ lines''', As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ - Expr: &ast.StructLiteral{ + Expr: &ast.TypelessStructLiteral{ Struct: 467, - Lparen: 473, Rparen: 481, - Fields: []*ast.StructField(nil), - Values: []ast.Expr{ - &ast.IntLiteral{ - ValuePos: 474, - ValueEnd: 475, - Base: 10, - Value: "1", + Values: []*ast.TypelessStructValue{ + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 474, + ValueEnd: 475, + Base: 10, + Value: "1", + }, + Name: (*ast.Ident)(nil), }, - &ast.IntLiteral{ - ValuePos: 477, - ValueEnd: 478, - Base: 10, - Value: "2", + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 477, + ValueEnd: 478, + Base: 10, + Value: "2", + }, + Name: (*ast.Ident)(nil), }, - &ast.IntLiteral{ - ValuePos: 480, - ValueEnd: 481, - Base: 10, - Value: "3", + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 480, + ValueEnd: 481, + Base: 10, + Value: "3", + }, + Name: (*ast.Ident)(nil), }, }, }, @@ -439,11 +446,9 @@ lines''', As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ - Expr: &ast.StructLiteral{ - Struct: 0, + Expr: &ast.TupleStructLiteral{ Lparen: 500, Rparen: 508, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 501, @@ -635,4 +640,4 @@ lines''', } --- SQL -SELECT "abc", "it\'s", "it\'s", "Title: \"Boy\"", "abc", "it\'s", "Title:\"Boy\"", "two\nlines", "why\?", "abc+", "abc+", "abc+", "f\\(abc,(.*),def\\)", B"abc", B"abc", B"abc", B"abc+", B"abc+", B"abc", 123, 0xABC, -123, -0xABC, 123.456e-67, .1E4, 58., 4e2, [1, 2, 3], ["x", "y", "xy"], ARRAY[1, 2, 3], ARRAY["x", "y", "xy"], ARRAY[], ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, 3)), DATE "2014-09-27", DATE("2014-09-27"), TIMESTAMP "2014-09-27 12:30:00.45-08", TIMESTAMP "2014-09-27 12:30:00.45 America/Los_Angeles", TIMESTAMP "2014-09-27", TIMESTAMP("2014-09-27"), JSON "1", JSON "[1, 2]", JSON "{}", NUMERIC "0", NUMERIC "0", TRUE, FALSE +SELECT "abc", "it\'s", "it\'s", "Title: \"Boy\"", "abc", "it\'s", "Title:\"Boy\"", "two\nlines", "why\?", "abc+", "abc+", "abc+", "f\\(abc,(.*),def\\)", B"abc", B"abc", B"abc", B"abc+", B"abc+", B"abc", 123, 0xABC, -123, -0xABC, 123.456e-67, .1E4, 58., 4e2, [1, 2, 3], ["x", "y", "xy"], ARRAY[1, 2, 3], ARRAY["x", "y", "xy"], ARRAY[], ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT (1, 2, 3)), DATE "2014-09-27", DATE("2014-09-27"), TIMESTAMP "2014-09-27 12:30:00.45-08", TIMESTAMP "2014-09-27 12:30:00.45 America/Los_Angeles", TIMESTAMP "2014-09-27", TIMESTAMP("2014-09-27"), JSON "1", JSON "[1, 2]", JSON "{}", NUMERIC "0", NUMERIC "0", TRUE, FALSE diff --git a/testdata/result/statement/select_literals_struct.sql.txt b/testdata/result/statement/select_literals_struct.sql.txt index 802fb1e0..272a9b5d 100644 --- a/testdata/result/statement/select_literals_struct.sql.txt +++ b/testdata/result/statement/select_literals_struct.sql.txt @@ -28,29 +28,36 @@ SELECT As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ - Expr: &ast.StructLiteral{ + Expr: &ast.TypelessStructLiteral{ Struct: 22, - Lparen: 28, Rparen: 36, - Fields: []*ast.StructField(nil), - Values: []ast.Expr{ - &ast.IntLiteral{ - ValuePos: 29, - ValueEnd: 30, - Base: 10, - Value: "1", + Values: []*ast.TypelessStructValue{ + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 29, + ValueEnd: 30, + Base: 10, + Value: "1", + }, + Name: (*ast.Ident)(nil), }, - &ast.IntLiteral{ - ValuePos: 32, - ValueEnd: 33, - Base: 10, - Value: "2", + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 32, + ValueEnd: 33, + Base: 10, + Value: "2", + }, + Name: (*ast.Ident)(nil), }, - &ast.IntLiteral{ - ValuePos: 35, - ValueEnd: 36, - Base: 10, - Value: "3", + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 35, + ValueEnd: 36, + Base: 10, + Value: "3", + }, + Name: (*ast.Ident)(nil), }, }, }, @@ -75,27 +82,34 @@ SELECT As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ - Expr: &ast.StructLiteral{ + Expr: &ast.TypelessStructLiteral{ Struct: 55, - Lparen: 61, Rparen: 72, - Fields: []*ast.StructField(nil), - Values: []ast.Expr{ - &ast.IntLiteral{ - ValuePos: 62, - ValueEnd: 63, - Base: 10, - Value: "1", + Values: []*ast.TypelessStructValue{ + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 62, + ValueEnd: 63, + Base: 10, + Value: "1", + }, + Name: (*ast.Ident)(nil), }, - &ast.IntLiteral{ - ValuePos: 65, - ValueEnd: 66, - Base: 10, - Value: "2", + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 65, + ValueEnd: 66, + Base: 10, + Value: "2", + }, + Name: (*ast.Ident)(nil), }, - &ast.BoolLiteral{ - ValuePos: 68, - Value: true, + &ast.TypelessStructValue{ + Expr: &ast.BoolLiteral{ + ValuePos: 68, + Value: true, + }, + Name: (*ast.Ident)(nil), }, }, }, @@ -120,9 +134,8 @@ SELECT As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ - Expr: &ast.StructLiteral{ + Expr: &ast.TypedStructLiteral{ Struct: 91, - Lparen: 124, Rparen: 132, Fields: []*ast.StructField{ &ast.StructField{ @@ -201,9 +214,8 @@ SELECT As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ - Expr: &ast.StructLiteral{ + Expr: &ast.TypedStructLiteral{ Struct: 151, - Lparen: 178, Rparen: 186, Fields: []*ast.StructField{ &ast.StructField{ @@ -270,9 +282,8 @@ SELECT As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ - Expr: &ast.StructLiteral{ + Expr: &ast.TypedStructLiteral{ Struct: 205, - Lparen: 234, Rparen: 242, Fields: []*ast.StructField{ &ast.StructField{ @@ -343,11 +354,9 @@ SELECT As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ - Expr: &ast.StructLiteral{ - Struct: 0, + Expr: &ast.TupleStructLiteral{ Lparen: 261, Rparen: 269, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 262, @@ -390,9 +399,8 @@ SELECT As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ - Expr: &ast.StructLiteral{ + Expr: &ast.TypedStructLiteral{ Struct: 288, - Lparen: 296, Rparen: 297, Fields: []*ast.StructField{}, Values: []ast.Expr(nil), @@ -419,11 +427,9 @@ SELECT As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ - Expr: &ast.StructLiteral{ - Struct: 0, + Expr: &ast.TupleStructLiteral{ Lparen: 317, Rparen: 322, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 318, @@ -461,4 +467,4 @@ SELECT } --- SQL -SELECT ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, TRUE)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT<>()), EXISTS(SELECT STRUCT(1, 2)) +SELECT ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, TRUE)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT (1, 2, 3)), ARRAY(SELECT STRUCT<>()), EXISTS(SELECT (1, 2)) diff --git a/testdata/result/statement/select_struct_compare_eq.sql.txt b/testdata/result/statement/select_struct_compare_eq.sql.txt index 0ecdcbf5..ca4bcf5a 100644 --- a/testdata/result/statement/select_struct_compare_eq.sql.txt +++ b/testdata/result/statement/select_struct_compare_eq.sql.txt @@ -40,9 +40,8 @@ SELECT ARRAY( As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ - Expr: &ast.StructLiteral{ + Expr: &ast.TypedStructLiteral{ Struct: 48, - Lparen: 81, Rparen: 89, Fields: []*ast.StructField{ &ast.StructField{ @@ -129,37 +128,45 @@ SELECT ARRAY( NameEnd: 106, Name: "S", }, - Right: &ast.StructLiteral{ + Right: &ast.TypelessStructLiteral{ Struct: 109, - Lparen: 115, Rparen: 131, - Fields: []*ast.StructField(nil), - Values: []ast.Expr{ - &ast.StructLiteral{ - Struct: 116, - Lparen: 122, - Rparen: 130, - Fields: []*ast.StructField(nil), - Values: []ast.Expr{ - &ast.IntLiteral{ - ValuePos: 123, - ValueEnd: 124, - Base: 10, - Value: "1", - }, - &ast.IntLiteral{ - ValuePos: 126, - ValueEnd: 127, - Base: 10, - Value: "2", - }, - &ast.IntLiteral{ - ValuePos: 129, - ValueEnd: 130, - Base: 10, - Value: "3", + Values: []*ast.TypelessStructValue{ + &ast.TypelessStructValue{ + Expr: &ast.TypelessStructLiteral{ + Struct: 116, + Rparen: 130, + Values: []*ast.TypelessStructValue{ + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 123, + ValueEnd: 124, + Base: 10, + Value: "1", + }, + Name: (*ast.Ident)(nil), + }, + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 126, + ValueEnd: 127, + Base: 10, + Value: "2", + }, + Name: (*ast.Ident)(nil), + }, + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 129, + ValueEnd: 130, + Base: 10, + Value: "3", + }, + Name: (*ast.Ident)(nil), + }, }, }, + Name: (*ast.Ident)(nil), }, }, }, diff --git a/testdata/result/statement/select_tablesample_with_unnest_invalid.sql.txt b/testdata/result/statement/select_tablesample_with_unnest_invalid.sql.txt index 397274f3..44d34a87 100644 --- a/testdata/result/statement/select_tablesample_with_unnest_invalid.sql.txt +++ b/testdata/result/statement/select_tablesample_with_unnest_invalid.sql.txt @@ -55,11 +55,9 @@ FROM }, }, Values: []ast.Expr{ - &ast.StructLiteral{ - Struct: 0, + &ast.TupleStructLiteral{ Lparen: 58, Rparen: 67, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 59, @@ -74,11 +72,9 @@ FROM }, }, }, - &ast.StructLiteral{ - Struct: 0, + &ast.TupleStructLiteral{ Lparen: 70, Rparen: 79, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 71, @@ -124,4 +120,4 @@ FROM } --- SQL -SELECT * FROM UNNEST(ARRAY>[STRUCT(1, "foo"), STRUCT(3, "bar")]) TABLESAMPLE BERNOULLI (90 PERCENT) +SELECT * FROM UNNEST(ARRAY>[(1, "foo"), (3, "bar")]) TABLESAMPLE BERNOULLI (90 PERCENT) diff --git a/testdata/result/statement/select_with_field_path.sql.txt b/testdata/result/statement/select_with_field_path.sql.txt index e977ad18..3b8d53c2 100644 --- a/testdata/result/statement/select_with_field_path.sql.txt +++ b/testdata/result/statement/select_with_field_path.sql.txt @@ -212,11 +212,9 @@ WHERE A.z.a = 2 }, }, Values: []ast.Expr{ - &ast.StructLiteral{ - Struct: 0, + &ast.TupleStructLiteral{ Lparen: 206, Rparen: 223, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 207, @@ -229,11 +227,9 @@ WHERE A.z.a = 2 ValueEnd: 215, Value: "foo", }, - &ast.StructLiteral{ - Struct: 0, + &ast.TupleStructLiteral{ Lparen: 217, Rparen: 222, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 218, @@ -251,11 +247,9 @@ WHERE A.z.a = 2 }, }, }, - &ast.StructLiteral{ - Struct: 0, + &ast.TupleStructLiteral{ Lparen: 226, Rparen: 243, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 227, @@ -268,11 +262,9 @@ WHERE A.z.a = 2 ValueEnd: 235, Value: "bar", }, - &ast.StructLiteral{ - Struct: 0, + &ast.TupleStructLiteral{ Lparen: 237, Rparen: 242, - Fields: []*ast.StructField(nil), Values: []ast.Expr{ &ast.IntLiteral{ ValuePos: 238, @@ -357,4 +349,4 @@ WHERE A.z.a = 2 } --- SQL -SELECT A.x, A.y, A.z.a, A.z.b FROM UNNEST(ARRAY(SELECT AS STRUCT x, y, z FROM UNNEST(ARRAY>>[STRUCT(1, "foo", STRUCT(2, 3)), STRUCT(3, "bar", STRUCT(4, 5))]))) AS A WHERE A.z.a = 2 +SELECT A.x, A.y, A.z.a, A.z.b FROM UNNEST(ARRAY(SELECT AS STRUCT x, y, z FROM UNNEST(ARRAY>>[(1, "foo", (2, 3)), (3, "bar", (4, 5))]))) AS A WHERE A.z.a = 2 From 432cdf0f15ba59d30f5cc44eab1fe3bb2c1f8685 Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Sun, 27 Oct 2024 00:10:19 +0900 Subject: [PATCH 15/22] Update testdata --- .../input/query/select_literals_struct.sql | 7 + .../query/select_literals_struct.sql.txt | 429 +++++++++++++++--- .../statement/select_literals_struct.sql.txt | 429 +++++++++++++++--- 3 files changed, 757 insertions(+), 108 deletions(-) diff --git a/testdata/input/query/select_literals_struct.sql b/testdata/input/query/select_literals_struct.sql index d939f987..bd447750 100644 --- a/testdata/input/query/select_literals_struct.sql +++ b/testdata/input/query/select_literals_struct.sql @@ -2,8 +2,15 @@ SELECT ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, TRUE)), ARRAY(SELECT STRUCT(1, 2, 3)), + ARRAY(SELECT STRUCT(1 AS X, 2 AS Y, 3 AS Z)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, 3)), + ARRAY(SELECT STRUCT(1 AS X, 2, 3)), ARRAY(SELECT (1, 2, 3)), + ARRAY(SELECT STRUCT(1)), + ARRAY(SELECT STRUCT(1 AS X)), + ARRAY(SELECT STRUCT(1)), + ARRAY(SELECT STRUCT(1)), ARRAY(SELECT STRUCT<>()), + ARRAY(SELECT STRUCT()), EXISTS(SELECT (1, 2)) diff --git a/testdata/result/query/select_literals_struct.sql.txt b/testdata/result/query/select_literals_struct.sql.txt index 272a9b5d..ec0b9588 100644 --- a/testdata/result/query/select_literals_struct.sql.txt +++ b/testdata/result/query/select_literals_struct.sql.txt @@ -3,10 +3,17 @@ SELECT ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, TRUE)), ARRAY(SELECT STRUCT(1, 2, 3)), + ARRAY(SELECT STRUCT(1 AS X, 2 AS Y, 3 AS Z)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, 3)), + ARRAY(SELECT STRUCT(1 AS X, 2, 3)), ARRAY(SELECT (1, 2, 3)), + ARRAY(SELECT STRUCT(1)), + ARRAY(SELECT STRUCT(1 AS X)), + ARRAY(SELECT STRUCT(1)), + ARRAY(SELECT STRUCT(1)), ARRAY(SELECT STRUCT<>()), + ARRAY(SELECT STRUCT()), EXISTS(SELECT (1, 2)) --- AST @@ -207,55 +214,121 @@ SELECT &ast.ExprSelectItem{ Expr: &ast.ArraySubQuery{ Array: 138, - Rparen: 187, + Rparen: 181, Query: &ast.Select{ Select: 144, Distinct: false, As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ - Expr: &ast.TypedStructLiteral{ + Expr: &ast.TypelessStructLiteral{ Struct: 151, - Rparen: 186, + Rparen: 180, + Values: []*ast.TypelessStructValue{ + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 158, + ValueEnd: 159, + Base: 10, + Value: "1", + }, + Name: &ast.Ident{ + NamePos: 163, + NameEnd: 164, + Name: "X", + }, + }, + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 166, + ValueEnd: 167, + Base: 10, + Value: "2", + }, + Name: &ast.Ident{ + NamePos: 171, + NameEnd: 172, + Name: "Y", + }, + }, + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 174, + ValueEnd: 175, + Base: 10, + Value: "3", + }, + Name: &ast.Ident{ + NamePos: 179, + NameEnd: 180, + Name: "Z", + }, + }, + }, + }, + }, + }, + From: (*ast.From)(nil), + Where: (*ast.Where)(nil), + GroupBy: (*ast.GroupBy)(nil), + Having: (*ast.Having)(nil), + OrderBy: (*ast.OrderBy)(nil), + Limit: (*ast.Limit)(nil), + }, + }, + }, + &ast.ExprSelectItem{ + Expr: &ast.ArraySubQuery{ + Array: 186, + Rparen: 235, + Query: &ast.Select{ + Select: 192, + Distinct: false, + As: nil, + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.TypedStructLiteral{ + Struct: 199, + Rparen: 234, Fields: []*ast.StructField{ &ast.StructField{ Ident: (*ast.Ident)(nil), Type: &ast.SimpleType{ - NamePos: 158, + NamePos: 206, Name: "INT64", }, }, &ast.StructField{ Ident: (*ast.Ident)(nil), Type: &ast.SimpleType{ - NamePos: 165, + NamePos: 213, Name: "INT64", }, }, &ast.StructField{ Ident: (*ast.Ident)(nil), Type: &ast.SimpleType{ - NamePos: 172, + NamePos: 220, Name: "INT64", }, }, }, Values: []ast.Expr{ &ast.IntLiteral{ - ValuePos: 179, - ValueEnd: 180, + ValuePos: 227, + ValueEnd: 228, Base: 10, Value: "1", }, &ast.IntLiteral{ - ValuePos: 182, - ValueEnd: 183, + ValuePos: 230, + ValueEnd: 231, Base: 10, Value: "2", }, &ast.IntLiteral{ - ValuePos: 185, - ValueEnd: 186, + ValuePos: 233, + ValueEnd: 234, Base: 10, Value: "3", }, @@ -274,60 +347,60 @@ SELECT }, &ast.ExprSelectItem{ Expr: &ast.ArraySubQuery{ - Array: 192, - Rparen: 243, + Array: 240, + Rparen: 291, Query: &ast.Select{ - Select: 198, + Select: 246, Distinct: false, As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ Expr: &ast.TypedStructLiteral{ - Struct: 205, - Rparen: 242, + Struct: 253, + Rparen: 290, Fields: []*ast.StructField{ &ast.StructField{ Ident: &ast.Ident{ - NamePos: 212, - NameEnd: 213, + NamePos: 260, + NameEnd: 261, Name: "X", }, Type: &ast.SimpleType{ - NamePos: 214, + NamePos: 262, Name: "INT64", }, }, &ast.StructField{ Ident: (*ast.Ident)(nil), Type: &ast.SimpleType{ - NamePos: 221, + NamePos: 269, Name: "INT64", }, }, &ast.StructField{ Ident: (*ast.Ident)(nil), Type: &ast.SimpleType{ - NamePos: 228, + NamePos: 276, Name: "INT64", }, }, }, Values: []ast.Expr{ &ast.IntLiteral{ - ValuePos: 235, - ValueEnd: 236, + ValuePos: 283, + ValueEnd: 284, Base: 10, Value: "1", }, &ast.IntLiteral{ - ValuePos: 238, - ValueEnd: 239, + ValuePos: 286, + ValueEnd: 287, Base: 10, Value: "2", }, &ast.IntLiteral{ - ValuePos: 241, - ValueEnd: 242, + ValuePos: 289, + ValueEnd: 290, Base: 10, Value: "3", }, @@ -346,33 +419,91 @@ SELECT }, &ast.ExprSelectItem{ Expr: &ast.ArraySubQuery{ - Array: 248, - Rparen: 270, + Array: 296, + Rparen: 329, Query: &ast.Select{ - Select: 254, + Select: 302, + Distinct: false, + As: nil, + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.TypelessStructLiteral{ + Struct: 309, + Rparen: 328, + Values: []*ast.TypelessStructValue{ + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 316, + ValueEnd: 317, + Base: 10, + Value: "1", + }, + Name: &ast.Ident{ + NamePos: 321, + NameEnd: 322, + Name: "X", + }, + }, + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 324, + ValueEnd: 325, + Base: 10, + Value: "2", + }, + Name: (*ast.Ident)(nil), + }, + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 327, + ValueEnd: 328, + Base: 10, + Value: "3", + }, + Name: (*ast.Ident)(nil), + }, + }, + }, + }, + }, + From: (*ast.From)(nil), + Where: (*ast.Where)(nil), + GroupBy: (*ast.GroupBy)(nil), + Having: (*ast.Having)(nil), + OrderBy: (*ast.OrderBy)(nil), + Limit: (*ast.Limit)(nil), + }, + }, + }, + &ast.ExprSelectItem{ + Expr: &ast.ArraySubQuery{ + Array: 334, + Rparen: 356, + Query: &ast.Select{ + Select: 340, Distinct: false, As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ Expr: &ast.TupleStructLiteral{ - Lparen: 261, - Rparen: 269, + Lparen: 347, + Rparen: 355, Values: []ast.Expr{ &ast.IntLiteral{ - ValuePos: 262, - ValueEnd: 263, + ValuePos: 348, + ValueEnd: 349, Base: 10, Value: "1", }, &ast.IntLiteral{ - ValuePos: 265, - ValueEnd: 266, + ValuePos: 351, + ValueEnd: 352, Base: 10, Value: "2", }, &ast.IntLiteral{ - ValuePos: 268, - ValueEnd: 269, + ValuePos: 354, + ValueEnd: 355, Base: 10, Value: "3", }, @@ -391,17 +522,181 @@ SELECT }, &ast.ExprSelectItem{ Expr: &ast.ArraySubQuery{ - Array: 275, - Rparen: 298, + Array: 361, + Rparen: 392, Query: &ast.Select{ - Select: 281, + Select: 367, Distinct: false, As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ Expr: &ast.TypedStructLiteral{ - Struct: 288, - Rparen: 297, + Struct: 374, + Rparen: 391, + Fields: []*ast.StructField{ + &ast.StructField{ + Ident: &ast.Ident{ + NamePos: 381, + NameEnd: 382, + Name: "X", + }, + Type: &ast.SimpleType{ + NamePos: 383, + Name: "INT64", + }, + }, + }, + Values: []ast.Expr{ + &ast.IntLiteral{ + ValuePos: 390, + ValueEnd: 391, + Base: 10, + Value: "1", + }, + }, + }, + }, + }, + From: (*ast.From)(nil), + Where: (*ast.Where)(nil), + GroupBy: (*ast.GroupBy)(nil), + Having: (*ast.Having)(nil), + OrderBy: (*ast.OrderBy)(nil), + Limit: (*ast.Limit)(nil), + }, + }, + }, + &ast.ExprSelectItem{ + Expr: &ast.ArraySubQuery{ + Array: 397, + Rparen: 424, + Query: &ast.Select{ + Select: 403, + Distinct: false, + As: nil, + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.TypelessStructLiteral{ + Struct: 410, + Rparen: 423, + Values: []*ast.TypelessStructValue{ + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 417, + ValueEnd: 418, + Base: 10, + Value: "1", + }, + Name: &ast.Ident{ + NamePos: 422, + NameEnd: 423, + Name: "X", + }, + }, + }, + }, + }, + }, + From: (*ast.From)(nil), + Where: (*ast.Where)(nil), + GroupBy: (*ast.GroupBy)(nil), + Having: (*ast.Having)(nil), + OrderBy: (*ast.OrderBy)(nil), + Limit: (*ast.Limit)(nil), + }, + }, + }, + &ast.ExprSelectItem{ + Expr: &ast.ArraySubQuery{ + Array: 429, + Rparen: 458, + Query: &ast.Select{ + Select: 435, + Distinct: false, + As: nil, + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.TypedStructLiteral{ + Struct: 442, + Rparen: 457, + Fields: []*ast.StructField{ + &ast.StructField{ + Ident: (*ast.Ident)(nil), + Type: &ast.SimpleType{ + NamePos: 449, + Name: "INT64", + }, + }, + }, + Values: []ast.Expr{ + &ast.IntLiteral{ + ValuePos: 456, + ValueEnd: 457, + Base: 10, + Value: "1", + }, + }, + }, + }, + }, + From: (*ast.From)(nil), + Where: (*ast.Where)(nil), + GroupBy: (*ast.GroupBy)(nil), + Having: (*ast.Having)(nil), + OrderBy: (*ast.OrderBy)(nil), + Limit: (*ast.Limit)(nil), + }, + }, + }, + &ast.ExprSelectItem{ + Expr: &ast.ArraySubQuery{ + Array: 463, + Rparen: 485, + Query: &ast.Select{ + Select: 469, + Distinct: false, + As: nil, + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.TypelessStructLiteral{ + Struct: 476, + Rparen: 484, + Values: []*ast.TypelessStructValue{ + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 483, + ValueEnd: 484, + Base: 10, + Value: "1", + }, + Name: (*ast.Ident)(nil), + }, + }, + }, + }, + }, + From: (*ast.From)(nil), + Where: (*ast.Where)(nil), + GroupBy: (*ast.GroupBy)(nil), + Having: (*ast.Having)(nil), + OrderBy: (*ast.OrderBy)(nil), + Limit: (*ast.Limit)(nil), + }, + }, + }, + &ast.ExprSelectItem{ + Expr: &ast.ArraySubQuery{ + Array: 490, + Rparen: 513, + Query: &ast.Select{ + Select: 496, + Distinct: false, + As: nil, + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.TypedStructLiteral{ + Struct: 503, + Rparen: 512, Fields: []*ast.StructField{}, Values: []ast.Expr(nil), }, @@ -416,30 +711,56 @@ SELECT }, }, }, + &ast.ExprSelectItem{ + Expr: &ast.ArraySubQuery{ + Array: 518, + Rparen: 539, + Query: &ast.Select{ + Select: 524, + Distinct: false, + As: nil, + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.TypelessStructLiteral{ + Struct: 531, + Rparen: 538, + Values: []*ast.TypelessStructValue(nil), + }, + }, + }, + From: (*ast.From)(nil), + Where: (*ast.Where)(nil), + GroupBy: (*ast.GroupBy)(nil), + Having: (*ast.Having)(nil), + OrderBy: (*ast.OrderBy)(nil), + Limit: (*ast.Limit)(nil), + }, + }, + }, &ast.ExprSelectItem{ Expr: &ast.ExistsSubQuery{ - Exists: 303, - Rparen: 323, + Exists: 544, + Rparen: 564, Hint: (*ast.Hint)(nil), Query: &ast.Select{ - Select: 310, + Select: 551, Distinct: false, As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ Expr: &ast.TupleStructLiteral{ - Lparen: 317, - Rparen: 322, + Lparen: 558, + Rparen: 563, Values: []ast.Expr{ &ast.IntLiteral{ - ValuePos: 318, - ValueEnd: 319, + ValuePos: 559, + ValueEnd: 560, Base: 10, Value: "1", }, &ast.IntLiteral{ - ValuePos: 321, - ValueEnd: 322, + ValuePos: 562, + ValueEnd: 563, Base: 10, Value: "2", }, @@ -467,4 +788,4 @@ SELECT } --- SQL -SELECT ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, TRUE)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT (1, 2, 3)), ARRAY(SELECT STRUCT<>()), EXISTS(SELECT (1, 2)) +SELECT ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, TRUE)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1 AS X, 2 AS Y, 3 AS Z)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1 AS X, 2, 3)), ARRAY(SELECT (1, 2, 3)), ARRAY(SELECT STRUCT(1)), ARRAY(SELECT STRUCT(1 AS X)), ARRAY(SELECT STRUCT(1)), ARRAY(SELECT STRUCT(1)), ARRAY(SELECT STRUCT<>()), ARRAY(SELECT STRUCT()), EXISTS(SELECT (1, 2)) diff --git a/testdata/result/statement/select_literals_struct.sql.txt b/testdata/result/statement/select_literals_struct.sql.txt index 272a9b5d..ec0b9588 100644 --- a/testdata/result/statement/select_literals_struct.sql.txt +++ b/testdata/result/statement/select_literals_struct.sql.txt @@ -3,10 +3,17 @@ SELECT ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, TRUE)), ARRAY(SELECT STRUCT(1, 2, 3)), + ARRAY(SELECT STRUCT(1 AS X, 2 AS Y, 3 AS Z)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, 3)), + ARRAY(SELECT STRUCT(1 AS X, 2, 3)), ARRAY(SELECT (1, 2, 3)), + ARRAY(SELECT STRUCT(1)), + ARRAY(SELECT STRUCT(1 AS X)), + ARRAY(SELECT STRUCT(1)), + ARRAY(SELECT STRUCT(1)), ARRAY(SELECT STRUCT<>()), + ARRAY(SELECT STRUCT()), EXISTS(SELECT (1, 2)) --- AST @@ -207,55 +214,121 @@ SELECT &ast.ExprSelectItem{ Expr: &ast.ArraySubQuery{ Array: 138, - Rparen: 187, + Rparen: 181, Query: &ast.Select{ Select: 144, Distinct: false, As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ - Expr: &ast.TypedStructLiteral{ + Expr: &ast.TypelessStructLiteral{ Struct: 151, - Rparen: 186, + Rparen: 180, + Values: []*ast.TypelessStructValue{ + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 158, + ValueEnd: 159, + Base: 10, + Value: "1", + }, + Name: &ast.Ident{ + NamePos: 163, + NameEnd: 164, + Name: "X", + }, + }, + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 166, + ValueEnd: 167, + Base: 10, + Value: "2", + }, + Name: &ast.Ident{ + NamePos: 171, + NameEnd: 172, + Name: "Y", + }, + }, + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 174, + ValueEnd: 175, + Base: 10, + Value: "3", + }, + Name: &ast.Ident{ + NamePos: 179, + NameEnd: 180, + Name: "Z", + }, + }, + }, + }, + }, + }, + From: (*ast.From)(nil), + Where: (*ast.Where)(nil), + GroupBy: (*ast.GroupBy)(nil), + Having: (*ast.Having)(nil), + OrderBy: (*ast.OrderBy)(nil), + Limit: (*ast.Limit)(nil), + }, + }, + }, + &ast.ExprSelectItem{ + Expr: &ast.ArraySubQuery{ + Array: 186, + Rparen: 235, + Query: &ast.Select{ + Select: 192, + Distinct: false, + As: nil, + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.TypedStructLiteral{ + Struct: 199, + Rparen: 234, Fields: []*ast.StructField{ &ast.StructField{ Ident: (*ast.Ident)(nil), Type: &ast.SimpleType{ - NamePos: 158, + NamePos: 206, Name: "INT64", }, }, &ast.StructField{ Ident: (*ast.Ident)(nil), Type: &ast.SimpleType{ - NamePos: 165, + NamePos: 213, Name: "INT64", }, }, &ast.StructField{ Ident: (*ast.Ident)(nil), Type: &ast.SimpleType{ - NamePos: 172, + NamePos: 220, Name: "INT64", }, }, }, Values: []ast.Expr{ &ast.IntLiteral{ - ValuePos: 179, - ValueEnd: 180, + ValuePos: 227, + ValueEnd: 228, Base: 10, Value: "1", }, &ast.IntLiteral{ - ValuePos: 182, - ValueEnd: 183, + ValuePos: 230, + ValueEnd: 231, Base: 10, Value: "2", }, &ast.IntLiteral{ - ValuePos: 185, - ValueEnd: 186, + ValuePos: 233, + ValueEnd: 234, Base: 10, Value: "3", }, @@ -274,60 +347,60 @@ SELECT }, &ast.ExprSelectItem{ Expr: &ast.ArraySubQuery{ - Array: 192, - Rparen: 243, + Array: 240, + Rparen: 291, Query: &ast.Select{ - Select: 198, + Select: 246, Distinct: false, As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ Expr: &ast.TypedStructLiteral{ - Struct: 205, - Rparen: 242, + Struct: 253, + Rparen: 290, Fields: []*ast.StructField{ &ast.StructField{ Ident: &ast.Ident{ - NamePos: 212, - NameEnd: 213, + NamePos: 260, + NameEnd: 261, Name: "X", }, Type: &ast.SimpleType{ - NamePos: 214, + NamePos: 262, Name: "INT64", }, }, &ast.StructField{ Ident: (*ast.Ident)(nil), Type: &ast.SimpleType{ - NamePos: 221, + NamePos: 269, Name: "INT64", }, }, &ast.StructField{ Ident: (*ast.Ident)(nil), Type: &ast.SimpleType{ - NamePos: 228, + NamePos: 276, Name: "INT64", }, }, }, Values: []ast.Expr{ &ast.IntLiteral{ - ValuePos: 235, - ValueEnd: 236, + ValuePos: 283, + ValueEnd: 284, Base: 10, Value: "1", }, &ast.IntLiteral{ - ValuePos: 238, - ValueEnd: 239, + ValuePos: 286, + ValueEnd: 287, Base: 10, Value: "2", }, &ast.IntLiteral{ - ValuePos: 241, - ValueEnd: 242, + ValuePos: 289, + ValueEnd: 290, Base: 10, Value: "3", }, @@ -346,33 +419,91 @@ SELECT }, &ast.ExprSelectItem{ Expr: &ast.ArraySubQuery{ - Array: 248, - Rparen: 270, + Array: 296, + Rparen: 329, Query: &ast.Select{ - Select: 254, + Select: 302, + Distinct: false, + As: nil, + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.TypelessStructLiteral{ + Struct: 309, + Rparen: 328, + Values: []*ast.TypelessStructValue{ + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 316, + ValueEnd: 317, + Base: 10, + Value: "1", + }, + Name: &ast.Ident{ + NamePos: 321, + NameEnd: 322, + Name: "X", + }, + }, + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 324, + ValueEnd: 325, + Base: 10, + Value: "2", + }, + Name: (*ast.Ident)(nil), + }, + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 327, + ValueEnd: 328, + Base: 10, + Value: "3", + }, + Name: (*ast.Ident)(nil), + }, + }, + }, + }, + }, + From: (*ast.From)(nil), + Where: (*ast.Where)(nil), + GroupBy: (*ast.GroupBy)(nil), + Having: (*ast.Having)(nil), + OrderBy: (*ast.OrderBy)(nil), + Limit: (*ast.Limit)(nil), + }, + }, + }, + &ast.ExprSelectItem{ + Expr: &ast.ArraySubQuery{ + Array: 334, + Rparen: 356, + Query: &ast.Select{ + Select: 340, Distinct: false, As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ Expr: &ast.TupleStructLiteral{ - Lparen: 261, - Rparen: 269, + Lparen: 347, + Rparen: 355, Values: []ast.Expr{ &ast.IntLiteral{ - ValuePos: 262, - ValueEnd: 263, + ValuePos: 348, + ValueEnd: 349, Base: 10, Value: "1", }, &ast.IntLiteral{ - ValuePos: 265, - ValueEnd: 266, + ValuePos: 351, + ValueEnd: 352, Base: 10, Value: "2", }, &ast.IntLiteral{ - ValuePos: 268, - ValueEnd: 269, + ValuePos: 354, + ValueEnd: 355, Base: 10, Value: "3", }, @@ -391,17 +522,181 @@ SELECT }, &ast.ExprSelectItem{ Expr: &ast.ArraySubQuery{ - Array: 275, - Rparen: 298, + Array: 361, + Rparen: 392, Query: &ast.Select{ - Select: 281, + Select: 367, Distinct: false, As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ Expr: &ast.TypedStructLiteral{ - Struct: 288, - Rparen: 297, + Struct: 374, + Rparen: 391, + Fields: []*ast.StructField{ + &ast.StructField{ + Ident: &ast.Ident{ + NamePos: 381, + NameEnd: 382, + Name: "X", + }, + Type: &ast.SimpleType{ + NamePos: 383, + Name: "INT64", + }, + }, + }, + Values: []ast.Expr{ + &ast.IntLiteral{ + ValuePos: 390, + ValueEnd: 391, + Base: 10, + Value: "1", + }, + }, + }, + }, + }, + From: (*ast.From)(nil), + Where: (*ast.Where)(nil), + GroupBy: (*ast.GroupBy)(nil), + Having: (*ast.Having)(nil), + OrderBy: (*ast.OrderBy)(nil), + Limit: (*ast.Limit)(nil), + }, + }, + }, + &ast.ExprSelectItem{ + Expr: &ast.ArraySubQuery{ + Array: 397, + Rparen: 424, + Query: &ast.Select{ + Select: 403, + Distinct: false, + As: nil, + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.TypelessStructLiteral{ + Struct: 410, + Rparen: 423, + Values: []*ast.TypelessStructValue{ + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 417, + ValueEnd: 418, + Base: 10, + Value: "1", + }, + Name: &ast.Ident{ + NamePos: 422, + NameEnd: 423, + Name: "X", + }, + }, + }, + }, + }, + }, + From: (*ast.From)(nil), + Where: (*ast.Where)(nil), + GroupBy: (*ast.GroupBy)(nil), + Having: (*ast.Having)(nil), + OrderBy: (*ast.OrderBy)(nil), + Limit: (*ast.Limit)(nil), + }, + }, + }, + &ast.ExprSelectItem{ + Expr: &ast.ArraySubQuery{ + Array: 429, + Rparen: 458, + Query: &ast.Select{ + Select: 435, + Distinct: false, + As: nil, + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.TypedStructLiteral{ + Struct: 442, + Rparen: 457, + Fields: []*ast.StructField{ + &ast.StructField{ + Ident: (*ast.Ident)(nil), + Type: &ast.SimpleType{ + NamePos: 449, + Name: "INT64", + }, + }, + }, + Values: []ast.Expr{ + &ast.IntLiteral{ + ValuePos: 456, + ValueEnd: 457, + Base: 10, + Value: "1", + }, + }, + }, + }, + }, + From: (*ast.From)(nil), + Where: (*ast.Where)(nil), + GroupBy: (*ast.GroupBy)(nil), + Having: (*ast.Having)(nil), + OrderBy: (*ast.OrderBy)(nil), + Limit: (*ast.Limit)(nil), + }, + }, + }, + &ast.ExprSelectItem{ + Expr: &ast.ArraySubQuery{ + Array: 463, + Rparen: 485, + Query: &ast.Select{ + Select: 469, + Distinct: false, + As: nil, + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.TypelessStructLiteral{ + Struct: 476, + Rparen: 484, + Values: []*ast.TypelessStructValue{ + &ast.TypelessStructValue{ + Expr: &ast.IntLiteral{ + ValuePos: 483, + ValueEnd: 484, + Base: 10, + Value: "1", + }, + Name: (*ast.Ident)(nil), + }, + }, + }, + }, + }, + From: (*ast.From)(nil), + Where: (*ast.Where)(nil), + GroupBy: (*ast.GroupBy)(nil), + Having: (*ast.Having)(nil), + OrderBy: (*ast.OrderBy)(nil), + Limit: (*ast.Limit)(nil), + }, + }, + }, + &ast.ExprSelectItem{ + Expr: &ast.ArraySubQuery{ + Array: 490, + Rparen: 513, + Query: &ast.Select{ + Select: 496, + Distinct: false, + As: nil, + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.TypedStructLiteral{ + Struct: 503, + Rparen: 512, Fields: []*ast.StructField{}, Values: []ast.Expr(nil), }, @@ -416,30 +711,56 @@ SELECT }, }, }, + &ast.ExprSelectItem{ + Expr: &ast.ArraySubQuery{ + Array: 518, + Rparen: 539, + Query: &ast.Select{ + Select: 524, + Distinct: false, + As: nil, + Results: []ast.SelectItem{ + &ast.ExprSelectItem{ + Expr: &ast.TypelessStructLiteral{ + Struct: 531, + Rparen: 538, + Values: []*ast.TypelessStructValue(nil), + }, + }, + }, + From: (*ast.From)(nil), + Where: (*ast.Where)(nil), + GroupBy: (*ast.GroupBy)(nil), + Having: (*ast.Having)(nil), + OrderBy: (*ast.OrderBy)(nil), + Limit: (*ast.Limit)(nil), + }, + }, + }, &ast.ExprSelectItem{ Expr: &ast.ExistsSubQuery{ - Exists: 303, - Rparen: 323, + Exists: 544, + Rparen: 564, Hint: (*ast.Hint)(nil), Query: &ast.Select{ - Select: 310, + Select: 551, Distinct: false, As: nil, Results: []ast.SelectItem{ &ast.ExprSelectItem{ Expr: &ast.TupleStructLiteral{ - Lparen: 317, - Rparen: 322, + Lparen: 558, + Rparen: 563, Values: []ast.Expr{ &ast.IntLiteral{ - ValuePos: 318, - ValueEnd: 319, + ValuePos: 559, + ValueEnd: 560, Base: 10, Value: "1", }, &ast.IntLiteral{ - ValuePos: 321, - ValueEnd: 322, + ValuePos: 562, + ValueEnd: 563, Base: 10, Value: "2", }, @@ -467,4 +788,4 @@ SELECT } --- SQL -SELECT ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, TRUE)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT (1, 2, 3)), ARRAY(SELECT STRUCT<>()), EXISTS(SELECT (1, 2)) +SELECT ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, TRUE)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1 AS X, 2 AS Y, 3 AS Z)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1, 2, 3)), ARRAY(SELECT STRUCT(1 AS X, 2, 3)), ARRAY(SELECT (1, 2, 3)), ARRAY(SELECT STRUCT(1)), ARRAY(SELECT STRUCT(1 AS X)), ARRAY(SELECT STRUCT(1)), ARRAY(SELECT STRUCT(1)), ARRAY(SELECT STRUCT<>()), ARRAY(SELECT STRUCT()), EXISTS(SELECT (1, 2)) From 15804dfef731fa07a95a414e0bbeb191aa17fcdf Mon Sep 17 00:00:00 2001 From: apstndb <803393+apstndb@users.noreply.github.com> Date: Sun, 27 Oct 2024 09:28:15 +0900 Subject: [PATCH 16/22] Fix comment --- ast/ast.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ast/ast.go b/ast/ast.go index 037f538d..384467e8 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -1425,7 +1425,7 @@ type TypedStructLiteral struct { // end = Rparen + 1 Struct token.Pos // position of "STRUCT" - Rparen token.Pos // position of "(" and ")" + Rparen token.Pos // position of ")" Fields []*StructField Values []Expr From 64f804290f0d110b015d17441194bfbb6c644ded Mon Sep 17 00:00:00 2001 From: TSUYUSATO Kitsune Date: Sun, 27 Oct 2024 23:11:54 +0900 Subject: [PATCH 17/22] Introduce AsExpr instead of TypelessStructValue and NewConstructorValue --- ast/ast.go | 37 +++--- ast/pos.go | 24 ++-- ast/sql.go | 19 ++- parser.go | 108 ++++++++---------- testdata/result/expr/new_constructor.sql.txt | 28 ++--- .../result/expr/new_constructor_empty.sql.txt | 2 +- testdata/result/query/select_cast.sql.txt | 4 +- .../result/query/select_literals_all.sql.txt | 8 +- .../query/select_literals_struct.sql.txt | 44 +++---- .../query/select_struct_compare_eq.sql.txt | 12 +- testdata/result/statement/select_cast.sql.txt | 4 +- .../statement/select_literals_all.sql.txt | 8 +- .../statement/select_literals_struct.sql.txt | 44 +++---- .../select_struct_compare_eq.sql.txt | 12 +- 14 files changed, 159 insertions(+), 195 deletions(-) diff --git a/ast/ast.go b/ast/ast.go index 384467e8..f5537f6e 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -1393,23 +1393,24 @@ type TupleStructLiteral struct { Values []Expr // len(Values) > 1 } -// TypelessStructLiteral is typeless struct literal node. +// TypedStructLiteral is typed struct literal node. // -// STRUCT({{.Values | sqlJoin ","}}) -type TypelessStructLiteral struct { +// STRUCT<{{.Fields | sqlJoin ","}}>({{.Values | sqlJoin ","}}) +type TypedStructLiteral struct { // pos = Struct // end = Rparen + 1 Struct token.Pos // position of "STRUCT" Rparen token.Pos // position of ")" - Values []*TypelessStructValue + Fields []*StructField + Values []Expr } -// TypelessStructValue is value with optional name in typeless struct literal. +// AsExpr is value with optional name in typeless struct literal or new constructor. // -// {{.Expr | sql}}{{if .Name}} AS {{.Name | sql}}{{end}} -type TypelessStructValue struct { +// {{.Expr | sql}} {{if .Name}}AS {{.Name | sql}}{{end}} +type AsExpr struct { // pos = Expr.pos // end = (Name ?? Expr).end @@ -1417,18 +1418,17 @@ type TypelessStructValue struct { Name *Ident // optional } -// TypedStructLiteral is typed struct literal node. +// TypelessStructLiteral is typeless struct literal node. // -// STRUCT<{{.Fields | sqlJoin ","}}>({{.Values | sqlJoin ","}}) -type TypedStructLiteral struct { +// STRUCT({{.Values | sqlJoin ","}}) +type TypelessStructLiteral struct { // pos = Struct // end = Rparen + 1 Struct token.Pos // position of "STRUCT" Rparen token.Pos // position of ")" - Fields []*StructField - Values []Expr + Values []*AsExpr } // NullLiteral is just NULL literal. @@ -1565,17 +1565,6 @@ type BracedConstructorFieldValue interface { func (*BracedConstructor) isBracedConstructorFieldValue() {} func (*BracedConstructorFieldValueExpr) isBracedConstructorFieldValue() {} -// NewConstructorArg represents a single argument in NEW constructor. -// -// {{Expr | sql}} {{Alias | sqlOpt}} -type NewConstructorArg struct { - // pos = Expr.pos - // end = (Alias ?? Expr).end - - Expr Expr - Alias *AsAlias // optional -} - // NewConstructor represents NEW operator which creates a protocol buffer using a parenthesized list of arguments. // // NEW {{.Type | sql}} ({{.Args | sqlJoin ", "}}) @@ -1586,7 +1575,7 @@ type NewConstructor struct { New token.Pos Type *NamedType - Args []*NewConstructorArg + Args []*AsExpr Rparen token.Pos } diff --git a/ast/pos.go b/ast/pos.go index b7220932..78553de5 100644 --- a/ast/pos.go +++ b/ast/pos.go @@ -582,27 +582,27 @@ func (t *TupleStructLiteral) End() token.Pos { return posAdd(t.Rparen, 1) } -func (t *TypelessStructLiteral) Pos() token.Pos { +func (t *TypedStructLiteral) Pos() token.Pos { return t.Struct } -func (t *TypelessStructLiteral) End() token.Pos { +func (t *TypedStructLiteral) End() token.Pos { return posAdd(t.Rparen, 1) } -func (t *TypelessStructValue) Pos() token.Pos { - return nodePos(wrapNode(t.Expr)) +func (a *AsExpr) Pos() token.Pos { + return nodePos(wrapNode(a.Expr)) } -func (t *TypelessStructValue) End() token.Pos { - return nodeEnd(nodeChoice(wrapNode(t.Name), wrapNode(t.Expr))) +func (a *AsExpr) End() token.Pos { + return nodeEnd(nodeChoice(wrapNode(a.Name), wrapNode(a.Expr))) } -func (t *TypedStructLiteral) Pos() token.Pos { +func (t *TypelessStructLiteral) Pos() token.Pos { return t.Struct } -func (t *TypedStructLiteral) End() token.Pos { +func (t *TypelessStructLiteral) End() token.Pos { return posAdd(t.Rparen, 1) } @@ -686,14 +686,6 @@ func (j *JSONLiteral) End() token.Pos { return nodeEnd(wrapNode(j.Value)) } -func (n *NewConstructorArg) Pos() token.Pos { - return nodePos(wrapNode(n.Expr)) -} - -func (n *NewConstructorArg) End() token.Pos { - return nodeEnd(nodeChoice(wrapNode(n.Alias), wrapNode(n.Expr))) -} - func (n *NewConstructor) Pos() token.Pos { return n.New } diff --git a/ast/sql.go b/ast/sql.go index 71df8579..6946f2ae 100644 --- a/ast/sql.go +++ b/ast/sql.go @@ -1,9 +1,10 @@ package ast import ( - "github.com/cloudspannerecosystem/memefish/token" "strconv" "strings" + + "github.com/cloudspannerecosystem/memefish/token" ) // ================================================================================ @@ -618,16 +619,16 @@ func (s *TupleStructLiteral) SQL() string { return "(" + sqlJoin(s.Values, ", ") + ")" } -func (s *TypelessStructLiteral) SQL() string { - return strOpt(!s.Struct.Invalid(), "STRUCT") + "(" + sqlJoin(s.Values, ", ") + ")" +func (s *TypedStructLiteral) SQL() string { + return "STRUCT<" + sqlJoin(s.Fields, ", ") + ">(" + sqlJoin(s.Values, ", ") + ")" } -func (s *TypelessStructValue) SQL() string { - return s.Expr.SQL() + sqlOpt(" AS ", s.Name, "") +func (a *AsExpr) SQL() string { + return a.Expr.SQL() + sqlOpt(" AS ", a.Name, "") } -func (s *TypedStructLiteral) SQL() string { - return "STRUCT<" + sqlJoin(s.Fields, ", ") + ">(" + sqlJoin(s.Values, ", ") + ")" +func (s *TypelessStructLiteral) SQL() string { + return strOpt(!s.Struct.Invalid(), "STRUCT") + "(" + sqlJoin(s.Values, ", ") + ")" } func (*NullLiteral) SQL() string { @@ -680,10 +681,6 @@ func (t *JSONLiteral) SQL() string { // // ================================================================================ -func (n *NewConstructorArg) SQL() string { - return n.Expr.SQL() + sqlOpt(" ", n.Alias, "") -} - func (n *NewConstructor) SQL() string { return "NEW " + n.Type.SQL() + "(" + sqlJoin(n.Args, ", ") + ")" } diff --git a/parser.go b/parser.go index 0bc3f53b..653cbafc 100644 --- a/parser.go +++ b/parser.go @@ -804,7 +804,7 @@ func (p *Parser) parseSimpleTableExpr() ast.TableExpr { p.expect("(") expr := p.parseExpr() rparen := p.expect(")").Pos - return p.parseUnnestSuffix(false, expr, unnest, rparen) + return p.parseUnnestSuffix(expr, unnest, rparen) } if p.Token.Kind == token.TokenIdent { @@ -827,7 +827,7 @@ func (p *Parser) parseIdentOrPath() []*ast.Ident { return ids } -func (p *Parser) parseUnnestSuffix(implicit bool, expr ast.Expr, unnest, rparen token.Pos) ast.TableExpr { +func (p *Parser) parseUnnestSuffix(expr ast.Expr, unnest, rparen token.Pos) ast.TableExpr { hint := p.tryParseHint() as := p.tryParseAsAlias() withOffset := p.tryParseWithOffset() @@ -1818,17 +1818,17 @@ func (p *Parser) parseParenExpr() ast.Expr { } } -func (p *Parser) parseTypelessStructField() *ast.TypelessStructValue { +func (p *Parser) parseAsExpr() *ast.AsExpr { expr := p.parseExpr() if p.Token.Kind != "AS" { - return &ast.TypelessStructValue{Expr: expr} + return &ast.AsExpr{Expr: expr} } p.nextToken() - ident := p.parseIdent() - return &ast.TypelessStructValue{ + name := p.parseIdent() + return &ast.AsExpr{ Expr: expr, - Name: ident, + Name: name, } } @@ -1889,31 +1889,30 @@ func (p *Parser) parseArrayLiteralBody() (values []ast.Expr, lbrack, rbrack toke } func (p *Parser) parseStructLiteral() ast.Expr { - // tuple struct syntax is handled in parseParenExpr. + // Note that tuple struct syntax is handled in parseParenExpr. + pos := p.expect("STRUCT").Pos - fields, gt := p.tryParseStructTypeFields() - p.expect("(") + if p.Token.Kind == "<" || p.Token.Kind == "<>" { + return p.parseTypedStructLiteral(pos) + } - if gt.Invalid() { - // typeless - var values []*ast.TypelessStructValue - if p.Token.Kind != ")" { - values = parseCommaSeparatedList(p, p.parseTypelessStructField) - } - rparen := p.expect(")").Pos - return &ast.TypelessStructLiteral{ - Struct: pos, - Rparen: rparen, - Values: values, - } + if p.Token.Kind != "(" { + p.panicfAtToken(&p.Token, "expected token: <, <>, ( but: %s", p.Token.Kind) } - // typed + return p.parseTypelessStructLiteral(pos) +} + +func (p *Parser) parseTypedStructLiteral(pos token.Pos) *ast.TypedStructLiteral { + fields, _ := p.parseStructTypeFields() + + p.expect("(") var values []ast.Expr if p.Token.Kind != ")" { values = parseCommaSeparatedList(p, p.parseExpr) } rparen := p.expect(")").Pos + return &ast.TypedStructLiteral{ Struct: pos, Rparen: rparen, @@ -1922,6 +1921,21 @@ func (p *Parser) parseStructLiteral() ast.Expr { } } +func (p *Parser) parseTypelessStructLiteral(pos token.Pos) *ast.TypelessStructLiteral { + p.expect("(") + var values []*ast.AsExpr + if p.Token.Kind != ")" { + values = parseCommaSeparatedList(p, p.parseAsExpr) + } + rparen := p.expect(")").Pos + + return &ast.TypelessStructLiteral{ + Struct: pos, + Rparen: rparen, + Values: values, + } +} + func (p *Parser) parseDateLiteral(id token.Token) *ast.DateLiteral { s := p.parseStringLiteral() return &ast.DateLiteral{ @@ -2083,10 +2097,10 @@ func (p *Parser) parseArrayType() *ast.ArrayType { func (p *Parser) parseStructType() *ast.StructType { pos := p.expect("STRUCT").Pos - fields, gt := p.tryParseStructTypeFields() - if fields == nil { + if p.Token.Kind != "<" && p.Token.Kind != "<>" { p.panicfAtToken(&p.Token, "expected token: <, <>, but: %s", p.Token.Kind) } + fields, gt := p.parseStructTypeFields() return &ast.StructType{ Struct: pos, Gt: gt, @@ -2094,29 +2108,20 @@ func (p *Parser) parseStructType() *ast.StructType { } } -func (p *Parser) tryParseStructTypeFields() (fields []*ast.StructField, gt token.Pos) { - gt = token.InvalidPos - if p.Token.Kind != "<" && p.Token.Kind != "<>" { - return - } - - fields = make([]*ast.StructField, 0) +func (p *Parser) parseStructTypeFields() ([]*ast.StructField, token.Pos) { if p.Token.Kind == "<>" { - gt = p.expect("<>").Pos + 1 - return + gt := p.Token.Pos + 1 + p.nextToken() + return nil, gt } + var fields []*ast.StructField p.expect("<") if p.Token.Kind != ">" && p.Token.Kind != ">>" { - for p.Token.Kind != token.TokenEOF { - fields = append(fields, p.parseFieldType()) - if p.Token.Kind != "," { - break - } - p.nextToken() - } + fields = parseCommaSeparatedList(p, p.parseFieldType) } + var gt token.Pos if p.Token.Kind == ">>" { p.Token.Kind = ">" p.Token.Raw = ">" @@ -2125,30 +2130,17 @@ func (p *Parser) tryParseStructTypeFields() (fields []*ast.StructField, gt token } else { gt = p.expect(">").Pos } - return -} - -func (p *Parser) parseNewConstructorArg() *ast.NewConstructorArg { - expr := p.parseExpr() - - // Whole "AS alias" is optional, but "AS" keyword can't be omitted. - var alias *ast.AsAlias - if p.Token.Kind == "AS" { - alias = p.tryParseAsAlias() - } - return &ast.NewConstructorArg{ - Expr: expr, - Alias: alias, - } + return fields, gt } + func (p *Parser) parseNewConstructor(newPos token.Pos, namedType *ast.NamedType) *ast.NewConstructor { p.expect("(") // Args can be empty like `NEW pkg.TypeName ()`. - var args []*ast.NewConstructorArg + var args []*ast.AsExpr if p.Token.Kind != ")" { - args = parseCommaSeparatedList(p, p.parseNewConstructorArg) + args = parseCommaSeparatedList(p, p.parseAsExpr) } rparen := p.expect(")").Pos diff --git a/testdata/result/expr/new_constructor.sql.txt b/testdata/result/expr/new_constructor.sql.txt index de222c2d..b42d790c 100644 --- a/testdata/result/expr/new_constructor.sql.txt +++ b/testdata/result/expr/new_constructor.sql.txt @@ -27,35 +27,29 @@ NEW googlesql.examples.music.Chart(key AS rank, name AS chart_name) }, }, }, - Args: []*ast.NewConstructorArg{ - &ast.NewConstructorArg{ + Args: []*ast.AsExpr{ + &ast.AsExpr{ Expr: &ast.Ident{ NamePos: 35, NameEnd: 38, Name: "key", }, - Alias: &ast.AsAlias{ - As: -1, - Alias: &ast.Ident{ - NamePos: 42, - NameEnd: 46, - Name: "rank", - }, + Name: &ast.Ident{ + NamePos: 42, + NameEnd: 46, + Name: "rank", }, }, - &ast.NewConstructorArg{ + &ast.AsExpr{ Expr: &ast.Ident{ NamePos: 48, NameEnd: 52, Name: "name", }, - Alias: &ast.AsAlias{ - As: -1, - Alias: &ast.Ident{ - NamePos: 56, - NameEnd: 66, - Name: "chart_name", - }, + Name: &ast.Ident{ + NamePos: 56, + NameEnd: 66, + Name: "chart_name", }, }, }, diff --git a/testdata/result/expr/new_constructor_empty.sql.txt b/testdata/result/expr/new_constructor_empty.sql.txt index 11db9262..e2a8df5a 100644 --- a/testdata/result/expr/new_constructor_empty.sql.txt +++ b/testdata/result/expr/new_constructor_empty.sql.txt @@ -28,7 +28,7 @@ NEW googlesql.examples.music.Chart() }, }, }, - Args: []*ast.NewConstructorArg(nil), + Args: []*ast.AsExpr(nil), Rparen: 35, } diff --git a/testdata/result/query/select_cast.sql.txt b/testdata/result/query/select_cast.sql.txt index d104b8e8..71151fd9 100644 --- a/testdata/result/query/select_cast.sql.txt +++ b/testdata/result/query/select_cast.sql.txt @@ -59,7 +59,7 @@ limit cast(1 as INT64) offset cast(@foo as INT64) &ast.TypelessStructLiteral{ Struct: 53, Rparen: 60, - Values: []*ast.TypelessStructValue(nil), + Values: []*ast.AsExpr(nil), }, &ast.IntLiteral{ ValuePos: 63, @@ -116,7 +116,7 @@ limit cast(1 as INT64) offset cast(@foo as INT64) Type: &ast.StructType{ Struct: 96, Gt: 103, - Fields: []*ast.StructField{}, + Fields: []*ast.StructField(nil), }, }, &ast.StructField{ diff --git a/testdata/result/query/select_literals_all.sql.txt b/testdata/result/query/select_literals_all.sql.txt index f92e62d1..2557efd7 100644 --- a/testdata/result/query/select_literals_all.sql.txt +++ b/testdata/result/query/select_literals_all.sql.txt @@ -395,8 +395,8 @@ lines''', Expr: &ast.TypelessStructLiteral{ Struct: 467, Rparen: 481, - Values: []*ast.TypelessStructValue{ - &ast.TypelessStructValue{ + Values: []*ast.AsExpr{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 474, ValueEnd: 475, @@ -405,7 +405,7 @@ lines''', }, Name: (*ast.Ident)(nil), }, - &ast.TypelessStructValue{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 477, ValueEnd: 478, @@ -414,7 +414,7 @@ lines''', }, Name: (*ast.Ident)(nil), }, - &ast.TypelessStructValue{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 480, ValueEnd: 481, diff --git a/testdata/result/query/select_literals_struct.sql.txt b/testdata/result/query/select_literals_struct.sql.txt index ec0b9588..9ce6fc39 100644 --- a/testdata/result/query/select_literals_struct.sql.txt +++ b/testdata/result/query/select_literals_struct.sql.txt @@ -38,8 +38,8 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 22, Rparen: 36, - Values: []*ast.TypelessStructValue{ - &ast.TypelessStructValue{ + Values: []*ast.AsExpr{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 29, ValueEnd: 30, @@ -48,7 +48,7 @@ SELECT }, Name: (*ast.Ident)(nil), }, - &ast.TypelessStructValue{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 32, ValueEnd: 33, @@ -57,7 +57,7 @@ SELECT }, Name: (*ast.Ident)(nil), }, - &ast.TypelessStructValue{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 35, ValueEnd: 36, @@ -92,8 +92,8 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 55, Rparen: 72, - Values: []*ast.TypelessStructValue{ - &ast.TypelessStructValue{ + Values: []*ast.AsExpr{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 62, ValueEnd: 63, @@ -102,7 +102,7 @@ SELECT }, Name: (*ast.Ident)(nil), }, - &ast.TypelessStructValue{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 65, ValueEnd: 66, @@ -111,7 +111,7 @@ SELECT }, Name: (*ast.Ident)(nil), }, - &ast.TypelessStructValue{ + &ast.AsExpr{ Expr: &ast.BoolLiteral{ ValuePos: 68, Value: true, @@ -224,8 +224,8 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 151, Rparen: 180, - Values: []*ast.TypelessStructValue{ - &ast.TypelessStructValue{ + Values: []*ast.AsExpr{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 158, ValueEnd: 159, @@ -238,7 +238,7 @@ SELECT Name: "X", }, }, - &ast.TypelessStructValue{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 166, ValueEnd: 167, @@ -251,7 +251,7 @@ SELECT Name: "Y", }, }, - &ast.TypelessStructValue{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 174, ValueEnd: 175, @@ -430,8 +430,8 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 309, Rparen: 328, - Values: []*ast.TypelessStructValue{ - &ast.TypelessStructValue{ + Values: []*ast.AsExpr{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 316, ValueEnd: 317, @@ -444,7 +444,7 @@ SELECT Name: "X", }, }, - &ast.TypelessStructValue{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 324, ValueEnd: 325, @@ -453,7 +453,7 @@ SELECT }, Name: (*ast.Ident)(nil), }, - &ast.TypelessStructValue{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 327, ValueEnd: 328, @@ -579,8 +579,8 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 410, Rparen: 423, - Values: []*ast.TypelessStructValue{ - &ast.TypelessStructValue{ + Values: []*ast.AsExpr{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 417, ValueEnd: 418, @@ -661,8 +661,8 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 476, Rparen: 484, - Values: []*ast.TypelessStructValue{ - &ast.TypelessStructValue{ + Values: []*ast.AsExpr{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 483, ValueEnd: 484, @@ -697,7 +697,7 @@ SELECT Expr: &ast.TypedStructLiteral{ Struct: 503, Rparen: 512, - Fields: []*ast.StructField{}, + Fields: []*ast.StructField(nil), Values: []ast.Expr(nil), }, }, @@ -724,7 +724,7 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 531, Rparen: 538, - Values: []*ast.TypelessStructValue(nil), + Values: []*ast.AsExpr(nil), }, }, }, diff --git a/testdata/result/query/select_struct_compare_eq.sql.txt b/testdata/result/query/select_struct_compare_eq.sql.txt index ca4bcf5a..9d58a237 100644 --- a/testdata/result/query/select_struct_compare_eq.sql.txt +++ b/testdata/result/query/select_struct_compare_eq.sql.txt @@ -131,13 +131,13 @@ SELECT ARRAY( Right: &ast.TypelessStructLiteral{ Struct: 109, Rparen: 131, - Values: []*ast.TypelessStructValue{ - &ast.TypelessStructValue{ + Values: []*ast.AsExpr{ + &ast.AsExpr{ Expr: &ast.TypelessStructLiteral{ Struct: 116, Rparen: 130, - Values: []*ast.TypelessStructValue{ - &ast.TypelessStructValue{ + Values: []*ast.AsExpr{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 123, ValueEnd: 124, @@ -146,7 +146,7 @@ SELECT ARRAY( }, Name: (*ast.Ident)(nil), }, - &ast.TypelessStructValue{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 126, ValueEnd: 127, @@ -155,7 +155,7 @@ SELECT ARRAY( }, Name: (*ast.Ident)(nil), }, - &ast.TypelessStructValue{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 129, ValueEnd: 130, diff --git a/testdata/result/statement/select_cast.sql.txt b/testdata/result/statement/select_cast.sql.txt index d104b8e8..71151fd9 100644 --- a/testdata/result/statement/select_cast.sql.txt +++ b/testdata/result/statement/select_cast.sql.txt @@ -59,7 +59,7 @@ limit cast(1 as INT64) offset cast(@foo as INT64) &ast.TypelessStructLiteral{ Struct: 53, Rparen: 60, - Values: []*ast.TypelessStructValue(nil), + Values: []*ast.AsExpr(nil), }, &ast.IntLiteral{ ValuePos: 63, @@ -116,7 +116,7 @@ limit cast(1 as INT64) offset cast(@foo as INT64) Type: &ast.StructType{ Struct: 96, Gt: 103, - Fields: []*ast.StructField{}, + Fields: []*ast.StructField(nil), }, }, &ast.StructField{ diff --git a/testdata/result/statement/select_literals_all.sql.txt b/testdata/result/statement/select_literals_all.sql.txt index f92e62d1..2557efd7 100644 --- a/testdata/result/statement/select_literals_all.sql.txt +++ b/testdata/result/statement/select_literals_all.sql.txt @@ -395,8 +395,8 @@ lines''', Expr: &ast.TypelessStructLiteral{ Struct: 467, Rparen: 481, - Values: []*ast.TypelessStructValue{ - &ast.TypelessStructValue{ + Values: []*ast.AsExpr{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 474, ValueEnd: 475, @@ -405,7 +405,7 @@ lines''', }, Name: (*ast.Ident)(nil), }, - &ast.TypelessStructValue{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 477, ValueEnd: 478, @@ -414,7 +414,7 @@ lines''', }, Name: (*ast.Ident)(nil), }, - &ast.TypelessStructValue{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 480, ValueEnd: 481, diff --git a/testdata/result/statement/select_literals_struct.sql.txt b/testdata/result/statement/select_literals_struct.sql.txt index ec0b9588..9ce6fc39 100644 --- a/testdata/result/statement/select_literals_struct.sql.txt +++ b/testdata/result/statement/select_literals_struct.sql.txt @@ -38,8 +38,8 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 22, Rparen: 36, - Values: []*ast.TypelessStructValue{ - &ast.TypelessStructValue{ + Values: []*ast.AsExpr{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 29, ValueEnd: 30, @@ -48,7 +48,7 @@ SELECT }, Name: (*ast.Ident)(nil), }, - &ast.TypelessStructValue{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 32, ValueEnd: 33, @@ -57,7 +57,7 @@ SELECT }, Name: (*ast.Ident)(nil), }, - &ast.TypelessStructValue{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 35, ValueEnd: 36, @@ -92,8 +92,8 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 55, Rparen: 72, - Values: []*ast.TypelessStructValue{ - &ast.TypelessStructValue{ + Values: []*ast.AsExpr{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 62, ValueEnd: 63, @@ -102,7 +102,7 @@ SELECT }, Name: (*ast.Ident)(nil), }, - &ast.TypelessStructValue{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 65, ValueEnd: 66, @@ -111,7 +111,7 @@ SELECT }, Name: (*ast.Ident)(nil), }, - &ast.TypelessStructValue{ + &ast.AsExpr{ Expr: &ast.BoolLiteral{ ValuePos: 68, Value: true, @@ -224,8 +224,8 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 151, Rparen: 180, - Values: []*ast.TypelessStructValue{ - &ast.TypelessStructValue{ + Values: []*ast.AsExpr{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 158, ValueEnd: 159, @@ -238,7 +238,7 @@ SELECT Name: "X", }, }, - &ast.TypelessStructValue{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 166, ValueEnd: 167, @@ -251,7 +251,7 @@ SELECT Name: "Y", }, }, - &ast.TypelessStructValue{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 174, ValueEnd: 175, @@ -430,8 +430,8 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 309, Rparen: 328, - Values: []*ast.TypelessStructValue{ - &ast.TypelessStructValue{ + Values: []*ast.AsExpr{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 316, ValueEnd: 317, @@ -444,7 +444,7 @@ SELECT Name: "X", }, }, - &ast.TypelessStructValue{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 324, ValueEnd: 325, @@ -453,7 +453,7 @@ SELECT }, Name: (*ast.Ident)(nil), }, - &ast.TypelessStructValue{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 327, ValueEnd: 328, @@ -579,8 +579,8 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 410, Rparen: 423, - Values: []*ast.TypelessStructValue{ - &ast.TypelessStructValue{ + Values: []*ast.AsExpr{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 417, ValueEnd: 418, @@ -661,8 +661,8 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 476, Rparen: 484, - Values: []*ast.TypelessStructValue{ - &ast.TypelessStructValue{ + Values: []*ast.AsExpr{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 483, ValueEnd: 484, @@ -697,7 +697,7 @@ SELECT Expr: &ast.TypedStructLiteral{ Struct: 503, Rparen: 512, - Fields: []*ast.StructField{}, + Fields: []*ast.StructField(nil), Values: []ast.Expr(nil), }, }, @@ -724,7 +724,7 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 531, Rparen: 538, - Values: []*ast.TypelessStructValue(nil), + Values: []*ast.AsExpr(nil), }, }, }, diff --git a/testdata/result/statement/select_struct_compare_eq.sql.txt b/testdata/result/statement/select_struct_compare_eq.sql.txt index ca4bcf5a..9d58a237 100644 --- a/testdata/result/statement/select_struct_compare_eq.sql.txt +++ b/testdata/result/statement/select_struct_compare_eq.sql.txt @@ -131,13 +131,13 @@ SELECT ARRAY( Right: &ast.TypelessStructLiteral{ Struct: 109, Rparen: 131, - Values: []*ast.TypelessStructValue{ - &ast.TypelessStructValue{ + Values: []*ast.AsExpr{ + &ast.AsExpr{ Expr: &ast.TypelessStructLiteral{ Struct: 116, Rparen: 130, - Values: []*ast.TypelessStructValue{ - &ast.TypelessStructValue{ + Values: []*ast.AsExpr{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 123, ValueEnd: 124, @@ -146,7 +146,7 @@ SELECT ARRAY( }, Name: (*ast.Ident)(nil), }, - &ast.TypelessStructValue{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 126, ValueEnd: 127, @@ -155,7 +155,7 @@ SELECT ARRAY( }, Name: (*ast.Ident)(nil), }, - &ast.TypelessStructValue{ + &ast.AsExpr{ Expr: &ast.IntLiteral{ ValuePos: 129, ValueEnd: 130, From 6a901274aed6949045cc1f40eeae63e4b7fe2d31 Mon Sep 17 00:00:00 2001 From: TSUYUSATO Kitsune Date: Mon, 28 Oct 2024 02:11:07 +0900 Subject: [PATCH 18/22] Rename AsExpr to ExprAsName, and use `AsAlias` Also, this fixes a `AsAlias.As` position bug. --- ast/ast.go | 34 +++--- ast/pos.go | 16 +-- ast/sql.go | 6 +- parser.go | 57 +++++---- .../result/ddl/create_or_replace_view.sql.txt | 4 +- testdata/result/ddl/create_view.sql.txt | 4 +- .../create_view_sql_security_definer.sql.txt | 4 +- testdata/result/dml/delete_as.sql.txt | 2 +- testdata/result/dml/update_as.sql.txt | 2 +- testdata/result/expr/new_constructor.sql.txt | 28 +++-- .../result/expr/new_constructor_empty.sql.txt | 2 +- ...ue_subquery_select_as_fqn_typename.sql.txt | 2 +- ...e_subquery_select_as_leaf_typename.sql.txt | 2 +- .../value_subquery_select_as_struct.sql.txt | 2 +- .../query/select_alias_without_as.sql.txt | 4 +- .../query/select_call_with_named_expr.sql.txt | 4 +- testdata/result/query/select_cast.sql.txt | 2 +- testdata/result/query/select_expr.sql.txt | 6 +- .../query/select_from_implicit_unnest.sql.txt | 6 +- .../result/query/select_from_path.sql.txt | 2 +- .../result/query/select_literals_all.sql.txt | 14 +-- .../result/query/select_literals_date.sql.txt | 4 +- .../query/select_literals_struct.sql.txt | 115 ++++++++++-------- .../result/query/select_nest_complex.sql.txt | 8 +- .../select_singer_with_column_names.sql.txt | 2 +- .../select_singer_with_cross_join.sql.txt | 6 +- .../select_singer_with_full_join.sql.txt | 4 +- .../select_singer_with_hash_join.sql.txt | 10 +- .../query/select_singer_with_join.sql.txt | 6 +- .../select_singer_with_join_hint.sql.txt | 12 +- .../select_singer_with_join_twice.sql.txt | 8 +- .../select_singer_with_join_using.sql.txt | 6 +- .../select_singer_with_join_various.sql.txt | 22 ++-- ..._singer_with_select_in_from_and_as.sql.txt | 2 +- ...ith_single_column_subquery_with_at.sql.txt | 2 +- .../select_singer_with_table_alias.sql.txt | 6 +- ..._singer_with_table_alias_with_hint.sql.txt | 2 +- .../select_singer_with_tablesample.sql.txt | 6 +- ...ect_singer_with_toplevel_join_hint.sql.txt | 6 +- .../query/select_struct_compare_eq.sql.txt | 22 ++-- ...select_tablesample_with_cross_join.sql.txt | 6 +- ...elect_tablesample_with_table_alias.sql.txt | 2 +- ...elect_unnest_with_offset_and_alias.sql.txt | 4 +- ...t_unnest_with_offset_and_alias_min.sql.txt | 6 +- .../query/select_with_field_path.sql.txt | 2 +- .../select_with_sequence_function.sql.txt | 2 +- .../statement/create_or_replace_view.sql.txt | 4 +- testdata/result/statement/create_view.sql.txt | 4 +- .../create_view_sql_security_definer.sql.txt | 4 +- testdata/result/statement/delete_as.sql.txt | 2 +- .../statement/select_alias_without_as.sql.txt | 4 +- .../select_call_with_named_expr.sql.txt | 4 +- testdata/result/statement/select_cast.sql.txt | 2 +- testdata/result/statement/select_expr.sql.txt | 6 +- .../select_from_implicit_unnest.sql.txt | 6 +- .../result/statement/select_from_path.sql.txt | 2 +- .../statement/select_literals_all.sql.txt | 14 +-- .../statement/select_literals_date.sql.txt | 4 +- .../statement/select_literals_struct.sql.txt | 115 ++++++++++-------- .../statement/select_nest_complex.sql.txt | 8 +- .../select_singer_with_column_names.sql.txt | 2 +- .../select_singer_with_cross_join.sql.txt | 6 +- .../select_singer_with_full_join.sql.txt | 4 +- .../select_singer_with_hash_join.sql.txt | 10 +- .../statement/select_singer_with_join.sql.txt | 6 +- .../select_singer_with_join_hint.sql.txt | 12 +- .../select_singer_with_join_twice.sql.txt | 8 +- .../select_singer_with_join_using.sql.txt | 6 +- .../select_singer_with_join_various.sql.txt | 22 ++-- ..._singer_with_select_in_from_and_as.sql.txt | 2 +- ...ith_single_column_subquery_with_at.sql.txt | 2 +- .../select_singer_with_table_alias.sql.txt | 6 +- ..._singer_with_table_alias_with_hint.sql.txt | 2 +- .../select_singer_with_tablesample.sql.txt | 6 +- ...ect_singer_with_toplevel_join_hint.sql.txt | 6 +- .../select_struct_compare_eq.sql.txt | 22 ++-- ...select_tablesample_with_cross_join.sql.txt | 6 +- ...elect_tablesample_with_table_alias.sql.txt | 2 +- ...elect_unnest_with_offset_and_alias.sql.txt | 4 +- ...t_unnest_with_offset_and_alias_min.sql.txt | 6 +- .../statement/select_with_field_path.sql.txt | 2 +- .../select_with_sequence_function.sql.txt | 2 +- testdata/result/statement/update_as.sql.txt | 2 +- 83 files changed, 415 insertions(+), 384 deletions(-) diff --git a/ast/ast.go b/ast/ast.go index f5537f6e..2f5f6a8e 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -627,16 +627,12 @@ type Alias struct { // // It is used in Alias node and some JoinExpr nodes. // -// NOTE: Sometime keyword AS can be omited. -// -// In this case, it.token.Pos() == it.Alias.token.Pos(), so we can detect this. -// -// AS {{.Alias | sql}} +// {{if not .As.Invalid}}AS {{end}}{{.Alias | sql}} type AsAlias struct { // pos = As || Alias.pos // end = Alias.end - As token.Pos // position of "AS" keyword + As token.Pos // position of "AS" keyword, optional Alias *Ident } @@ -1407,17 +1403,6 @@ type TypedStructLiteral struct { Values []Expr } -// AsExpr is value with optional name in typeless struct literal or new constructor. -// -// {{.Expr | sql}} {{if .Name}}AS {{.Name | sql}}{{end}} -type AsExpr struct { - // pos = Expr.pos - // end = (Name ?? Expr).end - - Expr Expr - Name *Ident // optional -} - // TypelessStructLiteral is typeless struct literal node. // // STRUCT({{.Values | sqlJoin ","}}) @@ -1428,7 +1413,18 @@ type TypelessStructLiteral struct { Struct token.Pos // position of "STRUCT" Rparen token.Pos // position of ")" - Values []*AsExpr + Values []*ExprAsName +} + +// ExprAsName is value with optional name in typeless struct literal or new constructor. +// +// {{.Expr | sql}} {{.As | sqlOpt}} +type ExprAsName struct { + // pos = Expr.pos + // end = (As ?? Expr).end + + Expr Expr + As *AsAlias // .As.As must not be invalid, optional } // NullLiteral is just NULL literal. @@ -1575,7 +1571,7 @@ type NewConstructor struct { New token.Pos Type *NamedType - Args []*AsExpr + Args []*ExprAsName Rparen token.Pos } diff --git a/ast/pos.go b/ast/pos.go index 78553de5..0dfc2445 100644 --- a/ast/pos.go +++ b/ast/pos.go @@ -590,14 +590,6 @@ func (t *TypedStructLiteral) End() token.Pos { return posAdd(t.Rparen, 1) } -func (a *AsExpr) Pos() token.Pos { - return nodePos(wrapNode(a.Expr)) -} - -func (a *AsExpr) End() token.Pos { - return nodeEnd(nodeChoice(wrapNode(a.Name), wrapNode(a.Expr))) -} - func (t *TypelessStructLiteral) Pos() token.Pos { return t.Struct } @@ -606,6 +598,14 @@ func (t *TypelessStructLiteral) End() token.Pos { return posAdd(t.Rparen, 1) } +func (e *ExprAsName) Pos() token.Pos { + return nodePos(wrapNode(e.Expr)) +} + +func (e *ExprAsName) End() token.Pos { + return nodeEnd(nodeChoice(wrapNode(e.As), wrapNode(e.Expr))) +} + func (n *NullLiteral) Pos() token.Pos { return n.Null } diff --git a/ast/sql.go b/ast/sql.go index 6946f2ae..9704f8e7 100644 --- a/ast/sql.go +++ b/ast/sql.go @@ -232,7 +232,7 @@ func (a *Alias) SQL() string { } func (a *AsAlias) SQL() string { - return "AS " + a.Alias.SQL() + return strOpt(!a.As.Invalid(), "AS ") + a.Alias.SQL() } func (e *ExprSelectItem) SQL() string { @@ -623,8 +623,8 @@ func (s *TypedStructLiteral) SQL() string { return "STRUCT<" + sqlJoin(s.Fields, ", ") + ">(" + sqlJoin(s.Values, ", ") + ")" } -func (a *AsExpr) SQL() string { - return a.Expr.SQL() + sqlOpt(" AS ", a.Name, "") +func (e *ExprAsName) SQL() string { + return e.Expr.SQL() + sqlOpt(" ", e.As, "") } func (s *TypelessStructLiteral) SQL() string { diff --git a/parser.go b/parser.go index 653cbafc..8a451c4a 100644 --- a/parser.go +++ b/parser.go @@ -458,7 +458,7 @@ func (p *Parser) parseSelectItem() ast.SelectItem { } expr := p.parseExpr() - if as := p.tryParseAsAlias(); as != nil { + if as := p.tryParseAsAlias( /* requiredAs */ false); as != nil { return &ast.Alias{ Expr: expr, As: as, @@ -479,22 +479,26 @@ func (p *Parser) parseSelectItem() ast.SelectItem { } } -func (p *Parser) tryParseAsAlias() *ast.AsAlias { +func (p *Parser) tryParseAsAlias(requiredAs bool) *ast.AsAlias { pos := p.Token.Pos if p.Token.Kind == "AS" { p.nextToken() id := p.parseIdent() return &ast.AsAlias{ - As: token.InvalidPos, + As: pos, Alias: id, } } + if requiredAs { + return nil + } + if p.Token.Kind == token.TokenIdent { id := p.parseIdent() return &ast.AsAlias{ - As: pos, + As: token.InvalidPos, Alias: id, } } @@ -777,7 +781,7 @@ func (p *Parser) parseSimpleTableExpr() ast.TableExpr { lparen := p.expect("(").Pos query := p.parseQueryExpr() rparen := p.expect(")").Pos - as := p.tryParseAsAlias() + as := p.tryParseAsAlias( /* requiredAs */ false) return p.parseTableExprSuffix(&ast.SubQueryTableExpr{ Lparen: lparen, Rparen: rparen, @@ -829,7 +833,7 @@ func (p *Parser) parseIdentOrPath() []*ast.Ident { func (p *Parser) parseUnnestSuffix(expr ast.Expr, unnest, rparen token.Pos) ast.TableExpr { hint := p.tryParseHint() - as := p.tryParseAsAlias() + as := p.tryParseAsAlias( /* requiredAs */ false) withOffset := p.tryParseWithOffset() return p.parseTableExprSuffix(&ast.Unnest{ @@ -849,7 +853,7 @@ func (p *Parser) tryParseWithOffset() *ast.WithOffset { with := p.expect("WITH").Pos offset := p.expectKeywordLike("OFFSET").Pos - as := p.tryParseAsAlias() + as := p.tryParseAsAlias( /* requiredAs */ false) return &ast.WithOffset{ With: with, @@ -860,7 +864,7 @@ func (p *Parser) tryParseWithOffset() *ast.WithOffset { func (p *Parser) parseTableNameSuffix(id *ast.Ident) ast.TableExpr { hint := p.tryParseHint() - as := p.tryParseAsAlias() + as := p.tryParseAsAlias( /* requiredAs */ false) return p.parseTableExprSuffix(&ast.TableName{ Table: id, Hint: hint, @@ -870,7 +874,7 @@ func (p *Parser) parseTableNameSuffix(id *ast.Ident) ast.TableExpr { func (p *Parser) parsePathTableExprSuffix(id *ast.Path) ast.TableExpr { hint := p.tryParseHint() - as := p.tryParseAsAlias() + as := p.tryParseAsAlias( /* requiredAs */ false) withOffset := p.tryParseWithOffset() return p.parseTableExprSuffix(&ast.PathTableExpr{ Path: id, @@ -1818,20 +1822,6 @@ func (p *Parser) parseParenExpr() ast.Expr { } } -func (p *Parser) parseAsExpr() *ast.AsExpr { - expr := p.parseExpr() - if p.Token.Kind != "AS" { - return &ast.AsExpr{Expr: expr} - } - - p.nextToken() - name := p.parseIdent() - return &ast.AsExpr{ - Expr: expr, - Name: name, - } -} - func (p *Parser) parseArrayLiteralOrSubQuery() ast.Expr { pos := p.expect("ARRAY").Pos @@ -1923,9 +1913,9 @@ func (p *Parser) parseTypedStructLiteral(pos token.Pos) *ast.TypedStructLiteral func (p *Parser) parseTypelessStructLiteral(pos token.Pos) *ast.TypelessStructLiteral { p.expect("(") - var values []*ast.AsExpr + var values []*ast.ExprAsName if p.Token.Kind != ")" { - values = parseCommaSeparatedList(p, p.parseAsExpr) + values = parseCommaSeparatedList(p, p.parseExprAsName) } rparen := p.expect(")").Pos @@ -1936,6 +1926,15 @@ func (p *Parser) parseTypelessStructLiteral(pos token.Pos) *ast.TypelessStructLi } } +func (p *Parser) parseExprAsName() *ast.ExprAsName { + e := p.parseExpr() + as := p.tryParseAsAlias( /* requiredAs */ true) + return &ast.ExprAsName{ + Expr: e, + As: as, + } +} + func (p *Parser) parseDateLiteral(id token.Token) *ast.DateLiteral { s := p.parseStringLiteral() return &ast.DateLiteral{ @@ -2138,9 +2137,9 @@ func (p *Parser) parseNewConstructor(newPos token.Pos, namedType *ast.NamedType) p.expect("(") // Args can be empty like `NEW pkg.TypeName ()`. - var args []*ast.AsExpr + var args []*ast.ExprAsName if p.Token.Kind != ")" { - args = parseCommaSeparatedList(p, p.parseAsExpr) + args = parseCommaSeparatedList(p, p.parseExprAsName) } rparen := p.expect(")").Pos @@ -3841,7 +3840,7 @@ func (p *Parser) parseDelete(pos token.Pos) *ast.Delete { } name := p.parseIdent() - as := p.tryParseAsAlias() + as := p.tryParseAsAlias( /* requiredAs */ false) where := p.parseWhere() return &ast.Delete{ @@ -3854,7 +3853,7 @@ func (p *Parser) parseDelete(pos token.Pos) *ast.Delete { func (p *Parser) parseUpdate(pos token.Pos) *ast.Update { name := p.parseIdent() - as := p.tryParseAsAlias() + as := p.tryParseAsAlias( /* requiredAs */ false) p.expect("SET") diff --git a/testdata/result/ddl/create_or_replace_view.sql.txt b/testdata/result/ddl/create_or_replace_view.sql.txt index 4a611ade..f3b38809 100644 --- a/testdata/result/ddl/create_or_replace_view.sql.txt +++ b/testdata/result/ddl/create_or_replace_view.sql.txt @@ -37,7 +37,7 @@ from singers }, }, As: &ast.AsAlias{ - As: -1, + As: 87, Alias: &ast.Ident{ NamePos: 90, NameEnd: 98, @@ -86,7 +86,7 @@ from singers }, }, As: &ast.AsAlias{ - As: -1, + As: 149, Alias: &ast.Ident{ NamePos: 152, NameEnd: 156, diff --git a/testdata/result/ddl/create_view.sql.txt b/testdata/result/ddl/create_view.sql.txt index da8ea657..e96ff6c8 100644 --- a/testdata/result/ddl/create_view.sql.txt +++ b/testdata/result/ddl/create_view.sql.txt @@ -37,7 +37,7 @@ from singers }, }, As: &ast.AsAlias{ - As: -1, + As: 76, Alias: &ast.Ident{ NamePos: 79, NameEnd: 87, @@ -86,7 +86,7 @@ from singers }, }, As: &ast.AsAlias{ - As: -1, + As: 138, Alias: &ast.Ident{ NamePos: 141, NameEnd: 145, diff --git a/testdata/result/ddl/create_view_sql_security_definer.sql.txt b/testdata/result/ddl/create_view_sql_security_definer.sql.txt index 5627d9ca..6d134f80 100644 --- a/testdata/result/ddl/create_view_sql_security_definer.sql.txt +++ b/testdata/result/ddl/create_view_sql_security_definer.sql.txt @@ -37,7 +37,7 @@ from singers }, }, As: &ast.AsAlias{ - As: -1, + As: 76, Alias: &ast.Ident{ NamePos: 79, NameEnd: 87, @@ -86,7 +86,7 @@ from singers }, }, As: &ast.AsAlias{ - As: -1, + As: 138, Alias: &ast.Ident{ NamePos: 141, NameEnd: 145, diff --git a/testdata/result/dml/delete_as.sql.txt b/testdata/result/dml/delete_as.sql.txt index d368be5c..2eee871a 100644 --- a/testdata/result/dml/delete_as.sql.txt +++ b/testdata/result/dml/delete_as.sql.txt @@ -9,7 +9,7 @@ delete foo as F where F.foo = 1 Name: "foo", }, As: &ast.AsAlias{ - As: -1, + As: 11, Alias: &ast.Ident{ NamePos: 14, NameEnd: 15, diff --git a/testdata/result/dml/update_as.sql.txt b/testdata/result/dml/update_as.sql.txt index 6f269aff..a647ea85 100644 --- a/testdata/result/dml/update_as.sql.txt +++ b/testdata/result/dml/update_as.sql.txt @@ -9,7 +9,7 @@ update foo as F set F.foo = F.bar + 1 where foo = F.bar Name: "foo", }, As: &ast.AsAlias{ - As: -1, + As: 11, Alias: &ast.Ident{ NamePos: 14, NameEnd: 15, diff --git a/testdata/result/expr/new_constructor.sql.txt b/testdata/result/expr/new_constructor.sql.txt index b42d790c..8cdcfc28 100644 --- a/testdata/result/expr/new_constructor.sql.txt +++ b/testdata/result/expr/new_constructor.sql.txt @@ -27,29 +27,35 @@ NEW googlesql.examples.music.Chart(key AS rank, name AS chart_name) }, }, }, - Args: []*ast.AsExpr{ - &ast.AsExpr{ + Args: []*ast.ExprAsName{ + &ast.ExprAsName{ Expr: &ast.Ident{ NamePos: 35, NameEnd: 38, Name: "key", }, - Name: &ast.Ident{ - NamePos: 42, - NameEnd: 46, - Name: "rank", + As: &ast.AsAlias{ + As: 39, + Alias: &ast.Ident{ + NamePos: 42, + NameEnd: 46, + Name: "rank", + }, }, }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.Ident{ NamePos: 48, NameEnd: 52, Name: "name", }, - Name: &ast.Ident{ - NamePos: 56, - NameEnd: 66, - Name: "chart_name", + As: &ast.AsAlias{ + As: 53, + Alias: &ast.Ident{ + NamePos: 56, + NameEnd: 66, + Name: "chart_name", + }, }, }, }, diff --git a/testdata/result/expr/new_constructor_empty.sql.txt b/testdata/result/expr/new_constructor_empty.sql.txt index e2a8df5a..231da676 100644 --- a/testdata/result/expr/new_constructor_empty.sql.txt +++ b/testdata/result/expr/new_constructor_empty.sql.txt @@ -28,7 +28,7 @@ NEW googlesql.examples.music.Chart() }, }, }, - Args: []*ast.AsExpr(nil), + Args: []*ast.ExprAsName(nil), Rparen: 35, } diff --git a/testdata/result/expr/value_subquery_select_as_fqn_typename.sql.txt b/testdata/result/expr/value_subquery_select_as_fqn_typename.sql.txt index f7e05493..73aed2a3 100644 --- a/testdata/result/expr/value_subquery_select_as_fqn_typename.sql.txt +++ b/testdata/result/expr/value_subquery_select_as_fqn_typename.sql.txt @@ -33,7 +33,7 @@ Value: "1", }, As: &ast.AsAlias{ - As: -1, + As: 30, Alias: &ast.Ident{ NamePos: 33, NameEnd: 34, diff --git a/testdata/result/expr/value_subquery_select_as_leaf_typename.sql.txt b/testdata/result/expr/value_subquery_select_as_leaf_typename.sql.txt index f73a77a9..e3aeb50b 100644 --- a/testdata/result/expr/value_subquery_select_as_leaf_typename.sql.txt +++ b/testdata/result/expr/value_subquery_select_as_leaf_typename.sql.txt @@ -28,7 +28,7 @@ Value: "1", }, As: &ast.AsAlias{ - As: -1, + As: 22, Alias: &ast.Ident{ NamePos: 25, NameEnd: 26, diff --git a/testdata/result/expr/value_subquery_select_as_struct.sql.txt b/testdata/result/expr/value_subquery_select_as_struct.sql.txt index 0308dc1a..f543cd53 100644 --- a/testdata/result/expr/value_subquery_select_as_struct.sql.txt +++ b/testdata/result/expr/value_subquery_select_as_struct.sql.txt @@ -21,7 +21,7 @@ Value: "1", }, As: &ast.AsAlias{ - As: -1, + As: 20, Alias: &ast.Ident{ NamePos: 23, NameEnd: 24, diff --git a/testdata/result/query/select_alias_without_as.sql.txt b/testdata/result/query/select_alias_without_as.sql.txt index da93020e..c4604a96 100644 --- a/testdata/result/query/select_alias_without_as.sql.txt +++ b/testdata/result/query/select_alias_without_as.sql.txt @@ -18,7 +18,7 @@ select 1 A Value: "1", }, As: &ast.AsAlias{ - As: 9, + As: -1, Alias: &ast.Ident{ NamePos: 9, NameEnd: 10, @@ -37,4 +37,4 @@ select 1 A } --- SQL -SELECT 1 AS A +SELECT 1 A diff --git a/testdata/result/query/select_call_with_named_expr.sql.txt b/testdata/result/query/select_call_with_named_expr.sql.txt index 78d1d157..bae8b868 100644 --- a/testdata/result/query/select_call_with_named_expr.sql.txt +++ b/testdata/result/query/select_call_with_named_expr.sql.txt @@ -54,7 +54,7 @@ WHERE a.SingerId = 1 AND SEARCH(a.DescriptionTokens, 'classic albums', enhance_q }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 44, + As: -1, Alias: &ast.Ident{ NamePos: 44, NameEnd: 45, @@ -150,4 +150,4 @@ WHERE a.SingerId = 1 AND SEARCH(a.DescriptionTokens, 'classic albums', enhance_q } --- SQL -SELECT a.AlbumId, a.Description FROM Albums AS a WHERE a.SingerId = 1 AND SEARCH(a.DescriptionTokens, "classic albums", enhance_query => TRUE) +SELECT a.AlbumId, a.Description FROM Albums a WHERE a.SingerId = 1 AND SEARCH(a.DescriptionTokens, "classic albums", enhance_query => TRUE) diff --git a/testdata/result/query/select_cast.sql.txt b/testdata/result/query/select_cast.sql.txt index 71151fd9..3ee5415f 100644 --- a/testdata/result/query/select_cast.sql.txt +++ b/testdata/result/query/select_cast.sql.txt @@ -59,7 +59,7 @@ limit cast(1 as INT64) offset cast(@foo as INT64) &ast.TypelessStructLiteral{ Struct: 53, Rparen: 60, - Values: []*ast.AsExpr(nil), + Values: []*ast.ExprAsName(nil), }, &ast.IntLiteral{ ValuePos: 63, diff --git a/testdata/result/query/select_expr.sql.txt b/testdata/result/query/select_expr.sql.txt index e6c89c30..9f1a2bc5 100644 --- a/testdata/result/query/select_expr.sql.txt +++ b/testdata/result/query/select_expr.sql.txt @@ -340,7 +340,7 @@ select 1 + 2, 1 - 2, Value: "1", }, As: &ast.AsAlias{ - As: 204, + As: -1, Alias: &ast.Ident{ NamePos: 204, NameEnd: 207, @@ -915,7 +915,7 @@ select 1 + 2, 1 - 2, }, }, As: &ast.AsAlias{ - As: -1, + As: 792, Alias: &ast.Ident{ NamePos: 795, NameEnd: 801, @@ -934,4 +934,4 @@ select 1 + 2, 1 - 2, } --- SQL -SELECT 1 + 2, 1 - 2, 1 * 2, 2 / 2, +1 + +1, -1 + -1, +1.2, -3.4, ~1 ^ ~1, 1 ^ 2, 2 & 1, 2 | 1, 1 << 2, 2 >> 1, foo.bar * +foo.bar * -foo.bar, (SELECT 1 AS `1`).`1`, NOT NOT TRUE, [1, 2, 3][OFFSET(1)], [1, 2, 3][OFFSET(1)], [1, 2, 3][ORDINAL(1)], CASE WHEN 1 = 1 THEN "1 = 1" ELSE "else" END, CASE 1 WHEN 1 THEN "1" WHEN 2 THEN "2" ELSE "other" END, date_add(DATE "2019-09-01", INTERVAL 5 day), timestamp_add(TIMESTAMP "2019-09-01 08:11:22", INTERVAL 5 hour), 1 IN (1, 2, 3), 2 IN UNNEST([1, 2, 3]), 3 IN (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3), [1] || [2], IF(1 > 1, 1, 2) + 1 AS result +SELECT 1 + 2, 1 - 2, 1 * 2, 2 / 2, +1 + +1, -1 + -1, +1.2, -3.4, ~1 ^ ~1, 1 ^ 2, 2 & 1, 2 | 1, 1 << 2, 2 >> 1, foo.bar * +foo.bar * -foo.bar, (SELECT 1 `1`).`1`, NOT NOT TRUE, [1, 2, 3][OFFSET(1)], [1, 2, 3][OFFSET(1)], [1, 2, 3][ORDINAL(1)], CASE WHEN 1 = 1 THEN "1 = 1" ELSE "else" END, CASE 1 WHEN 1 THEN "1" WHEN 2 THEN "2" ELSE "other" END, date_add(DATE "2019-09-01", INTERVAL 5 day), timestamp_add(TIMESTAMP "2019-09-01 08:11:22", INTERVAL 5 hour), 1 IN (1, 2, 3), 2 IN UNNEST([1, 2, 3]), 3 IN (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3), [1] || [2], IF(1 > 1, 1, 2) + 1 AS result diff --git a/testdata/result/query/select_from_implicit_unnest.sql.txt b/testdata/result/query/select_from_implicit_unnest.sql.txt index e29c72a3..f1d12b88 100644 --- a/testdata/result/query/select_from_implicit_unnest.sql.txt +++ b/testdata/result/query/select_from_implicit_unnest.sql.txt @@ -81,7 +81,7 @@ FROM UNNEST([STRUCT>(["foo"])]) AS t, }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: -1, + As: 64, Alias: &ast.Ident{ NamePos: 67, NameEnd: 68, @@ -108,7 +108,7 @@ FROM UNNEST([STRUCT>(["foo"])]) AS t, }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: -1, + As: 81, Alias: &ast.Ident{ NamePos: 84, NameEnd: 85, @@ -119,7 +119,7 @@ FROM UNNEST([STRUCT>(["foo"])]) AS t, With: 86, Offset: 91, As: &ast.AsAlias{ - As: -1, + As: 98, Alias: &ast.Ident{ NamePos: 101, NameEnd: 104, diff --git a/testdata/result/query/select_from_path.sql.txt b/testdata/result/query/select_from_path.sql.txt index f3331a1d..d58a1d70 100644 --- a/testdata/result/query/select_from_path.sql.txt +++ b/testdata/result/query/select_from_path.sql.txt @@ -35,7 +35,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: -1, + As: 44, Alias: &ast.Ident{ NamePos: 47, NameEnd: 48, diff --git a/testdata/result/query/select_literals_all.sql.txt b/testdata/result/query/select_literals_all.sql.txt index 2557efd7..9f7901bc 100644 --- a/testdata/result/query/select_literals_all.sql.txt +++ b/testdata/result/query/select_literals_all.sql.txt @@ -395,33 +395,33 @@ lines''', Expr: &ast.TypelessStructLiteral{ Struct: 467, Rparen: 481, - Values: []*ast.AsExpr{ - &ast.AsExpr{ + Values: []*ast.ExprAsName{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 474, ValueEnd: 475, Base: 10, Value: "1", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 477, ValueEnd: 478, Base: 10, Value: "2", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 480, ValueEnd: 481, Base: 10, Value: "3", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, }, }, diff --git a/testdata/result/query/select_literals_date.sql.txt b/testdata/result/query/select_literals_date.sql.txt index fd6b3596..7d21137b 100644 --- a/testdata/result/query/select_literals_date.sql.txt +++ b/testdata/result/query/select_literals_date.sql.txt @@ -149,7 +149,7 @@ SELECT Having: nil, }, As: &ast.AsAlias{ - As: -1, + As: 270, Alias: &ast.Ident{ NamePos: 273, NameEnd: 276, @@ -180,7 +180,7 @@ SELECT Having: nil, }, As: &ast.AsAlias{ - As: -1, + As: 304, Alias: &ast.Ident{ NamePos: 307, NameEnd: 310, diff --git a/testdata/result/query/select_literals_struct.sql.txt b/testdata/result/query/select_literals_struct.sql.txt index 9ce6fc39..32133a42 100644 --- a/testdata/result/query/select_literals_struct.sql.txt +++ b/testdata/result/query/select_literals_struct.sql.txt @@ -38,33 +38,33 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 22, Rparen: 36, - Values: []*ast.AsExpr{ - &ast.AsExpr{ + Values: []*ast.ExprAsName{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 29, ValueEnd: 30, Base: 10, Value: "1", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 32, ValueEnd: 33, Base: 10, Value: "2", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 35, ValueEnd: 36, Base: 10, Value: "3", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, }, }, @@ -92,31 +92,31 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 55, Rparen: 72, - Values: []*ast.AsExpr{ - &ast.AsExpr{ + Values: []*ast.ExprAsName{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 62, ValueEnd: 63, Base: 10, Value: "1", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 65, ValueEnd: 66, Base: 10, Value: "2", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.BoolLiteral{ ValuePos: 68, Value: true, }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, }, }, @@ -224,44 +224,53 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 151, Rparen: 180, - Values: []*ast.AsExpr{ - &ast.AsExpr{ + Values: []*ast.ExprAsName{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 158, ValueEnd: 159, Base: 10, Value: "1", }, - Name: &ast.Ident{ - NamePos: 163, - NameEnd: 164, - Name: "X", + As: &ast.AsAlias{ + As: 160, + Alias: &ast.Ident{ + NamePos: 163, + NameEnd: 164, + Name: "X", + }, }, }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 166, ValueEnd: 167, Base: 10, Value: "2", }, - Name: &ast.Ident{ - NamePos: 171, - NameEnd: 172, - Name: "Y", + As: &ast.AsAlias{ + As: 168, + Alias: &ast.Ident{ + NamePos: 171, + NameEnd: 172, + Name: "Y", + }, }, }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 174, ValueEnd: 175, Base: 10, Value: "3", }, - Name: &ast.Ident{ - NamePos: 179, - NameEnd: 180, - Name: "Z", + As: &ast.AsAlias{ + As: 176, + Alias: &ast.Ident{ + NamePos: 179, + NameEnd: 180, + Name: "Z", + }, }, }, }, @@ -430,37 +439,40 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 309, Rparen: 328, - Values: []*ast.AsExpr{ - &ast.AsExpr{ + Values: []*ast.ExprAsName{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 316, ValueEnd: 317, Base: 10, Value: "1", }, - Name: &ast.Ident{ - NamePos: 321, - NameEnd: 322, - Name: "X", + As: &ast.AsAlias{ + As: 318, + Alias: &ast.Ident{ + NamePos: 321, + NameEnd: 322, + Name: "X", + }, }, }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 324, ValueEnd: 325, Base: 10, Value: "2", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 327, ValueEnd: 328, Base: 10, Value: "3", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, }, }, @@ -579,18 +591,21 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 410, Rparen: 423, - Values: []*ast.AsExpr{ - &ast.AsExpr{ + Values: []*ast.ExprAsName{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 417, ValueEnd: 418, Base: 10, Value: "1", }, - Name: &ast.Ident{ - NamePos: 422, - NameEnd: 423, - Name: "X", + As: &ast.AsAlias{ + As: 419, + Alias: &ast.Ident{ + NamePos: 422, + NameEnd: 423, + Name: "X", + }, }, }, }, @@ -661,15 +676,15 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 476, Rparen: 484, - Values: []*ast.AsExpr{ - &ast.AsExpr{ + Values: []*ast.ExprAsName{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 483, ValueEnd: 484, Base: 10, Value: "1", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, }, }, @@ -724,7 +739,7 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 531, Rparen: 538, - Values: []*ast.AsExpr(nil), + Values: []*ast.ExprAsName(nil), }, }, }, diff --git a/testdata/result/query/select_nest_complex.sql.txt b/testdata/result/query/select_nest_complex.sql.txt index e328f52b..81059415 100644 --- a/testdata/result/query/select_nest_complex.sql.txt +++ b/testdata/result/query/select_nest_complex.sql.txt @@ -58,7 +58,7 @@ from ( Value: "1", }, As: &ast.AsAlias{ - As: 32, + As: -1, Alias: &ast.Ident{ NamePos: 32, NameEnd: 33, @@ -170,7 +170,7 @@ from ( Value: "1", }, As: &ast.AsAlias{ - As: 113, + As: -1, Alias: &ast.Ident{ NamePos: 113, NameEnd: 114, @@ -186,7 +186,7 @@ from ( Value: "2", }, As: &ast.AsAlias{ - As: 118, + As: -1, Alias: &ast.Ident{ NamePos: 118, NameEnd: 119, @@ -229,4 +229,4 @@ from ( } --- SQL -SELECT * FROM ((((SELECT 1 AS A UNION ALL (SELECT 2)) UNION DISTINCT (SELECT 1)) LIMIT 1) INNER JOIN (SELECT 1 AS A, 2 AS B) USING (A)) +SELECT * FROM ((((SELECT 1 A UNION ALL (SELECT 2)) UNION DISTINCT (SELECT 1)) LIMIT 1) INNER JOIN (SELECT 1 A, 2 B) USING (A)) diff --git a/testdata/result/query/select_singer_with_column_names.sql.txt b/testdata/result/query/select_singer_with_column_names.sql.txt index 2b8d7c19..7bef784a 100644 --- a/testdata/result/query/select_singer_with_column_names.sql.txt +++ b/testdata/result/query/select_singer_with_column_names.sql.txt @@ -23,7 +23,7 @@ FROM Singers Name: "SingerId", }, As: &ast.AsAlias{ - As: -1, + As: 18, Alias: &ast.Ident{ NamePos: 21, NameEnd: 23, diff --git a/testdata/result/query/select_singer_with_cross_join.sql.txt b/testdata/result/query/select_singer_with_cross_join.sql.txt index b6b16376..f7be0a42 100644 --- a/testdata/result/query/select_singer_with_cross_join.sql.txt +++ b/testdata/result/query/select_singer_with_cross_join.sql.txt @@ -33,7 +33,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 26, + As: -1, Alias: &ast.Ident{ NamePos: 26, NameEnd: 27, @@ -50,7 +50,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 51, + As: -1, Alias: &ast.Ident{ NamePos: 51, NameEnd: 52, @@ -71,4 +71,4 @@ FROM } --- SQL -SELECT * FROM Singers AS A CROSS JOIN Singers AS B +SELECT * FROM Singers A CROSS JOIN Singers B diff --git a/testdata/result/query/select_singer_with_full_join.sql.txt b/testdata/result/query/select_singer_with_full_join.sql.txt index 31d96645..8e364024 100644 --- a/testdata/result/query/select_singer_with_full_join.sql.txt +++ b/testdata/result/query/select_singer_with_full_join.sql.txt @@ -32,7 +32,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: -1, + As: 26, Alias: &ast.Ident{ NamePos: 29, NameEnd: 30, @@ -49,7 +49,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: -1, + As: 42, Alias: &ast.Ident{ NamePos: 45, NameEnd: 46, diff --git a/testdata/result/query/select_singer_with_hash_join.sql.txt b/testdata/result/query/select_singer_with_hash_join.sql.txt index c80ffc14..6a385ba4 100644 --- a/testdata/result/query/select_singer_with_hash_join.sql.txt +++ b/testdata/result/query/select_singer_with_hash_join.sql.txt @@ -48,7 +48,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 26, + As: -1, Alias: &ast.Ident{ NamePos: 26, NameEnd: 27, @@ -65,7 +65,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 50, + As: -1, Alias: &ast.Ident{ NamePos: 50, NameEnd: 51, @@ -117,7 +117,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 103, + As: -1, Alias: &ast.Ident{ NamePos: 103, NameEnd: 104, @@ -169,7 +169,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 155, + As: -1, Alias: &ast.Ident{ NamePos: 155, NameEnd: 156, @@ -223,4 +223,4 @@ FROM } --- SQL -SELECT * FROM Singers AS A INNER JOIN Singers AS B ON A.SingerID = B.SingerID INNER JOIN Singer AS C ON B.SingerID = C.SingerID INNER JOIN Singer AS D ON C.SingerID = D.SingerID +SELECT * FROM Singers A INNER JOIN Singers B ON A.SingerID = B.SingerID INNER JOIN Singer C ON B.SingerID = C.SingerID INNER JOIN Singer D ON C.SingerID = D.SingerID diff --git a/testdata/result/query/select_singer_with_join.sql.txt b/testdata/result/query/select_singer_with_join.sql.txt index be653b60..ab573b3f 100644 --- a/testdata/result/query/select_singer_with_join.sql.txt +++ b/testdata/result/query/select_singer_with_join.sql.txt @@ -34,7 +34,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 26, + As: -1, Alias: &ast.Ident{ NamePos: 26, NameEnd: 27, @@ -51,7 +51,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 56, + As: -1, Alias: &ast.Ident{ NamePos: 56, NameEnd: 57, @@ -105,4 +105,4 @@ FROM } --- SQL -SELECT * FROM Singers AS A LEFT OUTER JOIN Singers AS B ON A.SingerID = B.SingerID +SELECT * FROM Singers A LEFT OUTER JOIN Singers B ON A.SingerID = B.SingerID diff --git a/testdata/result/query/select_singer_with_join_hint.sql.txt b/testdata/result/query/select_singer_with_join_hint.sql.txt index 46983dcd..92a14a85 100644 --- a/testdata/result/query/select_singer_with_join_hint.sql.txt +++ b/testdata/result/query/select_singer_with_join_hint.sql.txt @@ -122,7 +122,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 26, + As: -1, Alias: &ast.Ident{ NamePos: 26, NameEnd: 27, @@ -139,7 +139,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 80, + As: -1, Alias: &ast.Ident{ NamePos: 80, NameEnd: 81, @@ -191,7 +191,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 150, + As: -1, Alias: &ast.Ident{ NamePos: 150, NameEnd: 151, @@ -243,7 +243,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 221, + As: -1, Alias: &ast.Ident{ NamePos: 221, NameEnd: 222, @@ -295,7 +295,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 291, + As: -1, Alias: &ast.Ident{ NamePos: 291, NameEnd: 292, @@ -349,4 +349,4 @@ FROM } --- SQL -SELECT * FROM Singers AS A LEFT OUTER JOIN @{FORCE_JOIN_ORDER=TRUE} Singers AS B ON A.SingerID = B.SingerID INNER JOIN @{JOIN_TYPE=HASH_JOIN} Singers AS C ON A.SingerID = C.SingerID INNER JOIN @{JOIN_TYPE=APPLY_JOIN} Singers AS D ON A.SingerID = D.SingerID INNER JOIN @{JOIN_TYPE=LOOP_JOIN} Singers AS E ON A.SingerID = E.SingerID +SELECT * FROM Singers A LEFT OUTER JOIN @{FORCE_JOIN_ORDER=TRUE} Singers B ON A.SingerID = B.SingerID INNER JOIN @{JOIN_TYPE=HASH_JOIN} Singers C ON A.SingerID = C.SingerID INNER JOIN @{JOIN_TYPE=APPLY_JOIN} Singers D ON A.SingerID = D.SingerID INNER JOIN @{JOIN_TYPE=LOOP_JOIN} Singers E ON A.SingerID = E.SingerID diff --git a/testdata/result/query/select_singer_with_join_twice.sql.txt b/testdata/result/query/select_singer_with_join_twice.sql.txt index b7d09824..035780a4 100644 --- a/testdata/result/query/select_singer_with_join_twice.sql.txt +++ b/testdata/result/query/select_singer_with_join_twice.sql.txt @@ -41,7 +41,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 26, + As: -1, Alias: &ast.Ident{ NamePos: 26, NameEnd: 27, @@ -58,7 +58,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 45, + As: -1, Alias: &ast.Ident{ NamePos: 45, NameEnd: 46, @@ -110,7 +110,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 99, + As: -1, Alias: &ast.Ident{ NamePos: 99, NameEnd: 100, @@ -164,4 +164,4 @@ FROM } --- SQL -SELECT * FROM Singers AS A INNER JOIN Singers AS B ON A.SingerID = B.SingerID INNER JOIN Singers AS C ON A.SingerID = C.SingerID +SELECT * FROM Singers A INNER JOIN Singers B ON A.SingerID = B.SingerID INNER JOIN Singers C ON A.SingerID = C.SingerID diff --git a/testdata/result/query/select_singer_with_join_using.sql.txt b/testdata/result/query/select_singer_with_join_using.sql.txt index 61f23fe2..e37df1cb 100644 --- a/testdata/result/query/select_singer_with_join_using.sql.txt +++ b/testdata/result/query/select_singer_with_join_using.sql.txt @@ -34,7 +34,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 26, + As: -1, Alias: &ast.Ident{ NamePos: 26, NameEnd: 27, @@ -51,7 +51,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 56, + As: -1, Alias: &ast.Ident{ NamePos: 56, NameEnd: 57, @@ -87,4 +87,4 @@ FROM } --- SQL -SELECT * FROM Singers AS A LEFT OUTER JOIN Singers AS B USING (SingerID, FirstName) +SELECT * FROM Singers A LEFT OUTER JOIN Singers B USING (SingerID, FirstName) diff --git a/testdata/result/query/select_singer_with_join_various.sql.txt b/testdata/result/query/select_singer_with_join_various.sql.txt index 823859c1..45d847b9 100644 --- a/testdata/result/query/select_singer_with_join_various.sql.txt +++ b/testdata/result/query/select_singer_with_join_various.sql.txt @@ -89,7 +89,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 26, + As: -1, Alias: &ast.Ident{ NamePos: 26, NameEnd: 27, @@ -106,7 +106,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 45, + As: -1, Alias: &ast.Ident{ NamePos: 45, NameEnd: 46, @@ -158,7 +158,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 99, + As: -1, Alias: &ast.Ident{ NamePos: 99, NameEnd: 100, @@ -210,7 +210,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 153, + As: -1, Alias: &ast.Ident{ NamePos: 153, NameEnd: 154, @@ -229,7 +229,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 177, + As: -1, Alias: &ast.Ident{ NamePos: 177, NameEnd: 178, @@ -281,7 +281,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 236, + As: -1, Alias: &ast.Ident{ NamePos: 236, NameEnd: 237, @@ -333,7 +333,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 289, + As: -1, Alias: &ast.Ident{ NamePos: 289, NameEnd: 290, @@ -385,7 +385,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 348, + As: -1, Alias: &ast.Ident{ NamePos: 348, NameEnd: 349, @@ -437,7 +437,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 402, + As: -1, Alias: &ast.Ident{ NamePos: 402, NameEnd: 403, @@ -489,7 +489,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 462, + As: -1, Alias: &ast.Ident{ NamePos: 462, NameEnd: 463, @@ -543,4 +543,4 @@ FROM } --- SQL -SELECT * FROM Singers AS A INNER JOIN Singers AS B ON A.SingerID = B.SingerID INNER JOIN Singers AS C ON A.SingerID = C.SingerID CROSS JOIN Singers AS D FULL OUTER JOIN Singers AS E ON A.SingerID = E.SingerID FULL OUTER JOIN Singers AS F ON A.SingerID = F.SingerID LEFT OUTER JOIN Singers AS G ON A.SingerID = G.SingerID LEFT OUTER JOIN Singers AS H ON A.SingerID = H.SingerID RIGHT OUTER JOIN Singers AS I ON A.SingerID = I.SingerID RIGHT OUTER JOIN Singers AS J ON A.SingerID = J.SingerID +SELECT * FROM Singers A INNER JOIN Singers B ON A.SingerID = B.SingerID INNER JOIN Singers C ON A.SingerID = C.SingerID CROSS JOIN Singers D FULL OUTER JOIN Singers E ON A.SingerID = E.SingerID FULL OUTER JOIN Singers F ON A.SingerID = F.SingerID LEFT OUTER JOIN Singers G ON A.SingerID = G.SingerID LEFT OUTER JOIN Singers H ON A.SingerID = H.SingerID RIGHT OUTER JOIN Singers I ON A.SingerID = I.SingerID RIGHT OUTER JOIN Singers J ON A.SingerID = J.SingerID diff --git a/testdata/result/query/select_singer_with_select_in_from_and_as.sql.txt b/testdata/result/query/select_singer_with_select_in_from_and_as.sql.txt index a081c2e1..fda2490e 100644 --- a/testdata/result/query/select_singer_with_select_in_from_and_as.sql.txt +++ b/testdata/result/query/select_singer_with_select_in_from_and_as.sql.txt @@ -73,7 +73,7 @@ FROM ( Limit: (*ast.Limit)(nil), }, As: &ast.AsAlias{ - As: -1, + As: 79, Alias: &ast.Ident{ NamePos: 82, NameEnd: 83, diff --git a/testdata/result/query/select_singer_with_single_column_subquery_with_at.sql.txt b/testdata/result/query/select_singer_with_single_column_subquery_with_at.sql.txt index ccbe8175..c420f982 100644 --- a/testdata/result/query/select_singer_with_single_column_subquery_with_at.sql.txt +++ b/testdata/result/query/select_singer_with_single_column_subquery_with_at.sql.txt @@ -60,7 +60,7 @@ SELECT ( }, }, As: &ast.AsAlias{ - As: -1, + As: 55, Alias: &ast.Ident{ NamePos: 58, NameEnd: 60, diff --git a/testdata/result/query/select_singer_with_table_alias.sql.txt b/testdata/result/query/select_singer_with_table_alias.sql.txt index a491a947..190521fb 100644 --- a/testdata/result/query/select_singer_with_table_alias.sql.txt +++ b/testdata/result/query/select_singer_with_table_alias.sql.txt @@ -38,7 +38,7 @@ FROM Singers S }, }, As: &ast.AsAlias{ - As: -1, + As: 27, Alias: &ast.Ident{ NamePos: 30, NameEnd: 32, @@ -73,7 +73,7 @@ FROM Singers S }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 61, + As: -1, Alias: &ast.Ident{ NamePos: 61, NameEnd: 62, @@ -92,4 +92,4 @@ FROM Singers S } --- SQL -SELECT S.*, S.SingerId AS ID, S.FirstName FROM Singers AS S +SELECT S.*, S.SingerId AS ID, S.FirstName FROM Singers S diff --git a/testdata/result/query/select_singer_with_table_alias_with_hint.sql.txt b/testdata/result/query/select_singer_with_table_alias_with_hint.sql.txt index 3c85380c..3d72f5bf 100644 --- a/testdata/result/query/select_singer_with_table_alias_with_hint.sql.txt +++ b/testdata/result/query/select_singer_with_table_alias_with_hint.sql.txt @@ -44,7 +44,7 @@ FROM }, }, As: &ast.AsAlias{ - As: -1, + As: 63, Alias: &ast.Ident{ NamePos: 66, NameEnd: 67, diff --git a/testdata/result/query/select_singer_with_tablesample.sql.txt b/testdata/result/query/select_singer_with_tablesample.sql.txt index bcbd6127..f333017d 100644 --- a/testdata/result/query/select_singer_with_tablesample.sql.txt +++ b/testdata/result/query/select_singer_with_tablesample.sql.txt @@ -37,7 +37,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: -1, + As: 26, Alias: &ast.Ident{ NamePos: 29, NameEnd: 30, @@ -68,7 +68,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: -1, + As: 75, Alias: &ast.Ident{ NamePos: 78, NameEnd: 79, @@ -100,7 +100,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: -1, + As: 127, Alias: &ast.Ident{ NamePos: 130, NameEnd: 131, diff --git a/testdata/result/query/select_singer_with_toplevel_join_hint.sql.txt b/testdata/result/query/select_singer_with_toplevel_join_hint.sql.txt index 2dba1755..450aca21 100644 --- a/testdata/result/query/select_singer_with_toplevel_join_hint.sql.txt +++ b/testdata/result/query/select_singer_with_toplevel_join_hint.sql.txt @@ -51,7 +51,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 51, + As: -1, Alias: &ast.Ident{ NamePos: 51, NameEnd: 52, @@ -68,7 +68,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 81, + As: -1, Alias: &ast.Ident{ NamePos: 81, NameEnd: 82, @@ -122,4 +122,4 @@ FROM } --- SQL -@{FORCE_JOIN_ORDER=TRUE} SELECT * FROM Singers AS A LEFT OUTER JOIN Singers AS B ON A.SingerID = B.SingerID +@{FORCE_JOIN_ORDER=TRUE} SELECT * FROM Singers A LEFT OUTER JOIN Singers B ON A.SingerID = B.SingerID diff --git a/testdata/result/query/select_struct_compare_eq.sql.txt b/testdata/result/query/select_struct_compare_eq.sql.txt index 9d58a237..047f65fe 100644 --- a/testdata/result/query/select_struct_compare_eq.sql.txt +++ b/testdata/result/query/select_struct_compare_eq.sql.txt @@ -109,7 +109,7 @@ SELECT ARRAY( Limit: (*ast.Limit)(nil), }, As: &ast.AsAlias{ - As: -1, + As: 92, Alias: &ast.Ident{ NamePos: 95, NameEnd: 96, @@ -131,42 +131,42 @@ SELECT ARRAY( Right: &ast.TypelessStructLiteral{ Struct: 109, Rparen: 131, - Values: []*ast.AsExpr{ - &ast.AsExpr{ + Values: []*ast.ExprAsName{ + &ast.ExprAsName{ Expr: &ast.TypelessStructLiteral{ Struct: 116, Rparen: 130, - Values: []*ast.AsExpr{ - &ast.AsExpr{ + Values: []*ast.ExprAsName{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 123, ValueEnd: 124, Base: 10, Value: "1", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 126, ValueEnd: 127, Base: 10, Value: "2", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 129, ValueEnd: 130, Base: 10, Value: "3", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, }, }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, }, }, diff --git a/testdata/result/query/select_tablesample_with_cross_join.sql.txt b/testdata/result/query/select_tablesample_with_cross_join.sql.txt index bf654a1f..b1e29e4a 100644 --- a/testdata/result/query/select_tablesample_with_cross_join.sql.txt +++ b/testdata/result/query/select_tablesample_with_cross_join.sql.txt @@ -34,7 +34,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 26, + As: -1, Alias: &ast.Ident{ NamePos: 26, NameEnd: 27, @@ -51,7 +51,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 51, + As: -1, Alias: &ast.Ident{ NamePos: 51, NameEnd: 52, @@ -86,4 +86,4 @@ FROM } --- SQL -SELECT * FROM Singers AS A CROSS JOIN Singers AS B TABLESAMPLE BERNOULLI (90 PERCENT) +SELECT * FROM Singers A CROSS JOIN Singers B TABLESAMPLE BERNOULLI (90 PERCENT) diff --git a/testdata/result/query/select_tablesample_with_table_alias.sql.txt b/testdata/result/query/select_tablesample_with_table_alias.sql.txt index 1f99e18d..102ff2ed 100644 --- a/testdata/result/query/select_tablesample_with_table_alias.sql.txt +++ b/testdata/result/query/select_tablesample_with_table_alias.sql.txt @@ -27,7 +27,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: -1, + As: 26, Alias: &ast.Ident{ NamePos: 29, NameEnd: 30, diff --git a/testdata/result/query/select_unnest_with_offset_and_alias.sql.txt b/testdata/result/query/select_unnest_with_offset_and_alias.sql.txt index ecedf6ad..3b88c15d 100644 --- a/testdata/result/query/select_unnest_with_offset_and_alias.sql.txt +++ b/testdata/result/query/select_unnest_with_offset_and_alias.sql.txt @@ -50,7 +50,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: -1, + As: 34, Alias: &ast.Ident{ NamePos: 37, NameEnd: 42, @@ -61,7 +61,7 @@ FROM With: 43, Offset: 48, As: &ast.AsAlias{ - As: -1, + As: 55, Alias: &ast.Ident{ NamePos: 58, NameEnd: 61, diff --git a/testdata/result/query/select_unnest_with_offset_and_alias_min.sql.txt b/testdata/result/query/select_unnest_with_offset_and_alias_min.sql.txt index b8d57900..684b1116 100644 --- a/testdata/result/query/select_unnest_with_offset_and_alias_min.sql.txt +++ b/testdata/result/query/select_unnest_with_offset_and_alias_min.sql.txt @@ -50,7 +50,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 34, + As: -1, Alias: &ast.Ident{ NamePos: 34, NameEnd: 39, @@ -61,7 +61,7 @@ FROM With: 40, Offset: 45, As: &ast.AsAlias{ - As: 52, + As: -1, Alias: &ast.Ident{ NamePos: 52, NameEnd: 55, @@ -81,4 +81,4 @@ FROM } --- SQL -SELECT * FROM UNNEST([1, 2, 3]) AS value WITH OFFSET AS num +SELECT * FROM UNNEST([1, 2, 3]) value WITH OFFSET num diff --git a/testdata/result/query/select_with_field_path.sql.txt b/testdata/result/query/select_with_field_path.sql.txt index 3b8d53c2..fb07732a 100644 --- a/testdata/result/query/select_with_field_path.sql.txt +++ b/testdata/result/query/select_with_field_path.sql.txt @@ -299,7 +299,7 @@ WHERE A.z.a = 2 }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: -1, + As: 257, Alias: &ast.Ident{ NamePos: 260, NameEnd: 261, diff --git a/testdata/result/query/select_with_sequence_function.sql.txt b/testdata/result/query/select_with_sequence_function.sql.txt index 491d47f0..333ec82a 100644 --- a/testdata/result/query/select_with_sequence_function.sql.txt +++ b/testdata/result/query/select_with_sequence_function.sql.txt @@ -34,7 +34,7 @@ SELECT GET_NEXT_SEQUENCE_VALUE(SEQUENCE my_sequence) as next_id Having: nil, }, As: &ast.AsAlias{ - As: -1, + As: 53, Alias: &ast.Ident{ NamePos: 56, NameEnd: 63, diff --git a/testdata/result/statement/create_or_replace_view.sql.txt b/testdata/result/statement/create_or_replace_view.sql.txt index 4a611ade..f3b38809 100644 --- a/testdata/result/statement/create_or_replace_view.sql.txt +++ b/testdata/result/statement/create_or_replace_view.sql.txt @@ -37,7 +37,7 @@ from singers }, }, As: &ast.AsAlias{ - As: -1, + As: 87, Alias: &ast.Ident{ NamePos: 90, NameEnd: 98, @@ -86,7 +86,7 @@ from singers }, }, As: &ast.AsAlias{ - As: -1, + As: 149, Alias: &ast.Ident{ NamePos: 152, NameEnd: 156, diff --git a/testdata/result/statement/create_view.sql.txt b/testdata/result/statement/create_view.sql.txt index da8ea657..e96ff6c8 100644 --- a/testdata/result/statement/create_view.sql.txt +++ b/testdata/result/statement/create_view.sql.txt @@ -37,7 +37,7 @@ from singers }, }, As: &ast.AsAlias{ - As: -1, + As: 76, Alias: &ast.Ident{ NamePos: 79, NameEnd: 87, @@ -86,7 +86,7 @@ from singers }, }, As: &ast.AsAlias{ - As: -1, + As: 138, Alias: &ast.Ident{ NamePos: 141, NameEnd: 145, diff --git a/testdata/result/statement/create_view_sql_security_definer.sql.txt b/testdata/result/statement/create_view_sql_security_definer.sql.txt index 5627d9ca..6d134f80 100644 --- a/testdata/result/statement/create_view_sql_security_definer.sql.txt +++ b/testdata/result/statement/create_view_sql_security_definer.sql.txt @@ -37,7 +37,7 @@ from singers }, }, As: &ast.AsAlias{ - As: -1, + As: 76, Alias: &ast.Ident{ NamePos: 79, NameEnd: 87, @@ -86,7 +86,7 @@ from singers }, }, As: &ast.AsAlias{ - As: -1, + As: 138, Alias: &ast.Ident{ NamePos: 141, NameEnd: 145, diff --git a/testdata/result/statement/delete_as.sql.txt b/testdata/result/statement/delete_as.sql.txt index d368be5c..2eee871a 100644 --- a/testdata/result/statement/delete_as.sql.txt +++ b/testdata/result/statement/delete_as.sql.txt @@ -9,7 +9,7 @@ delete foo as F where F.foo = 1 Name: "foo", }, As: &ast.AsAlias{ - As: -1, + As: 11, Alias: &ast.Ident{ NamePos: 14, NameEnd: 15, diff --git a/testdata/result/statement/select_alias_without_as.sql.txt b/testdata/result/statement/select_alias_without_as.sql.txt index da93020e..c4604a96 100644 --- a/testdata/result/statement/select_alias_without_as.sql.txt +++ b/testdata/result/statement/select_alias_without_as.sql.txt @@ -18,7 +18,7 @@ select 1 A Value: "1", }, As: &ast.AsAlias{ - As: 9, + As: -1, Alias: &ast.Ident{ NamePos: 9, NameEnd: 10, @@ -37,4 +37,4 @@ select 1 A } --- SQL -SELECT 1 AS A +SELECT 1 A diff --git a/testdata/result/statement/select_call_with_named_expr.sql.txt b/testdata/result/statement/select_call_with_named_expr.sql.txt index 78d1d157..bae8b868 100644 --- a/testdata/result/statement/select_call_with_named_expr.sql.txt +++ b/testdata/result/statement/select_call_with_named_expr.sql.txt @@ -54,7 +54,7 @@ WHERE a.SingerId = 1 AND SEARCH(a.DescriptionTokens, 'classic albums', enhance_q }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 44, + As: -1, Alias: &ast.Ident{ NamePos: 44, NameEnd: 45, @@ -150,4 +150,4 @@ WHERE a.SingerId = 1 AND SEARCH(a.DescriptionTokens, 'classic albums', enhance_q } --- SQL -SELECT a.AlbumId, a.Description FROM Albums AS a WHERE a.SingerId = 1 AND SEARCH(a.DescriptionTokens, "classic albums", enhance_query => TRUE) +SELECT a.AlbumId, a.Description FROM Albums a WHERE a.SingerId = 1 AND SEARCH(a.DescriptionTokens, "classic albums", enhance_query => TRUE) diff --git a/testdata/result/statement/select_cast.sql.txt b/testdata/result/statement/select_cast.sql.txt index 71151fd9..3ee5415f 100644 --- a/testdata/result/statement/select_cast.sql.txt +++ b/testdata/result/statement/select_cast.sql.txt @@ -59,7 +59,7 @@ limit cast(1 as INT64) offset cast(@foo as INT64) &ast.TypelessStructLiteral{ Struct: 53, Rparen: 60, - Values: []*ast.AsExpr(nil), + Values: []*ast.ExprAsName(nil), }, &ast.IntLiteral{ ValuePos: 63, diff --git a/testdata/result/statement/select_expr.sql.txt b/testdata/result/statement/select_expr.sql.txt index e6c89c30..9f1a2bc5 100644 --- a/testdata/result/statement/select_expr.sql.txt +++ b/testdata/result/statement/select_expr.sql.txt @@ -340,7 +340,7 @@ select 1 + 2, 1 - 2, Value: "1", }, As: &ast.AsAlias{ - As: 204, + As: -1, Alias: &ast.Ident{ NamePos: 204, NameEnd: 207, @@ -915,7 +915,7 @@ select 1 + 2, 1 - 2, }, }, As: &ast.AsAlias{ - As: -1, + As: 792, Alias: &ast.Ident{ NamePos: 795, NameEnd: 801, @@ -934,4 +934,4 @@ select 1 + 2, 1 - 2, } --- SQL -SELECT 1 + 2, 1 - 2, 1 * 2, 2 / 2, +1 + +1, -1 + -1, +1.2, -3.4, ~1 ^ ~1, 1 ^ 2, 2 & 1, 2 | 1, 1 << 2, 2 >> 1, foo.bar * +foo.bar * -foo.bar, (SELECT 1 AS `1`).`1`, NOT NOT TRUE, [1, 2, 3][OFFSET(1)], [1, 2, 3][OFFSET(1)], [1, 2, 3][ORDINAL(1)], CASE WHEN 1 = 1 THEN "1 = 1" ELSE "else" END, CASE 1 WHEN 1 THEN "1" WHEN 2 THEN "2" ELSE "other" END, date_add(DATE "2019-09-01", INTERVAL 5 day), timestamp_add(TIMESTAMP "2019-09-01 08:11:22", INTERVAL 5 hour), 1 IN (1, 2, 3), 2 IN UNNEST([1, 2, 3]), 3 IN (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3), [1] || [2], IF(1 > 1, 1, 2) + 1 AS result +SELECT 1 + 2, 1 - 2, 1 * 2, 2 / 2, +1 + +1, -1 + -1, +1.2, -3.4, ~1 ^ ~1, 1 ^ 2, 2 & 1, 2 | 1, 1 << 2, 2 >> 1, foo.bar * +foo.bar * -foo.bar, (SELECT 1 `1`).`1`, NOT NOT TRUE, [1, 2, 3][OFFSET(1)], [1, 2, 3][OFFSET(1)], [1, 2, 3][ORDINAL(1)], CASE WHEN 1 = 1 THEN "1 = 1" ELSE "else" END, CASE 1 WHEN 1 THEN "1" WHEN 2 THEN "2" ELSE "other" END, date_add(DATE "2019-09-01", INTERVAL 5 day), timestamp_add(TIMESTAMP "2019-09-01 08:11:22", INTERVAL 5 hour), 1 IN (1, 2, 3), 2 IN UNNEST([1, 2, 3]), 3 IN (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3), [1] || [2], IF(1 > 1, 1, 2) + 1 AS result diff --git a/testdata/result/statement/select_from_implicit_unnest.sql.txt b/testdata/result/statement/select_from_implicit_unnest.sql.txt index e29c72a3..f1d12b88 100644 --- a/testdata/result/statement/select_from_implicit_unnest.sql.txt +++ b/testdata/result/statement/select_from_implicit_unnest.sql.txt @@ -81,7 +81,7 @@ FROM UNNEST([STRUCT>(["foo"])]) AS t, }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: -1, + As: 64, Alias: &ast.Ident{ NamePos: 67, NameEnd: 68, @@ -108,7 +108,7 @@ FROM UNNEST([STRUCT>(["foo"])]) AS t, }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: -1, + As: 81, Alias: &ast.Ident{ NamePos: 84, NameEnd: 85, @@ -119,7 +119,7 @@ FROM UNNEST([STRUCT>(["foo"])]) AS t, With: 86, Offset: 91, As: &ast.AsAlias{ - As: -1, + As: 98, Alias: &ast.Ident{ NamePos: 101, NameEnd: 104, diff --git a/testdata/result/statement/select_from_path.sql.txt b/testdata/result/statement/select_from_path.sql.txt index f3331a1d..d58a1d70 100644 --- a/testdata/result/statement/select_from_path.sql.txt +++ b/testdata/result/statement/select_from_path.sql.txt @@ -35,7 +35,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: -1, + As: 44, Alias: &ast.Ident{ NamePos: 47, NameEnd: 48, diff --git a/testdata/result/statement/select_literals_all.sql.txt b/testdata/result/statement/select_literals_all.sql.txt index 2557efd7..9f7901bc 100644 --- a/testdata/result/statement/select_literals_all.sql.txt +++ b/testdata/result/statement/select_literals_all.sql.txt @@ -395,33 +395,33 @@ lines''', Expr: &ast.TypelessStructLiteral{ Struct: 467, Rparen: 481, - Values: []*ast.AsExpr{ - &ast.AsExpr{ + Values: []*ast.ExprAsName{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 474, ValueEnd: 475, Base: 10, Value: "1", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 477, ValueEnd: 478, Base: 10, Value: "2", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 480, ValueEnd: 481, Base: 10, Value: "3", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, }, }, diff --git a/testdata/result/statement/select_literals_date.sql.txt b/testdata/result/statement/select_literals_date.sql.txt index fd6b3596..7d21137b 100644 --- a/testdata/result/statement/select_literals_date.sql.txt +++ b/testdata/result/statement/select_literals_date.sql.txt @@ -149,7 +149,7 @@ SELECT Having: nil, }, As: &ast.AsAlias{ - As: -1, + As: 270, Alias: &ast.Ident{ NamePos: 273, NameEnd: 276, @@ -180,7 +180,7 @@ SELECT Having: nil, }, As: &ast.AsAlias{ - As: -1, + As: 304, Alias: &ast.Ident{ NamePos: 307, NameEnd: 310, diff --git a/testdata/result/statement/select_literals_struct.sql.txt b/testdata/result/statement/select_literals_struct.sql.txt index 9ce6fc39..32133a42 100644 --- a/testdata/result/statement/select_literals_struct.sql.txt +++ b/testdata/result/statement/select_literals_struct.sql.txt @@ -38,33 +38,33 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 22, Rparen: 36, - Values: []*ast.AsExpr{ - &ast.AsExpr{ + Values: []*ast.ExprAsName{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 29, ValueEnd: 30, Base: 10, Value: "1", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 32, ValueEnd: 33, Base: 10, Value: "2", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 35, ValueEnd: 36, Base: 10, Value: "3", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, }, }, @@ -92,31 +92,31 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 55, Rparen: 72, - Values: []*ast.AsExpr{ - &ast.AsExpr{ + Values: []*ast.ExprAsName{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 62, ValueEnd: 63, Base: 10, Value: "1", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 65, ValueEnd: 66, Base: 10, Value: "2", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.BoolLiteral{ ValuePos: 68, Value: true, }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, }, }, @@ -224,44 +224,53 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 151, Rparen: 180, - Values: []*ast.AsExpr{ - &ast.AsExpr{ + Values: []*ast.ExprAsName{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 158, ValueEnd: 159, Base: 10, Value: "1", }, - Name: &ast.Ident{ - NamePos: 163, - NameEnd: 164, - Name: "X", + As: &ast.AsAlias{ + As: 160, + Alias: &ast.Ident{ + NamePos: 163, + NameEnd: 164, + Name: "X", + }, }, }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 166, ValueEnd: 167, Base: 10, Value: "2", }, - Name: &ast.Ident{ - NamePos: 171, - NameEnd: 172, - Name: "Y", + As: &ast.AsAlias{ + As: 168, + Alias: &ast.Ident{ + NamePos: 171, + NameEnd: 172, + Name: "Y", + }, }, }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 174, ValueEnd: 175, Base: 10, Value: "3", }, - Name: &ast.Ident{ - NamePos: 179, - NameEnd: 180, - Name: "Z", + As: &ast.AsAlias{ + As: 176, + Alias: &ast.Ident{ + NamePos: 179, + NameEnd: 180, + Name: "Z", + }, }, }, }, @@ -430,37 +439,40 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 309, Rparen: 328, - Values: []*ast.AsExpr{ - &ast.AsExpr{ + Values: []*ast.ExprAsName{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 316, ValueEnd: 317, Base: 10, Value: "1", }, - Name: &ast.Ident{ - NamePos: 321, - NameEnd: 322, - Name: "X", + As: &ast.AsAlias{ + As: 318, + Alias: &ast.Ident{ + NamePos: 321, + NameEnd: 322, + Name: "X", + }, }, }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 324, ValueEnd: 325, Base: 10, Value: "2", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 327, ValueEnd: 328, Base: 10, Value: "3", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, }, }, @@ -579,18 +591,21 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 410, Rparen: 423, - Values: []*ast.AsExpr{ - &ast.AsExpr{ + Values: []*ast.ExprAsName{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 417, ValueEnd: 418, Base: 10, Value: "1", }, - Name: &ast.Ident{ - NamePos: 422, - NameEnd: 423, - Name: "X", + As: &ast.AsAlias{ + As: 419, + Alias: &ast.Ident{ + NamePos: 422, + NameEnd: 423, + Name: "X", + }, }, }, }, @@ -661,15 +676,15 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 476, Rparen: 484, - Values: []*ast.AsExpr{ - &ast.AsExpr{ + Values: []*ast.ExprAsName{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 483, ValueEnd: 484, Base: 10, Value: "1", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, }, }, @@ -724,7 +739,7 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 531, Rparen: 538, - Values: []*ast.AsExpr(nil), + Values: []*ast.ExprAsName(nil), }, }, }, diff --git a/testdata/result/statement/select_nest_complex.sql.txt b/testdata/result/statement/select_nest_complex.sql.txt index e328f52b..81059415 100644 --- a/testdata/result/statement/select_nest_complex.sql.txt +++ b/testdata/result/statement/select_nest_complex.sql.txt @@ -58,7 +58,7 @@ from ( Value: "1", }, As: &ast.AsAlias{ - As: 32, + As: -1, Alias: &ast.Ident{ NamePos: 32, NameEnd: 33, @@ -170,7 +170,7 @@ from ( Value: "1", }, As: &ast.AsAlias{ - As: 113, + As: -1, Alias: &ast.Ident{ NamePos: 113, NameEnd: 114, @@ -186,7 +186,7 @@ from ( Value: "2", }, As: &ast.AsAlias{ - As: 118, + As: -1, Alias: &ast.Ident{ NamePos: 118, NameEnd: 119, @@ -229,4 +229,4 @@ from ( } --- SQL -SELECT * FROM ((((SELECT 1 AS A UNION ALL (SELECT 2)) UNION DISTINCT (SELECT 1)) LIMIT 1) INNER JOIN (SELECT 1 AS A, 2 AS B) USING (A)) +SELECT * FROM ((((SELECT 1 A UNION ALL (SELECT 2)) UNION DISTINCT (SELECT 1)) LIMIT 1) INNER JOIN (SELECT 1 A, 2 B) USING (A)) diff --git a/testdata/result/statement/select_singer_with_column_names.sql.txt b/testdata/result/statement/select_singer_with_column_names.sql.txt index 2b8d7c19..7bef784a 100644 --- a/testdata/result/statement/select_singer_with_column_names.sql.txt +++ b/testdata/result/statement/select_singer_with_column_names.sql.txt @@ -23,7 +23,7 @@ FROM Singers Name: "SingerId", }, As: &ast.AsAlias{ - As: -1, + As: 18, Alias: &ast.Ident{ NamePos: 21, NameEnd: 23, diff --git a/testdata/result/statement/select_singer_with_cross_join.sql.txt b/testdata/result/statement/select_singer_with_cross_join.sql.txt index b6b16376..f7be0a42 100644 --- a/testdata/result/statement/select_singer_with_cross_join.sql.txt +++ b/testdata/result/statement/select_singer_with_cross_join.sql.txt @@ -33,7 +33,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 26, + As: -1, Alias: &ast.Ident{ NamePos: 26, NameEnd: 27, @@ -50,7 +50,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 51, + As: -1, Alias: &ast.Ident{ NamePos: 51, NameEnd: 52, @@ -71,4 +71,4 @@ FROM } --- SQL -SELECT * FROM Singers AS A CROSS JOIN Singers AS B +SELECT * FROM Singers A CROSS JOIN Singers B diff --git a/testdata/result/statement/select_singer_with_full_join.sql.txt b/testdata/result/statement/select_singer_with_full_join.sql.txt index 31d96645..8e364024 100644 --- a/testdata/result/statement/select_singer_with_full_join.sql.txt +++ b/testdata/result/statement/select_singer_with_full_join.sql.txt @@ -32,7 +32,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: -1, + As: 26, Alias: &ast.Ident{ NamePos: 29, NameEnd: 30, @@ -49,7 +49,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: -1, + As: 42, Alias: &ast.Ident{ NamePos: 45, NameEnd: 46, diff --git a/testdata/result/statement/select_singer_with_hash_join.sql.txt b/testdata/result/statement/select_singer_with_hash_join.sql.txt index c80ffc14..6a385ba4 100644 --- a/testdata/result/statement/select_singer_with_hash_join.sql.txt +++ b/testdata/result/statement/select_singer_with_hash_join.sql.txt @@ -48,7 +48,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 26, + As: -1, Alias: &ast.Ident{ NamePos: 26, NameEnd: 27, @@ -65,7 +65,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 50, + As: -1, Alias: &ast.Ident{ NamePos: 50, NameEnd: 51, @@ -117,7 +117,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 103, + As: -1, Alias: &ast.Ident{ NamePos: 103, NameEnd: 104, @@ -169,7 +169,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 155, + As: -1, Alias: &ast.Ident{ NamePos: 155, NameEnd: 156, @@ -223,4 +223,4 @@ FROM } --- SQL -SELECT * FROM Singers AS A INNER JOIN Singers AS B ON A.SingerID = B.SingerID INNER JOIN Singer AS C ON B.SingerID = C.SingerID INNER JOIN Singer AS D ON C.SingerID = D.SingerID +SELECT * FROM Singers A INNER JOIN Singers B ON A.SingerID = B.SingerID INNER JOIN Singer C ON B.SingerID = C.SingerID INNER JOIN Singer D ON C.SingerID = D.SingerID diff --git a/testdata/result/statement/select_singer_with_join.sql.txt b/testdata/result/statement/select_singer_with_join.sql.txt index be653b60..ab573b3f 100644 --- a/testdata/result/statement/select_singer_with_join.sql.txt +++ b/testdata/result/statement/select_singer_with_join.sql.txt @@ -34,7 +34,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 26, + As: -1, Alias: &ast.Ident{ NamePos: 26, NameEnd: 27, @@ -51,7 +51,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 56, + As: -1, Alias: &ast.Ident{ NamePos: 56, NameEnd: 57, @@ -105,4 +105,4 @@ FROM } --- SQL -SELECT * FROM Singers AS A LEFT OUTER JOIN Singers AS B ON A.SingerID = B.SingerID +SELECT * FROM Singers A LEFT OUTER JOIN Singers B ON A.SingerID = B.SingerID diff --git a/testdata/result/statement/select_singer_with_join_hint.sql.txt b/testdata/result/statement/select_singer_with_join_hint.sql.txt index 46983dcd..92a14a85 100644 --- a/testdata/result/statement/select_singer_with_join_hint.sql.txt +++ b/testdata/result/statement/select_singer_with_join_hint.sql.txt @@ -122,7 +122,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 26, + As: -1, Alias: &ast.Ident{ NamePos: 26, NameEnd: 27, @@ -139,7 +139,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 80, + As: -1, Alias: &ast.Ident{ NamePos: 80, NameEnd: 81, @@ -191,7 +191,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 150, + As: -1, Alias: &ast.Ident{ NamePos: 150, NameEnd: 151, @@ -243,7 +243,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 221, + As: -1, Alias: &ast.Ident{ NamePos: 221, NameEnd: 222, @@ -295,7 +295,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 291, + As: -1, Alias: &ast.Ident{ NamePos: 291, NameEnd: 292, @@ -349,4 +349,4 @@ FROM } --- SQL -SELECT * FROM Singers AS A LEFT OUTER JOIN @{FORCE_JOIN_ORDER=TRUE} Singers AS B ON A.SingerID = B.SingerID INNER JOIN @{JOIN_TYPE=HASH_JOIN} Singers AS C ON A.SingerID = C.SingerID INNER JOIN @{JOIN_TYPE=APPLY_JOIN} Singers AS D ON A.SingerID = D.SingerID INNER JOIN @{JOIN_TYPE=LOOP_JOIN} Singers AS E ON A.SingerID = E.SingerID +SELECT * FROM Singers A LEFT OUTER JOIN @{FORCE_JOIN_ORDER=TRUE} Singers B ON A.SingerID = B.SingerID INNER JOIN @{JOIN_TYPE=HASH_JOIN} Singers C ON A.SingerID = C.SingerID INNER JOIN @{JOIN_TYPE=APPLY_JOIN} Singers D ON A.SingerID = D.SingerID INNER JOIN @{JOIN_TYPE=LOOP_JOIN} Singers E ON A.SingerID = E.SingerID diff --git a/testdata/result/statement/select_singer_with_join_twice.sql.txt b/testdata/result/statement/select_singer_with_join_twice.sql.txt index b7d09824..035780a4 100644 --- a/testdata/result/statement/select_singer_with_join_twice.sql.txt +++ b/testdata/result/statement/select_singer_with_join_twice.sql.txt @@ -41,7 +41,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 26, + As: -1, Alias: &ast.Ident{ NamePos: 26, NameEnd: 27, @@ -58,7 +58,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 45, + As: -1, Alias: &ast.Ident{ NamePos: 45, NameEnd: 46, @@ -110,7 +110,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 99, + As: -1, Alias: &ast.Ident{ NamePos: 99, NameEnd: 100, @@ -164,4 +164,4 @@ FROM } --- SQL -SELECT * FROM Singers AS A INNER JOIN Singers AS B ON A.SingerID = B.SingerID INNER JOIN Singers AS C ON A.SingerID = C.SingerID +SELECT * FROM Singers A INNER JOIN Singers B ON A.SingerID = B.SingerID INNER JOIN Singers C ON A.SingerID = C.SingerID diff --git a/testdata/result/statement/select_singer_with_join_using.sql.txt b/testdata/result/statement/select_singer_with_join_using.sql.txt index 61f23fe2..e37df1cb 100644 --- a/testdata/result/statement/select_singer_with_join_using.sql.txt +++ b/testdata/result/statement/select_singer_with_join_using.sql.txt @@ -34,7 +34,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 26, + As: -1, Alias: &ast.Ident{ NamePos: 26, NameEnd: 27, @@ -51,7 +51,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 56, + As: -1, Alias: &ast.Ident{ NamePos: 56, NameEnd: 57, @@ -87,4 +87,4 @@ FROM } --- SQL -SELECT * FROM Singers AS A LEFT OUTER JOIN Singers AS B USING (SingerID, FirstName) +SELECT * FROM Singers A LEFT OUTER JOIN Singers B USING (SingerID, FirstName) diff --git a/testdata/result/statement/select_singer_with_join_various.sql.txt b/testdata/result/statement/select_singer_with_join_various.sql.txt index 823859c1..45d847b9 100644 --- a/testdata/result/statement/select_singer_with_join_various.sql.txt +++ b/testdata/result/statement/select_singer_with_join_various.sql.txt @@ -89,7 +89,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 26, + As: -1, Alias: &ast.Ident{ NamePos: 26, NameEnd: 27, @@ -106,7 +106,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 45, + As: -1, Alias: &ast.Ident{ NamePos: 45, NameEnd: 46, @@ -158,7 +158,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 99, + As: -1, Alias: &ast.Ident{ NamePos: 99, NameEnd: 100, @@ -210,7 +210,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 153, + As: -1, Alias: &ast.Ident{ NamePos: 153, NameEnd: 154, @@ -229,7 +229,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 177, + As: -1, Alias: &ast.Ident{ NamePos: 177, NameEnd: 178, @@ -281,7 +281,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 236, + As: -1, Alias: &ast.Ident{ NamePos: 236, NameEnd: 237, @@ -333,7 +333,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 289, + As: -1, Alias: &ast.Ident{ NamePos: 289, NameEnd: 290, @@ -385,7 +385,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 348, + As: -1, Alias: &ast.Ident{ NamePos: 348, NameEnd: 349, @@ -437,7 +437,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 402, + As: -1, Alias: &ast.Ident{ NamePos: 402, NameEnd: 403, @@ -489,7 +489,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 462, + As: -1, Alias: &ast.Ident{ NamePos: 462, NameEnd: 463, @@ -543,4 +543,4 @@ FROM } --- SQL -SELECT * FROM Singers AS A INNER JOIN Singers AS B ON A.SingerID = B.SingerID INNER JOIN Singers AS C ON A.SingerID = C.SingerID CROSS JOIN Singers AS D FULL OUTER JOIN Singers AS E ON A.SingerID = E.SingerID FULL OUTER JOIN Singers AS F ON A.SingerID = F.SingerID LEFT OUTER JOIN Singers AS G ON A.SingerID = G.SingerID LEFT OUTER JOIN Singers AS H ON A.SingerID = H.SingerID RIGHT OUTER JOIN Singers AS I ON A.SingerID = I.SingerID RIGHT OUTER JOIN Singers AS J ON A.SingerID = J.SingerID +SELECT * FROM Singers A INNER JOIN Singers B ON A.SingerID = B.SingerID INNER JOIN Singers C ON A.SingerID = C.SingerID CROSS JOIN Singers D FULL OUTER JOIN Singers E ON A.SingerID = E.SingerID FULL OUTER JOIN Singers F ON A.SingerID = F.SingerID LEFT OUTER JOIN Singers G ON A.SingerID = G.SingerID LEFT OUTER JOIN Singers H ON A.SingerID = H.SingerID RIGHT OUTER JOIN Singers I ON A.SingerID = I.SingerID RIGHT OUTER JOIN Singers J ON A.SingerID = J.SingerID diff --git a/testdata/result/statement/select_singer_with_select_in_from_and_as.sql.txt b/testdata/result/statement/select_singer_with_select_in_from_and_as.sql.txt index a081c2e1..fda2490e 100644 --- a/testdata/result/statement/select_singer_with_select_in_from_and_as.sql.txt +++ b/testdata/result/statement/select_singer_with_select_in_from_and_as.sql.txt @@ -73,7 +73,7 @@ FROM ( Limit: (*ast.Limit)(nil), }, As: &ast.AsAlias{ - As: -1, + As: 79, Alias: &ast.Ident{ NamePos: 82, NameEnd: 83, diff --git a/testdata/result/statement/select_singer_with_single_column_subquery_with_at.sql.txt b/testdata/result/statement/select_singer_with_single_column_subquery_with_at.sql.txt index ccbe8175..c420f982 100644 --- a/testdata/result/statement/select_singer_with_single_column_subquery_with_at.sql.txt +++ b/testdata/result/statement/select_singer_with_single_column_subquery_with_at.sql.txt @@ -60,7 +60,7 @@ SELECT ( }, }, As: &ast.AsAlias{ - As: -1, + As: 55, Alias: &ast.Ident{ NamePos: 58, NameEnd: 60, diff --git a/testdata/result/statement/select_singer_with_table_alias.sql.txt b/testdata/result/statement/select_singer_with_table_alias.sql.txt index a491a947..190521fb 100644 --- a/testdata/result/statement/select_singer_with_table_alias.sql.txt +++ b/testdata/result/statement/select_singer_with_table_alias.sql.txt @@ -38,7 +38,7 @@ FROM Singers S }, }, As: &ast.AsAlias{ - As: -1, + As: 27, Alias: &ast.Ident{ NamePos: 30, NameEnd: 32, @@ -73,7 +73,7 @@ FROM Singers S }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 61, + As: -1, Alias: &ast.Ident{ NamePos: 61, NameEnd: 62, @@ -92,4 +92,4 @@ FROM Singers S } --- SQL -SELECT S.*, S.SingerId AS ID, S.FirstName FROM Singers AS S +SELECT S.*, S.SingerId AS ID, S.FirstName FROM Singers S diff --git a/testdata/result/statement/select_singer_with_table_alias_with_hint.sql.txt b/testdata/result/statement/select_singer_with_table_alias_with_hint.sql.txt index 3c85380c..3d72f5bf 100644 --- a/testdata/result/statement/select_singer_with_table_alias_with_hint.sql.txt +++ b/testdata/result/statement/select_singer_with_table_alias_with_hint.sql.txt @@ -44,7 +44,7 @@ FROM }, }, As: &ast.AsAlias{ - As: -1, + As: 63, Alias: &ast.Ident{ NamePos: 66, NameEnd: 67, diff --git a/testdata/result/statement/select_singer_with_tablesample.sql.txt b/testdata/result/statement/select_singer_with_tablesample.sql.txt index bcbd6127..f333017d 100644 --- a/testdata/result/statement/select_singer_with_tablesample.sql.txt +++ b/testdata/result/statement/select_singer_with_tablesample.sql.txt @@ -37,7 +37,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: -1, + As: 26, Alias: &ast.Ident{ NamePos: 29, NameEnd: 30, @@ -68,7 +68,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: -1, + As: 75, Alias: &ast.Ident{ NamePos: 78, NameEnd: 79, @@ -100,7 +100,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: -1, + As: 127, Alias: &ast.Ident{ NamePos: 130, NameEnd: 131, diff --git a/testdata/result/statement/select_singer_with_toplevel_join_hint.sql.txt b/testdata/result/statement/select_singer_with_toplevel_join_hint.sql.txt index 2dba1755..450aca21 100644 --- a/testdata/result/statement/select_singer_with_toplevel_join_hint.sql.txt +++ b/testdata/result/statement/select_singer_with_toplevel_join_hint.sql.txt @@ -51,7 +51,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 51, + As: -1, Alias: &ast.Ident{ NamePos: 51, NameEnd: 52, @@ -68,7 +68,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 81, + As: -1, Alias: &ast.Ident{ NamePos: 81, NameEnd: 82, @@ -122,4 +122,4 @@ FROM } --- SQL -@{FORCE_JOIN_ORDER=TRUE} SELECT * FROM Singers AS A LEFT OUTER JOIN Singers AS B ON A.SingerID = B.SingerID +@{FORCE_JOIN_ORDER=TRUE} SELECT * FROM Singers A LEFT OUTER JOIN Singers B ON A.SingerID = B.SingerID diff --git a/testdata/result/statement/select_struct_compare_eq.sql.txt b/testdata/result/statement/select_struct_compare_eq.sql.txt index 9d58a237..047f65fe 100644 --- a/testdata/result/statement/select_struct_compare_eq.sql.txt +++ b/testdata/result/statement/select_struct_compare_eq.sql.txt @@ -109,7 +109,7 @@ SELECT ARRAY( Limit: (*ast.Limit)(nil), }, As: &ast.AsAlias{ - As: -1, + As: 92, Alias: &ast.Ident{ NamePos: 95, NameEnd: 96, @@ -131,42 +131,42 @@ SELECT ARRAY( Right: &ast.TypelessStructLiteral{ Struct: 109, Rparen: 131, - Values: []*ast.AsExpr{ - &ast.AsExpr{ + Values: []*ast.ExprAsName{ + &ast.ExprAsName{ Expr: &ast.TypelessStructLiteral{ Struct: 116, Rparen: 130, - Values: []*ast.AsExpr{ - &ast.AsExpr{ + Values: []*ast.ExprAsName{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 123, ValueEnd: 124, Base: 10, Value: "1", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 126, ValueEnd: 127, Base: 10, Value: "2", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, - &ast.AsExpr{ + &ast.ExprAsName{ Expr: &ast.IntLiteral{ ValuePos: 129, ValueEnd: 130, Base: 10, Value: "3", }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, }, }, - Name: (*ast.Ident)(nil), + As: (*ast.AsAlias)(nil), }, }, }, diff --git a/testdata/result/statement/select_tablesample_with_cross_join.sql.txt b/testdata/result/statement/select_tablesample_with_cross_join.sql.txt index bf654a1f..b1e29e4a 100644 --- a/testdata/result/statement/select_tablesample_with_cross_join.sql.txt +++ b/testdata/result/statement/select_tablesample_with_cross_join.sql.txt @@ -34,7 +34,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 26, + As: -1, Alias: &ast.Ident{ NamePos: 26, NameEnd: 27, @@ -51,7 +51,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 51, + As: -1, Alias: &ast.Ident{ NamePos: 51, NameEnd: 52, @@ -86,4 +86,4 @@ FROM } --- SQL -SELECT * FROM Singers AS A CROSS JOIN Singers AS B TABLESAMPLE BERNOULLI (90 PERCENT) +SELECT * FROM Singers A CROSS JOIN Singers B TABLESAMPLE BERNOULLI (90 PERCENT) diff --git a/testdata/result/statement/select_tablesample_with_table_alias.sql.txt b/testdata/result/statement/select_tablesample_with_table_alias.sql.txt index 1f99e18d..102ff2ed 100644 --- a/testdata/result/statement/select_tablesample_with_table_alias.sql.txt +++ b/testdata/result/statement/select_tablesample_with_table_alias.sql.txt @@ -27,7 +27,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: -1, + As: 26, Alias: &ast.Ident{ NamePos: 29, NameEnd: 30, diff --git a/testdata/result/statement/select_unnest_with_offset_and_alias.sql.txt b/testdata/result/statement/select_unnest_with_offset_and_alias.sql.txt index ecedf6ad..3b88c15d 100644 --- a/testdata/result/statement/select_unnest_with_offset_and_alias.sql.txt +++ b/testdata/result/statement/select_unnest_with_offset_and_alias.sql.txt @@ -50,7 +50,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: -1, + As: 34, Alias: &ast.Ident{ NamePos: 37, NameEnd: 42, @@ -61,7 +61,7 @@ FROM With: 43, Offset: 48, As: &ast.AsAlias{ - As: -1, + As: 55, Alias: &ast.Ident{ NamePos: 58, NameEnd: 61, diff --git a/testdata/result/statement/select_unnest_with_offset_and_alias_min.sql.txt b/testdata/result/statement/select_unnest_with_offset_and_alias_min.sql.txt index b8d57900..684b1116 100644 --- a/testdata/result/statement/select_unnest_with_offset_and_alias_min.sql.txt +++ b/testdata/result/statement/select_unnest_with_offset_and_alias_min.sql.txt @@ -50,7 +50,7 @@ FROM }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: 34, + As: -1, Alias: &ast.Ident{ NamePos: 34, NameEnd: 39, @@ -61,7 +61,7 @@ FROM With: 40, Offset: 45, As: &ast.AsAlias{ - As: 52, + As: -1, Alias: &ast.Ident{ NamePos: 52, NameEnd: 55, @@ -81,4 +81,4 @@ FROM } --- SQL -SELECT * FROM UNNEST([1, 2, 3]) AS value WITH OFFSET AS num +SELECT * FROM UNNEST([1, 2, 3]) value WITH OFFSET num diff --git a/testdata/result/statement/select_with_field_path.sql.txt b/testdata/result/statement/select_with_field_path.sql.txt index 3b8d53c2..fb07732a 100644 --- a/testdata/result/statement/select_with_field_path.sql.txt +++ b/testdata/result/statement/select_with_field_path.sql.txt @@ -299,7 +299,7 @@ WHERE A.z.a = 2 }, Hint: (*ast.Hint)(nil), As: &ast.AsAlias{ - As: -1, + As: 257, Alias: &ast.Ident{ NamePos: 260, NameEnd: 261, diff --git a/testdata/result/statement/select_with_sequence_function.sql.txt b/testdata/result/statement/select_with_sequence_function.sql.txt index 491d47f0..333ec82a 100644 --- a/testdata/result/statement/select_with_sequence_function.sql.txt +++ b/testdata/result/statement/select_with_sequence_function.sql.txt @@ -34,7 +34,7 @@ SELECT GET_NEXT_SEQUENCE_VALUE(SEQUENCE my_sequence) as next_id Having: nil, }, As: &ast.AsAlias{ - As: -1, + As: 53, Alias: &ast.Ident{ NamePos: 56, NameEnd: 63, diff --git a/testdata/result/statement/update_as.sql.txt b/testdata/result/statement/update_as.sql.txt index 6f269aff..a647ea85 100644 --- a/testdata/result/statement/update_as.sql.txt +++ b/testdata/result/statement/update_as.sql.txt @@ -9,7 +9,7 @@ update foo as F set F.foo = F.bar + 1 where foo = F.bar Name: "foo", }, As: &ast.AsAlias{ - As: -1, + As: 11, Alias: &ast.Ident{ NamePos: 14, NameEnd: 15, From c256076c9caf0f7e9e27d5d55fc9c25ca9f3c959 Mon Sep 17 00:00:00 2001 From: Hiroya Fujinami Date: Mon, 28 Oct 2024 20:28:56 +0900 Subject: [PATCH 19/22] Update parser.go Co-authored-by: apstndb <803393+apstndb@users.noreply.github.com> --- parser.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parser.go b/parser.go index 8a451c4a..34d99543 100644 --- a/parser.go +++ b/parser.go @@ -1807,7 +1807,7 @@ func (p *Parser) parseParenExpr() ast.Expr { } if p.Token.Kind != "," { - p.panicfAtToken(&paren, "cannot parse (...) as expression, typeless struct literal or subquery") + p.panicfAtToken(&paren, "cannot parse (...) as expression, tuple struct literal or subquery") } p.expect(",") From d23d57692e313127fc009a2cffb40da8081ef94d Mon Sep 17 00:00:00 2001 From: TSUYUSATO Kitsune Date: Mon, 28 Oct 2024 21:06:46 +0900 Subject: [PATCH 20/22] Introduce `TypelessStructLiteralArg` and `NewConstructorArg` --- ast/ast.go | 38 +++++++++----- ast/pos.go | 8 --- ast/sql.go | 4 -- parser.go | 36 ++++++++++--- testdata/result/expr/new_constructor.sql.txt | 6 +-- .../result/expr/new_constructor_empty.sql.txt | 2 +- testdata/result/query/select_cast.sql.txt | 2 +- .../result/query/select_literals_all.sql.txt | 11 ++-- .../query/select_literals_struct.sql.txt | 51 ++++++++----------- .../query/select_struct_compare_eq.sql.txt | 16 +++--- testdata/result/statement/select_cast.sql.txt | 2 +- .../statement/select_literals_all.sql.txt | 11 ++-- .../statement/select_literals_struct.sql.txt | 51 ++++++++----------- .../select_struct_compare_eq.sql.txt | 16 +++--- 14 files changed, 121 insertions(+), 133 deletions(-) diff --git a/ast/ast.go b/ast/ast.go index 2f5f6a8e..75bf2373 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -226,6 +226,24 @@ func (UnnestInCondition) isInCondition() {} func (SubQueryInCondition) isInCondition() {} func (ValuesInCondition) isInCondition() {} +// TypelessStructLiteralArg represents an argument of typeless STRUCT literals. +type TypelessStructLiteralArg interface { + Node + isTypelessStructLiteralArg() +} + +func (ExprArg) isTypelessStructLiteralArg() {} +func (Alias) isTypelessStructLiteralArg() {} + +// NewConstructorArg represents an argument of NEW constructors. +type NewConstructorArg interface { + Node + isNewConstructorArg() +} + +func (ExprArg) isNewConstructorArg() {} +func (Alias) isNewConstructorArg() {} + // Type represents type node. type Type interface { Node @@ -612,7 +630,10 @@ type DotStar struct { Expr Expr } -// Alias is aliased expression by AS clause in SELECT result columns list. +// Alias is aliased expression by AS clause. +// +// Typically, this appears in SELECT result columns list, but this can appear in typeless STRUCT literals +// and NEW constructors. // // {{.Expr | sql}} {{.As | sql}} type Alias struct { @@ -1413,18 +1434,7 @@ type TypelessStructLiteral struct { Struct token.Pos // position of "STRUCT" Rparen token.Pos // position of ")" - Values []*ExprAsName -} - -// ExprAsName is value with optional name in typeless struct literal or new constructor. -// -// {{.Expr | sql}} {{.As | sqlOpt}} -type ExprAsName struct { - // pos = Expr.pos - // end = (As ?? Expr).end - - Expr Expr - As *AsAlias // .As.As must not be invalid, optional + Values []TypelessStructLiteralArg } // NullLiteral is just NULL literal. @@ -1571,7 +1581,7 @@ type NewConstructor struct { New token.Pos Type *NamedType - Args []*ExprAsName + Args []NewConstructorArg Rparen token.Pos } diff --git a/ast/pos.go b/ast/pos.go index 0dfc2445..e25d3247 100644 --- a/ast/pos.go +++ b/ast/pos.go @@ -598,14 +598,6 @@ func (t *TypelessStructLiteral) End() token.Pos { return posAdd(t.Rparen, 1) } -func (e *ExprAsName) Pos() token.Pos { - return nodePos(wrapNode(e.Expr)) -} - -func (e *ExprAsName) End() token.Pos { - return nodeEnd(nodeChoice(wrapNode(e.As), wrapNode(e.Expr))) -} - func (n *NullLiteral) Pos() token.Pos { return n.Null } diff --git a/ast/sql.go b/ast/sql.go index 9704f8e7..4818624c 100644 --- a/ast/sql.go +++ b/ast/sql.go @@ -623,10 +623,6 @@ func (s *TypedStructLiteral) SQL() string { return "STRUCT<" + sqlJoin(s.Fields, ", ") + ">(" + sqlJoin(s.Values, ", ") + ")" } -func (e *ExprAsName) SQL() string { - return e.Expr.SQL() + sqlOpt(" ", e.As, "") -} - func (s *TypelessStructLiteral) SQL() string { return strOpt(!s.Struct.Invalid(), "STRUCT") + "(" + sqlJoin(s.Values, ", ") + ")" } diff --git a/parser.go b/parser.go index 34d99543..4e5970b6 100644 --- a/parser.go +++ b/parser.go @@ -1913,9 +1913,9 @@ func (p *Parser) parseTypedStructLiteral(pos token.Pos) *ast.TypedStructLiteral func (p *Parser) parseTypelessStructLiteral(pos token.Pos) *ast.TypelessStructLiteral { p.expect("(") - var values []*ast.ExprAsName + var values []ast.TypelessStructLiteralArg if p.Token.Kind != ")" { - values = parseCommaSeparatedList(p, p.parseExprAsName) + values = parseCommaSeparatedList(p, p.parseTypelessStructLiteralArg) } rparen := p.expect(")").Pos @@ -1926,12 +1926,17 @@ func (p *Parser) parseTypelessStructLiteral(pos token.Pos) *ast.TypelessStructLi } } -func (p *Parser) parseExprAsName() *ast.ExprAsName { +func (p *Parser) parseTypelessStructLiteralArg() ast.TypelessStructLiteralArg { e := p.parseExpr() as := p.tryParseAsAlias( /* requiredAs */ true) - return &ast.ExprAsName{ + if as != nil { + return &ast.Alias{ + Expr: e, + As: as, + } + } + return &ast.ExprArg{ Expr: e, - As: as, } } @@ -2137,9 +2142,9 @@ func (p *Parser) parseNewConstructor(newPos token.Pos, namedType *ast.NamedType) p.expect("(") // Args can be empty like `NEW pkg.TypeName ()`. - var args []*ast.ExprAsName + var args []ast.NewConstructorArg if p.Token.Kind != ")" { - args = parseCommaSeparatedList(p, p.parseExprAsName) + args = parseCommaSeparatedList(p, p.parseNewConstructorArg) } rparen := p.expect(")").Pos @@ -2151,6 +2156,23 @@ func (p *Parser) parseNewConstructor(newPos token.Pos, namedType *ast.NamedType) } } +func (p *Parser) parseNewConstructorArg() ast.NewConstructorArg { + // Currently, this method's contents are the same as `parseTypelessStructLiteralArg`. + // It exists as an individual method for future extensibility. + + e := p.parseExpr() + as := p.tryParseAsAlias( /* requiredAs */ true) + if as != nil { + return &ast.Alias{ + Expr: e, + As: as, + } + } + return &ast.ExprArg{ + Expr: e, + } +} + func (p *Parser) parseBracedNewConstructorField() *ast.BracedConstructorField { name := p.parseIdent() var fieldValue ast.BracedConstructorFieldValue diff --git a/testdata/result/expr/new_constructor.sql.txt b/testdata/result/expr/new_constructor.sql.txt index 8cdcfc28..63cb5d39 100644 --- a/testdata/result/expr/new_constructor.sql.txt +++ b/testdata/result/expr/new_constructor.sql.txt @@ -27,8 +27,8 @@ NEW googlesql.examples.music.Chart(key AS rank, name AS chart_name) }, }, }, - Args: []*ast.ExprAsName{ - &ast.ExprAsName{ + Args: []ast.NewConstructorArg{ + &ast.Alias{ Expr: &ast.Ident{ NamePos: 35, NameEnd: 38, @@ -43,7 +43,7 @@ NEW googlesql.examples.music.Chart(key AS rank, name AS chart_name) }, }, }, - &ast.ExprAsName{ + &ast.Alias{ Expr: &ast.Ident{ NamePos: 48, NameEnd: 52, diff --git a/testdata/result/expr/new_constructor_empty.sql.txt b/testdata/result/expr/new_constructor_empty.sql.txt index 231da676..805f975b 100644 --- a/testdata/result/expr/new_constructor_empty.sql.txt +++ b/testdata/result/expr/new_constructor_empty.sql.txt @@ -28,7 +28,7 @@ NEW googlesql.examples.music.Chart() }, }, }, - Args: []*ast.ExprAsName(nil), + Args: []ast.NewConstructorArg(nil), Rparen: 35, } diff --git a/testdata/result/query/select_cast.sql.txt b/testdata/result/query/select_cast.sql.txt index 3ee5415f..84154e99 100644 --- a/testdata/result/query/select_cast.sql.txt +++ b/testdata/result/query/select_cast.sql.txt @@ -59,7 +59,7 @@ limit cast(1 as INT64) offset cast(@foo as INT64) &ast.TypelessStructLiteral{ Struct: 53, Rparen: 60, - Values: []*ast.ExprAsName(nil), + Values: []ast.TypelessStructLiteralArg(nil), }, &ast.IntLiteral{ ValuePos: 63, diff --git a/testdata/result/query/select_literals_all.sql.txt b/testdata/result/query/select_literals_all.sql.txt index 9f7901bc..17137993 100644 --- a/testdata/result/query/select_literals_all.sql.txt +++ b/testdata/result/query/select_literals_all.sql.txt @@ -395,33 +395,30 @@ lines''', Expr: &ast.TypelessStructLiteral{ Struct: 467, Rparen: 481, - Values: []*ast.ExprAsName{ - &ast.ExprAsName{ + Values: []ast.TypelessStructLiteralArg{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 474, ValueEnd: 475, Base: 10, Value: "1", }, - As: (*ast.AsAlias)(nil), }, - &ast.ExprAsName{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 477, ValueEnd: 478, Base: 10, Value: "2", }, - As: (*ast.AsAlias)(nil), }, - &ast.ExprAsName{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 480, ValueEnd: 481, Base: 10, Value: "3", }, - As: (*ast.AsAlias)(nil), }, }, }, diff --git a/testdata/result/query/select_literals_struct.sql.txt b/testdata/result/query/select_literals_struct.sql.txt index 32133a42..3b45c25d 100644 --- a/testdata/result/query/select_literals_struct.sql.txt +++ b/testdata/result/query/select_literals_struct.sql.txt @@ -38,33 +38,30 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 22, Rparen: 36, - Values: []*ast.ExprAsName{ - &ast.ExprAsName{ + Values: []ast.TypelessStructLiteralArg{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 29, ValueEnd: 30, Base: 10, Value: "1", }, - As: (*ast.AsAlias)(nil), }, - &ast.ExprAsName{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 32, ValueEnd: 33, Base: 10, Value: "2", }, - As: (*ast.AsAlias)(nil), }, - &ast.ExprAsName{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 35, ValueEnd: 36, Base: 10, Value: "3", }, - As: (*ast.AsAlias)(nil), }, }, }, @@ -92,31 +89,28 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 55, Rparen: 72, - Values: []*ast.ExprAsName{ - &ast.ExprAsName{ + Values: []ast.TypelessStructLiteralArg{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 62, ValueEnd: 63, Base: 10, Value: "1", }, - As: (*ast.AsAlias)(nil), }, - &ast.ExprAsName{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 65, ValueEnd: 66, Base: 10, Value: "2", }, - As: (*ast.AsAlias)(nil), }, - &ast.ExprAsName{ + &ast.ExprArg{ Expr: &ast.BoolLiteral{ ValuePos: 68, Value: true, }, - As: (*ast.AsAlias)(nil), }, }, }, @@ -224,8 +218,8 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 151, Rparen: 180, - Values: []*ast.ExprAsName{ - &ast.ExprAsName{ + Values: []ast.TypelessStructLiteralArg{ + &ast.Alias{ Expr: &ast.IntLiteral{ ValuePos: 158, ValueEnd: 159, @@ -241,7 +235,7 @@ SELECT }, }, }, - &ast.ExprAsName{ + &ast.Alias{ Expr: &ast.IntLiteral{ ValuePos: 166, ValueEnd: 167, @@ -257,7 +251,7 @@ SELECT }, }, }, - &ast.ExprAsName{ + &ast.Alias{ Expr: &ast.IntLiteral{ ValuePos: 174, ValueEnd: 175, @@ -439,8 +433,8 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 309, Rparen: 328, - Values: []*ast.ExprAsName{ - &ast.ExprAsName{ + Values: []ast.TypelessStructLiteralArg{ + &ast.Alias{ Expr: &ast.IntLiteral{ ValuePos: 316, ValueEnd: 317, @@ -456,23 +450,21 @@ SELECT }, }, }, - &ast.ExprAsName{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 324, ValueEnd: 325, Base: 10, Value: "2", }, - As: (*ast.AsAlias)(nil), }, - &ast.ExprAsName{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 327, ValueEnd: 328, Base: 10, Value: "3", }, - As: (*ast.AsAlias)(nil), }, }, }, @@ -591,8 +583,8 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 410, Rparen: 423, - Values: []*ast.ExprAsName{ - &ast.ExprAsName{ + Values: []ast.TypelessStructLiteralArg{ + &ast.Alias{ Expr: &ast.IntLiteral{ ValuePos: 417, ValueEnd: 418, @@ -676,15 +668,14 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 476, Rparen: 484, - Values: []*ast.ExprAsName{ - &ast.ExprAsName{ + Values: []ast.TypelessStructLiteralArg{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 483, ValueEnd: 484, Base: 10, Value: "1", }, - As: (*ast.AsAlias)(nil), }, }, }, @@ -739,7 +730,7 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 531, Rparen: 538, - Values: []*ast.ExprAsName(nil), + Values: []ast.TypelessStructLiteralArg(nil), }, }, }, diff --git a/testdata/result/query/select_struct_compare_eq.sql.txt b/testdata/result/query/select_struct_compare_eq.sql.txt index 047f65fe..ff3acbd9 100644 --- a/testdata/result/query/select_struct_compare_eq.sql.txt +++ b/testdata/result/query/select_struct_compare_eq.sql.txt @@ -131,42 +131,38 @@ SELECT ARRAY( Right: &ast.TypelessStructLiteral{ Struct: 109, Rparen: 131, - Values: []*ast.ExprAsName{ - &ast.ExprAsName{ + Values: []ast.TypelessStructLiteralArg{ + &ast.ExprArg{ Expr: &ast.TypelessStructLiteral{ Struct: 116, Rparen: 130, - Values: []*ast.ExprAsName{ - &ast.ExprAsName{ + Values: []ast.TypelessStructLiteralArg{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 123, ValueEnd: 124, Base: 10, Value: "1", }, - As: (*ast.AsAlias)(nil), }, - &ast.ExprAsName{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 126, ValueEnd: 127, Base: 10, Value: "2", }, - As: (*ast.AsAlias)(nil), }, - &ast.ExprAsName{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 129, ValueEnd: 130, Base: 10, Value: "3", }, - As: (*ast.AsAlias)(nil), }, }, }, - As: (*ast.AsAlias)(nil), }, }, }, diff --git a/testdata/result/statement/select_cast.sql.txt b/testdata/result/statement/select_cast.sql.txt index 3ee5415f..84154e99 100644 --- a/testdata/result/statement/select_cast.sql.txt +++ b/testdata/result/statement/select_cast.sql.txt @@ -59,7 +59,7 @@ limit cast(1 as INT64) offset cast(@foo as INT64) &ast.TypelessStructLiteral{ Struct: 53, Rparen: 60, - Values: []*ast.ExprAsName(nil), + Values: []ast.TypelessStructLiteralArg(nil), }, &ast.IntLiteral{ ValuePos: 63, diff --git a/testdata/result/statement/select_literals_all.sql.txt b/testdata/result/statement/select_literals_all.sql.txt index 9f7901bc..17137993 100644 --- a/testdata/result/statement/select_literals_all.sql.txt +++ b/testdata/result/statement/select_literals_all.sql.txt @@ -395,33 +395,30 @@ lines''', Expr: &ast.TypelessStructLiteral{ Struct: 467, Rparen: 481, - Values: []*ast.ExprAsName{ - &ast.ExprAsName{ + Values: []ast.TypelessStructLiteralArg{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 474, ValueEnd: 475, Base: 10, Value: "1", }, - As: (*ast.AsAlias)(nil), }, - &ast.ExprAsName{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 477, ValueEnd: 478, Base: 10, Value: "2", }, - As: (*ast.AsAlias)(nil), }, - &ast.ExprAsName{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 480, ValueEnd: 481, Base: 10, Value: "3", }, - As: (*ast.AsAlias)(nil), }, }, }, diff --git a/testdata/result/statement/select_literals_struct.sql.txt b/testdata/result/statement/select_literals_struct.sql.txt index 32133a42..3b45c25d 100644 --- a/testdata/result/statement/select_literals_struct.sql.txt +++ b/testdata/result/statement/select_literals_struct.sql.txt @@ -38,33 +38,30 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 22, Rparen: 36, - Values: []*ast.ExprAsName{ - &ast.ExprAsName{ + Values: []ast.TypelessStructLiteralArg{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 29, ValueEnd: 30, Base: 10, Value: "1", }, - As: (*ast.AsAlias)(nil), }, - &ast.ExprAsName{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 32, ValueEnd: 33, Base: 10, Value: "2", }, - As: (*ast.AsAlias)(nil), }, - &ast.ExprAsName{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 35, ValueEnd: 36, Base: 10, Value: "3", }, - As: (*ast.AsAlias)(nil), }, }, }, @@ -92,31 +89,28 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 55, Rparen: 72, - Values: []*ast.ExprAsName{ - &ast.ExprAsName{ + Values: []ast.TypelessStructLiteralArg{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 62, ValueEnd: 63, Base: 10, Value: "1", }, - As: (*ast.AsAlias)(nil), }, - &ast.ExprAsName{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 65, ValueEnd: 66, Base: 10, Value: "2", }, - As: (*ast.AsAlias)(nil), }, - &ast.ExprAsName{ + &ast.ExprArg{ Expr: &ast.BoolLiteral{ ValuePos: 68, Value: true, }, - As: (*ast.AsAlias)(nil), }, }, }, @@ -224,8 +218,8 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 151, Rparen: 180, - Values: []*ast.ExprAsName{ - &ast.ExprAsName{ + Values: []ast.TypelessStructLiteralArg{ + &ast.Alias{ Expr: &ast.IntLiteral{ ValuePos: 158, ValueEnd: 159, @@ -241,7 +235,7 @@ SELECT }, }, }, - &ast.ExprAsName{ + &ast.Alias{ Expr: &ast.IntLiteral{ ValuePos: 166, ValueEnd: 167, @@ -257,7 +251,7 @@ SELECT }, }, }, - &ast.ExprAsName{ + &ast.Alias{ Expr: &ast.IntLiteral{ ValuePos: 174, ValueEnd: 175, @@ -439,8 +433,8 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 309, Rparen: 328, - Values: []*ast.ExprAsName{ - &ast.ExprAsName{ + Values: []ast.TypelessStructLiteralArg{ + &ast.Alias{ Expr: &ast.IntLiteral{ ValuePos: 316, ValueEnd: 317, @@ -456,23 +450,21 @@ SELECT }, }, }, - &ast.ExprAsName{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 324, ValueEnd: 325, Base: 10, Value: "2", }, - As: (*ast.AsAlias)(nil), }, - &ast.ExprAsName{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 327, ValueEnd: 328, Base: 10, Value: "3", }, - As: (*ast.AsAlias)(nil), }, }, }, @@ -591,8 +583,8 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 410, Rparen: 423, - Values: []*ast.ExprAsName{ - &ast.ExprAsName{ + Values: []ast.TypelessStructLiteralArg{ + &ast.Alias{ Expr: &ast.IntLiteral{ ValuePos: 417, ValueEnd: 418, @@ -676,15 +668,14 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 476, Rparen: 484, - Values: []*ast.ExprAsName{ - &ast.ExprAsName{ + Values: []ast.TypelessStructLiteralArg{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 483, ValueEnd: 484, Base: 10, Value: "1", }, - As: (*ast.AsAlias)(nil), }, }, }, @@ -739,7 +730,7 @@ SELECT Expr: &ast.TypelessStructLiteral{ Struct: 531, Rparen: 538, - Values: []*ast.ExprAsName(nil), + Values: []ast.TypelessStructLiteralArg(nil), }, }, }, diff --git a/testdata/result/statement/select_struct_compare_eq.sql.txt b/testdata/result/statement/select_struct_compare_eq.sql.txt index 047f65fe..ff3acbd9 100644 --- a/testdata/result/statement/select_struct_compare_eq.sql.txt +++ b/testdata/result/statement/select_struct_compare_eq.sql.txt @@ -131,42 +131,38 @@ SELECT ARRAY( Right: &ast.TypelessStructLiteral{ Struct: 109, Rparen: 131, - Values: []*ast.ExprAsName{ - &ast.ExprAsName{ + Values: []ast.TypelessStructLiteralArg{ + &ast.ExprArg{ Expr: &ast.TypelessStructLiteral{ Struct: 116, Rparen: 130, - Values: []*ast.ExprAsName{ - &ast.ExprAsName{ + Values: []ast.TypelessStructLiteralArg{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 123, ValueEnd: 124, Base: 10, Value: "1", }, - As: (*ast.AsAlias)(nil), }, - &ast.ExprAsName{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 126, ValueEnd: 127, Base: 10, Value: "2", }, - As: (*ast.AsAlias)(nil), }, - &ast.ExprAsName{ + &ast.ExprArg{ Expr: &ast.IntLiteral{ ValuePos: 129, ValueEnd: 130, Base: 10, Value: "3", }, - As: (*ast.AsAlias)(nil), }, }, }, - As: (*ast.AsAlias)(nil), }, }, }, From 41ae342b3e37205e6b228c25f269378a2b390b2a Mon Sep 17 00:00:00 2001 From: TSUYUSATO Kitsune Date: Tue, 29 Oct 2024 00:59:53 +0900 Subject: [PATCH 21/22] Remove requiredAs comments --- parser.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/parser.go b/parser.go index 4e5970b6..3c7f5c3e 100644 --- a/parser.go +++ b/parser.go @@ -458,7 +458,7 @@ func (p *Parser) parseSelectItem() ast.SelectItem { } expr := p.parseExpr() - if as := p.tryParseAsAlias( /* requiredAs */ false); as != nil { + if as := p.tryParseAsAlias(false); as != nil { return &ast.Alias{ Expr: expr, As: as, @@ -781,7 +781,7 @@ func (p *Parser) parseSimpleTableExpr() ast.TableExpr { lparen := p.expect("(").Pos query := p.parseQueryExpr() rparen := p.expect(")").Pos - as := p.tryParseAsAlias( /* requiredAs */ false) + as := p.tryParseAsAlias(false) return p.parseTableExprSuffix(&ast.SubQueryTableExpr{ Lparen: lparen, Rparen: rparen, @@ -833,7 +833,7 @@ func (p *Parser) parseIdentOrPath() []*ast.Ident { func (p *Parser) parseUnnestSuffix(expr ast.Expr, unnest, rparen token.Pos) ast.TableExpr { hint := p.tryParseHint() - as := p.tryParseAsAlias( /* requiredAs */ false) + as := p.tryParseAsAlias(false) withOffset := p.tryParseWithOffset() return p.parseTableExprSuffix(&ast.Unnest{ @@ -853,7 +853,7 @@ func (p *Parser) tryParseWithOffset() *ast.WithOffset { with := p.expect("WITH").Pos offset := p.expectKeywordLike("OFFSET").Pos - as := p.tryParseAsAlias( /* requiredAs */ false) + as := p.tryParseAsAlias(false) return &ast.WithOffset{ With: with, @@ -864,7 +864,7 @@ func (p *Parser) tryParseWithOffset() *ast.WithOffset { func (p *Parser) parseTableNameSuffix(id *ast.Ident) ast.TableExpr { hint := p.tryParseHint() - as := p.tryParseAsAlias( /* requiredAs */ false) + as := p.tryParseAsAlias(false) return p.parseTableExprSuffix(&ast.TableName{ Table: id, Hint: hint, @@ -874,7 +874,7 @@ func (p *Parser) parseTableNameSuffix(id *ast.Ident) ast.TableExpr { func (p *Parser) parsePathTableExprSuffix(id *ast.Path) ast.TableExpr { hint := p.tryParseHint() - as := p.tryParseAsAlias( /* requiredAs */ false) + as := p.tryParseAsAlias(false) withOffset := p.tryParseWithOffset() return p.parseTableExprSuffix(&ast.PathTableExpr{ Path: id, @@ -1928,7 +1928,7 @@ func (p *Parser) parseTypelessStructLiteral(pos token.Pos) *ast.TypelessStructLi func (p *Parser) parseTypelessStructLiteralArg() ast.TypelessStructLiteralArg { e := p.parseExpr() - as := p.tryParseAsAlias( /* requiredAs */ true) + as := p.tryParseAsAlias(true) if as != nil { return &ast.Alias{ Expr: e, @@ -2161,7 +2161,7 @@ func (p *Parser) parseNewConstructorArg() ast.NewConstructorArg { // It exists as an individual method for future extensibility. e := p.parseExpr() - as := p.tryParseAsAlias( /* requiredAs */ true) + as := p.tryParseAsAlias(true) if as != nil { return &ast.Alias{ Expr: e, @@ -3862,7 +3862,7 @@ func (p *Parser) parseDelete(pos token.Pos) *ast.Delete { } name := p.parseIdent() - as := p.tryParseAsAlias( /* requiredAs */ false) + as := p.tryParseAsAlias(false) where := p.parseWhere() return &ast.Delete{ @@ -3875,7 +3875,7 @@ func (p *Parser) parseDelete(pos token.Pos) *ast.Delete { func (p *Parser) parseUpdate(pos token.Pos) *ast.Update { name := p.parseIdent() - as := p.tryParseAsAlias( /* requiredAs */ false) + as := p.tryParseAsAlias(false) p.expect("SET") From 8ea0e5398734aaff2c8fe2526bccc2e722e1dde4 Mon Sep 17 00:00:00 2001 From: TSUYUSATO Kitsune Date: Tue, 29 Oct 2024 11:03:11 +0900 Subject: [PATCH 22/22] Add constants for the tryParseAsAlias argument --- parser.go | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/parser.go b/parser.go index 3c7f5c3e..239bc6ac 100644 --- a/parser.go +++ b/parser.go @@ -458,7 +458,7 @@ func (p *Parser) parseSelectItem() ast.SelectItem { } expr := p.parseExpr() - if as := p.tryParseAsAlias(false); as != nil { + if as := p.tryParseAsAlias(withOptionalAs); as != nil { return &ast.Alias{ Expr: expr, As: as, @@ -479,7 +479,14 @@ func (p *Parser) parseSelectItem() ast.SelectItem { } } -func (p *Parser) tryParseAsAlias(requiredAs bool) *ast.AsAlias { +type withAs bool + +const ( + withRequiredAs withAs = true + withOptionalAs withAs = false +) + +func (p *Parser) tryParseAsAlias(requiredAs withAs) *ast.AsAlias { pos := p.Token.Pos if p.Token.Kind == "AS" { @@ -781,7 +788,7 @@ func (p *Parser) parseSimpleTableExpr() ast.TableExpr { lparen := p.expect("(").Pos query := p.parseQueryExpr() rparen := p.expect(")").Pos - as := p.tryParseAsAlias(false) + as := p.tryParseAsAlias(withOptionalAs) return p.parseTableExprSuffix(&ast.SubQueryTableExpr{ Lparen: lparen, Rparen: rparen, @@ -833,7 +840,7 @@ func (p *Parser) parseIdentOrPath() []*ast.Ident { func (p *Parser) parseUnnestSuffix(expr ast.Expr, unnest, rparen token.Pos) ast.TableExpr { hint := p.tryParseHint() - as := p.tryParseAsAlias(false) + as := p.tryParseAsAlias(withOptionalAs) withOffset := p.tryParseWithOffset() return p.parseTableExprSuffix(&ast.Unnest{ @@ -853,7 +860,7 @@ func (p *Parser) tryParseWithOffset() *ast.WithOffset { with := p.expect("WITH").Pos offset := p.expectKeywordLike("OFFSET").Pos - as := p.tryParseAsAlias(false) + as := p.tryParseAsAlias(withOptionalAs) return &ast.WithOffset{ With: with, @@ -864,7 +871,7 @@ func (p *Parser) tryParseWithOffset() *ast.WithOffset { func (p *Parser) parseTableNameSuffix(id *ast.Ident) ast.TableExpr { hint := p.tryParseHint() - as := p.tryParseAsAlias(false) + as := p.tryParseAsAlias(withOptionalAs) return p.parseTableExprSuffix(&ast.TableName{ Table: id, Hint: hint, @@ -874,7 +881,7 @@ func (p *Parser) parseTableNameSuffix(id *ast.Ident) ast.TableExpr { func (p *Parser) parsePathTableExprSuffix(id *ast.Path) ast.TableExpr { hint := p.tryParseHint() - as := p.tryParseAsAlias(false) + as := p.tryParseAsAlias(withOptionalAs) withOffset := p.tryParseWithOffset() return p.parseTableExprSuffix(&ast.PathTableExpr{ Path: id, @@ -1928,7 +1935,7 @@ func (p *Parser) parseTypelessStructLiteral(pos token.Pos) *ast.TypelessStructLi func (p *Parser) parseTypelessStructLiteralArg() ast.TypelessStructLiteralArg { e := p.parseExpr() - as := p.tryParseAsAlias(true) + as := p.tryParseAsAlias(withRequiredAs) if as != nil { return &ast.Alias{ Expr: e, @@ -2161,7 +2168,7 @@ func (p *Parser) parseNewConstructorArg() ast.NewConstructorArg { // It exists as an individual method for future extensibility. e := p.parseExpr() - as := p.tryParseAsAlias(true) + as := p.tryParseAsAlias(withRequiredAs) if as != nil { return &ast.Alias{ Expr: e, @@ -3862,7 +3869,7 @@ func (p *Parser) parseDelete(pos token.Pos) *ast.Delete { } name := p.parseIdent() - as := p.tryParseAsAlias(false) + as := p.tryParseAsAlias(withOptionalAs) where := p.parseWhere() return &ast.Delete{ @@ -3875,7 +3882,7 @@ func (p *Parser) parseDelete(pos token.Pos) *ast.Delete { func (p *Parser) parseUpdate(pos token.Pos) *ast.Update { name := p.parseIdent() - as := p.tryParseAsAlias(false) + as := p.tryParseAsAlias(withOptionalAs) p.expect("SET")