Skip to content

Commit 0b37cb6

Browse files
apstndbmakenowjust
andauthored
Support full-text search DDLs (#111)
* Implement CREATE/DROP/ALTER SEARCH INDEX * Make STORED optional * Support HIDDEN columns * Add TOKENLIST type * Update testdata * Implement CREATE/DROP/ALTER SEARCH INDEX * Add parser functions/methods * Add TOKENLIST as simple type * Fix HIDDEN implementation * Update testdata * Fix ast of search index DDLs * Fix some SQL() * Add create_search_index_full.sql * Implement SearchIndexOptions on GenericOptions * Fix ast_test.go * Update TestDDL * Improve placement of GenericOptions/GenericOption * Refine Find/FindBool * Remove GeneratedColumnExpr.IsStored * Move SearchIndexOptions methods to correct place * Fix comment * Refactor using Pos arithmetic * Remove unnecessary comment * Revert unneeded change * Add Options * Migrate to parseCommaSeparatedList * Remove p.tryExpect() and p.tryExpectKeywordLike() * Add *Field methods * Update testdata * Fix some wording and ordering * Add parseIndexAlteration method * Remove unneeded newlines * Update ast/ast.go Co-authored-by: Hiroya Fujinami <make.just.on@gmail.com> * Remove useless use of isnil * Update testdata --------- Co-authored-by: Hiroya Fujinami <make.just.on@gmail.com>
1 parent dd9ab2b commit 0b37cb6

File tree

58 files changed

+1382
-45
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+1382
-45
lines changed

ast/ast.go

+85-4
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ func (RenameTable) isStatement() {}
6565
func (CreateIndex) isStatement() {}
6666
func (AlterIndex) isStatement() {}
6767
func (DropIndex) isStatement() {}
68+
func (CreateSearchIndex) isStatement() {}
69+
func (DropSearchIndex) isStatement() {}
70+
func (AlterSearchIndex) isStatement() {}
6871
func (CreateView) isStatement() {}
6972
func (DropView) isStatement() {}
7073
func (CreateChangeStream) isStatement() {}
@@ -277,6 +280,9 @@ func (CreateIndex) isDDL() {}
277280
func (AlterIndex) isDDL() {}
278281
func (DropIndex) isDDL() {}
279282
func (CreateView) isDDL() {}
283+
func (CreateSearchIndex) isDDL() {}
284+
func (DropSearchIndex) isDDL() {}
285+
func (AlterSearchIndex) isDDL() {}
280286
func (DropView) isDDL() {}
281287
func (CreateChangeStream) isDDL() {}
282288
func (AlterChangeStream) isDDL() {}
@@ -1720,10 +1726,11 @@ type CreateSequence struct {
17201726
// {{.Type | sql}} {{if .NotNull}}NOT NULL{{end}}
17211727
// {{.DefaultExpr | sqlOpt}}
17221728
// {{.GeneratedExpr | sqlOpt}}
1729+
// {{if .Hidden.Invalid | not)}}HIDDEN{{end}}
17231730
// {{.Options | sqlOpt}}
17241731
type ColumnDef struct {
17251732
// pos = Name.pos
1726-
// end = Options.end || GeneratedExpr.end || DefaultExpr.end || Null + 4 || Type.end
1733+
// end = Options.end || Hidden + 6 || GeneratedExpr.end || DefaultExpr.end || Null + 4 || Type.end
17271734

17281735
Null token.Pos // position of "NULL"
17291736

@@ -1732,6 +1739,7 @@ type ColumnDef struct {
17321739
NotNull bool
17331740
DefaultExpr *ColumnDefaultExpr // optional
17341741
GeneratedExpr *GeneratedColumnExpr // optional
1742+
Hidden token.Pos // InvalidPos if not hidden
17351743
Options *Options // optional
17361744
}
17371745

@@ -1750,17 +1758,31 @@ type ColumnDefaultExpr struct {
17501758

17511759
// GeneratedColumnExpr is generated column expression.
17521760
//
1753-
// AS ({{.Expr | sql}}) STORED
1761+
// AS ({{.Expr | sql}}) {{if .IsStored}}STORED{{end}}
17541762
type GeneratedColumnExpr struct {
17551763
// pos = As
1756-
// end = Stored + 6
1764+
// end = Stored + 6 || Rparen + 1
17571765

17581766
As token.Pos // position of "AS" keyword
1759-
Stored token.Pos // position of "STORED" keyword
1767+
Stored token.Pos // position of "STORED" keyword, optional
1768+
Rparen token.Pos // position of ")"
17601769

17611770
Expr Expr
17621771
}
17631772

1773+
// ColumnDefOption is options for column definition.
1774+
//
1775+
// OPTIONS(allow_commit_timestamp = {{if .AllowCommitTimestamp}}true{{else}null{{end}}})
1776+
type ColumnDefOptions struct {
1777+
// pos = Options
1778+
// end = Rparen + 1
1779+
1780+
Options token.Pos // position of "OPTIONS" keyword
1781+
Rparen token.Pos // position of ")"
1782+
1783+
AllowCommitTimestamp bool
1784+
}
1785+
17641786
// TableConstraint is table constraint in CREATE TABLE and ALTER TABLE.
17651787
//
17661788
// {{if .Name}}CONSTRAINT {{.Name}}{{end}}{{.Constraint | sql}}
@@ -2628,6 +2650,65 @@ type ArraySchemaType struct {
26282650
Item SchemaType // ScalarSchemaType or SizedSchemaType
26292651
}
26302652

2653+
// ================================================================================
2654+
//
2655+
// Search Index DDL
2656+
//
2657+
// ================================================================================
2658+
2659+
// CreateSearchIndex represents CREATE SEARCH INDEX statement
2660+
//
2661+
// CREATE SEARCH INDEX {{.Name | sql}}
2662+
// ON {{.TableName | sql}}
2663+
// ({{.TokenListPart | sqlJoin ", "}})
2664+
// {{.Storing | sqlOpt}}
2665+
// {{if .PartitionColumns}}PARTITION BY {{.PartitionColumns | sqlJoin ", "}}{{end}}
2666+
// {{.OrderBy | sqlOpt}}
2667+
// {{.Where | sqlOpt}}
2668+
// {{.Interleave | sqlOpt}}
2669+
// {{.Options | sqlOpt}}
2670+
type CreateSearchIndex struct {
2671+
// pos = Create
2672+
// end = (Options ?? Interleave ?? Where ?? OrderBy ?? PartitionColumns[$] ?? Storing).end || Rparen + 1
2673+
2674+
Create token.Pos
2675+
2676+
Name *Ident
2677+
TableName *Ident
2678+
TokenListPart []*Ident
2679+
Rparen token.Pos // position of ")" after TokenListPart
2680+
Storing *Storing // optional
2681+
PartitionColumns []*Ident // optional
2682+
OrderBy *OrderBy // optional
2683+
Where *Where // optional
2684+
Interleave *InterleaveIn // optional
2685+
Options *Options // optional
2686+
}
2687+
2688+
// DropSearchIndex represents DROP SEARCH INDEX statement.
2689+
//
2690+
// DROP SEARCH INDEX{{if .IfExists}}IF EXISTS{{end}} {{Name | sql}}
2691+
type DropSearchIndex struct {
2692+
// pos = Drop
2693+
// end = Name.end
2694+
2695+
Drop token.Pos
2696+
IfExists bool
2697+
Name *Ident
2698+
}
2699+
2700+
// AlterSearchIndex represents ALTER SEARCH INDEX statement.
2701+
//
2702+
// ALTER SEARCH INDEX {{.Name | sql}} {{.IndexAlteration | sql}}
2703+
type AlterSearchIndex struct {
2704+
// pos = Alter
2705+
// end = IndexAlteration.end
2706+
2707+
Alter token.Pos
2708+
Name *Ident
2709+
IndexAlteration IndexAlteration
2710+
}
2711+
26312712
// ================================================================================
26322713
//
26332714
// DML

ast/ast_test.go

+3
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ func TestDDL(t *testing.T) {
144144
DDL(&CreateIndex{}).isDDL()
145145
DDL(&AlterIndex{}).isDDL()
146146
DDL(&DropIndex{}).isDDL()
147+
DDL(&CreateSearchIndex{}).isDDL()
148+
DDL(&DropSearchIndex{}).isDDL()
149+
DDL(&AlterSearchIndex{}).isDDL()
147150
DDL(&CreateView{}).isDDL()
148151
DDL(&DropView{}).isDDL()
149152
DDL(&CreateChangeStream{}).isDDL()

ast/const.go

+1
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ const (
109109
TimestampTypeName ScalarTypeName = "TIMESTAMP"
110110
NumericTypeName ScalarTypeName = "NUMERIC"
111111
JSONTypeName ScalarTypeName = "JSON"
112+
TokenListTypeName ScalarTypeName = "TOKENLIST"
112113
)
113114

114115
type OnDeleteAction string

ast/pos.go

+54-14
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,17 @@ func lastEnd[T Node](s []T) token.Pos {
4949
return lastNode(s).End()
5050
}
5151

52+
// firstValid returns the first valid token.Pos in arguments.
53+
// This function corresponds to PosExpr ("||" PosExpr)* in ast.go
54+
func firstValid(ps ...token.Pos) token.Pos {
55+
for _, p := range ps {
56+
if !p.Invalid() {
57+
return p
58+
}
59+
}
60+
return token.InvalidPos
61+
}
62+
5263
// ================================================================================
5364
//
5465
// SELECT
@@ -593,26 +604,25 @@ func (c *ColumnDef) Pos() token.Pos {
593604
}
594605

595606
func (c *ColumnDef) End() token.Pos {
596-
if c.Options != nil {
597-
return c.Options.End()
598-
}
599-
if c.GeneratedExpr != nil {
600-
return c.GeneratedExpr.End()
601-
}
602-
if c.DefaultExpr != nil {
603-
return c.DefaultExpr.End()
604-
}
605-
if !c.Null.Invalid() {
606-
return c.Null + 4
607-
}
608-
return c.Type.End()
607+
return firstValid(
608+
firstValidEnd(c.Options),
609+
c.Hidden.Add(6),
610+
firstValidEnd(c.GeneratedExpr, c.DefaultExpr),
611+
c.Null.Add(4),
612+
c.Type.End(),
613+
)
609614
}
610615

611616
func (g *ColumnDefaultExpr) Pos() token.Pos { return g.Default }
612617
func (g *ColumnDefaultExpr) End() token.Pos { return g.Rparen }
613618

614619
func (g *GeneratedColumnExpr) Pos() token.Pos { return g.As }
615-
func (g *GeneratedColumnExpr) End() token.Pos { return g.Stored + 6 }
620+
func (g *GeneratedColumnExpr) End() token.Pos {
621+
return firstValid(g.Stored.Add(6), g.Rparen.Add(1))
622+
}
623+
624+
func (c *ColumnDefOptions) Pos() token.Pos { return c.Options }
625+
func (c *ColumnDefOptions) End() token.Pos { return c.Rparen + 1 }
616626

617627
func (c *TableConstraint) Pos() token.Pos {
618628
if c.Name != nil {
@@ -917,6 +927,36 @@ func (c *ChangeStreamForTable) End() token.Pos {
917927
return c.Rparen + 1
918928
}
919929

930+
// ================================================================================
931+
//
932+
// Search Index DDL
933+
//
934+
// ================================================================================
935+
936+
func (c *CreateSearchIndex) Pos() token.Pos { return c.Create }
937+
938+
func (c *CreateSearchIndex) End() token.Pos {
939+
return firstValid(
940+
firstValidEnd(c.Options,
941+
c.Interleave,
942+
c.Where,
943+
c.OrderBy,
944+
lastNode(c.PartitionColumns),
945+
c.Storing),
946+
c.Rparen.Add(1))
947+
}
948+
949+
func (d *DropSearchIndex) Pos() token.Pos {
950+
return d.Drop
951+
}
952+
953+
func (d *DropSearchIndex) End() token.Pos {
954+
return d.Name.End()
955+
}
956+
957+
func (a *AlterSearchIndex) Pos() token.Pos { return a.Alter }
958+
func (a *AlterSearchIndex) End() token.Pos { return a.IndexAlteration.End() }
959+
920960
// ================================================================================
921961
//
922962
// DML

ast/sql.go

+32-15
Original file line numberDiff line numberDiff line change
@@ -810,20 +810,12 @@ func (c *CreateView) SQL() string {
810810
func (d *DropView) SQL() string { return "DROP VIEW " + d.Name.SQL() }
811811

812812
func (c *ColumnDef) SQL() string {
813-
sql := c.Name.SQL() + " " + c.Type.SQL()
814-
if c.NotNull {
815-
sql += " NOT NULL"
816-
}
817-
if c.DefaultExpr != nil {
818-
sql += " " + c.DefaultExpr.SQL()
819-
}
820-
if c.GeneratedExpr != nil {
821-
sql += " " + c.GeneratedExpr.SQL()
822-
}
823-
if c.Options != nil {
824-
sql += " " + c.Options.SQL()
825-
}
826-
return sql
813+
return c.Name.SQL() + " " + c.Type.SQL() +
814+
strOpt(c.NotNull, " NOT NULL") +
815+
sqlOpt(" ", c.DefaultExpr, "") +
816+
sqlOpt(" ", c.GeneratedExpr, "") +
817+
strOpt(!c.Hidden.Invalid(), " HIDDEN") +
818+
sqlOpt(" ", c.Options, "")
827819
}
828820

829821
func (c *TableConstraint) SQL() string {
@@ -868,7 +860,7 @@ func (c *ColumnDefaultExpr) SQL() string {
868860
}
869861

870862
func (g *GeneratedColumnExpr) SQL() string {
871-
return "AS (" + g.Expr.SQL() + ") STORED"
863+
return "AS (" + g.Expr.SQL() + ")" + strOpt(!g.Stored.Invalid(), " STORED")
872864
}
873865

874866
func (i *IndexKey) SQL() string {
@@ -1267,6 +1259,31 @@ func (a *ArraySchemaType) SQL() string {
12671259
return "ARRAY<" + a.Item.SQL() + ">"
12681260
}
12691261

1262+
// ================================================================================
1263+
//
1264+
// Search Index DDL
1265+
//
1266+
// ================================================================================
1267+
1268+
func (c *CreateSearchIndex) SQL() string {
1269+
return "CREATE SEARCH INDEX " + c.Name.SQL() + " ON " + c.TableName.SQL() +
1270+
"(" + sqlJoin(c.TokenListPart, ", ") + ")" +
1271+
sqlOpt(" ", c.Storing, "") +
1272+
strOpt(len(c.PartitionColumns) > 0, " PARTITION BY "+sqlJoin(c.PartitionColumns, ", ")) +
1273+
sqlOpt(" ", c.OrderBy, "") +
1274+
sqlOpt(" ", c.Where, "") +
1275+
sqlOpt("", c.Interleave, "") +
1276+
sqlOpt(" ", c.Options, "")
1277+
}
1278+
1279+
func (d *DropSearchIndex) SQL() string {
1280+
return "DROP SEARCH INDEX " + strOpt(d.IfExists, "IF EXISTS ") + d.Name.SQL()
1281+
}
1282+
1283+
func (a *AlterSearchIndex) SQL() string {
1284+
return "ALTER SEARCH INDEX " + a.Name.SQL() + " " + a.IndexAlteration.SQL()
1285+
}
1286+
12701287
// ================================================================================
12711288
//
12721289
// DML

0 commit comments

Comments
 (0)