Skip to content

Commit e11cd83

Browse files
authored
Support DDLs for Protocol Buffers (#176)
* Implement Protocol Buffer DDLs * Update testdata * Fix doc comments and placement in ast.go
1 parent 57d0f92 commit e11cd83

19 files changed

+565
-0
lines changed

ast/ast.go

+105
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ func (CreateSchema) isStatement() {}
6464
func (DropSchema) isStatement() {}
6565
func (CreateDatabase) isStatement() {}
6666
func (AlterDatabase) isStatement() {}
67+
func (CreateProtoBundle) isStatement() {}
68+
func (AlterProtoBundle) isStatement() {}
69+
func (DropProtoBundle) isStatement() {}
6770
func (CreateTable) isStatement() {}
6871
func (AlterTable) isStatement() {}
6972
func (DropTable) isStatement() {}
@@ -303,6 +306,9 @@ func (CreateSchema) isDDL() {}
303306
func (DropSchema) isDDL() {}
304307
func (CreateDatabase) isDDL() {}
305308
func (AlterDatabase) isDDL() {}
309+
func (CreateProtoBundle) isDDL() {}
310+
func (AlterProtoBundle) isDDL() {}
311+
func (DropProtoBundle) isDDL() {}
306312
func (CreateTable) isDDL() {}
307313
func (AlterTable) isDDL() {}
308314
func (DropTable) isDDL() {}
@@ -1819,6 +1825,105 @@ type AlterDatabase struct {
18191825
Options *Options
18201826
}
18211827

1828+
// ================================================================================
1829+
//
1830+
// PROTO BUNDLE statements
1831+
//
1832+
// ================================================================================
1833+
1834+
type ProtoBundleAlteration interface {
1835+
Node
1836+
isProtoBundleAlteration()
1837+
}
1838+
1839+
func (AlterProtoBundleInsert) isProtoBundleAlteration() {}
1840+
func (AlterProtoBundleUpdate) isProtoBundleAlteration() {}
1841+
func (AlterProtoBundleDelete) isProtoBundleAlteration() {}
1842+
1843+
// ProtoBundleTypes is parenthesized Protocol Buffers type names node IN CREATE/ALTER PROTO BUNDLE statement.
1844+
//
1845+
// ({{.Types | sqlJoin ", "}})
1846+
type ProtoBundleTypes struct {
1847+
// pos = Lparen
1848+
// end = Rparen + 1
1849+
1850+
Lparen, Rparen token.Pos
1851+
Types []*NamedType
1852+
}
1853+
1854+
// CreateProtoBundle is CREATE PROTO BUNDLE statement node.
1855+
//
1856+
// CREATE PROTO BUNDLE {{.Types, | sql}}
1857+
type CreateProtoBundle struct {
1858+
// pos = Create
1859+
// end = Types.end
1860+
1861+
Create token.Pos // position of "CREATE" keyword
1862+
1863+
Types *ProtoBundleTypes
1864+
}
1865+
1866+
// AlterProtoBundle is ALTER PROTO BUNDLE statement node.
1867+
//
1868+
// ALTER PROTO BUNDLE {{.Alteration | sql}}
1869+
type AlterProtoBundle struct {
1870+
// pos = Alter
1871+
// end = Alteration.end
1872+
1873+
Alter token.Pos // position of "ALTER" keyword
1874+
1875+
Alteration ProtoBundleAlteration
1876+
}
1877+
1878+
// AlterProtoBundleInsert is INSERT (proto_type_name, ...) node in ALTER PROTO BUNDLE.
1879+
//
1880+
// INSERT {{.Types | sql}}
1881+
type AlterProtoBundleInsert struct {
1882+
// pos = Insert
1883+
// end = Types.end
1884+
1885+
Insert token.Pos // position of "INSERT" pseudo keyword
1886+
1887+
Types *ProtoBundleTypes
1888+
}
1889+
1890+
// AlterProtoBundleUpdate is UPDATE (proto_type_name, ...) node in ALTER PROTO BUNDLE.
1891+
//
1892+
// UPDATE {{.Types | sql}}
1893+
type AlterProtoBundleUpdate struct {
1894+
// pos = Update
1895+
// end = Types.end
1896+
1897+
Update token.Pos // position of "UPDATE" pseudo keyword
1898+
1899+
Types *ProtoBundleTypes
1900+
}
1901+
1902+
// AlterProtoBundleDelete is DELETE (proto_type_name, ...) node in ALTER PROTO BUNDLE.
1903+
//
1904+
// DELETE {{.Types | sql}}
1905+
type AlterProtoBundleDelete struct {
1906+
// pos = Delete
1907+
// end = Types.end
1908+
1909+
Delete token.Pos // position of "DELETE" pseudo keyword
1910+
1911+
Types *ProtoBundleTypes
1912+
}
1913+
1914+
// DropProtoBundle is DROP PROTO BUNDLE statement node.
1915+
//
1916+
// DROP PROTO BUNDLE
1917+
type DropProtoBundle struct {
1918+
// pos = Drop
1919+
// end = Bundle + 6
1920+
1921+
Drop token.Pos // position of "DROP" pseudo keyword
1922+
Bundle token.Pos // position of "BUNDLE" pseudo keyword
1923+
}
1924+
1925+
// end of PROTO BUNDLE statements
1926+
18221927
// CreateTable is CREATE TABLE statement node.
18231928
//
18241929
// CREATE TABLE {{if .IfNotExists}}IF NOT EXISTS{{end}} {{.Name | sql}} (

ast/pos.go

+56
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ast/sql.go

+14
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,20 @@ func (d *AlterDatabase) SQL() string {
794794
return "ALTER DATABASE " + d.Name.SQL() + " SET " + d.Options.SQL()
795795
}
796796

797+
func (p *ProtoBundleTypes) SQL() string { return "(" + sqlJoin(p.Types, ", ") + ")" }
798+
799+
func (b *CreateProtoBundle) SQL() string { return "CREATE PROTO BUNDLE " + b.Types.SQL() }
800+
801+
func (a *AlterProtoBundle) SQL() string { return "ALTER PROTO BUNDLE " + a.Alteration.SQL() }
802+
803+
func (a *AlterProtoBundleInsert) SQL() string { return "INSERT " + a.Types.SQL() }
804+
805+
func (a *AlterProtoBundleUpdate) SQL() string { return "UPDATE " + a.Types.SQL() }
806+
807+
func (a *AlterProtoBundleDelete) SQL() string { return "DELETE " + a.Types.SQL() }
808+
809+
func (d *DropProtoBundle) SQL() string { return "DROP PROTO BUNDLE" }
810+
797811
func (c *CreateTable) SQL() string {
798812
return "CREATE TABLE " +
799813
strOpt(c.IfNotExists, "IF NOT EXISTS ") +

parser.go

+78
Original file line numberDiff line numberDiff line change
@@ -2303,6 +2303,8 @@ func (p *Parser) parseDDL() ast.DDL {
23032303
return p.parseCreateSchema(pos)
23042304
case p.Token.IsKeywordLike("DATABASE"):
23052305
return p.parseCreateDatabase(pos)
2306+
case p.Token.Kind == "PROTO":
2307+
return p.parseCreateProtoBundle(pos)
23062308
case p.Token.IsKeywordLike("TABLE"):
23072309
return p.parseCreateTable(pos)
23082310
case p.Token.IsKeywordLike("SEQUENCE"):
@@ -2328,6 +2330,8 @@ func (p *Parser) parseDDL() ast.DDL {
23282330
return p.parseAlterTable(pos)
23292331
case p.Token.IsKeywordLike("DATABASE"):
23302332
return p.parseAlterDatabase(pos)
2333+
case p.Token.Kind == "PROTO":
2334+
return p.parseAlterProtoBundle(pos)
23312335
case p.Token.IsKeywordLike("INDEX"):
23322336
return p.parseAlterIndex(pos)
23332337
case p.Token.IsKeywordLike("SEARCH"):
@@ -2345,6 +2349,8 @@ func (p *Parser) parseDDL() ast.DDL {
23452349
switch {
23462350
case p.Token.IsKeywordLike("SCHEMA"):
23472351
return p.parseDropSchema(pos)
2352+
case p.Token.Kind == "PROTO":
2353+
return p.parseDropProtoBundle(pos)
23482354
case p.Token.IsKeywordLike("TABLE"):
23492355
return p.parseDropTable(pos)
23502356
case p.Token.IsKeywordLike("INDEX"):
@@ -2421,6 +2427,47 @@ func (p *Parser) parseAlterDatabase(pos token.Pos) *ast.AlterDatabase {
24212427
}
24222428
}
24232429

2430+
func (p *Parser) parseProtoBundleTypes() *ast.ProtoBundleTypes {
2431+
lparen := p.expect("(").Pos
2432+
types := parseCommaSeparatedList(p, p.parseNamedType)
2433+
rparen := p.expect(")").Pos
2434+
return &ast.ProtoBundleTypes{
2435+
Lparen: lparen,
2436+
Rparen: rparen,
2437+
Types: types,
2438+
}
2439+
}
2440+
2441+
func (p *Parser) parseCreateProtoBundle(pos token.Pos) *ast.CreateProtoBundle {
2442+
p.expect("PROTO")
2443+
p.expectKeywordLike("BUNDLE")
2444+
types := p.parseProtoBundleTypes()
2445+
2446+
return &ast.CreateProtoBundle{
2447+
Create: pos,
2448+
Types: types,
2449+
}
2450+
}
2451+
2452+
func (p *Parser) parseAlterProtoBundle(pos token.Pos) *ast.AlterProtoBundle {
2453+
p.expect("PROTO")
2454+
p.expectKeywordLike("BUNDLE")
2455+
alteration := p.parseProtoBundleAlteration()
2456+
return &ast.AlterProtoBundle{
2457+
Alter: pos,
2458+
Alteration: alteration,
2459+
}
2460+
}
2461+
2462+
func (p *Parser) parseDropProtoBundle(pos token.Pos) *ast.DropProtoBundle {
2463+
p.expect("PROTO")
2464+
bundle := p.expectKeywordLike("BUNDLE").Pos
2465+
2466+
return &ast.DropProtoBundle{
2467+
Drop: pos,
2468+
Bundle: bundle,
2469+
}
2470+
}
24242471
func (p *Parser) parseCreateTable(pos token.Pos) *ast.CreateTable {
24252472
p.expectKeywordLike("TABLE")
24262473
ifNotExists := p.parseIfNotExists()
@@ -4194,3 +4241,34 @@ func (p *Parser) parseRenameTable(pos token.Pos) *ast.RenameTable {
41944241
}
41954242

41964243
}
4244+
4245+
func (p *Parser) parseProtoBundleAlteration() ast.ProtoBundleAlteration {
4246+
switch {
4247+
case p.Token.IsKeywordLike("INSERT"):
4248+
insert := p.expectKeywordLike("INSERT").Pos
4249+
types := p.parseProtoBundleTypes()
4250+
4251+
return &ast.AlterProtoBundleInsert{
4252+
Insert: insert,
4253+
Types: types,
4254+
}
4255+
case p.Token.IsKeywordLike("UPDATE"):
4256+
update := p.expectKeywordLike("UPDATE").Pos
4257+
types := p.parseProtoBundleTypes()
4258+
4259+
return &ast.AlterProtoBundleUpdate{
4260+
Update: update,
4261+
Types: types,
4262+
}
4263+
case p.Token.IsKeywordLike("DELETE"):
4264+
delete := p.expectKeywordLike("DELETE").Pos
4265+
types := p.parseProtoBundleTypes()
4266+
4267+
return &ast.AlterProtoBundleDelete{
4268+
Delete: delete,
4269+
Types: types,
4270+
}
4271+
default:
4272+
panic(p.errorfAtToken(&p.Token, `expected INSERT, UPDATE or DELETE, but: %v`, p.Token.AsString))
4273+
}
4274+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER PROTO BUNDLE DELETE(`examples.shipping.OrderHistory`)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
ALTER PROTO BUNDLE INSERT (
2+
examples.shipping.OrderHistory
3+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER PROTO BUNDLE UPDATE(`examples.shipping.Order`)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
-- If you're using a protocol buffer type and any part of the type name is a Spanner reserved keyword,
2+
-- enclose the entire protocol buffer type name in backticks.
3+
CREATE PROTO BUNDLE (
4+
`examples.shipping.Order`,
5+
`examples.shipping.Order.Address`,
6+
`examples.shipping.Order.Item`)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
DROP PROTO BUNDLE
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--- alter_proto_bundle_delete.sql
2+
ALTER PROTO BUNDLE DELETE(`examples.shipping.OrderHistory`)
3+
--- AST
4+
&ast.AlterProtoBundle{
5+
Alter: 0,
6+
Alteration: &ast.AlterProtoBundleDelete{
7+
Delete: 19,
8+
Types: &ast.ProtoBundleTypes{
9+
Lparen: 25,
10+
Rparen: 58,
11+
Types: []*ast.NamedType{
12+
&ast.NamedType{
13+
Path: []*ast.Ident{
14+
&ast.Ident{
15+
NamePos: 26,
16+
NameEnd: 58,
17+
Name: "examples.shipping.OrderHistory",
18+
},
19+
},
20+
},
21+
},
22+
},
23+
},
24+
}
25+
26+
--- SQL
27+
ALTER PROTO BUNDLE DELETE (`examples.shipping.OrderHistory`)

0 commit comments

Comments
 (0)