Repository: cloudspannerecosystem/memefish (go)

Issue:
Support ALTER STATISTICS statement
`ALTER STATISTICS` statement is not yet supported.

## Syntax

https://cloud.google.com/spanner/docs/reference/standard-sql/data-definition-language#alter-statistics

```
ALTER STATISTICS package_name
    action

where package_name is:
    {a—z}[{a—z|0—9|_|-}+]{a—z|0—9}

and action is:
    SET OPTIONS ( options_def )

and options_def is:
    { allow_gc = { true | false } }
```

Pull request description:
Implement ALTER STATISTICS statement
This PR implements `ALTER STATISTICS` statement.

fix #162

Patch:
diff --git a/ast/ast.go b/ast/ast.go
index bcc2f89..0f5ae5c 100644
--- a/ast/ast.go
+++ b/ast/ast.go
@@ -77,6 +77,7 @@ func (Revoke) isStatement()             {}
 func (CreateSequence) isStatement()     {}
 func (AlterSequence) isStatement()      {}
 func (DropSequence) isStatement()       {}
+func (AlterStatistics) isStatement()    {}
 func (CreateVectorIndex) isStatement()  {}
 func (DropVectorIndex) isStatement()    {}
 func (Insert) isStatement()             {}
@@ -287,6 +288,7 @@ func (Revoke) isDDL()             {}
 func (CreateSequence) isDDL()     {}
 func (AlterSequence) isDDL()      {}
 func (DropSequence) isDDL()       {}
+func (AlterStatistics) isDDL()    {}
 func (CreateVectorIndex) isDDL()  {}
 func (DropVectorIndex) isDDL()    {}
 
@@ -2566,6 +2568,19 @@ type RolePrivilege struct {
 	Names []*Ident // len(Names) > 0
 }
 
+// AlterStatistics is ALTER STATISTICS statement node.
+//
+//	ALTER STATISTICS {{.Name | sql}} SET {{.Options | sql}}
+type AlterStatistics struct {
+	// pos = Alter
+	// end = Options.end
+
+	Alter token.Pos // position of "ALTER" keyword
+
+	Name    *Ident
+	Options *Options
+}
+
 // ================================================================================
 //
 // Types for Schema
