Repository: cloudspannerecosystem/memefish
Pull request #85 (2024-08-20 13:02:30)

Add support of DROP|ALTER SEQUENCE syntax
For the documentation, please refer to:

- [ALTER SEQUENCE](https://cloud.google.com/spanner/docs/reference/standard-sql/data-definition-language#alter-sequence)
- [DROP SEQUENCE](https://cloud.google.com/spanner/docs/reference/standard-sql/data-definition-language#drop-sequence)


Patch:
diff --git a/ast/ast.go b/ast/ast.go
index 834070a..a58895c 100644
--- a/ast/ast.go
+++ b/ast/ast.go
@@ -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()             {}
@@ -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()              {}
@@ -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.
@@ -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}}
@@ -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}}
@@ -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
+}
diff --git a/ast/pos.go b/ast/pos.go
index aec0536..ad28dca 100644
--- a/ast/pos.go
+++ b/ast/pos.go
@@ -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 {
@@ -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() }
 
@@ -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() }
 
@@ -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 }
diff --git a/ast/sql.go b/ast/sql.go
index 25bdd7b..8c3fdad 100644
--- a/ast/sql.go
+++ b/ast/sql.go
@@ -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()
 }
@@ -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 {
@@ -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()
 }
diff --git a/parser.go b/parser.go
index ead5e3c..fb5473c 100644
--- a/parser.go
+++ b/parser.go
@@ -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)
 		}
@@ -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"):
@@ -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
@@ -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,
 		})
@@ -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,
@@ -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")
@@ -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()


