diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6f66b75..c205eb0 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.15.x, 1.16.x] + go-version: [1.16.x, 1.17.x] steps: - name: Checkout code uses: actions/checkout@v2 diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 5a8d383..cd0b9d6 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -14,7 +14,7 @@ jobs: - name: Install Go uses: actions/setup-go@v2 with: - go-version: 1.16.x + go-version: 1.17.x - name: Run coverage run: go test -v -race -coverprofile=coverage.out -covermode=atomic -failfast diff --git a/README.md b/README.md index f6bbb1d..2dcf585 100644 --- a/README.md +++ b/README.md @@ -89,11 +89,28 @@ func main() { if err != nil { log.Fatal(err) } + // sql = "DROP TABLE users;" + + sql, _, err = bob.DropTableIfExists("users").ToSql() + if err != nil { + log.Fatal(err) + } + // sql = "DROP TABLE IF EXISTS users;" + + sql, _, err = bob.DropTable("users").Cascade().ToSql() + if err != nil { + log.Fatal(err) + } + // sql = "DROP TABLE users CASCADE;" + + sql, _, err = bob.DropTable("users").Restrict().ToSql() + if err != nil { + log.Fatal(err) + } + // sql = "DROP TABLE users RESTRICT;" } ``` -You could also do `bob.DropTableIfExists("users")` to output a `DROP TABLE IF EXISTS "users"` query. - ### Truncate table ```go diff --git a/drop.go b/drop.go index 9d08962..c8ba42d 100644 --- a/drop.go +++ b/drop.go @@ -1,8 +1,8 @@ package bob import ( - "bytes" "errors" + "strings" "github.com/lann/builder" ) @@ -12,6 +12,8 @@ type DropBuilder builder.Builder type dropData struct { TableName string IfExists bool + Cascade bool + Restrict bool } func init() { @@ -27,6 +29,14 @@ func (b DropBuilder) ifExists() DropBuilder { return builder.Set(b, "IfExists", true).(DropBuilder) } +func (b DropBuilder) Cascade() DropBuilder { + return builder.Set(b, "Cascade", true).(DropBuilder) +} + +func (b DropBuilder) Restrict() DropBuilder { + return builder.Set(b, "Restrict", true).(DropBuilder) +} + // ToSql returns 3 variables filled out with the correct values based on bindings, etc. func (b DropBuilder) ToSql() (string, []interface{}, error) { data := builder.GetStruct(b).(dropData) @@ -38,7 +48,7 @@ func (d *dropData) ToSql() (sqlStr string, args []interface{}, err error) { if len(d.TableName) == 0 || d.TableName == "" { err = errors.New("drop statement must specify a table") } - sql := &bytes.Buffer{} + var sql strings.Builder sql.WriteString("DROP TABLE ") @@ -46,7 +56,15 @@ func (d *dropData) ToSql() (sqlStr string, args []interface{}, err error) { sql.WriteString("IF EXISTS ") } - sql.WriteString("\"" + d.TableName + "\";") + sql.WriteString("\"" + d.TableName + "\"") + + if d.Cascade { + sql.WriteString(" CASCADE") + } else if d.Restrict { + sql.WriteString(" RESTRICT") + } + + sql.WriteString(";") sqlStr = sql.String() return diff --git a/drop_test.go b/drop_test.go index ec4785c..4c7906a 100644 --- a/drop_test.go +++ b/drop_test.go @@ -6,35 +6,57 @@ import ( "github.com/aldy505/bob" ) -func TestDrop(t *testing.T) { - t.Run("should be able to create regular drop query", func(t *testing.T) { - sql, _, err := bob.DropTable("users").ToSql() - if err != nil { - t.Error(err) - } +func TestDrop_Regular(t *testing.T) { + sql, _, err := bob.DropTable("users").ToSql() + if err != nil { + t.Error(err) + } - result := "DROP TABLE \"users\";" - if sql != result { - t.Error("sql is not the same as result: ", sql) - } - }) - - t.Run("should be able to create drop if exists query", func(t *testing.T) { - sql, _, err := bob.DropTableIfExists("users").ToSql() - if err != nil { - t.Error(err) - } - - result := "DROP TABLE IF EXISTS \"users\";" - if sql != result { - t.Error("sql is not the same as result: ", sql) - } - }) - - t.Run("should expect an error for no table name", func(t *testing.T) { - _, _, err := bob.DropTableIfExists("").ToSql() - if err == nil && err.Error() != "drop statement must specify a table" { - t.Error(err) - } - }) + result := "DROP TABLE \"users\";" + if sql != result { + t.Error("sql is not the same as result: ", sql) + } +} + +func TestDrop_IfExists(t *testing.T) { + sql, _, err := bob.DropTableIfExists("users").ToSql() + if err != nil { + t.Error(err) + } + + result := "DROP TABLE IF EXISTS \"users\";" + if sql != result { + t.Error("sql is not the same as result: ", sql) + } +} + +func TestDrop_Cascade(t *testing.T) { + sql, _, err := bob.DropTable("users").Cascade().ToSql() + if err != nil { + t.Error(err) + } + + result := "DROP TABLE \"users\" CASCADE;" + if sql != result { + t.Error("sql is not the same as result: ", sql) + } +} + +func TestDrop_Restrict(t *testing.T) { + sql, _, err := bob.DropTable("users").Restrict().ToSql() + if err != nil { + t.Error(err) + } + + result := "DROP TABLE \"users\" RESTRICT;" + if sql != result { + t.Error("sql is not the same as result: ", sql) + } +} + +func TestDrop_ErrNoTable(t *testing.T) { + _, _, err := bob.DropTableIfExists("").ToSql() + if err == nil && err.Error() != "drop statement must specify a table" { + t.Error(err) + } } diff --git a/go.mod b/go.mod index 4374723..bcf0890 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/aldy505/bob -go 1.16 +go 1.17 require ( github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 diff --git a/has.go b/has.go index 896127b..d1d2e4c 100644 --- a/has.go +++ b/has.go @@ -4,7 +4,6 @@ import ( "bytes" "errors" - "github.com/aldy505/bob/util" "github.com/lann/builder" ) @@ -21,12 +20,14 @@ func init() { builder.Register(HasBuilder{}, hasData{}) } -// HasTable checks for a table's existence by tableName, resolving with a boolean to signal if the table exists. +// HasTable checks for a table's existence by tableName, +// resolving with a boolean to signal if the table exists. func (h HasBuilder) HasTable(table string) HasBuilder { return builder.Set(h, "Name", table).(HasBuilder) } -// HasColumn checks if a column exists in the current table, resolves the promise with a boolean, true if the column exists, false otherwise. +// HasColumn checks if a column exists in the current table, +// resolves the promise with a boolean, true if the column exists, false otherwise. func (h HasBuilder) HasColumn(column string) HasBuilder { return builder.Set(h, "Column", column).(HasBuilder) } @@ -69,6 +70,6 @@ func (d *hasData) ToSql() (sqlStr string, args []interface{}, err error) { } sqlStr = ReplacePlaceholder(sql.String(), d.Placeholder) - args = util.CreateArgs(d.Name, d.Column, d.Schema) + args = createArgs(d.Name, d.Column, d.Schema) return } diff --git a/internal.go b/internal.go new file mode 100644 index 0000000..3d13aa4 --- /dev/null +++ b/internal.go @@ -0,0 +1,34 @@ +package bob + +// createArgs should create an argument []interface{} for SQL query +// I'm using the idiot approach for creating args +func createArgs(keys ...interface{}) []interface{} { + var args []interface{} + for _, v := range keys { + if v == "" { + continue + } + args = append(args, v) + } + return args +} + +// isIn checks if an array have a value +func isIn(arr []string, value string) bool { + for _, item := range arr { + if item == value { + return true + } + } + return false +} + +// findPosition search for value position on an array +func findPosition(arr []string, value string) int { + for i, item := range arr { + if item == value { + return i + } + } + return -1 +} diff --git a/util/arguments.go b/util/arguments.go deleted file mode 100644 index 30d7119..0000000 --- a/util/arguments.go +++ /dev/null @@ -1,14 +0,0 @@ -package util - -// createArgs should create an argument []interface{} for SQL query -// I'm using the idiot approach for creating args -func CreateArgs(keys ...interface{}) []interface{} { - var args []interface{} - for _, v := range keys { - if v == "" { - continue - } - args = append(args, v) - } - return args -} diff --git a/util/check.go b/util/check.go deleted file mode 100644 index f1b27fb..0000000 --- a/util/check.go +++ /dev/null @@ -1,21 +0,0 @@ -package util - -// IsIn checks if an array have a value -func IsIn(arr []string, value string) bool { - for _, item := range arr { - if item == value { - return true - } - } - return false -} - -// FindPosition search for value position on an array -func FindPosition(arr []string, value string) int { - for i, item := range arr { - if item == value { - return i - } - } - return -1 -}