diff --git a/ast/pos.go b/ast/pos.go
index cdc5b27..72a2a05 100644
--- a/ast/pos.go
+++ b/ast/pos.go
@@ -892,6 +892,9 @@ func (e *ExecutePrivilegeOnTableFunction) End() token.Pos { return e.Names[len(e
 func (r *RolePrivilege) Pos() token.Pos { return r.Role }
 func (r *RolePrivilege) End() token.Pos { return r.Names[len(r.Names)-1].End() }
 
+func (s *AlterStatistics) Pos() token.Pos { return s.Alter }
+func (s *AlterStatistics) End() token.Pos { return s.Options.End() }
+
 // ================================================================================
 //
 // Types for Schema
diff --git a/ast/sql.go b/ast/sql.go
index ce23dbe..65c3f46 100644
--- a/ast/sql.go
+++ b/ast/sql.go
@@ -1238,6 +1238,10 @@ func (r *RolePrivilege) SQL() string {
 	return sql
 }
 
+func (s *AlterStatistics) SQL() string {
+	return "ALTER STATISTICS " + s.Name.SQL() + " SET " + s.Options.SQL()
+}
+
 // ================================================================================
 //
 // Types for Schema
diff --git a/parser.go b/parser.go
index 369fa36..fa2017f 100644
--- a/parser.go
+++ b/parser.go
@@ -2180,6 +2180,8 @@ func (p *Parser) parseDDL() ast.DDL {
 			return p.parseAlterSequence(pos)
 		case p.Token.IsKeywordLike("CHANGE"):
 			return p.parseAlterChangeStream(pos)
+		case p.Token.IsKeywordLike("STATISTICS"):
+			return p.parseAlterStatistics(pos)
 		}
 		p.panicfAtToken(&p.Token, "expected pseudo keyword: TABLE, CHANGE, but: %s", p.Token.AsString)
 	case p.Token.IsKeywordLike("DROP"):
@@ -3408,6 +3410,19 @@ func (p *Parser) parseSchemaType() ast.SchemaType {
 	panic(p.errorfAtToken(&p.Token, "expected token: ARRAY, <ident>, but: %s", p.Token.Kind))
 }
 
+func (p *Parser) parseAlterStatistics(pos token.Pos) *ast.AlterStatistics {
+	p.expectKeywordLike("STATISTICS")
+	name := p.parseIdent()
+	p.expect("SET")
+	options := p.parseOptions()
+
+	return &ast.AlterStatistics{
+		Alter:   pos,
+		Name:    name,
+		Options: options,
+	}
+}
+
 var scalarSchemaTypes = []string{
 	"BOOL",
 	"INT64",


Test patch:
diff --git a/testdata/input/ddl/alter_statistics.sql b/testdata/input/ddl/alter_statistics.sql
new file mode 100644
index 0000000..7f53d07
--- /dev/null
+++ b/testdata/input/ddl/alter_statistics.sql
@@ -0,0 +1,1 @@
+ALTER STATISTICS auto_20191128_14_47_22UTC SET OPTIONS (allow_gc=false)
\ No newline at end of file
diff --git a/testdata/result/ddl/alter_statistics.sql.txt b/testdata/result/ddl/alter_statistics.sql.txt
new file mode 100644
index 0000000..5e513ed
--- /dev/null
+++ b/testdata/result/ddl/alter_statistics.sql.txt
@@ -0,0 +1,31 @@
+--- alter_statistics.sql
+ALTER STATISTICS auto_20191128_14_47_22UTC SET OPTIONS (allow_gc=false)
+--- AST
+&ast.AlterStatistics{
+  Alter: 0,
+  Name:  &ast.Ident{
+    NamePos: 17,
+    NameEnd: 42,
+    Name:    "auto_20191128_14_47_22UTC",
+  },
+  Options: &ast.Options{
+    Options: 47,
+    Rparen:  70,
+    Records: []*ast.OptionsDef{
+      &ast.OptionsDef{
+        Name: &ast.Ident{
+          NamePos: 56,
+          NameEnd: 64,
+          Name:    "allow_gc",
+        },
+        Value: &ast.BoolLiteral{
+          ValuePos: 65,
+          Value:    false,
+        },
+      },
+    },
+  },
+}
+
+--- SQL
+ALTER STATISTICS auto_20191128_14_47_22UTC SET OPTIONS (allow_gc = false)
diff --git a/testdata/result/statement/alter_statistics.sql.txt b/testdata/result/statement/alter_statistics.sql.txt
new file mode 100644
index 0000000..5e513ed
--- /dev/null
+++ b/testdata/result/statement/alter_statistics.sql.txt
@@ -0,0 +1,31 @@
+--- alter_statistics.sql
+ALTER STATISTICS auto_20191128_14_47_22UTC SET OPTIONS (allow_gc=false)
+--- AST
+&ast.AlterStatistics{
+  Alter: 0,
+  Name:  &ast.Ident{
+    NamePos: 17,
+    NameEnd: 42,
+    Name:    "auto_20191128_14_47_22UTC",
+  },
+  Options: &ast.Options{
+    Options: 47,
+    Rparen:  70,
+    Records: []*ast.OptionsDef{
+      &ast.OptionsDef{
+        Name: &ast.Ident{
+          NamePos: 56,
+          NameEnd: 64,
+          Name:    "allow_gc",
+        },
+        Value: &ast.BoolLiteral{
+          ValuePos: 65,
+          Value:    false,
+        },
+      },
+    },
+  },
+}
+
+--- SQL
+ALTER STATISTICS auto_20191128_14_47_22UTC SET OPTIONS (allow_gc = false)