mirror of https://github.com/aldy505/bob.git
Merge pull request #7 from aldy505/feat/drop_cascade
feat: drop cascade & restrict
This commit is contained in:
commit
f1008bdf4a
|
@ -9,7 +9,7 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||||
go-version: [1.15.x, 1.16.x]
|
go-version: [1.16.x, 1.17.x]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
|
@ -14,7 +14,7 @@ jobs:
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: 1.16.x
|
go-version: 1.17.x
|
||||||
|
|
||||||
- name: Run coverage
|
- name: Run coverage
|
||||||
run: go test -v -race -coverprofile=coverage.out -covermode=atomic -failfast
|
run: go test -v -race -coverprofile=coverage.out -covermode=atomic -failfast
|
||||||
|
|
21
README.md
21
README.md
|
@ -89,11 +89,28 @@ func main() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
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
|
### Truncate table
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
|
24
drop.go
24
drop.go
|
@ -1,8 +1,8 @@
|
||||||
package bob
|
package bob
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"errors"
|
"errors"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/lann/builder"
|
"github.com/lann/builder"
|
||||||
)
|
)
|
||||||
|
@ -12,6 +12,8 @@ type DropBuilder builder.Builder
|
||||||
type dropData struct {
|
type dropData struct {
|
||||||
TableName string
|
TableName string
|
||||||
IfExists bool
|
IfExists bool
|
||||||
|
Cascade bool
|
||||||
|
Restrict bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -27,6 +29,14 @@ func (b DropBuilder) ifExists() DropBuilder {
|
||||||
return builder.Set(b, "IfExists", true).(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.
|
// ToSql returns 3 variables filled out with the correct values based on bindings, etc.
|
||||||
func (b DropBuilder) ToSql() (string, []interface{}, error) {
|
func (b DropBuilder) ToSql() (string, []interface{}, error) {
|
||||||
data := builder.GetStruct(b).(dropData)
|
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 == "" {
|
if len(d.TableName) == 0 || d.TableName == "" {
|
||||||
err = errors.New("drop statement must specify a table")
|
err = errors.New("drop statement must specify a table")
|
||||||
}
|
}
|
||||||
sql := &bytes.Buffer{}
|
var sql strings.Builder
|
||||||
|
|
||||||
sql.WriteString("DROP TABLE ")
|
sql.WriteString("DROP TABLE ")
|
||||||
|
|
||||||
|
@ -46,7 +56,15 @@ func (d *dropData) ToSql() (sqlStr string, args []interface{}, err error) {
|
||||||
sql.WriteString("IF EXISTS ")
|
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()
|
sqlStr = sql.String()
|
||||||
return
|
return
|
||||||
|
|
36
drop_test.go
36
drop_test.go
|
@ -6,8 +6,7 @@ import (
|
||||||
"github.com/aldy505/bob"
|
"github.com/aldy505/bob"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDrop(t *testing.T) {
|
func TestDrop_Regular(t *testing.T) {
|
||||||
t.Run("should be able to create regular drop query", func(t *testing.T) {
|
|
||||||
sql, _, err := bob.DropTable("users").ToSql()
|
sql, _, err := bob.DropTable("users").ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -17,9 +16,9 @@ func TestDrop(t *testing.T) {
|
||||||
if sql != result {
|
if sql != result {
|
||||||
t.Error("sql is not the same as result: ", sql)
|
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) {
|
func TestDrop_IfExists(t *testing.T) {
|
||||||
sql, _, err := bob.DropTableIfExists("users").ToSql()
|
sql, _, err := bob.DropTableIfExists("users").ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -29,12 +28,35 @@ func TestDrop(t *testing.T) {
|
||||||
if sql != result {
|
if sql != result {
|
||||||
t.Error("sql is not the same as result: ", sql)
|
t.Error("sql is not the same as result: ", sql)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
t.Run("should expect an error for no table name", func(t *testing.T) {
|
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()
|
_, _, err := bob.DropTableIfExists("").ToSql()
|
||||||
if err == nil && err.Error() != "drop statement must specify a table" {
|
if err == nil && err.Error() != "drop statement must specify a table" {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -1,6 +1,6 @@
|
||||||
module github.com/aldy505/bob
|
module github.com/aldy505/bob
|
||||||
|
|
||||||
go 1.16
|
go 1.17
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0
|
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0
|
||||||
|
|
9
has.go
9
has.go
|
@ -4,7 +4,6 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/aldy505/bob/util"
|
|
||||||
"github.com/lann/builder"
|
"github.com/lann/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -21,12 +20,14 @@ func init() {
|
||||||
builder.Register(HasBuilder{}, hasData{})
|
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 {
|
func (h HasBuilder) HasTable(table string) HasBuilder {
|
||||||
return builder.Set(h, "Name", table).(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 {
|
func (h HasBuilder) HasColumn(column string) HasBuilder {
|
||||||
return builder.Set(h, "Column", column).(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)
|
sqlStr = ReplacePlaceholder(sql.String(), d.Placeholder)
|
||||||
args = util.CreateArgs(d.Name, d.Column, d.Schema)
|
args = createArgs(d.Name, d.Column, d.Schema)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
Loading…
Reference in New Issue