From b9dea2ba24e4c03cd74908958aa2800d4c660e56 Mon Sep 17 00:00:00 2001 From: Reinaldy Rafli Date: Wed, 10 Nov 2021 12:27:55 +0700 Subject: [PATCH] feat: added some alter function in addition to drop builder --- .github/workflows/build.yml | 9 ++- alter.go | 92 +++++++++++++++++++++++++++ alter_test.go | 123 ++++++++++++++++++++++++++++++++++++ bob.go | 32 ++++++++++ 4 files changed, 253 insertions(+), 3 deletions(-) create mode 100644 alter.go create mode 100644 alter_test.go diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c205eb0..32bd3aa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,7 +9,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] - go-version: [1.16.x, 1.17.x] + go-version: [1.15.x, 1.16.x, 1.17.x] steps: - name: Checkout code uses: actions/checkout@v2 @@ -19,5 +19,8 @@ jobs: with: go-version: ${{ matrix.go-version }} - - name: Build - run: go build ./ \ No newline at end of file + - name: Run go vet + run: go vet + + - name: Test + run: go test -v -race -coverprofile=coverage.out -covermode=atomic -failfast \ No newline at end of file diff --git a/alter.go b/alter.go new file mode 100644 index 0000000..b8c1fda --- /dev/null +++ b/alter.go @@ -0,0 +1,92 @@ +package bob + +import ( + "errors" + "strings" + + "github.com/lann/builder" +) + +type AlterBuilder builder.Builder + +type alter int + +const ( + alterDropColumn alter = iota + alterDropConstraint + alterRenameColumn + alterRenameConstraint +) + +type alterData struct { + What alter + TableName string + FirstKey string + SecondKey string + Suffix string +} + +func init() { + builder.Register(AlterBuilder{}, alterData{}) +} + +func (b AlterBuilder) whatToAlter(what alter) AlterBuilder { + return builder.Set(b, "What", what).(AlterBuilder) +} + +func (b AlterBuilder) tableName(table string) AlterBuilder { + return builder.Set(b, "TableName", table).(AlterBuilder) +} + +func (b AlterBuilder) firstKey(key string) AlterBuilder { + return builder.Set(b, "FirstKey", key).(AlterBuilder) +} + +func (b AlterBuilder) secondKey(key string) AlterBuilder { + return builder.Set(b, "SecondKey", key).(AlterBuilder) +} + +func (b AlterBuilder) Suffix(any string) AlterBuilder { + return builder.Set(b, "Suffix", any).(AlterBuilder) +} + +func (b AlterBuilder) ToSql() (string, []interface{}, error) { + data := builder.GetStruct(b).(alterData) + return data.ToSql() +} + +func (d *alterData) ToSql() (sqlStr string, args []interface{}, err error) { + if d.TableName == "" { + err = errors.New("table name must not be empty") + return + } + + if d.FirstKey == "" { + err = errors.New("the second argument must not be empty") + return + } + + var sql strings.Builder + + sql.WriteString("ALTER TABLE ") + + sql.WriteString(d.TableName + " ") + + switch d.What { + case alterDropColumn: + sql.WriteString("DROP COLUMN " + d.FirstKey) + case alterDropConstraint: + sql.WriteString("DROP CONSTRAINT " + d.FirstKey) + case alterRenameColumn: + sql.WriteString("RENAME COLUMN " + d.FirstKey + " TO " + d.SecondKey) + case alterRenameConstraint: + sql.WriteString("RENAME CONSTRAINT " + d.FirstKey + " TO " + d.SecondKey) + } + + if d.Suffix != "" { + sql.WriteString(" " + d.Suffix) + } + + sqlStr = sql.String() + return +} diff --git a/alter_test.go b/alter_test.go new file mode 100644 index 0000000..8cde2e6 --- /dev/null +++ b/alter_test.go @@ -0,0 +1,123 @@ +package bob_test + +import ( + "testing" + + "github.com/aldy505/bob" +) + +func TestDropColumn(t *testing.T) { + t.Run("Plain", func(t *testing.T) { + sql, _, err := bob.DropColumn("users", "name").ToSql() + if err != nil { + t.Fatal(err.Error()) + } + + expected := "ALTER TABLE users DROP COLUMN name" + if sql != expected { + t.Fatalf("Expected %s, got %s", expected, sql) + } + }) + + t.Run("Complex", func(t *testing.T) { + sql, _, err := bob.DropColumn("users", "name").Suffix("CASCADE").ToSql() + if err != nil { + t.Fatal(err.Error()) + } + + expected := "ALTER TABLE users DROP COLUMN name CASCADE" + if sql != expected { + t.Fatalf("Got: %s, Expected: %s", sql, expected) + } + }) +} + +func TestDropConstraint(t *testing.T) { + t.Run("Plain", func(t *testing.T) { + sql, _, err := bob.DropConstraint("users", "name").ToSql() + if err != nil { + t.Fatal(err.Error()) + } + + expected := "ALTER TABLE users DROP CONSTRAINT name" + if sql != expected { + t.Fatalf("Expected %s, got %s", expected, sql) + } + }) + + t.Run("Complex", func(t *testing.T) { + sql, _, err := bob.DropConstraint("users", "name").Suffix("CASCADE").ToSql() + if err != nil { + t.Fatal(err.Error()) + } + + expected := "ALTER TABLE users DROP CONSTRAINT name CASCADE" + if sql != expected { + t.Fatalf("Got: %s, Expected: %s", sql, expected) + } + }) +} + +func TestRenameColumn(t *testing.T) { + t.Run("Plain", func(t *testing.T) { + sql, _, err := bob.RenameColumn("users", "name", "full_name").ToSql() + if err != nil { + t.Fatal(err.Error()) + } + + expected := "ALTER TABLE users RENAME COLUMN name TO full_name" + if sql != expected { + t.Fatalf("Expected %s, got %s", expected, sql) + } + }) + + t.Run("Complex", func(t *testing.T) { + sql, _, err := bob.RenameColumn("users", "name", "full_name").Suffix("CASCADE").ToSql() + if err != nil { + t.Fatal(err.Error()) + } + + expected := "ALTER TABLE users RENAME COLUMN name TO full_name CASCADE" + if sql != expected { + t.Fatalf("Got: %s, Expected: %s", sql, expected) + } + }) +} + +func TestRenameConstraint(t *testing.T) { + t.Run("Plain", func(t *testing.T) { + sql, _, err := bob.RenameConstraint("users", "name", "full_name").ToSql() + if err != nil { + t.Fatal(err.Error()) + } + + expected := "ALTER TABLE users RENAME CONSTRAINT name TO full_name" + if sql != expected { + t.Fatalf("Expected %s, got %s", expected, sql) + } + }) + + t.Run("Complex", func(t *testing.T) { + sql, _, err := bob.RenameConstraint("users", "name", "full_name").Suffix("CASCADE").ToSql() + if err != nil { + t.Fatal(err.Error()) + } + + expected := "ALTER TABLE users RENAME CONSTRAINT name TO full_name CASCADE" + if sql != expected { + t.Fatalf("Got: %s, Expected: %s", sql, expected) + } + }) +} + +func TestAlter_Error(t *testing.T) { + _, _, err := bob.DropColumn("", "").ToSql() + if err.Error() != "table name must not be empty" { + t.Fatal("Expected error: table name must not be empty. Got:", err.Error()) + } + + _, _, err = bob.DropColumn("users", "").ToSql() + if err.Error() != "the second argument must not be empty" { + t.Fatal("Expected error: the second argument must not be empty. Got:", err.Error()) + } +} diff --git a/bob.go b/bob.go index 18d48d2..26c86a0 100644 --- a/bob.go +++ b/bob.go @@ -84,6 +84,22 @@ func (b BobBuilderType) Upsert(table string, dialect int) UpsertBuilder { return UpsertBuilder(b).dialect(dialect).into(table) } +func (b BobBuilderType) DropColumn(table, column string) AlterBuilder { + return AlterBuilder(b).whatToAlter(alterDropColumn).tableName(table).firstKey(column) +} + +func (b BobBuilderType) DropConstraint(table, constraint string) AlterBuilder { + return AlterBuilder(b).whatToAlter(alterDropConstraint).tableName(table).firstKey(constraint) +} + +func (b BobBuilderType) RenameColumn(table, from, to string) AlterBuilder { + return AlterBuilder(b).whatToAlter(alterRenameColumn).tableName(table).firstKey(from).secondKey(to) +} + +func (b BobBuilderType) RenameConstraint(table, from, to string) AlterBuilder { + return AlterBuilder(b).whatToAlter(alterRenameConstraint).tableName(table).firstKey(from).secondKey(to) +} + // BobStmtBuilder is the parent builder for BobBuilderType var BobStmtBuilder = BobBuilderType(builder.EmptyBuilder) @@ -192,3 +208,19 @@ func CreateIndex(name string) IndexBuilder { func CreateIndexIfNotExists(name string) IndexBuilder { return BobStmtBuilder.CreateIndexIfNotExists(name) } + +func DropColumn(table, column string) AlterBuilder { + return BobStmtBuilder.DropColumn(table, column) +} + +func DropConstraint(table, constraint string) AlterBuilder { + return BobStmtBuilder.DropConstraint(table, constraint) +} + +func RenameColumn(table, from, to string) AlterBuilder { + return BobStmtBuilder.RenameColumn(table, from, to) +} + +func RenameConstraint(table, from, to string) AlterBuilder { + return BobStmtBuilder.RenameConstraint(table, from, to) +}