Repository: cloudspannerecosystem/memefish
Pull request #70 (2023-08-29 13:21:11)

Add support for DROP TABLE IF EXISTS statement
This PR adds support for [DROP TABLE IF EXISTS](https://cloud.google.com/spanner/docs/reference/standard-sql/data-definition-language#drop_table) statement.

makenowjust: Seems good. Thank you @toga4 for you contribution!

Patch:
diff --git a/ast/ast.go b/ast/ast.go
index c960482..c6259e9 100644
--- a/ast/ast.go
+++ b/ast/ast.go
@@ -1725,14 +1725,15 @@ type AlterColumnSet struct {
 
 // DropTable is DROP TABLE statement node.
 //
-//	DROP TABLE {{.Name | sql}}
+//	DROP TABLE {{if .IfExists}}IF NOT EXISTS{{end}} {{.Name | sql}}
 type DropTable struct {
 	// pos = Drop
 	// end = Name.end
 
 	Drop token.Pos // position of "DROP" keyword
 
-	Name *Ident
+	IfExists bool
+	Name     *Ident
 }
 
 // CreateIndex is CREATE INDEX statement node.
diff --git a/ast/sql.go b/ast/sql.go
index d816c5f..5300efe 100644
--- a/ast/sql.go
+++ b/ast/sql.go
@@ -925,7 +925,11 @@ func (a *AlterColumnSet) SQL() string {
 }
 
 func (d *DropTable) SQL() string {
-	return "DROP TABLE " + d.Name.SQL()
+	sql := "DROP TABLE "
+	if d.IfExists {
+		sql += "IF EXISTS "
+	}
+	return sql + d.Name.SQL()
 }
 
 func (c *CreateIndex) SQL() string {
diff --git a/parser.go b/parser.go
index 4bdd0dd..66517d7 100644
--- a/parser.go
+++ b/parser.go
@@ -2696,10 +2696,17 @@ func (p *Parser) parseAlterColumn() ast.TableAlternation {
 
 func (p *Parser) parseDropTable(pos token.Pos) *ast.DropTable {
 	p.expectKeywordLike("TABLE")
+	ifExists := false
+	if p.Token.IsKeywordLike("IF") {
+		p.nextToken()
+		p.expect("EXISTS")
+		ifExists = true
+	}
 	name := p.parseIdent()
 	return &ast.DropTable{
-		Drop: pos,
-		Name: name,
+		Drop:     pos,
+		IfExists: ifExists,
+		Name:     name,
 	}
 }
 


Test patch:
diff --git a/testdata/input/ddl/drop_table_if_exists.sql b/testdata/input/ddl/drop_table_if_exists.sql
new file mode 100644
index 0000000..4121939
--- /dev/null
+++ b/testdata/input/ddl/drop_table_if_exists.sql
@@ -0,0 +1,1 @@
+drop table if exists foo
diff --git a/testdata/result/ddl/drop_table.sql.txt b/testdata/result/ddl/drop_table.sql.txt
index 095f343..70ee12d 100644
--- a/testdata/result/ddl/drop_table.sql.txt
+++ b/testdata/result/ddl/drop_table.sql.txt
@@ -3,8 +3,9 @@ drop table foo
 
 --- AST
 &ast.DropTable{
-  Drop: 0,
-  Name: &ast.Ident{
+  Drop:     0,
+  IfExists: false,
+  Name:     &ast.Ident{
     NamePos: 11,
     NameEnd: 14,
     Name:    "foo",
diff --git a/testdata/result/ddl/drop_table_if_exists.sql.txt b/testdata/result/ddl/drop_table_if_exists.sql.txt
new file mode 100644
index 0000000..299373d
--- /dev/null
+++ b/testdata/result/ddl/drop_table_if_exists.sql.txt
@@ -0,0 +1,16 @@
+--- drop_table_if_exists.sql
+drop table if exists foo
+
+--- AST
+&ast.DropTable{
+  Drop:     0,
+  IfExists: true,
+  Name:     &ast.Ident{
+    NamePos: 21,
+    NameEnd: 24,
+    Name:    "foo",
+  },
+}
+
+--- SQL
+DROP TABLE IF EXISTS foo
diff --git a/testdata/result/statement/drop_table.sql.txt b/testdata/result/statement/drop_table.sql.txt
index 095f343..70ee12d 100644
--- a/testdata/result/statement/drop_table.sql.txt
+++ b/testdata/result/statement/drop_table.sql.txt
@@ -3,8 +3,9 @@ drop table foo
 
 --- AST
 &ast.DropTable{
-  Drop: 0,
-  Name: &ast.Ident{
+  Drop:     0,
+  IfExists: false,
+  Name:     &ast.Ident{
     NamePos: 11,
     NameEnd: 14,
     Name:    "foo",
diff --git a/testdata/result/statement/drop_table_if_exists.sql.txt b/testdata/result/statement/drop_table_if_exists.sql.txt
new file mode 100644
index 0000000..299373d
--- /dev/null
+++ b/testdata/result/statement/drop_table_if_exists.sql.txt
@@ -0,0 +1,16 @@
+--- drop_table_if_exists.sql
+drop table if exists foo
+
+--- AST
+&ast.DropTable{
+  Drop:     0,
+  IfExists: true,
+  Name:     &ast.Ident{
+    NamePos: 21,
+    NameEnd: 24,
+    Name:    "foo",
+  },
+}
+
+--- SQL
+DROP TABLE IF EXISTS foo