Skip to content

Commit

Permalink
use (Or/And)Where(Not)In alongside Where (#86)
Browse files Browse the repository at this point in the history
  • Loading branch information
maikttt authored Oct 29, 2022
1 parent cb5b8c9 commit 2c5cbbd
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 33 deletions.
19 changes: 9 additions & 10 deletions builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"log"
"os"
"strconv"
"strings"
)

const (
Expand Down Expand Up @@ -243,10 +242,9 @@ func (r *DB) OrWhere(operand, operator string, val interface{}) *DB {

func (r *DB) buildWhere(prefix, operand, operator string, val interface{}) *DB {
if prefix != "" {
r.Builder.whereBindings = append(r.Builder.whereBindings, map[string]interface{}{" " + prefix + " " + operand + " " + operator: val})
} else {
r.Builder.whereBindings = append(r.Builder.whereBindings, map[string]interface{}{operand + " " + operator: val})
prefix =" " + prefix + " "
}
r.Builder.whereBindings = append(r.Builder.whereBindings, map[string]interface{}{prefix + operand + " " + operator: val})
return r
}

Expand Down Expand Up @@ -367,7 +365,7 @@ func (r *DB) WhereIn(field string, in interface{}) *DB {
if err != nil {
return nil
}
r.Builder.where = where + field + " IN (" + strings.Join(prepareSlice(ins), ", ") + ")"
r.buildWhere("", field, "IN", ins)
return r
}

Expand All @@ -377,7 +375,7 @@ func (r *DB) WhereNotIn(field string, in interface{}) *DB {
if err != nil {
return nil
}
r.Builder.where = where + field + " NOT IN (" + strings.Join(prepareSlice(ins), ", ") + ")"
r.buildWhere("", field, "NOT IN", ins)
return r
}

Expand All @@ -387,7 +385,7 @@ func (r *DB) OrWhereIn(field string, in interface{}) *DB {
if err != nil {
return nil
}
r.Builder.where += or + field + " IN (" + strings.Join(prepareSlice(ins), ", ") + ")"
r.buildWhere("OR", field, "IN", ins)
return r
}

Expand All @@ -397,7 +395,7 @@ func (r *DB) OrWhereNotIn(field string, in interface{}) *DB {
if err != nil {
return nil
}
r.Builder.where += or + field + " NOT IN (" + strings.Join(prepareSlice(ins), ", ") + ")"
r.buildWhere("OR", field, "NOT IN", ins)
return r
}

Expand All @@ -407,7 +405,8 @@ func (r *DB) AndWhereIn(field string, in interface{}) *DB {
if err != nil {
return nil
}
r.Builder.where += and + field + " IN (" + strings.Join(prepareSlice(ins), ", ") + ")"
r.buildWhere("AND", field, "IN", ins)
// r.buildWhere("AND", field, "IN", prepareSlice(ins))
return r
}

Expand All @@ -417,7 +416,7 @@ func (r *DB) AndWhereNotIn(field string, in interface{}) *DB {
if err != nil {
return nil
}
r.Builder.where += and + field + " NOT IN (" + strings.Join(prepareSlice(ins), ", ") + ")"
r.buildWhere("AND", field, "NOT IN", ins)
return r
}

Expand Down
73 changes: 50 additions & 23 deletions factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,20 @@ func composeWhere(whereBindings []map[string]interface{}, startedAt int) string
where := " WHERE "
i := startedAt
for _, m := range whereBindings {
for k := range m {
for k, v := range m {
// operand >= $i
where += k + " $" + strconv.Itoa(i)
i++
switch vi := v.(type) {
case []interface{}:
placeholders := make([]string, 0, len(vi))
for range vi {
placeholders = append(placeholders, "$" + strconv.Itoa(i))
i++
}
where += k + " (" + strings.Join(placeholders, ", ") + ")"
default:
where += k + " $" + strconv.Itoa(i)
i++
}
}
}
return where
Expand Down Expand Up @@ -217,33 +227,50 @@ func (r *DB) InsertGetId(data map[string]interface{}) (uint64, error) {
return id, nil
}

func prepareValue(value interface{}) []interface{} {
values := []interface{}{}
switch v := value.(type) {
case string:
//if where { // todo: left comments for further exploration, probably incorrect behaviour for pg driver
// values = append(values, "'"+v+"'")
//} else {
values = append(values, v)
//}
case int:
values = append(values, strconv.FormatInt(int64(v), 10))
case float64:
values = append(values, fmt.Sprintf("%g", v))
case int64:
values = append(values, strconv.FormatInt(v, 10))
case uint64:
values = append(values, strconv.FormatUint(v, 10))
case []interface{}:
for _, vi := range v {
values = append(values, prepareValue(vi)...)
}
case nil:
values = append(values, nil)
}

return values
}

// prepareBindings prepares slices to split in favor of INSERT sql statement
func prepareBindings(data map[string]interface{}) (columns []string, values []interface{}, bindings []string) {
i := 1
for column, value := range data {
columns = append(columns, column)

switch v := value.(type) {
case string:
//if where { // todo: left comments for further exploration, probably incorrect behaviour for pg driver
// values = append(values, "'"+v+"'")
//} else {
values = append(values, v)
//}
case int:
values = append(values, strconv.FormatInt(int64(v), 10))
case float64:
values = append(values, fmt.Sprintf("%g", v))
case int64:
values = append(values, strconv.FormatInt(v, 10))
case uint64:
values = append(values, strconv.FormatUint(v, 10))
case nil:
values = append(values, nil)
}
pValues := prepareValue(value)

bindings = append(bindings, "$"+strconv.FormatInt(int64(i), 10))
i++
if len(pValues) > 0 {
values = append(values, pValues...)

for range pValues {
bindings = append(bindings, "$"+strconv.FormatInt(int64(i), 10))
i++
}
}
}

return
Expand Down

0 comments on commit 2c5cbbd

Please sign in to comment.