Skip to content

Commit

Permalink
Add support of DROP|ALTER SEQUENCE syntax (#85)
Browse files Browse the repository at this point in the history
* Add support of DROP SEQUENCE statement

* Add support of ALTER SEQUENCE statement
  • Loading branch information
git-hulk authored Aug 20, 2024
1 parent 2482e84 commit 9cf46ee
Show file tree
Hide file tree
Showing 16 changed files with 386 additions and 118 deletions.
44 changes: 41 additions & 3 deletions ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,11 @@ func (CreateVectorIndex) isStatement() {}
func (CreateRole) isStatement() {}
func (AlterTable) isStatement() {}
func (AlterIndex) isStatement() {}
func (AlterSequence) isStatement() {}
func (DropTable) isStatement() {}
func (DropIndex) isStatement() {}
func (DropVectorIndex) isStatement() {}
func (DropSequence) isStatement() {}
func (DropRole) isStatement() {}
func (Insert) isStatement() {}
func (Delete) isStatement() {}
Expand Down Expand Up @@ -230,8 +232,10 @@ func (DropTable) isDDL() {}
func (CreateIndex) isDDL() {}
func (CreateVectorIndex) isDDL() {}
func (AlterIndex) isDDL() {}
func (AlterSequence) isDDL() {}
func (DropIndex) isDDL() {}
func (DropVectorIndex) isDDL() {}
func (DropSequence) isDDL() {}
func (CreateRole) isDDL() {}
func (DropRole) isDDL() {}
func (Grant) isDDL() {}
Expand Down Expand Up @@ -1448,14 +1452,13 @@ type CreateTable struct {
// CREATE SEQUENCE {{if .IfNotExists}}IF NOT EXISTS{{end}} {{.Name | sql}} }} OPTIONS ({{.Options | sqlJoin ","}})
type CreateSequence struct {
// pos = Create
// end = Rparen + 1
// end = Options.end

Create token.Pos // position of "CREATE" keyword
Rparen token.Pos // position of ")" of OPTIONS clause

Name *Ident
IfNotExists bool
Options []*SequenceOption // len(Options) > 0
Options *SequenceOptions
}

// ColumnDef is column definition in CREATE TABLE.
Expand Down Expand Up @@ -1654,6 +1657,17 @@ type AlterIndex struct {
IndexAlteration IndexAlteration
}

// AlterSequence is ALTER SEQUENCE statement node.
type AlterSequence struct {
// pos = Alter
// end = Options.end

Alter token.Pos // position of "ALTER" keyword

Name *Ident
Options *SequenceOptions
}

// AlterChangeStream is ALTER CHANGE STREAM statement node.
//
// ALTER CHANGE STREAM {{.Name | sql}} {{.ChangeStreamAlteration | sql}}
Expand Down Expand Up @@ -2067,6 +2081,17 @@ type DropVectorIndex struct {
Name *Ident
}

// DropSequence is DROP SEQUENCE statement node.
//
// DROP SEQUENCE {{if .IfExists}}IF EXISTS{{end}} {{.Name | sql}}
type DropSequence struct {
// pos = Drop
// end = Name.end
Drop token.Pos
IfExists bool
Name *Ident
}

// CreateRole is CREATE ROLE statement node.
//
// CREATE ROLE {{.Name | sql}}
Expand Down Expand Up @@ -2392,3 +2417,16 @@ type SequenceOption struct {
Name *Ident
Value Expr
}

// SequenceOptions is OPTIONS clause node in CREATE|ALTER SEQUENCE .
//
// OPTIONS ({{.Records | sqlJoin ","}})
type SequenceOptions struct {
// pos = Options
// end = Rparen + 1

Options token.Pos // position of "OPTIONS" keyword
Rparen token.Pos // position of ")"

Records []*SequenceOption // len(Records) > 0
}
2 changes: 2 additions & 0 deletions ast/ast_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ func TestDDL(t *testing.T) {
DDL(&CreateIndex{}).isDDL()
DDL(&CreateVectorIndex{}).isDDL()
DDL(&CreateSequence{}).isDDL()
DDL(&AlterSequence{}).isDDL()
DDL(&DropSequence{}).isDDL()
DDL(&CreateView{}).isDDL()
DDL(&AlterTable{}).isDDL()
DDL(&DropTable{}).isDDL()
Expand Down
11 changes: 10 additions & 1 deletion ast/pos.go
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ func (c *CreateSequence) Pos() token.Pos {
}

func (c *CreateSequence) End() token.Pos {
return c.Rparen + 1
return c.Options.End()
}

func (c *CreateView) Pos() token.Pos {
Expand Down Expand Up @@ -703,6 +703,9 @@ func (i *InterleaveIn) End() token.Pos { return i.TableName.End() }
func (a *AlterIndex) Pos() token.Pos { return a.Alter }
func (a *AlterIndex) End() token.Pos { return a.IndexAlteration.End() }

func (a *AlterSequence) Pos() token.Pos { return a.Alter }
func (a *AlterSequence) End() token.Pos { return a.Options.End() }

func (a *AddStoredColumn) Pos() token.Pos { return a.Add }
func (a *AddStoredColumn) End() token.Pos { return a.Name.End() }

Expand All @@ -715,6 +718,9 @@ func (d *DropIndex) End() token.Pos { return d.Name.End() }
func (d *DropVectorIndex) Pos() token.Pos { return d.Drop }
func (d *DropVectorIndex) End() token.Pos { return d.Name.End() }

func (d *DropSequence) Pos() token.Pos { return d.Drop }
func (d *DropSequence) End() token.Pos { return d.Name.End() }

func (c *CreateRole) Pos() token.Pos { return c.Create }
func (c *CreateRole) End() token.Pos { return c.Name.End() }

Expand Down Expand Up @@ -855,3 +861,6 @@ func (u *UpdateItem) End() token.Pos { return u.Expr.End() }

func (o *SequenceOption) Pos() token.Pos { return o.Name.Pos() }
func (o *SequenceOption) End() token.Pos { return o.Value.End() }

func (o *SequenceOptions) Pos() token.Pos { return o.Options }
func (o *SequenceOptions) End() token.Pos { return o.Rparen + 1 }
33 changes: 25 additions & 8 deletions ast/sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,18 @@ func (o *SequenceOption) SQL() string {
return o.Name.SQL() + " = " + o.Value.SQL()
}

func (o *SequenceOptions) SQL() string {
sql := "OPTIONS ("
for i, o := range o.Records {
if i > 0 {
sql += ", "
}
sql += o.SQL()
}
sql += ")"
return sql
}

func (s *ExprArg) SQL() string {
return s.Expr.SQL()
}
Expand Down Expand Up @@ -755,17 +767,14 @@ func (c *CreateSequence) SQL() string {
if c.IfNotExists {
sql += "IF NOT EXISTS "
}
sql += c.Name.SQL() + " OPTIONS ("
for i, o := range c.Options {
if i > 0 {
sql += ", "
}
sql += o.SQL()
}
sql += ")"
sql += c.Name.SQL() + " " + c.Options.SQL()
return sql
}

func (c *AlterSequence) SQL() string {
return "ALTER SEQUENCE " + c.Name.SQL() + " SET " + c.Options.SQL()
}

func (c *CreateView) SQL() string {
sql := "CREATE"
if c.OrReplace {
Expand Down Expand Up @@ -1115,6 +1124,14 @@ func (d *DropVectorIndex) SQL() string {
return sql + d.Name.SQL()
}

func (d *DropSequence) SQL() string {
sql := "DROP SEQUENCE "
if d.IfExists {
sql += "IF EXISTS "
}
return sql + d.Name.SQL()
}

func (c *CreateRole) SQL() string {
return "CREATE ROLE " + c.Name.SQL()
}
Expand Down
55 changes: 45 additions & 10 deletions parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -2002,6 +2002,8 @@ func (p *Parser) parseDDL() ast.DDL {
return p.parseAlterTable(pos)
case p.Token.IsKeywordLike("INDEX"):
return p.parseAlterIndex(pos)
case p.Token.IsKeywordLike("SEQUENCE"):
return p.parseAlterSequence(pos)
case p.Token.IsKeywordLike("CHANGE"):
return p.parseAlterChangeStream(pos)
}
Expand All @@ -2015,6 +2017,8 @@ func (p *Parser) parseDDL() ast.DDL {
return p.parseDropIndex(pos)
case p.Token.IsKeywordLike("VECTOR"):
return p.parseDropVectorIndex(pos)
case p.Token.IsKeywordLike("SEQUENCE"):
return p.parseDropSequence(pos)
case p.Token.IsKeywordLike("ROLE"):
return p.parseDropRole(pos)
case p.Token.IsKeywordLike("CHANGE"):
Expand Down Expand Up @@ -2111,14 +2115,10 @@ func (p *Parser) parseCreateTable(pos token.Pos) *ast.CreateTable {
}
}

func (p *Parser) parseCreateSequence(pos token.Pos) *ast.CreateSequence {
p.expectKeywordLike("SEQUENCE")
ifNotExists := p.parseIfNotExists()
name := p.parseIdent()

func (p *Parser) parseSequenceOptions(pos token.Pos) *ast.SequenceOptions {
p.expectKeywordLike("OPTIONS")
p.expect("(")
var options []*ast.SequenceOption
var records []*ast.SequenceOption
for p.Token.Kind != token.TokenEOF {
if p.Token.Kind == ")" {
break
Expand All @@ -2134,7 +2134,7 @@ func (p *Parser) parseCreateSequence(pos token.Pos) *ast.CreateSequence {
default:
p.panicfAtToken(&p.Token, "expected token: <int>, <string>, but: %s", p.Token.Kind)
}
options = append(options, &ast.SequenceOption{
records = append(records, &ast.SequenceOption{
Name: optionName,
Value: value,
})
Expand All @@ -2144,14 +2144,25 @@ func (p *Parser) parseCreateSequence(pos token.Pos) *ast.CreateSequence {
p.nextToken()

}
if len(options) == 0 {
rparen := p.expect(")").Pos
if len(records) == 0 {
p.panicfAtToken(&p.Token, "required at least one option")
}
return &ast.SequenceOptions{
Options: pos,
Rparen: rparen,
Records: records,
}
}

func (p *Parser) parseCreateSequence(pos token.Pos) *ast.CreateSequence {
p.expectKeywordLike("SEQUENCE")
ifNotExists := p.parseIfNotExists()
name := p.parseIdent()
options := p.parseSequenceOptions(p.Token.Pos)

rparent := p.expect(")").Pos
return &ast.CreateSequence{
Create: pos,
Rparen: rparent,
Name: name,
IfNotExists: ifNotExists,
Options: options,
Expand Down Expand Up @@ -2929,6 +2940,19 @@ func (p *Parser) parseAlterIndex(pos token.Pos) *ast.AlterIndex {
}
}

func (p *Parser) parseAlterSequence(pos token.Pos) *ast.AlterSequence {
p.expectKeywordLike("SEQUENCE")
name := p.parseIdent()
p.expect("SET")
options := p.parseSequenceOptions(p.Token.Pos)

return &ast.AlterSequence{
Alter: pos,
Name: name,
Options: options,
}
}

func (p *Parser) parseAddStoredColumn() ast.IndexAlteration {
pos := p.expectKeywordLike("ADD").Pos
p.expectKeywordLike("STORED")
Expand Down Expand Up @@ -2988,6 +3012,17 @@ func (p *Parser) parseDropVectorIndex(pos token.Pos) *ast.DropVectorIndex {
}
}

func (p *Parser) parseDropSequence(pos token.Pos) *ast.DropSequence {
p.expectKeywordLike("SEQUENCE")
ifExists := p.parseIfExists()
name := p.parseIdent()
return &ast.DropSequence{
Drop: pos,
IfExists: ifExists,
Name: name,
}
}

func (p *Parser) parseCreateRole(pos token.Pos) *ast.CreateRole {
p.expectKeywordLike("ROLE")
name := p.parseIdent()
Expand Down
1 change: 1 addition & 0 deletions testdata/input/ddl/alter_sequence.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER SEQUENCE my_sequence SET OPTIONS (skip_range_min=1, skip_range_max=1234567)
1 change: 1 addition & 0 deletions testdata/input/ddl/drop_sequence.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP SEQUENCE my_sequence
1 change: 1 addition & 0 deletions testdata/input/ddl/drop_sequence_if_exits.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP SEQUENCE IF EXISTS my_sequence
47 changes: 47 additions & 0 deletions testdata/result/ddl/alter_sequence.sql.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
--- alter_sequence.sql
ALTER SEQUENCE my_sequence SET OPTIONS (skip_range_min=1, skip_range_max=1234567)

--- AST
&ast.AlterSequence{
Alter: 0,
Name: &ast.Ident{
NamePos: 15,
NameEnd: 26,
Name: "my_sequence",
},
Options: &ast.SequenceOptions{
Options: 31,
Rparen: 80,
Records: []*ast.SequenceOption{
&ast.SequenceOption{
Name: &ast.Ident{
NamePos: 40,
NameEnd: 54,
Name: "skip_range_min",
},
Value: &ast.IntLiteral{
ValuePos: 55,
ValueEnd: 56,
Base: 10,
Value: "1",
},
},
&ast.SequenceOption{
Name: &ast.Ident{
NamePos: 58,
NameEnd: 72,
Name: "skip_range_max",
},
Value: &ast.IntLiteral{
ValuePos: 73,
ValueEnd: 80,
Base: 10,
Value: "1234567",
},
},
},
},
}

--- SQL
ALTER SEQUENCE my_sequence SET OPTIONS (skip_range_min = 1, skip_range_max = 1234567)
Loading

0 comments on commit 9cf46ee

Please sign in to comment.