From fca44380e105a3d7a11847559db44007467ca406 Mon Sep 17 00:00:00 2001 From: qbart Date: Tue, 23 Nov 2021 00:55:51 +0100 Subject: [PATCH] Add drop index DDL --- krab/action_migrate_down.go | 15 +++++++------ krab/action_migrate_up.go | 15 +++++++------ krab/sql_statement.go | 24 +++++++++++++++++++++ krab/type_ddl_drop_index.go | 28 ++++++++++++++++++++++++ krab/type_migration.go | 31 +++++++++++++++------------ spec/action_migrate_dsl_index_test.go | 18 ++++++++++------ spec/parser_test.go | 4 ++-- 7 files changed, 99 insertions(+), 36 deletions(-) create mode 100644 krab/sql_statement.go create mode 100644 krab/type_ddl_drop_index.go diff --git a/krab/action_migrate_down.go b/krab/action_migrate_down.go index 7d8c75c..65ce514 100644 --- a/krab/action_migrate_down.go +++ b/krab/action_migrate_down.go @@ -3,7 +3,6 @@ package krab import ( "context" "fmt" - "strings" "github.com/ohkrab/krab/cli" "github.com/ohkrab/krab/cliargs" @@ -167,14 +166,16 @@ func (a *ActionMigrateDown) Do(ctx context.Context, db krabdb.DB, tpl *tpls.Temp } func (a *ActionMigrateDown) migrateDown(ctx context.Context, tx krabdb.TransactionExecerContext, migration *Migration, versions SchemaMigrationTable) error { - sql := &strings.Builder{} - migration.Down.ToSQL(sql) - _, err := tx.ExecContext(ctx, sql.String()) - if err != nil { - return errors.Wrap(err, "Failed to execute migration") + sqls := migration.Down.ToSQLStatements() + for _, sql := range sqls { + // fmt.Println(ctc.ForegroundYellow, string(sql), ctc.Reset) + _, err := tx.ExecContext(ctx, string(sql)) + if err != nil { + return errors.Wrap(err, "Failed to execute migration") + } } - err = versions.Delete(ctx, tx, migration.Version) + err := versions.Delete(ctx, tx, migration.Version) if err != nil { return errors.Wrap(err, "Failed to delete migration") } diff --git a/krab/action_migrate_up.go b/krab/action_migrate_up.go index ab7540e..cdb1b9d 100644 --- a/krab/action_migrate_up.go +++ b/krab/action_migrate_up.go @@ -3,7 +3,6 @@ package krab import ( "context" "fmt" - "strings" "github.com/ohkrab/krab/cli" "github.com/ohkrab/krab/cliargs" @@ -138,14 +137,16 @@ func (a *ActionMigrateUp) Do(ctx context.Context, db krabdb.DB, tpl *tpls.Templa } func (a *ActionMigrateUp) migrateUp(ctx context.Context, tx krabdb.TransactionExecerContext, migration *Migration, versions SchemaMigrationTable) error { - sql := &strings.Builder{} - migration.Up.ToSQL(sql) - _, err := tx.ExecContext(ctx, sql.String()) - if err != nil { - return errors.Wrap(err, "Failed to execute migration") + sqls := migration.Up.ToSQLStatements() + for _, sql := range sqls { + // fmt.Println(ctc.ForegroundYellow, string(sql), ctc.Reset) + _, err := tx.ExecContext(ctx, string(sql)) + if err != nil { + return errors.Wrap(err, "Failed to execute migration") + } } - err = versions.Insert(ctx, tx, migration.Version) + err := versions.Insert(ctx, tx, migration.Version) if err != nil { return errors.Wrap(err, "Failed to insert migration") } diff --git a/krab/sql_statement.go b/krab/sql_statement.go new file mode 100644 index 0000000..f6fc780 --- /dev/null +++ b/krab/sql_statement.go @@ -0,0 +1,24 @@ +package krab + +import ( + "io" + "strings" +) + +// ToSQL converts DSL struct to SQL. +type ToSQL interface { + ToSQL(w io.StringWriter) +} + +// SQLStatement represents raw SQL statement. +type SQLStatement string + +// SQLStatements represents list of raw SQL statements. +type SQLStatements []SQLStatement + +// Append adds new SQL statement to the list from object that satisfies ToSQL interface. +func (s *SQLStatements) Append(sql ToSQL) { + sb := &strings.Builder{} + sql.ToSQL(sb) + *s = append(*s, SQLStatement(sb.String())) +} diff --git a/krab/type_ddl_drop_index.go b/krab/type_ddl_drop_index.go new file mode 100644 index 0000000..98f0f4d --- /dev/null +++ b/krab/type_ddl_drop_index.go @@ -0,0 +1,28 @@ +package krab + +import ( + "io" + + "github.com/ohkrab/krab/krabdb" +) + +// DDLDropIndex contains DSL for dropping indicies. +type DDLDropIndex struct { + Name string `hcl:"name,label"` + + Cascade bool `hcl:"cascade,optional"` + Concurrently bool `hcl:"concurrently,optional"` +} + +// ToSQL converts migration definition to SQL. +func (d *DDLDropIndex) ToSQL(w io.StringWriter) { + w.WriteString("DROP INDEX") + if d.Concurrently { + w.WriteString(" CONCURRENTLY") + } + w.WriteString(" ") + w.WriteString(krabdb.QuoteIdentWithDots(d.Name)) + if d.Cascade { + w.WriteString(" CASCADE") + } +} diff --git a/krab/type_migration.go b/krab/type_migration.go index 290c943..051fe07 100644 --- a/krab/type_migration.go +++ b/krab/type_migration.go @@ -5,11 +5,6 @@ import ( "io" ) -// ToSQL converts DSL struct to SQL. -type ToSQL interface { - ToSQL(w io.StringWriter) -} - // Migration represents single up/down migration pair. // type Migration struct { @@ -27,6 +22,7 @@ type MigrationUpOrDown struct { CreateTables []*DDLCreateTable `hcl:"create_table,block"` CreateIndices []*DDLCreateIndex `hcl:"create_index,block"` DropTables []*DDLDropTable `hcl:"drop_table,block"` + DropIndices []*DDLDropIndex `hcl:"drop_index,block"` } func (ms *Migration) Validate() error { @@ -50,23 +46,30 @@ func (m *MigrationUpOrDown) Validate() error { return nil } -// ToSQL converts migration definition to SQL. func (m *MigrationUpOrDown) ToSQL(w io.StringWriter) { + w.WriteString(m.SQL) +} + +// ToSQLStatements returns list of SQL statements to executre during the migration. +func (m *MigrationUpOrDown) ToSQLStatements() SQLStatements { + sqls := SQLStatements{} + if m.SQL != "" { - w.WriteString(m.SQL) - w.WriteString(";\n") + sqls.Append(m) } for _, t := range m.CreateTables { - t.ToSQL(w) - w.WriteString(";\n") + sqls.Append(t) } for _, t := range m.CreateIndices { - t.ToSQL(w) - w.WriteString(";\n") + sqls.Append(t) + } + for _, t := range m.DropIndices { + sqls.Append(t) } for _, t := range m.DropTables { - t.ToSQL(w) - w.WriteString(";\n") + sqls.Append(t) } + + return sqls } diff --git a/spec/action_migrate_dsl_index_test.go b/spec/action_migrate_dsl_index_test.go index 93d460e..0bb49d9 100644 --- a/spec/action_migrate_dsl_index_test.go +++ b/spec/action_migrate_dsl_index_test.go @@ -36,6 +36,14 @@ migration "create_animals" { } down { + drop_index "public.idx_uniq_name" { + cascade = true + } + + drop_index "idx_heavy_animals" { + concurrently = true + } + drop_table "animals" {} } } @@ -65,11 +73,9 @@ CREATE TABLE "animals"( `) c.AssertSQLContains(t, ` CREATE UNIQUE INDEX "idx_uniq_name" ON "animals" USING btree ("name") INCLUDE ("weight_kg") -) `) c.AssertSQLContains(t, ` -CREATE INDEX CONCURRENTLY "idx_heavy_animals" ON "animals" USING btree ("weight_kg") WHERE ("weight_kg > 5000") -) +CREATE INDEX CONCURRENTLY "idx_heavy_animals" ON "animals" ("weight_kg") WHERE (weight_kg > 5000) `) if c.AssertSuccessfulRun(t, []string{"migrate", "down", "animals", "-version", "v1"}) { @@ -79,9 +85,9 @@ CREATE INDEX CONCURRENTLY "idx_heavy_animals" ON "animals" USING btree ("weight_ Done `, ) - c.AssertSQLContains(t, ` -DROP TABLE "animals" - `) + c.AssertSQLContains(t, `DROP INDEX "public"."idx_uniq_name" CASCADE`) + c.AssertSQLContains(t, `DROP INDEX CONCURRENTLY "idx_heavy_animals"`) + c.AssertSQLContains(t, `DROP TABLE "animals"`) } } } diff --git a/spec/parser_test.go b/spec/parser_test.go index 91e7d3f..f66b7f8 100644 --- a/spec/parser_test.go +++ b/spec/parser_test.go @@ -99,8 +99,8 @@ migration "abc" { var down strings.Builder migration.Up.ToSQL(&up) migration.Down.ToSQL(&down) - assert.Equal(up.String(), "CREATE TABLE abc;\n") - assert.Equal(down.String(), "DROP TABLE abc;\n") + assert.Equal(up.String(), "CREATE TABLE abc") + assert.Equal(down.String(), "DROP TABLE abc") } } }