Repository: cloudspannerecosystem/memefish
Pull request #65 (2023-08-28 01:40:36)

Improve AST definitions and docs
This PR adds the package docs for describing `text/template` fashion comments and pos/end comments of nodes.
Also, this fixes code styles and removes some unnecessary fields.


Patch:
diff --git a/ast/ast.go b/ast/ast.go
index 67899c9..fdf0cbf 100644
--- a/ast/ast.go
+++ b/ast/ast.go
@@ -1,3 +1,34 @@
+// Package ast provides AST nodes definitions.
+//
+// The definitions of ASTs are based on the following document.
+//
+//   - <https://cloud.google.com/spanner/docs/reference/standard-sql/data-definition-language>
+//   - <https://cloud.google.com/spanner/docs/query-syntax>
+//
+// Each `Node`'s documentation describes its syntax (SQL representation) in a `text/template`
+// fashion with thw following custom functions.
+//
+//   - `sql node`: Returns the SQL representation of `node`.
+//   - `sqlOpt node`: Like `sql node`, but returns the empty string if `node` is `nil`.
+//   - `sqlJoin sep nodes`: Concatenates the SQL representations of `nodes` with `sep`.
+//   - `sqlIdentQuote x`: Quotes the given identifier string if needed.
+//   - `sqlStringQuote s`: Returns the SQL quoted string of `s`.
+//   - `sqlBytesQuote bs`: Returns the SQL quotes bytes of `bs`.
+//   - `isnil v`: Checks whether `v` is `nil` or others.
+//
+// Each `Node`s documentation has `pos` and `end` information using the following EBNF.
+//
+//	PosChoice -> PosExpr ("||" PosExpr)*
+//	PosExpr   -> PosAtom (PosOp IntAtom)?
+//	PosAtom   -> PosVar | NodeExpr "." ("pos" | "end")
+//	NodeExpr  -> NodeAtom | "(" NodeAtom ("??" NodeAtom)* ")"
+//	NodeAtom  -> NodeVar | NodeSliceVar "[" (IntAtom | "$") "]"
+//	IntAtom   -> IntVal
+//	           | "len" "(" StringVar ")"
+//	           | "(" BoolVar "?" IntAtom ":" IntAtom ")"
+//	IntVal    -> "0" | "1" | ...
+//
+//	(PosVar, NodeVar, NodeSliceVar, and BoolVar are derived by its `struct` definition.)
 package ast
 
 import (
@@ -185,6 +216,15 @@ func (DropRole) isDDL()       {}
 func (Grant) isDDL()          {}
 func (Revoke) isDDL()         {}
 
+// Constraint represents table constraint of CONSTARINT clause.
+type Constraint interface {
+	Node
+	isConstraint()
+}
+
+func (ForeignKey) isConstraint() {}
+func (Check) isConstraint()      {}
+
 // TableAlternation represents ALTER TABLE action.
 type TableAlternation interface {
 	Node
@@ -488,7 +528,7 @@ type OrderBy struct {
 //	{{.Expr | sql}} {{.Collate | sqlOpt}} {{.Direction}}
 type OrderByItem struct {
 	// pos = Expr.pos
-	// end = DirPos + len(Dir) || (Collate ?? Expr).pos
+	// end = DirPos + len(Dir) || (Collate ?? Expr).end
 
 	DirPos token.Pos // position of Dir
 
@@ -1055,10 +1095,10 @@ type ArrayLiteral struct {
 
 // StructLiteral is struct literal node.
 //
-//	STRUCT{{if .Type}}<{{.Fields | sqlJoin ","}}>{{end}}({{.Values | sqlJoin ","}})
+//	STRUCT{{if not (isnil .Fields)}}<{{.Fields | sqlJoin ","}}>{{end}}({{.Values | sqlJoin ","}})
 type StructLiteral struct {
 	// pos = Struct || Lparen
-	// end = Rparen
+	// end = Rparen + 1
 
 	Struct         token.Pos // position of "STRUCT"
 	Lparen, Rparen token.Pos // position of "(" and ")"
@@ -1130,7 +1170,7 @@ type StringLiteral struct {
 
 // BytesLiteral is bytes literal node.
 //
-//	B{{.Value | sqlByesQuote}}
+//	B{{.Value | sqlBytesQuote}}
 type BytesLiteral struct {
 	// pos = ValuePos
 	// end = ValueEnd
@@ -1286,10 +1326,15 @@ type CreateDatabase struct {
 //
 //	CREATE TABLE {{.Name | sql}} (
 //	  {{.Columns | sqlJoin ","}}
+//	  {{if and .Columns .TableConstrains}},{{end}}{{.TableConstraints | sqlJoin ","}}
 //	)
 //	PRIMARY KEY ({{.PrimaryKeys | sqlJoin ","}})
 //	{{.Cluster | sqlOpt}}
 //	{{.CreateRowDeletionPolicy | sqlOpt}}
+//
+// Spanner SQL allows to mix `Columns` and `TableConstraints`, however they are
+// separated in AST definition for historical reasons. If you want to get
+// the original order of them, please sort them by their `Pos()`.
 type CreateTable struct {
 	// pos = Create
 	// end = CreateRowDeletionPolicy.end || Cluster.end || Rparen + 1
@@ -1299,27 +1344,12 @@ type CreateTable struct {
 
 	Name              *Ident
 	Columns           []*ColumnDef
-	PrimaryKeys       []*IndexKey
 	TableConstraints  []*TableConstraint
+	PrimaryKeys       []*IndexKey
 	Cluster           *Cluster                 // optional
 	RowDeletionPolicy *CreateRowDeletionPolicy // optional
 }
 
-// CreateView is CREATE VIEW statement node.
-//
-//	CREATE {{if .OrReplace}}OR REPLACE{{end}} VIEW {{.Name | sql}}
-//	SQL SECURITY INVOKER AS
-//	{{.Query | sql}}
-type CreateView struct {
-	// pos = Create
-	// end = Query.end
-	Create token.Pos
-
-	Name      *Ident
-	OrReplace bool
-	Query     QueryExpr
-}
-
 // ColumnDef is column definition in CREATE TABLE.
 //
 //	{{.Name | sql}}
@@ -1382,7 +1412,7 @@ type ColumnDefOptions struct {
 
 // TableConstraint is table constraint in CREATE TABLE and ALTER TABLE.
 //
-//	{{if .Name}}CONSTRAINT {{.Name}}{{end}}{{.Constraint}}
+//	{{if .Name}}CONSTRAINT {{.Name}}{{end}}{{.Constraint | sql}}
 type TableConstraint struct {
 	ConstraintPos token.Pos // position of "CONSTRAINT" keyword when Name presents
 
@@ -1390,14 +1420,9 @@ type TableConstraint struct {
 	Constraint Constraint
 }
 
-type Constraint interface {
-	isConstraint()
-	Node
-}
-
 // ForeignKey is foreign key specifier in CREATE TABLE and ALTER TABLE.
 //
-//	FOREIGN KEY ({{.ColumnNames | sqlJoin ","}}) REFERENCES {{.ReferenceTable}}({{.ReferenceColumns | sqlJoin ","}})
+//	FOREIGN KEY ({{.ColumnNames | sqlJoin ","}}) REFERENCES {{.ReferenceTable}} ({{.ReferenceColumns | sqlJoin ","}})
 type ForeignKey struct {
 	// pos = Foreign
 	// end = Rparen + 1
@@ -1407,11 +1432,9 @@ type ForeignKey struct {
 
 	Columns          []*Ident
 	ReferenceTable   *Ident
-	ReferenceColumns []*Ident
+	ReferenceColumns []*Ident // len(ReferenceColumns) > 0
 }
 
-func (*ForeignKey) isConstraint() {}
-
 // Check is check constraint in CREATE TABLE and ALTER TABLE.
 //
 //	Check ({{.Expr}})
@@ -1425,8 +1448,6 @@ type Check struct {
 	Expr Expr
 }
 
-func (*Check) isConstraint() {}
-
 // IndexKey is index key specifier in CREATE TABLE and CREATE INDEX.
 //
 //	{{.Name | sql}} {{.Dir}}
@@ -1460,7 +1481,9 @@ type Cluster struct {
 type CreateRowDeletionPolicy struct {
 	// pos = Comma
 	// end = RowDeletionPolicy.end
-	Comma             token.Pos // position of ","
+
+	Comma token.Pos // position of ","
+
 	RowDeletionPolicy *RowDeletionPolicy
 }
 
@@ -1470,10 +1493,27 @@ type CreateRowDeletionPolicy struct {
 type RowDeletionPolicy struct {
 	// pos = Row
 	// end = Rparen + 1
-	Row        token.Pos // position of "ROW"
+
+	Row    token.Pos // position of "ROW"
+	Rparen token.Pos // position of ")"
+
 	ColumnName *Ident
 	NumDays    *IntLiteral
-	Rparen     token.Pos // position of ")"
+}
+
+// CreateView is CREATE VIEW statement node.
+//
+//	CREATE {{if .OrReplace}}OR REPLACE{{end}} VIEW {{.Name | sql}}
+//	SQL SECURITY INVOKER AS
+//	{{.Query | sql}}
+type CreateView struct {
+	// pos = Create
+	// end = Query.end
+	Create token.Pos
+
+	Name      *Ident
+	OrReplace bool
+	Query     QueryExpr
 }
 
 // AlterTable is ALTER TABLE statement node.
@@ -1631,11 +1671,11 @@ type DropTable struct {
 //	CREATE
 //	  {{if .Unique}}UNIQUE{{end}}
 //	  {{if .NullFiltered}}NULL_FILTERED{{end}}
-//	  INDEX {{.Name | sql}} ON {{.TableName | sql}} (
-//	    {{.Keys | sqlJoin ","}}
-//	  )
-//	  {{.Storing | sqlOpt}}
-//	  {{.InterleaveIn | sqlOpt}}
+//	INDEX {{.Name | sql}} ON {{.TableName | sql}} (
+//	  {{.Keys | sqlJoin ","}}
+//	)
+//	{{.Storing | sqlOpt}}
+//	{{.InterleaveIn | sqlOpt}}
 type CreateIndex struct {
 	// pos = Create
 	// end = (InterleaveIn ?? Storing).end || Rparen + 1
@@ -1658,8 +1698,10 @@ type CreateIndex struct {
 type CreateRole struct {
 	// pos = Create
 	// end = Name.end
+
 	Create token.Pos // position of "CREATE" keyword
-	Name   *Ident
+
+	Name *Ident
 }
 
 // Storing is STORING clause in CREATE INDEX.
@@ -1707,24 +1749,25 @@ type DropRole struct {
 	// end = Name.end
 
 	Drop token.Pos // position of "DROP" keyword
+
 	Name *Ident
 }
 
 // Grant is GRANT statement node.
 //
-// GRANT
-//
-//	{{ if .GrantRoleNames }}
-//	ROLE {{ .GrantRoleNames | sqlJoin "," }}
-//	{{ else }}
-//	{{ .Privileges | sqlJoin ","}} ON TABLE {{ .TableNames | sqlJoin "," }}
-//	{{ end }}
-//	TO ROLE {{ .ToRoleNames | sqlJoin "," }}
+//	GRANT
+//	{{if .GrantRoleNames}}
+//	ROLE {{.GrantRoleNames | sqlJoin ","}}
+//	{{else}}
+//	{{.Privileges | sqlJoin ","}} ON TABLE {{.TableNames | sqlJoin ","}}
+//	{{end}}
+//	TO ROLE {{.ToRoleNames | sqlJoin ","}}
 type Grant struct {
 	// pos = Grant
-	// end = ToRoleNames[len(ToRoleNames)-1].end
+	// end = ToRoleNames[$].end
+
+	Grant token.Pos // position of "GRANT" keyword
 
-	Grant          token.Pos // position of "GRANT" keyword
 	ToRoleNames    []*Ident
 	GrantRoleNames []*Ident
 	Privileges     []*Privilege
@@ -1733,9 +1776,8 @@ type Grant struct {
 
 // Revoke is REVOKE statement node.
 //
-// REVOKE
-//
-//	{{ if .RoleNames }}
+//	REVOKE
+//	{{if .RoleNames}}
 //	ROLE {{ .RevokeRoleNames | sqlJoin "," }}
 //	{{ else }}
 //	{{ .Privileges | sqlJoin ","}} ON TABLE {{ .TableNames | sqlJoin "," }}
@@ -1745,13 +1787,28 @@ type Revoke struct {
 	// pos = Revoke
 	// end = Name.end
 
-	Revoke          token.Pos // position of "REVOKE" keyword
+	Revoke token.Pos // position of "REVOKE" keyword
+
 	FromRoleNames   []*Ident
 	RevokeRoleNames []*Ident
 	Privileges      []*Privilege
 	TableNames      []*Ident
 }
 
+// Privilege is plivilege type node in schema.
+//
+//	{{.Name}} {{if .Columns}}({{.Columns | sqlJoin ","}}){{end}}
+type Privilege struct {
+	// pos = NamePos
+	// end = Rparen + 1 || NamePos + len(Name)
+
+	NamePos token.Pos // position of this privilege
+	Rparen  token.Pos // position of ")" when len(Columns) > 0
+
+	Name    PrivilegeTypeName
+	Columns []*Ident
+}
+
 // ================================================================================
 //
 // Types for Schema
@@ -1799,20 +1856,6 @@ type ArraySchemaType struct {
 	Item SchemaType // ScalarSchemaType or SizedSchemaType
 }
 
-// Privilege is plivilege type node in schema.
-//
-//	{{.Name}} {{if .Columns}}({{ .Columns | sqlJoin ","}}){{end}}
-type Privilege struct {
-	// pos = NamePos
-	// end = {{if .Columns }}{{ Rparen + 1 }}{{else}}Name.end{{end}}
-
-	NamePos        token.Pos // position of this privilege
-	Name           PrivilegeTypeName
-	Columns        []*Ident
-	Lparen, Rparen token.Pos // position of "(" and ")"
-
-}
-
 // ================================================================================
 //
 // DML


Test patch:
diff --git a/testdata/result/ddl/alter_table_add_row_deletion_policy.sql.txt b/testdata/result/ddl/alter_table_add_row_deletion_policy.sql.txt
index 1eeacc6..a50e246 100644
--- a/testdata/result/ddl/alter_table_add_row_deletion_policy.sql.txt
+++ b/testdata/result/ddl/alter_table_add_row_deletion_policy.sql.txt
@@ -13,6 +13,7 @@ alter table foo add row deletion policy ( older_than ( bar, interval 30 day ))
     Add:               16,
     RowDeletionPolicy: &ast.RowDeletionPolicy{
       Row:        20,
+      Rparen:     77,
       ColumnName: &ast.Ident{
         NamePos: 55,
         NameEnd: 58,
@@ -24,7 +25,6 @@ alter table foo add row deletion policy ( older_than ( bar, interval 30 day ))
         Base:     10,
         Value:    "30",
       },
-      Rparen: 77,
     },
   },
 }
diff --git a/testdata/result/ddl/alter_table_replace_row_deletion_policy.sql.txt b/testdata/result/ddl/alter_table_replace_row_deletion_policy.sql.txt
index c8d1a1a..0ea5e70 100644
--- a/testdata/result/ddl/alter_table_replace_row_deletion_policy.sql.txt
+++ b/testdata/result/ddl/alter_table_replace_row_deletion_policy.sql.txt
@@ -13,6 +13,7 @@ alter table foo replace row deletion policy ( older_than ( bar, interval 30 day
     Replace:           16,
     RowDeletionPolicy: &ast.RowDeletionPolicy{
       Row:        24,
+      Rparen:     81,
       ColumnName: &ast.Ident{
         NamePos: 59,
         NameEnd: 62,
@@ -24,7 +25,6 @@ alter table foo replace row deletion policy ( older_than ( bar, interval 30 day
         Base:     10,
         Value:    "30",
       },
-      Rparen: 81,
     },
   },
 }
diff --git a/testdata/result/ddl/create_table.sql.txt b/testdata/result/ddl/create_table.sql.txt
index 871e231..4622af8 100644
--- a/testdata/result/ddl/create_table.sql.txt
+++ b/testdata/result/ddl/create_table.sql.txt
@@ -184,26 +184,6 @@ create table foo (
       Options:       (*ast.ColumnDefOptions)(nil),
     },
   },
-  PrimaryKeys: []*ast.IndexKey{
-    &ast.IndexKey{
-      DirPos: -1,
-      Name:   &ast.Ident{
-        NamePos: 439,
-        NameEnd: 442,
-        Name:    "foo",
-      },
-      Dir: "",
-    },
-    &ast.IndexKey{
-      DirPos: -1,
-      Name:   &ast.Ident{
-        NamePos: 444,
-        NameEnd: 447,
-        Name:    "bar",
-      },
-      Dir: "",
-    },
-  },
   TableConstraints: []*ast.TableConstraint{
     &ast.TableConstraint{
       ConstraintPos: 0,
@@ -322,6 +302,26 @@ create table foo (
       },
     },
   },
+  PrimaryKeys: []*ast.IndexKey{
+    &ast.IndexKey{
+      DirPos: -1,
+      Name:   &ast.Ident{
+        NamePos: 439,
+        NameEnd: 442,
+        Name:    "foo",
+      },
+      Dir: "",
+    },
+    &ast.IndexKey{
+      DirPos: -1,
+      Name:   &ast.Ident{
+        NamePos: 444,
+        NameEnd: 447,
+        Name:    "bar",
+      },
+      Dir: "",
+    },
+  },
   Cluster:           (*ast.Cluster)(nil),
   RowDeletionPolicy: (*ast.CreateRowDeletionPolicy)(nil),
 }
diff --git a/testdata/result/ddl/create_table_cluster.sql.txt b/testdata/result/ddl/create_table_cluster.sql.txt
index a5f32d9..7569729 100644
--- a/testdata/result/ddl/create_table_cluster.sql.txt
+++ b/testdata/result/ddl/create_table_cluster.sql.txt
@@ -48,8 +48,8 @@ create table foo (
       Options:       (*ast.ColumnDefOptions)(nil),
     },
   },
-  PrimaryKeys:      []*ast.IndexKey(nil),
   TableConstraints: []*ast.TableConstraint(nil),
+  PrimaryKeys:      []*ast.IndexKey(nil),
   Cluster:          &ast.Cluster{
     Comma:       60,
     OnDeleteEnd: -1,
diff --git a/testdata/result/ddl/create_table_cluster_and_row_deletion_policy.sql.txt b/testdata/result/ddl/create_table_cluster_and_row_deletion_policy.sql.txt
index e8c44a5..7f6e638 100644
--- a/testdata/result/ddl/create_table_cluster_and_row_deletion_policy.sql.txt
+++ b/testdata/result/ddl/create_table_cluster_and_row_deletion_policy.sql.txt
@@ -66,8 +66,8 @@ create table foo (
       Options:       (*ast.ColumnDefOptions)(nil),
     },
   },
-  PrimaryKeys:      []*ast.IndexKey(nil),
   TableConstraints: []*ast.TableConstraint(nil),
+  PrimaryKeys:      []*ast.IndexKey(nil),
   Cluster:          &ast.Cluster{
     Comma:       78,
     OnDeleteEnd: -1,
@@ -82,6 +82,7 @@ create table foo (
     Comma:             109,
     RowDeletionPolicy: &ast.RowDeletionPolicy{
       Row:        113,
+      Rparen:     171,
       ColumnName: &ast.Ident{
         NamePos: 148,
         NameEnd: 151,
@@ -93,7 +94,6 @@ create table foo (
         Base:     10,
         Value:    "30",
       },
-      Rparen: 171,
     },
   },
 }
diff --git a/testdata/result/ddl/create_table_cluster_on_delete_no_action.sql.txt b/testdata/result/ddl/create_table_cluster_on_delete_no_action.sql.txt
index 3c3bbef..8802ba7 100644
--- a/testdata/result/ddl/create_table_cluster_on_delete_no_action.sql.txt
+++ b/testdata/result/ddl/create_table_cluster_on_delete_no_action.sql.txt
@@ -31,7 +31,8 @@ create table foo (
       Options:       (*ast.ColumnDefOptions)(nil),
     },
   },
-  PrimaryKeys: []*ast.IndexKey{
+  TableConstraints: []*ast.TableConstraint(nil),
+  PrimaryKeys:      []*ast.IndexKey{
     &ast.IndexKey{
       DirPos: -1,
       Name:   &ast.Ident{
@@ -42,8 +43,7 @@ create table foo (
       Dir: "",
     },
   },
-  TableConstraints: []*ast.TableConstraint(nil),
-  Cluster:          &ast.Cluster{
+  Cluster: &ast.Cluster{
     Comma:       51,
     OnDeleteEnd: 115,
     TableName:   &ast.Ident{
diff --git a/testdata/result/ddl/create_table_cluster_set_on_delete.sql.txt b/testdata/result/ddl/create_table_cluster_set_on_delete.sql.txt
index debcc5d..093b5cc 100644
--- a/testdata/result/ddl/create_table_cluster_set_on_delete.sql.txt
+++ b/testdata/result/ddl/create_table_cluster_set_on_delete.sql.txt
@@ -31,7 +31,8 @@ create table foo (
       Options:       (*ast.ColumnDefOptions)(nil),
     },
   },
-  PrimaryKeys: []*ast.IndexKey{
+  TableConstraints: []*ast.TableConstraint(nil),
+  PrimaryKeys:      []*ast.IndexKey{
     &ast.IndexKey{
       DirPos: -1,
       Name:   &ast.Ident{
@@ -42,8 +43,7 @@ create table foo (
       Dir: "",
     },
   },
-  TableConstraints: []*ast.TableConstraint(nil),
-  Cluster:          &ast.Cluster{
+  Cluster: &ast.Cluster{
     Comma:       50,
     OnDeleteEnd: 112,
     TableName:   &ast.Ident{
diff --git a/testdata/result/ddl/create_table_row_deletion_policy.sql.txt b/testdata/result/ddl/create_table_row_deletion_policy.sql.txt
index cf7ac86..fe72eed 100644
--- a/testdata/result/ddl/create_table_row_deletion_policy.sql.txt
+++ b/testdata/result/ddl/create_table_row_deletion_policy.sql.txt
@@ -65,13 +65,14 @@ create table foo (
       Options:       (*ast.ColumnDefOptions)(nil),
     },
   },
-  PrimaryKeys:       []*ast.IndexKey(nil),
   TableConstraints:  []*ast.TableConstraint(nil),
+  PrimaryKeys:       []*ast.IndexKey(nil),
   Cluster:           (*ast.Cluster)(nil),
   RowDeletionPolicy: &ast.CreateRowDeletionPolicy{
     Comma:             78,
     RowDeletionPolicy: &ast.RowDeletionPolicy{
       Row:        82,
+      Rparen:     140,
       ColumnName: &ast.Ident{
         NamePos: 117,
         NameEnd: 120,
@@ -83,7 +84,6 @@ create table foo (
         Base:     10,
         Value:    "30",
       },
-      Rparen: 140,
     },
   },
 }
diff --git a/testdata/result/ddl/create_table_trailing_comma.sql.txt b/testdata/result/ddl/create_table_trailing_comma.sql.txt
index 728d5d4..a7a8aa8 100644
--- a/testdata/result/ddl/create_table_trailing_comma.sql.txt
+++ b/testdata/result/ddl/create_table_trailing_comma.sql.txt
@@ -50,7 +50,8 @@ create table foo (
       Options:       (*ast.ColumnDefOptions)(nil),
     },
   },
-  PrimaryKeys: []*ast.IndexKey{
+  TableConstraints: []*ast.TableConstraint(nil),
+  PrimaryKeys:      []*ast.IndexKey{
     &ast.IndexKey{
       DirPos: 66,
       Name:   &ast.Ident{
@@ -70,7 +71,6 @@ create table foo (
       Dir: "DESC",
     },
   },
-  TableConstraints:  []*ast.TableConstraint(nil),
   Cluster:           (*ast.Cluster)(nil),
   RowDeletionPolicy: (*ast.CreateRowDeletionPolicy)(nil),
 }
diff --git a/testdata/result/ddl/create_table_types.sql.txt b/testdata/result/ddl/create_table_types.sql.txt
index 497514b..71d7773 100644
--- a/testdata/result/ddl/create_table_types.sql.txt
+++ b/testdata/result/ddl/create_table_types.sql.txt
@@ -233,7 +233,8 @@ create table types (
       Options:       (*ast.ColumnDefOptions)(nil),
     },
   },
-  PrimaryKeys: []*ast.IndexKey{
+  TableConstraints: []*ast.TableConstraint(nil),
+  PrimaryKeys:      []*ast.IndexKey{
     &ast.IndexKey{
       DirPos: -1,
       Name:   &ast.Ident{
@@ -244,7 +245,6 @@ create table types (
       Dir: "",
     },
   },
-  TableConstraints:  []*ast.TableConstraint(nil),
   Cluster:           (*ast.Cluster)(nil),
   RowDeletionPolicy: (*ast.CreateRowDeletionPolicy)(nil),
 }
diff --git a/testdata/result/ddl/grant_privileges.sql.txt b/testdata/result/ddl/grant_privileges.sql.txt
index c7576ea..d6fc5cd 100644
--- a/testdata/result/ddl/grant_privileges.sql.txt
+++ b/testdata/result/ddl/grant_privileges.sql.txt
@@ -20,6 +20,7 @@ GRANT SELECT(name, level, location), UPDATE(location) ON TABLE employees, contra
   Privileges:     []*ast.Privilege{
     &ast.Privilege{
       NamePos: 0,
+      Rparen:  0,
       Name:    "SELECT",
       Columns: []*ast.Ident{
         &ast.Ident{
@@ -38,11 +39,10 @@ GRANT SELECT(name, level, location), UPDATE(location) ON TABLE employees, contra
           Name:    "location",
         },
       },
-      Lparen: 0,
-      Rparen: 0,
     },
     &ast.Privilege{
       NamePos: 0,
+      Rparen:  0,
       Name:    "UPDATE",
       Columns: []*ast.Ident{
         &ast.Ident{
@@ -51,8 +51,6 @@ GRANT SELECT(name, level, location), UPDATE(location) ON TABLE employees, contra
           Name:    "location",
         },
       },
-      Lparen: 0,
-      Rparen: 0,
     },
   },
   TableNames: []*ast.Ident{
diff --git a/testdata/result/ddl/revoke_privileges.sql.txt b/testdata/result/ddl/revoke_privileges.sql.txt
index 7bb1e77..5452208 100644
--- a/testdata/result/ddl/revoke_privileges.sql.txt
+++ b/testdata/result/ddl/revoke_privileges.sql.txt
@@ -20,6 +20,7 @@ REVOKE SELECT(name, level, location), UPDATE(location) ON TABLE employees, contr
   Privileges:      []*ast.Privilege{
     &ast.Privilege{
       NamePos: 0,
+      Rparen:  0,
       Name:    "SELECT",
       Columns: []*ast.Ident{
         &ast.Ident{
@@ -38,11 +39,10 @@ REVOKE SELECT(name, level, location), UPDATE(location) ON TABLE employees, contr
           Name:    "location",
         },
       },
-      Lparen: 0,
-      Rparen: 0,
     },
     &ast.Privilege{
       NamePos: 0,
+      Rparen:  0,
       Name:    "UPDATE",
       Columns: []*ast.Ident{
         &ast.Ident{
@@ -51,8 +51,6 @@ REVOKE SELECT(name, level, location), UPDATE(location) ON TABLE employees, contr
           Name:    "location",
         },
       },
-      Lparen: 0,
-      Rparen: 0,
     },
   },
   TableNames: []*ast.Ident{
diff --git a/testdata/result/statement/alter_table_add_row_deletion_policy.sql.txt b/testdata/result/statement/alter_table_add_row_deletion_policy.sql.txt
index 1eeacc6..a50e246 100644
--- a/testdata/result/statement/alter_table_add_row_deletion_policy.sql.txt
+++ b/testdata/result/statement/alter_table_add_row_deletion_policy.sql.txt
@@ -13,6 +13,7 @@ alter table foo add row deletion policy ( older_than ( bar, interval 30 day ))
     Add:               16,
     RowDeletionPolicy: &ast.RowDeletionPolicy{
       Row:        20,
+      Rparen:     77,
       ColumnName: &ast.Ident{
         NamePos: 55,
         NameEnd: 58,
@@ -24,7 +25,6 @@ alter table foo add row deletion policy ( older_than ( bar, interval 30 day ))
         Base:     10,
         Value:    "30",
       },
-      Rparen: 77,
     },
   },
 }
diff --git a/testdata/result/statement/alter_table_replace_row_deletion_policy.sql.txt b/testdata/result/statement/alter_table_replace_row_deletion_policy.sql.txt
index c8d1a1a..0ea5e70 100644
--- a/testdata/result/statement/alter_table_replace_row_deletion_policy.sql.txt
+++ b/testdata/result/statement/alter_table_replace_row_deletion_policy.sql.txt
@@ -13,6 +13,7 @@ alter table foo replace row deletion policy ( older_than ( bar, interval 30 day
     Replace:           16,
     RowDeletionPolicy: &ast.RowDeletionPolicy{
       Row:        24,
+      Rparen:     81,
       ColumnName: &ast.Ident{
         NamePos: 59,
         NameEnd: 62,
@@ -24,7 +25,6 @@ alter table foo replace row deletion policy ( older_than ( bar, interval 30 day
         Base:     10,
         Value:    "30",
       },
-      Rparen: 81,
     },
   },
 }
diff --git a/testdata/result/statement/create_table.sql.txt b/testdata/result/statement/create_table.sql.txt
index 871e231..4622af8 100644
--- a/testdata/result/statement/create_table.sql.txt
+++ b/testdata/result/statement/create_table.sql.txt
@@ -184,26 +184,6 @@ create table foo (
       Options:       (*ast.ColumnDefOptions)(nil),
     },
   },
-  PrimaryKeys: []*ast.IndexKey{
-    &ast.IndexKey{
-      DirPos: -1,
-      Name:   &ast.Ident{
-        NamePos: 439,
-        NameEnd: 442,
-        Name:    "foo",
-      },
-      Dir: "",
-    },
-    &ast.IndexKey{
-      DirPos: -1,
-      Name:   &ast.Ident{
-        NamePos: 444,
-        NameEnd: 447,
-        Name:    "bar",
-      },
-      Dir: "",
-    },
-  },
   TableConstraints: []*ast.TableConstraint{
     &ast.TableConstraint{
       ConstraintPos: 0,
@@ -322,6 +302,26 @@ create table foo (
       },
     },
   },
+  PrimaryKeys: []*ast.IndexKey{
+    &ast.IndexKey{
+      DirPos: -1,
+      Name:   &ast.Ident{
+        NamePos: 439,
+        NameEnd: 442,
+        Name:    "foo",
+      },
+      Dir: "",
+    },
+    &ast.IndexKey{
+      DirPos: -1,
+      Name:   &ast.Ident{
+        NamePos: 444,
+        NameEnd: 447,
+        Name:    "bar",
+      },
+      Dir: "",
+    },
+  },
   Cluster:           (*ast.Cluster)(nil),
   RowDeletionPolicy: (*ast.CreateRowDeletionPolicy)(nil),
 }
diff --git a/testdata/result/statement/create_table_cluster.sql.txt b/testdata/result/statement/create_table_cluster.sql.txt
index a5f32d9..7569729 100644
--- a/testdata/result/statement/create_table_cluster.sql.txt
+++ b/testdata/result/statement/create_table_cluster.sql.txt
@@ -48,8 +48,8 @@ create table foo (
       Options:       (*ast.ColumnDefOptions)(nil),
     },
   },
-  PrimaryKeys:      []*ast.IndexKey(nil),
   TableConstraints: []*ast.TableConstraint(nil),
+  PrimaryKeys:      []*ast.IndexKey(nil),
   Cluster:          &ast.Cluster{
     Comma:       60,
     OnDeleteEnd: -1,
diff --git a/testdata/result/statement/create_table_cluster_and_row_deletion_policy.sql.txt b/testdata/result/statement/create_table_cluster_and_row_deletion_policy.sql.txt
index e8c44a5..7f6e638 100644
--- a/testdata/result/statement/create_table_cluster_and_row_deletion_policy.sql.txt
+++ b/testdata/result/statement/create_table_cluster_and_row_deletion_policy.sql.txt
@@ -66,8 +66,8 @@ create table foo (
       Options:       (*ast.ColumnDefOptions)(nil),
     },
   },
-  PrimaryKeys:      []*ast.IndexKey(nil),
   TableConstraints: []*ast.TableConstraint(nil),
+  PrimaryKeys:      []*ast.IndexKey(nil),
   Cluster:          &ast.Cluster{
     Comma:       78,
     OnDeleteEnd: -1,
@@ -82,6 +82,7 @@ create table foo (
     Comma:             109,
     RowDeletionPolicy: &ast.RowDeletionPolicy{
       Row:        113,
+      Rparen:     171,
       ColumnName: &ast.Ident{
         NamePos: 148,
         NameEnd: 151,
@@ -93,7 +94,6 @@ create table foo (
         Base:     10,
         Value:    "30",
       },
-      Rparen: 171,
     },
   },
 }
diff --git a/testdata/result/statement/create_table_cluster_on_delete_no_action.sql.txt b/testdata/result/statement/create_table_cluster_on_delete_no_action.sql.txt
index 3c3bbef..8802ba7 100644
--- a/testdata/result/statement/create_table_cluster_on_delete_no_action.sql.txt
+++ b/testdata/result/statement/create_table_cluster_on_delete_no_action.sql.txt
@@ -31,7 +31,8 @@ create table foo (
       Options:       (*ast.ColumnDefOptions)(nil),
     },
   },
-  PrimaryKeys: []*ast.IndexKey{
+  TableConstraints: []*ast.TableConstraint(nil),
+  PrimaryKeys:      []*ast.IndexKey{
     &ast.IndexKey{
       DirPos: -1,
       Name:   &ast.Ident{
@@ -42,8 +43,7 @@ create table foo (
       Dir: "",
     },
   },
-  TableConstraints: []*ast.TableConstraint(nil),
-  Cluster:          &ast.Cluster{
+  Cluster: &ast.Cluster{
     Comma:       51,
     OnDeleteEnd: 115,
     TableName:   &ast.Ident{
diff --git a/testdata/result/statement/create_table_cluster_set_on_delete.sql.txt b/testdata/result/statement/create_table_cluster_set_on_delete.sql.txt
index debcc5d..093b5cc 100644
--- a/testdata/result/statement/create_table_cluster_set_on_delete.sql.txt
+++ b/testdata/result/statement/create_table_cluster_set_on_delete.sql.txt
@@ -31,7 +31,8 @@ create table foo (
       Options:       (*ast.ColumnDefOptions)(nil),
     },
   },
-  PrimaryKeys: []*ast.IndexKey{
+  TableConstraints: []*ast.TableConstraint(nil),
+  PrimaryKeys:      []*ast.IndexKey{
     &ast.IndexKey{
       DirPos: -1,
       Name:   &ast.Ident{
@@ -42,8 +43,7 @@ create table foo (
       Dir: "",
     },
   },
-  TableConstraints: []*ast.TableConstraint(nil),
-  Cluster:          &ast.Cluster{
+  Cluster: &ast.Cluster{
     Comma:       50,
     OnDeleteEnd: 112,
     TableName:   &ast.Ident{
diff --git a/testdata/result/statement/create_table_row_deletion_policy.sql.txt b/testdata/result/statement/create_table_row_deletion_policy.sql.txt
index cf7ac86..fe72eed 100644
--- a/testdata/result/statement/create_table_row_deletion_policy.sql.txt
+++ b/testdata/result/statement/create_table_row_deletion_policy.sql.txt
@@ -65,13 +65,14 @@ create table foo (
       Options:       (*ast.ColumnDefOptions)(nil),
     },
   },
-  PrimaryKeys:       []*ast.IndexKey(nil),
   TableConstraints:  []*ast.TableConstraint(nil),
+  PrimaryKeys:       []*ast.IndexKey(nil),
   Cluster:           (*ast.Cluster)(nil),
   RowDeletionPolicy: &ast.CreateRowDeletionPolicy{
     Comma:             78,
     RowDeletionPolicy: &ast.RowDeletionPolicy{
       Row:        82,
+      Rparen:     140,
       ColumnName: &ast.Ident{
         NamePos: 117,
         NameEnd: 120,
@@ -83,7 +84,6 @@ create table foo (
         Base:     10,
         Value:    "30",
       },
-      Rparen: 140,
     },
   },
 }
diff --git a/testdata/result/statement/create_table_trailing_comma.sql.txt b/testdata/result/statement/create_table_trailing_comma.sql.txt
index 728d5d4..a7a8aa8 100644
--- a/testdata/result/statement/create_table_trailing_comma.sql.txt
+++ b/testdata/result/statement/create_table_trailing_comma.sql.txt
@@ -50,7 +50,8 @@ create table foo (
       Options:       (*ast.ColumnDefOptions)(nil),
     },
   },
-  PrimaryKeys: []*ast.IndexKey{
+  TableConstraints: []*ast.TableConstraint(nil),
+  PrimaryKeys:      []*ast.IndexKey{
     &ast.IndexKey{
       DirPos: 66,
       Name:   &ast.Ident{
@@ -70,7 +71,6 @@ create table foo (
       Dir: "DESC",
     },
   },
-  TableConstraints:  []*ast.TableConstraint(nil),
   Cluster:           (*ast.Cluster)(nil),
   RowDeletionPolicy: (*ast.CreateRowDeletionPolicy)(nil),
 }
diff --git a/testdata/result/statement/create_table_types.sql.txt b/testdata/result/statement/create_table_types.sql.txt
index 497514b..71d7773 100644
--- a/testdata/result/statement/create_table_types.sql.txt
+++ b/testdata/result/statement/create_table_types.sql.txt
@@ -233,7 +233,8 @@ create table types (
       Options:       (*ast.ColumnDefOptions)(nil),
     },
   },
-  PrimaryKeys: []*ast.IndexKey{
+  TableConstraints: []*ast.TableConstraint(nil),
+  PrimaryKeys:      []*ast.IndexKey{
     &ast.IndexKey{
       DirPos: -1,
       Name:   &ast.Ident{
@@ -244,7 +245,6 @@ create table types (
       Dir: "",
     },
   },
-  TableConstraints:  []*ast.TableConstraint(nil),
   Cluster:           (*ast.Cluster)(nil),
   RowDeletionPolicy: (*ast.CreateRowDeletionPolicy)(nil),
 }
diff --git a/testdata/result/statement/grant_privileges.sql.txt b/testdata/result/statement/grant_privileges.sql.txt
index c7576ea..d6fc5cd 100644
--- a/testdata/result/statement/grant_privileges.sql.txt
+++ b/testdata/result/statement/grant_privileges.sql.txt
@@ -20,6 +20,7 @@ GRANT SELECT(name, level, location), UPDATE(location) ON TABLE employees, contra
   Privileges:     []*ast.Privilege{
     &ast.Privilege{
       NamePos: 0,
+      Rparen:  0,
       Name:    "SELECT",
       Columns: []*ast.Ident{
         &ast.Ident{
@@ -38,11 +39,10 @@ GRANT SELECT(name, level, location), UPDATE(location) ON TABLE employees, contra
           Name:    "location",
         },
       },
-      Lparen: 0,
-      Rparen: 0,
     },
     &ast.Privilege{
       NamePos: 0,
+      Rparen:  0,
       Name:    "UPDATE",
       Columns: []*ast.Ident{
         &ast.Ident{
@@ -51,8 +51,6 @@ GRANT SELECT(name, level, location), UPDATE(location) ON TABLE employees, contra
           Name:    "location",
         },
       },
-      Lparen: 0,
-      Rparen: 0,
     },
   },
   TableNames: []*ast.Ident{
diff --git a/testdata/result/statement/revoke_privileges.sql.txt b/testdata/result/statement/revoke_privileges.sql.txt
index 7bb1e77..5452208 100644
--- a/testdata/result/statement/revoke_privileges.sql.txt
+++ b/testdata/result/statement/revoke_privileges.sql.txt
@@ -20,6 +20,7 @@ REVOKE SELECT(name, level, location), UPDATE(location) ON TABLE employees, contr
   Privileges:      []*ast.Privilege{
     &ast.Privilege{
       NamePos: 0,
+      Rparen:  0,
       Name:    "SELECT",
       Columns: []*ast.Ident{
         &ast.Ident{
@@ -38,11 +39,10 @@ REVOKE SELECT(name, level, location), UPDATE(location) ON TABLE employees, contr
           Name:    "location",
         },
       },
-      Lparen: 0,
-      Rparen: 0,
     },
     &ast.Privilege{
       NamePos: 0,
+      Rparen:  0,
       Name:    "UPDATE",
       Columns: []*ast.Ident{
         &ast.Ident{
@@ -51,8 +51,6 @@ REVOKE SELECT(name, level, location), UPDATE(location) ON TABLE employees, contr
           Name:    "location",
         },
       },
-      Lparen: 0,
-      Rparen: 0,
     },
   },
   TableNames: []*ast.Ident{