Skip to content

Commit

Permalink
Support proto/enum as typename (#121)
Browse files Browse the repository at this point in the history
* Support PROTO/ENUM in parseType

* Add testdata/*/expr/cast_as_typename.sql

* Support PROTO/ENUM in parseSchemaType()

* Update testdata for NamedType

* Fix placement of NamedType

* Fix NamedType to use raw []*Ident

* Fix comment

* Update testdata

* Fix control flow

* Fix comment
  • Loading branch information
apstndb authored Oct 1, 2024
1 parent 8af8b41 commit cdd31d5
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 11 deletions.
14 changes: 14 additions & 0 deletions ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ type Type interface {
func (SimpleType) isType() {}
func (ArrayType) isType() {}
func (StructType) isType() {}
func (NamedType) isType() {}

// IntValue represents integer values in SQL.
type IntValue interface {
Expand Down Expand Up @@ -302,6 +303,7 @@ type SchemaType interface {
func (ScalarSchemaType) isSchemaType() {}
func (SizedSchemaType) isSchemaType() {}
func (ArraySchemaType) isSchemaType() {}
func (NamedType) isSchemaType() {}

// IndexAlteration represents ALTER INDEX action.
type IndexAlteration interface {
Expand Down Expand Up @@ -1392,6 +1394,18 @@ type StructField struct {
Type Type
}

// NamedType is named type node.
// It is currently PROTO or ENUM.
// Name is full qualified name, but it can be len(Name) == 1 if it doesn't contain ".".
//
// {{.Path | sqlJoin "."}}
type NamedType struct {
// pos = Name.pos
// end = Name.end

Path []*Ident // len(Path) > 0
}

// ================================================================================
//
// Cast for Special Cases
Expand Down
3 changes: 3 additions & 0 deletions ast/pos.go
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,9 @@ func (f *StructField) End() token.Pos {
return f.Type.End()
}

func (n *NamedType) Pos() token.Pos { return n.Path[0].Pos() }
func (n *NamedType) End() token.Pos { return n.Path[len(n.Path)-1].End() }

// ================================================================================
//
// Cast for Special Cases
Expand Down
11 changes: 11 additions & 0 deletions ast/sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,17 @@ func (f *StructField) SQL() string {
return sql
}

func (n *NamedType) SQL() string {
var sql string
for i, elem := range n.Path {
if i > 0 {
sql += "."
}
sql += elem.SQL()
}
return sql
}

// ================================================================================
//
// Cast for Special Cases
Expand Down
27 changes: 27 additions & 0 deletions parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -1888,9 +1888,17 @@ func (p *Parser) lookaheadSubQuery() bool {
//
// ================================================================================

func (p *Parser) parseNamedType() *ast.NamedType {
path := p.parseIdentOrPath()
return &ast.NamedType{Path: path}
}

func (p *Parser) parseType() ast.Type {
switch p.Token.Kind {
case token.TokenIdent:
if !p.lookaheadSimpleType() {
return p.parseNamedType()
}
return p.parseSimpleType()
case "ARRAY":
return p.parseArrayType()
Expand All @@ -1911,6 +1919,7 @@ var simpleTypes = []string{
"NUMERIC",
"STRING",
"BYTES",
"JSON",
}

func (p *Parser) parseSimpleType() *ast.SimpleType {
Expand Down Expand Up @@ -2018,6 +2027,21 @@ func (p *Parser) lookaheadType() bool {
return p.Token.Kind == token.TokenIdent || p.Token.Kind == "ARRAY" || p.Token.Kind == "STRUCT"
}

func (p *Parser) lookaheadSimpleType() bool {
if p.Token.Kind != token.TokenIdent {
return false
}

id := p.Token

for _, name := range simpleTypes {
if id.IsIdent(name) {
return true
}
}
return false
}

// ================================================================================
//
// DDL
Expand Down Expand Up @@ -3279,6 +3303,9 @@ func (p *Parser) tryParseTablePrivilegeColumns() ([]*ast.Ident, token.Pos) {
func (p *Parser) parseSchemaType() ast.SchemaType {
switch p.Token.Kind {
case token.TokenIdent:
if !p.lookaheadSimpleType() {
return p.parseNamedType()
}
return p.parseScalarSchemaType()
case "ARRAY":
pos := p.expect("ARRAY").Pos
Expand Down
3 changes: 2 additions & 1 deletion testdata/input/ddl/create_table_types.sql
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ create table types (
bs bytes(256),
bsmax bytes(max),
ab array<bool>,
abs array<bytes(max)>
abs array<bytes(max)>,
p examples.ProtoType,
) primary key (i)
1 change: 1 addition & 0 deletions testdata/input/expr/cast_as_typename.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CAST('order_number: "123"' AS examples.shipping.`Order`)
37 changes: 32 additions & 5 deletions testdata/result/ddl/create_table_types.sql.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ create table types (
bs bytes(256),
bsmax bytes(max),
ab array<bool>,
abs array<bytes(max)>
abs array<bytes(max)>,
p examples.ProtoType,
) primary key (i)

--- AST
&ast.CreateTable{
Create: 0,
Rparen: 227,
Rparen: 252,
IfNotExists: false,
Name: &ast.Ident{
NamePos: 13,
Expand Down Expand Up @@ -250,14 +251,40 @@ create table types (
GeneratedExpr: (*ast.GeneratedColumnExpr)(nil),
Options: (*ast.ColumnDefOptions)(nil),
},
&ast.ColumnDef{
Null: -1,
Name: &ast.Ident{
NamePos: 214,
NameEnd: 215,
Name: "p",
},
Type: &ast.NamedType{
Path: []*ast.Ident{
&ast.Ident{
NamePos: 216,
NameEnd: 224,
Name: "examples",
},
&ast.Ident{
NamePos: 225,
NameEnd: 234,
Name: "ProtoType",
},
},
},
NotNull: false,
DefaultExpr: (*ast.ColumnDefaultExpr)(nil),
GeneratedExpr: (*ast.GeneratedColumnExpr)(nil),
Options: (*ast.ColumnDefOptions)(nil),
},
},
TableConstraints: []*ast.TableConstraint(nil),
PrimaryKeys: []*ast.IndexKey{
&ast.IndexKey{
DirPos: -1,
Name: &ast.Ident{
NamePos: 226,
NameEnd: 227,
NamePos: 251,
NameEnd: 252,
Name: "i",
},
Dir: "",
Expand All @@ -268,4 +295,4 @@ create table types (
}

--- SQL
CREATE TABLE types (b BOOL, i INT64, f32 FLOAT32, f FLOAT64, d DATE, t TIMESTAMP, s STRING(256), smax STRING(MAX), bs BYTES(256), bsmax BYTES(MAX), ab ARRAY<BOOL>, abs ARRAY<BYTES(MAX)>) PRIMARY KEY (i)
CREATE TABLE types (b BOOL, i INT64, f32 FLOAT32, f FLOAT64, d DATE, t TIMESTAMP, s STRING(256), smax STRING(MAX), bs BYTES(256), bsmax BYTES(MAX), ab ARRAY<BOOL>, abs ARRAY<BYTES(MAX)>, p examples.ProtoType) PRIMARY KEY (i)
34 changes: 34 additions & 0 deletions testdata/result/expr/cast_as_typename.sql.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
--- cast_as_typename.sql
CAST('order_number: "123"' AS examples.shipping.`Order`)
--- AST
&ast.CastExpr{
Cast: 0,
Rparen: 55,
Expr: &ast.StringLiteral{
ValuePos: 5,
ValueEnd: 26,
Value: "order_number: \"123\"",
},
Type: &ast.NamedType{
Path: []*ast.Ident{
&ast.Ident{
NamePos: 30,
NameEnd: 38,
Name: "examples",
},
&ast.Ident{
NamePos: 39,
NameEnd: 47,
Name: "shipping",
},
&ast.Ident{
NamePos: 48,
NameEnd: 55,
Name: "Order",
},
},
},
}

--- SQL
CAST("order_number: \"123\"" AS examples.shipping.`Order`)
37 changes: 32 additions & 5 deletions testdata/result/statement/create_table_types.sql.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ create table types (
bs bytes(256),
bsmax bytes(max),
ab array<bool>,
abs array<bytes(max)>
abs array<bytes(max)>,
p examples.ProtoType,
) primary key (i)

--- AST
&ast.CreateTable{
Create: 0,
Rparen: 227,
Rparen: 252,
IfNotExists: false,
Name: &ast.Ident{
NamePos: 13,
Expand Down Expand Up @@ -250,14 +251,40 @@ create table types (
GeneratedExpr: (*ast.GeneratedColumnExpr)(nil),
Options: (*ast.ColumnDefOptions)(nil),
},
&ast.ColumnDef{
Null: -1,
Name: &ast.Ident{
NamePos: 214,
NameEnd: 215,
Name: "p",
},
Type: &ast.NamedType{
Path: []*ast.Ident{
&ast.Ident{
NamePos: 216,
NameEnd: 224,
Name: "examples",
},
&ast.Ident{
NamePos: 225,
NameEnd: 234,
Name: "ProtoType",
},
},
},
NotNull: false,
DefaultExpr: (*ast.ColumnDefaultExpr)(nil),
GeneratedExpr: (*ast.GeneratedColumnExpr)(nil),
Options: (*ast.ColumnDefOptions)(nil),
},
},
TableConstraints: []*ast.TableConstraint(nil),
PrimaryKeys: []*ast.IndexKey{
&ast.IndexKey{
DirPos: -1,
Name: &ast.Ident{
NamePos: 226,
NameEnd: 227,
NamePos: 251,
NameEnd: 252,
Name: "i",
},
Dir: "",
Expand All @@ -268,4 +295,4 @@ create table types (
}

--- SQL
CREATE TABLE types (b BOOL, i INT64, f32 FLOAT32, f FLOAT64, d DATE, t TIMESTAMP, s STRING(256), smax STRING(MAX), bs BYTES(256), bsmax BYTES(MAX), ab ARRAY<BOOL>, abs ARRAY<BYTES(MAX)>) PRIMARY KEY (i)
CREATE TABLE types (b BOOL, i INT64, f32 FLOAT32, f FLOAT64, d DATE, t TIMESTAMP, s STRING(256), smax STRING(MAX), bs BYTES(256), bsmax BYTES(MAX), ab ARRAY<BOOL>, abs ARRAY<BYTES(MAX)>, p examples.ProtoType) PRIMARY KEY (i)

0 comments on commit cdd31d5

Please sign in to comment.