Skip to content

Commit

Permalink
condition IN supports the []int32, []uint32 and map type
Browse files Browse the repository at this point in the history
  • Loading branch information
xgfone committed May 29, 2024
1 parent 0ebad4b commit 973a43a
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 19 deletions.
111 changes: 92 additions & 19 deletions op_condition.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,47 +105,120 @@ func newCondIn(format string) OpBuilder {
return "1=0"

case []interface{}:
return fmtcondin(format, ab, op, vs)
return fmtcondin_slice(format, ab, op, vs)

case []int:
return fmtcondin(format, ab, op, vs)
return fmtcondin_slice(format, ab, op, vs)

case []uint:
return fmtcondin(format, ab, op, vs)
return fmtcondin_slice(format, ab, op, vs)

case []int32:
return fmtcondin_slice(format, ab, op, vs)

case []uint32:
return fmtcondin_slice(format, ab, op, vs)

case []int64:
return fmtcondin(format, ab, op, vs)
return fmtcondin_slice(format, ab, op, vs)

case []uint64:
return fmtcondin(format, ab, op, vs)
return fmtcondin_slice(format, ab, op, vs)

case []string:
return fmtcondin(format, ab, op, vs)
return fmtcondin_slice(format, ab, op, vs)

case map[string]bool:
return fmtcondin_map(format, ab, op, vs)

case map[string]struct{}:
return fmtcondin_map(format, ab, op, vs)

case map[int]bool:
return fmtcondin_map(format, ab, op, vs)

case map[int]struct{}:
return fmtcondin_map(format, ab, op, vs)

case map[uint]bool:
return fmtcondin_map(format, ab, op, vs)

case map[uint]struct{}:
return fmtcondin_map(format, ab, op, vs)

case map[int32]bool:
return fmtcondin_map(format, ab, op, vs)

case map[int32]struct{}:
return fmtcondin_map(format, ab, op, vs)

case map[uint32]bool:
return fmtcondin_map(format, ab, op, vs)

case map[uint32]struct{}:
return fmtcondin_map(format, ab, op, vs)

case map[int64]bool:
return fmtcondin_map(format, ab, op, vs)

case map[int64]struct{}:
return fmtcondin_map(format, ab, op, vs)

case map[uint64]bool:
return fmtcondin_map(format, ab, op, vs)

case map[uint64]struct{}:
return fmtcondin_map(format, ab, op, vs)

default:
vf := reflect.ValueOf(op.Val)
switch vf.Kind() {
var ss []string
switch vf := reflect.ValueOf(op.Val); vf.Kind() {
case reflect.Array, reflect.Slice:
_len := vf.Len()
if _len == 0 {
return "1=0"
}

ss = make([]string, _len)
for i := 0; i < _len; i++ {
ss[i] = ab.Add(vf.Index(i).Interface())
}

case reflect.Map:
_len := vf.Len()
if _len == 0 {
return "1=0"
}

ss = make([]string, 0, _len)
for _, key := range vf.MapKeys() {
ss = append(ss, ab.Add(vf.MapIndex(key).Interface()))
}

default:
panic(fmt.Errorf("sqlx: condition IN not support type %T", op.Val))
}

_len := vf.Len()
if _len == 0 {
return "1=0"
}

ss := make([]string, _len)
for i := 0; i < _len; i++ {
ss[i] = ab.Add(vf.Index(i).Interface())
}

return fmt.Sprintf(format, ab.Quote(getOpKey(op)), strings.Join(ss, ", "))
}
})
}

func fmtcondin[T any](format string, ab *ArgsBuilder, op op.Op, vs []T) string {
func fmtcondin_map[M ~map[K]V, K comparable, V bool | struct{}](format string, ab *ArgsBuilder, op op.Op, vs M) string {
switch _len := len(vs); _len {
case 0:
return "1=0"

default:
ss := make([]string, 0, _len)
for k := range vs {
ss = append(ss, ab.Add(k))
}
return fmt.Sprintf(format, ab.Quote(getOpKey(op)), strings.Join(ss, ", "))
}
}

func fmtcondin_slice[T any](format string, ab *ArgsBuilder, op op.Op, vs []T) string {
switch _len := len(vs); _len {
case 0:
return "1=0"
Expand Down
32 changes: 32 additions & 0 deletions op_condition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,35 @@ func TestCondInForOne(t *testing.T) {
t.Errorf("expect args %v, but got %v", expectargs, args)
}
}

func TestCondInForMapNil(t *testing.T) {
ab := NewArgsBuilder(MySQL)
sql := BuildOper(ab, op.Key("field").In(map[string]struct{}(nil)))
args := ab.Args()

expectsql := "1=0"
expectargs := []any{}

if sql != expectsql {
t.Errorf("expect sql '%s', but got '%s'", expectsql, sql)
}
if !reflect.DeepEqual(args, expectargs) {
t.Errorf("expect args %v, but got %v", expectargs, args)
}
}

func TestCondInForMap(t *testing.T) {
ab := NewArgsBuilder(MySQL)
sql := BuildOper(ab, op.Key("field").In(map[string]bool{"value": false}))
args := ab.Args()

expectsql := "`field` IN (?)"
expectargs := []any{"value"}

if sql != expectsql {
t.Errorf("expect sql '%s', but got '%s'", expectsql, sql)
}
if !reflect.DeepEqual(args, expectargs) {
t.Errorf("expect args %v, but got %v", expectargs, args)
}
}

0 comments on commit 973a43a

Please sign in to comment.