Skip to content

Commit

Permalink
feat: Support CockroachDB Hash-sharded Indexes (#97)
Browse files Browse the repository at this point in the history
  • Loading branch information
kunitsudev authored Aug 14, 2024
2 parents c9a2b0e + 9be6b6a commit 533cfb9
Show file tree
Hide file tree
Showing 11 changed files with 295 additions and 45 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/go-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ jobs:
direnv exec . make test
fi
- uses: codecov/codecov-action@v4 # ref. https://github.com/codecov/codecov-action#example-workflowyml-with-codecov-action
if: env.COVER
if: ${{ env.COVER == 'true' }}
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ${{ env.WORKDIR }}/coverage.txt
Expand Down
29 changes: 29 additions & 0 deletions pkg/ddl/cockroachdb/ddl.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,32 @@ func (s *DataType) StringForDiff() string {

return str
}

type Using struct {
Value *Expr
With *With
}

func (u *Using) String() string {
if u == nil {
return ""
}

str := "USING " + u.Value.String()
if u.With != nil {
str += " " + u.With.String()
}
return str
}

type With struct {
Value *Expr
}

func (w *With) String() string {
if w == nil {
return ""
}

return "WITH " + w.Value.String()
}
36 changes: 23 additions & 13 deletions pkg/ddl/cockroachdb/ddl_index_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@ import (
var _ Stmt = (*CreateIndexStmt)(nil)

type CreateIndexStmt struct {
Comment string
Unique bool
IfNotExists bool
Name *Ident
TableName *ObjectName
Using []*Ident
Columns []*ColumnIdent
Comment string
Unique bool
IfNotExists bool
Name *Ident
TableName *ObjectName
UsingPreColumns *Using
Columns []*ColumnIdent
UsingPostColumns *Using
}

func (s *CreateIndexStmt) GetNameForDiff() string {
Expand All @@ -45,11 +46,14 @@ func (s *CreateIndexStmt) String() string {
str += "IF NOT EXISTS "
}
str += s.Name.String() + " ON " + s.TableName.String()
if len(s.Using) > 0 {
str += " USING "
str += stringz.JoinStringers(" ", s.Using...)
if s.UsingPreColumns != nil {
str += " " + s.UsingPreColumns.String()
}
str += " (" + stringz.JoinStringers(", ", s.Columns...) + ");\n"
str += " (" + stringz.JoinStringers(", ", s.Columns...) + ")"
if s.UsingPostColumns != nil {
str += " " + s.UsingPostColumns.String()
}
str += ";\n"
return str
}

Expand All @@ -60,15 +64,21 @@ func (s *CreateIndexStmt) StringForDiff() string {
}
str += "INDEX "
str += s.Name.StringForDiff() + " ON " + s.TableName.StringForDiff()
// TODO: add USING
if s.UsingPreColumns != nil {
str += " " + s.UsingPreColumns.String()
}
str += " ("
for i, c := range s.Columns {
if i > 0 {
str += ", "
}
str += c.StringForDiff()
}
str += ");\n"
str += ")"
if s.UsingPostColumns != nil {
str += " " + s.UsingPostColumns.String()
}
str += ";\n"
return str
}

Expand Down
10 changes: 5 additions & 5 deletions pkg/ddl/cockroachdb/ddl_index_create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ func TestCreateIndexStmt_String(t *testing.T) {
t.Parallel()

stmt := &CreateIndexStmt{
Comment: "test comment content",
IfNotExists: true,
Name: &Ident{Name: "test", QuotationMark: `"`, Raw: `"test"`},
TableName: &ObjectName{Name: &Ident{Name: "users", QuotationMark: `"`, Raw: `"users"`}},
Using: []*Ident{{Name: "btree", QuotationMark: ``, Raw: `btree`}},
Comment: "test comment content",
IfNotExists: true,
Name: &Ident{Name: "test", QuotationMark: `"`, Raw: `"test"`},
TableName: &ObjectName{Name: &Ident{Name: "users", QuotationMark: `"`, Raw: `"users"`}},
UsingPreColumns: &Using{Value: &Expr{Idents: []*Ident{{Name: "btree", QuotationMark: ``, Raw: `btree`}}}},
Columns: []*ColumnIdent{
{
Ident: &Ident{Name: "id", QuotationMark: `"`, Raw: `"id"`},
Expand Down
84 changes: 77 additions & 7 deletions pkg/ddl/cockroachdb/ddl_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,11 @@ func (c *ForeignKeyConstraint) StringForDiff() string {

// IndexConstraint represents a UNIQUE constraint. //diff:ignore-line-postgres-cockroach.
type IndexConstraint struct { //diff:ignore-line-postgres-cockroach
Name *Ident
Unique bool //diff:ignore-line-postgres-cockroach
Columns []*ColumnIdent
Name *Ident
Unique bool //diff:ignore-line-postgres-cockroach
UsingPreColumns *Using
Columns []*ColumnIdent
UsingPostColumns *Using
}

var _ Constraint = (*IndexConstraint)(nil) //diff:ignore-line-postgres-cockroach
Expand All @@ -157,7 +159,13 @@ func (c *IndexConstraint) String() string { //diff:ignore-line-postgres-cockroac
if c.Name != nil { //diff:ignore-line-postgres-cockroach
str += "INDEX " + c.Name.String() + " " //diff:ignore-line-postgres-cockroach
}
if c.UsingPreColumns != nil {
str += " " + c.UsingPreColumns.String()
}
str += "(" + stringz.JoinStringers(", ", c.Columns...) + ")"
if c.UsingPostColumns != nil {
str += " " + c.UsingPostColumns.String()
}
return str
}

Expand All @@ -169,6 +177,9 @@ func (c *IndexConstraint) StringForDiff() string { //diff:ignore-line-postgres-c
if c.Name != nil {
str += "INDEX " + c.Name.StringForDiff() + " " //diff:ignore-line-postgres-cockroach
}
if c.UsingPreColumns != nil {
str += " " + c.UsingPreColumns.String()
}
str += "("
for i, v := range c.Columns {
if i != 0 {
Expand All @@ -177,6 +188,9 @@ func (c *IndexConstraint) StringForDiff() string { //diff:ignore-line-postgres-c
str += v.StringForDiff()
}
str += ")"
if c.UsingPostColumns != nil {
str += " " + c.UsingPostColumns.String()
}
return str
}

Expand Down Expand Up @@ -260,10 +274,12 @@ func (t *ObjectName) StringForDiff() string {
}

type Column struct {
Name *Ident
DataType *DataType
Default *Default
NotNull bool
Name *Ident
DataType *DataType
Default *Default
NotNull bool
NotVisible bool
As *As //diff:ignore-line-postgres-cockroach
}

type Default struct {
Expand Down Expand Up @@ -339,15 +355,69 @@ func (d *Default) StringForDiff() string {
return ""
}

type As struct {
Value *Expr
Type TokenType
}

func (d *As) GoString() string { return internal.GoString(*d) }

func (d *As) String() string {
var str string
if d == nil {
return ""
}

if d.Value != nil {
str += "AS " + d.Value.String()
if d.Type != "" {
str += " " + d.Type.String()
}
return str
}

return ""
}

func (d *As) StringForDiff() string {
if d == nil {
return ""
}

if e := d.Value; e != nil {
str := "AS "
for i, v := range d.Value.Idents {
if i != 0 {
str += " "
}
str += v.StringForDiff()
}

if d.Type != "" {
str += " " + d.Type.String()
}

return str
}

return ""
}

func (c *Column) String() string {
str := c.Name.String() + " " +
c.DataType.String()
if c.NotVisible {
str += " NOT VISIBLE"
}
if c.NotNull { //diff:ignore-line-postgres-cockroach
str += " NOT NULL" //diff:ignore-line-postgres-cockroach
} //diff:ignore-line-postgres-cockroach
if s := c.Default.String(); s != "" { //diff:ignore-line-postgres-cockroach
str += " " + s //diff:ignore-line-postgres-cockroach
}
if c.As != nil {
str += " " + c.As.String()
}
return str
}

Expand Down
31 changes: 21 additions & 10 deletions pkg/ddl/cockroachdb/diff_create_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/kunitsucom/util.go/exp/diff/simplediff"

apperr "github.com/kunitsucom/ddlctl/pkg/apperr"
"github.com/kunitsucom/ddlctl/pkg/logs"

"github.com/kunitsucom/ddlctl/pkg/ddl"
)
Expand Down Expand Up @@ -109,13 +110,16 @@ func DiffCreateTable(before, after *CreateTableStmt, opts ...DiffCreateTableOpti
result.Stmts = append( //diff:ignore-line-postgres-cockroach
result.Stmts, //diff:ignore-line-postgres-cockroach
&DropIndexStmt{ //diff:ignore-line-postgres-cockroach
Name: beforeConstraint.GetName(), //diff:ignore-line-postgres-cockroach
Comment: simplediff.Diff(beforeConstraint.String(), afterConstraint.String()).String(), //diff:ignore-line-postgres-cockroach
Name: beforeConstraint.GetName(), //diff:ignore-line-postgres-cockroach
}, //diff:ignore-line-postgres-cockroach
&CreateIndexStmt{ //diff:ignore-line-postgres-cockroach
Unique: ac.Unique, //diff:ignore-line-postgres-cockroach
Name: ac.GetName(), //diff:ignore-line-postgres-cockroach
TableName: after.Name, //diff:ignore-line-postgres-cockroach
Columns: ac.Columns, //diff:ignore-line-postgres-cockroach
Unique: ac.Unique, //diff:ignore-line-postgres-cockroach
Name: ac.GetName(), //diff:ignore-line-postgres-cockroach
TableName: after.Name, //diff:ignore-line-postgres-cockroach
UsingPreColumns: ac.UsingPreColumns, //diff:ignore-line-postgres-cockroach
Columns: ac.Columns, //diff:ignore-line-postgres-cockroach
UsingPostColumns: ac.UsingPostColumns, //diff:ignore-line-postgres-cockroach
}, //diff:ignore-line-postgres-cockroach
) //diff:ignore-line-postgres-cockroach
default: //diff:ignore-line-postgres-cockroach
Expand Down Expand Up @@ -150,11 +154,13 @@ func DiffCreateTable(before, after *CreateTableStmt, opts ...DiffCreateTableOpti
case *IndexConstraint: //diff:ignore-line-postgres-cockroach
// CREATE INDEX index_name ON table_name (column_name); //diff:ignore-line-postgres-cockroach
result.Stmts = append(result.Stmts, &CreateIndexStmt{ //diff:ignore-line-postgres-cockroach
Comment: simplediff.Diff("", ac.StringForDiff()).String(), //diff:ignore-line-postgres-cockroach
Unique: ac.Unique, //diff:ignore-line-postgres-cockroach
Name: ac.GetName(), //diff:ignore-line-postgres-cockroach
TableName: after.Name, //diff:ignore-line-postgres-cockroach
Columns: ac.Columns, //diff:ignore-line-postgres-cockroach
Comment: simplediff.Diff("", ac.StringForDiff()).String(), //diff:ignore-line-postgres-cockroach
Unique: ac.Unique, //diff:ignore-line-postgres-cockroach
Name: ac.GetName(), //diff:ignore-line-postgres-cockroach
TableName: after.Name, //diff:ignore-line-postgres-cockroach
UsingPreColumns: ac.UsingPreColumns, //diff:ignore-line-postgres-cockroach
Columns: ac.Columns, //diff:ignore-line-postgres-cockroach
UsingPostColumns: ac.UsingPostColumns, //diff:ignore-line-postgres-cockroach
}) //diff:ignore-line-postgres-cockroach
default: //diff:ignore-line-postgres-cockroach
// ALTER TABLE table_name ADD CONSTRAINT constraint_name constraint;
Expand All @@ -181,6 +187,11 @@ func (config *DiffCreateTableConfig) diffCreateTableColumn(ddls *DDL, before, af
for _, beforeColumn := range before.Columns {
afterColumn := findColumnByName(beforeColumn.Name.Name, after.Columns)
if afterColumn == nil {
if beforeColumn.NotVisible && beforeColumn.As != nil && beforeColumn.As.Type == TOKEN_VIRTUAL {
// ref. https://www.cockroachlabs.com/docs/v24.2/hash-sharded-indexes
logs.Debug.Printf("🪲: If the column is a NOT VISIBLE VIRTUAL column, it may be a Hash-sharded Index. SKIP. ref. https://www.cockroachlabs.com/docs/v24.2/hash-sharded-indexes")
continue
}
// ALTER TABLE table_name DROP COLUMN column_name;
ddls.Stmts = append(ddls.Stmts, &AlterTableStmt{
Comment: simplediff.Diff(beforeColumn.String(), "").String(),
Expand Down
4 changes: 3 additions & 1 deletion pkg/ddl/cockroachdb/diff_create_table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,9 @@ ALTER TABLE "users" ADD CONSTRAINT users_group_id_fkey FOREIGN KEY (group_id, na
afterDDL, err := NewParser(NewLexer(after)).Parse()
require.NoError(t, err)

expectedStr := `DROP INDEX users_unique_name;
expectedStr := `-- -UNIQUE INDEX users_unique_name ("name")
-- +UNIQUE INDEX users_unique_name ("id" ASC, name ASC)
DROP INDEX users_unique_name;
CREATE UNIQUE INDEX users_unique_name ON "users" ("id" ASC, name ASC);
`

Expand Down
4 changes: 3 additions & 1 deletion pkg/ddl/cockroachdb/diff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,9 @@ ALTER TABLE public.users ADD COLUMN updated_at TIMESTAMP WITH TIME ZONE NOT NULL
`)).Parse()
require.NoError(t, err)

expected := `DROP INDEX users_idx_by_username;
expected := `-- -INDEX users_idx_by_username (username DESC)
-- +INDEX users_idx_by_username (username ASC)
DROP INDEX users_idx_by_username;
CREATE INDEX users_idx_by_username ON public.users (username ASC);
`
actual, err := Diff(before, after)
Expand Down
12 changes: 12 additions & 0 deletions pkg/ddl/cockroachdb/lexar.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,15 @@ const (
// COLUMN.
TOKEN_DEFAULT TokenType = "DEFAULT"
TOKEN_NOT TokenType = "NOT"
TOKEN_VISIBLE TokenType = "VISIBLE"
TOKEN_AS TokenType = "AS"
TOKEN_ASC TokenType = "ASC"
TOKEN_DESC TokenType = "DESC"
TOKEN_CASCADE TokenType = "CASCADE"
TOKEN_NO TokenType = "NO"
TOKEN_ACTION TokenType = "ACTION"
TOKEN_STORED TokenType = "STORED"
TOKEN_VIRTUAL TokenType = "VIRTUAL"

// CONSTRAINT.
TOKEN_CONSTRAINT TokenType = "CONSTRAINT"
Expand Down Expand Up @@ -228,6 +232,10 @@ func lookupIdent(ident string) TokenType {
return TOKEN_DEFAULT
case "NOT":
return TOKEN_NOT
case "VISIBLE":
return TOKEN_VISIBLE
case "AS":
return TOKEN_AS
case "ASC":
return TOKEN_ASC
case "DESC":
Expand All @@ -238,6 +246,10 @@ func lookupIdent(ident string) TokenType {
return TOKEN_NO
case "ACTION":
return TOKEN_ACTION
case "STORED":
return TOKEN_STORED
case "VIRTUAL":
return TOKEN_VIRTUAL
case "CONSTRAINT":
return TOKEN_CONSTRAINT
case "PRIMARY":
Expand Down
Loading

0 comments on commit 533cfb9

Please sign in to comment.