Test patch:
diff --git a/ast/ast_test.go b/ast/ast_test.go
index 51e90ea..e3ab0b7 100644
--- a/ast/ast_test.go
+++ b/ast/ast_test.go
@@ -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()
diff --git a/testdata/input/ddl/alter_sequence.sql b/testdata/input/ddl/alter_sequence.sql
new file mode 100644
index 0000000..bdaab1f
--- /dev/null
+++ b/testdata/input/ddl/alter_sequence.sql
@@ -0,0 +1,1 @@
+ALTER SEQUENCE my_sequence SET OPTIONS (skip_range_min=1, skip_range_max=1234567)
diff --git a/testdata/input/ddl/drop_sequence.sql b/testdata/input/ddl/drop_sequence.sql
new file mode 100644
index 0000000..5233216
--- /dev/null
+++ b/testdata/input/ddl/drop_sequence.sql
@@ -0,0 +1,1 @@
+DROP SEQUENCE my_sequence
diff --git a/testdata/input/ddl/drop_sequence_if_exits.sql b/testdata/input/ddl/drop_sequence_if_exits.sql
new file mode 100644
index 0000000..fc6962b
--- /dev/null
+++ b/testdata/input/ddl/drop_sequence_if_exits.sql
@@ -0,0 +1,1 @@
+DROP SEQUENCE IF EXISTS my_sequence
diff --git a/testdata/result/ddl/alter_sequence.sql.txt b/testdata/result/ddl/alter_sequence.sql.txt
new file mode 100644
index 0000000..c8e8305
--- /dev/null
+++ b/testdata/result/ddl/alter_sequence.sql.txt
@@ -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)
diff --git a/testdata/result/ddl/create_sequance.sql.txt b/testdata/result/ddl/create_sequance.sql.txt
index 37c68aa..9d6a557 100644
--- a/testdata/result/ddl/create_sequance.sql.txt
+++ b/testdata/result/ddl/create_sequance.sql.txt
@@ -8,63 +8,66 @@ CREATE SEQUENCE IF NOT EXISTS MySequence OPTIONS (
 --- AST
 &ast.CreateSequence{
   Create: 0,
-  Rparen: 172,
   Name:   &ast.Ident{
     NamePos: 30,
     NameEnd: 40,
     Name:    "MySequence",
   },
   IfNotExists: true,
-  Options:     []*ast.SequenceOption{
-    &ast.SequenceOption{
-      Name: &ast.Ident{
-        NamePos: 55,
-        NameEnd: 68,
-        Name:    "sequence_kind",
+  Options:     &ast.SequenceOptions{
+    Options: 41,
+    Rparen:  172,
+    Records: []*ast.SequenceOption{
+      &ast.SequenceOption{
+        Name: &ast.Ident{
+          NamePos: 55,
+          NameEnd: 68,
+          Name:    "sequence_kind",
+        },
+        Value: &ast.StringLiteral{
+          ValuePos: 69,
+          ValueEnd: 92,
+          Value:    "bit_reversed_positive",
+        },
       },
-      Value: &ast.StringLiteral{
-        ValuePos: 69,
-        ValueEnd: 92,
-        Value:    "bit_reversed_positive",
+      &ast.SequenceOption{
+        Name: &ast.Ident{
+          NamePos: 98,
+          NameEnd: 112,
+          Name:    "skip_range_min",
+        },
+        Value: &ast.IntLiteral{
+          ValuePos: 115,
+          ValueEnd: 116,
+          Base:     10,
+          Value:    "1",
+        },
       },
-    },
-    &ast.SequenceOption{
-      Name: &ast.Ident{
-        NamePos: 98,
-        NameEnd: 112,
-        Name:    "skip_range_min",
-      },
-      Value: &ast.IntLiteral{
-        ValuePos: 115,
-        ValueEnd: 116,
-        Base:     10,
-        Value:    "1",
-      },
-    },
-    &ast.SequenceOption{
-      Name: &ast.Ident{
-        NamePos: 122,
-        NameEnd: 136,
-        Name:    "skip_range_max",
-      },
-      Value: &ast.IntLiteral{
-        ValuePos: 139,
-        ValueEnd: 143,
-        Base:     10,
-        Value:    "1000",
-      },
-    },
-    &ast.SequenceOption{
-      Name: &ast.Ident{
-        NamePos: 149,
-        NameEnd: 167,
-        Name:    "start_with_counter",
+      &ast.SequenceOption{
+        Name: &ast.Ident{
+          NamePos: 122,
+          NameEnd: 136,
+          Name:    "skip_range_max",
+        },
+        Value: &ast.IntLiteral{
+          ValuePos: 139,
+          ValueEnd: 143,
+          Base:     10,
+          Value:    "1000",
+        },
       },
-      Value: &ast.IntLiteral{
-        ValuePos: 170,
-        ValueEnd: 172,
-        Base:     10,
-        Value:    "50",
+      &ast.SequenceOption{
+        Name: &ast.Ident{
+          NamePos: 149,
+          NameEnd: 167,
+          Name:    "start_with_counter",
+        },
+        Value: &ast.IntLiteral{
+          ValuePos: 170,
+          ValueEnd: 172,
+          Base:     10,
+          Value:    "50",
+        },
       },
     },
   },
diff --git a/testdata/result/ddl/drop_sequence.sql.txt b/testdata/result/ddl/drop_sequence.sql.txt
new file mode 100644
index 0000000..5cf3fb9
--- /dev/null
+++ b/testdata/result/ddl/drop_sequence.sql.txt
@@ -0,0 +1,16 @@
+--- drop_sequence.sql
+DROP SEQUENCE my_sequence
+
+--- AST
+&ast.DropSequence{
+  Drop:     0,
+  IfExists: false,
+  Name:     &ast.Ident{
+    NamePos: 14,
+    NameEnd: 25,
+    Name:    "my_sequence",
+  },
+}
+
+--- SQL
+DROP SEQUENCE my_sequence
diff --git a/testdata/result/ddl/drop_sequence_if_exits.sql.txt b/testdata/result/ddl/drop_sequence_if_exits.sql.txt
new file mode 100644
index 0000000..8d420cb
--- /dev/null
+++ b/testdata/result/ddl/drop_sequence_if_exits.sql.txt
@@ -0,0 +1,16 @@
+--- drop_sequence_if_exits.sql
+DROP SEQUENCE IF EXISTS my_sequence
+
+--- AST
+&ast.DropSequence{
+  Drop:     0,
+  IfExists: true,
+  Name:     &ast.Ident{
+    NamePos: 24,
+    NameEnd: 35,
+    Name:    "my_sequence",
+  },
+}
+
+--- SQL
+DROP SEQUENCE IF EXISTS my_sequence
diff --git a/testdata/result/statement/alter_sequence.sql.txt b/testdata/result/statement/alter_sequence.sql.txt
new file mode 100644
index 0000000..c8e8305
--- /dev/null
+++ b/testdata/result/statement/alter_sequence.sql.txt
@@ -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)
diff --git a/testdata/result/statement/create_sequance.sql.txt b/testdata/result/statement/create_sequance.sql.txt
index 37c68aa..9d6a557 100644
--- a/testdata/result/statement/create_sequance.sql.txt
+++ b/testdata/result/statement/create_sequance.sql.txt
@@ -8,63 +8,66 @@ CREATE SEQUENCE IF NOT EXISTS MySequence OPTIONS (
 --- AST
 &ast.CreateSequence{
   Create: 0,
-  Rparen: 172,
   Name:   &ast.Ident{
     NamePos: 30,
     NameEnd: 40,
     Name:    "MySequence",
   },
   IfNotExists: true,
-  Options:     []*ast.SequenceOption{
-    &ast.SequenceOption{
-      Name: &ast.Ident{
-        NamePos: 55,
-        NameEnd: 68,
-        Name:    "sequence_kind",
+  Options:     &ast.SequenceOptions{
+    Options: 41,
+    Rparen:  172,
+    Records: []*ast.SequenceOption{
+      &ast.SequenceOption{
+        Name: &ast.Ident{
+          NamePos: 55,
+          NameEnd: 68,
+          Name:    "sequence_kind",
+        },
+        Value: &ast.StringLiteral{
+          ValuePos: 69,
+          ValueEnd: 92,
+          Value:    "bit_reversed_positive",
+        },
       },
-      Value: &ast.StringLiteral{
-        ValuePos: 69,
-        ValueEnd: 92,
-        Value:    "bit_reversed_positive",
+      &ast.SequenceOption{
+        Name: &ast.Ident{
+          NamePos: 98,
+          NameEnd: 112,
+          Name:    "skip_range_min",
+        },
+        Value: &ast.IntLiteral{
+          ValuePos: 115,
+          ValueEnd: 116,
+          Base:     10,
+          Value:    "1",
+        },
       },
-    },
-    &ast.SequenceOption{
-      Name: &ast.Ident{
-        NamePos: 98,
-        NameEnd: 112,
-        Name:    "skip_range_min",
-      },
-      Value: &ast.IntLiteral{
-        ValuePos: 115,
-        ValueEnd: 116,
-        Base:     10,
-        Value:    "1",
-      },
-    },
-    &ast.SequenceOption{
-      Name: &ast.Ident{
-        NamePos: 122,
-        NameEnd: 136,
-        Name:    "skip_range_max",
-      },
-      Value: &ast.IntLiteral{
-        ValuePos: 139,
-        ValueEnd: 143,
-        Base:     10,
-        Value:    "1000",
-      },
-    },
-    &ast.SequenceOption{
-      Name: &ast.Ident{
-        NamePos: 149,
-        NameEnd: 167,
-        Name:    "start_with_counter",
+      &ast.SequenceOption{
+        Name: &ast.Ident{
+          NamePos: 122,
+          NameEnd: 136,
+          Name:    "skip_range_max",
+        },
+        Value: &ast.IntLiteral{
+          ValuePos: 139,
+          ValueEnd: 143,
+          Base:     10,
+          Value:    "1000",
+        },
       },
-      Value: &ast.IntLiteral{
-        ValuePos: 170,
-        ValueEnd: 172,
-        Base:     10,
-        Value:    "50",
+      &ast.SequenceOption{
+        Name: &ast.Ident{
+          NamePos: 149,
+          NameEnd: 167,
+          Name:    "start_with_counter",
+        },
+        Value: &ast.IntLiteral{
+          ValuePos: 170,
+          ValueEnd: 172,
+          Base:     10,
+          Value:    "50",
+        },
       },
     },
   },
diff --git a/testdata/result/statement/drop_sequence.sql.txt b/testdata/result/statement/drop_sequence.sql.txt
new file mode 100644
index 0000000..5cf3fb9
--- /dev/null
+++ b/testdata/result/statement/drop_sequence.sql.txt
@@ -0,0 +1,16 @@
+--- drop_sequence.sql
+DROP SEQUENCE my_sequence
+
+--- AST
+&ast.DropSequence{
+  Drop:     0,
+  IfExists: false,
+  Name:     &ast.Ident{
+    NamePos: 14,
+    NameEnd: 25,
+    Name:    "my_sequence",
+  },
+}
+
+--- SQL
+DROP SEQUENCE my_sequence
diff --git a/testdata/result/statement/drop_sequence_if_exits.sql.txt b/testdata/result/statement/drop_sequence_if_exits.sql.txt
new file mode 100644
index 0000000..8d420cb
--- /dev/null
+++ b/testdata/result/statement/drop_sequence_if_exits.sql.txt
@@ -0,0 +1,16 @@
+--- drop_sequence_if_exits.sql
+DROP SEQUENCE IF EXISTS my_sequence
+
+--- AST
+&ast.DropSequence{
+  Drop:     0,
+  IfExists: true,
+  Name:     &ast.Ident{
+    NamePos: 24,
+    NameEnd: 35,
+    Name:    "my_sequence",
+  },
+}
+
+--- SQL
+DROP SEQUENCE IF EXISTS my_sequence