Skip to content

Commit ca6e42f

Browse files
Chen Cohenido50
authored andcommitted
Support "ANY" with an array of values
This commit adds the ability to use "ANY(...Array)" to look up for a value matching against an array. For example: dbz.Select("id").From("table").Where(ANY("id",[]int{1,2,3,4,5})) We added that support in order to workaround a limitation of postgres of maximum parameters in IN condition ("PostgreSQL only supports 65535 parameters").
1 parent b7e9b6d commit ca6e42f

File tree

2 files changed

+22
-8
lines changed

2 files changed

+22
-8
lines changed

select_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,10 @@ func TestSelect(t *testing.T) {
5353

5454
{
5555
"select with array comparisons",
56-
dbz.Select("*").From("table").Where(EqAny("array_col", 3), GtAll("other_array_col", 1), NeAny("yet_another_col", Indirect("NOW()"))),
57-
"SELECT * FROM table WHERE ? = ANY(array_col) AND ? > ALL(other_array_col) AND NOW() <> ANY(yet_another_col)",
58-
[]interface{}{3, 1},
56+
dbz.Select("*").From("table").Where(EqAny("array_col", 3), GtAll("other_array_col", 1), NeAny("yet_another_col", Indirect("NOW()")),
57+
Any(Indirect("column"),[]int{1,2,3})),
58+
"SELECT * FROM table WHERE ? = ANY(array_col) AND ? > ALL(other_array_col) AND NOW() <> ANY(yet_another_col) AND column = ANY(?)",
59+
[]interface{}{3, 1 ,"'{1,2,3}'"},
5960
},
6061

6162
{

sqlz.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"database/sql"
66
"fmt"
77
"sort"
8+
"strconv"
89
"strings"
910

1011
"github.com/jmoiron/sqlx"
@@ -305,6 +306,12 @@ type ArrayCondition struct {
305306
Right interface{}
306307
}
307308

309+
// Any creates an "ANY (array)" condition, to lookup for a value matching against an array of possible values
310+
// as similar to IN condition
311+
func Any(arr interface{}, value interface{}) ArrayCondition {
312+
return ArrayCondition{arr, "=", "ANY", value}
313+
}
314+
308315
// EqAny creates an "= ANY" condition on an array column
309316
func EqAny(arr interface{}, value interface{}) ArrayCondition {
310317
return ArrayCondition{value, "=", "ANY", arr}
@@ -399,22 +406,28 @@ func (cond SQLCondition) Parse() (asSQL string, bindings []interface{}) {
399406
// Parse implements the WhereCondition interface, generating SQL from
400407
// the condition
401408
func (array ArrayCondition) Parse() (asSQL string, bindings []interface{}) {
402-
var rightAsSQL, leftAsSQL string
409+
rightAsSQL := "?"
410+
leftAsSQL := "?"
403411

404412
if indirect, isIndirect := array.Left.(IndirectValue); isIndirect {
405413
leftAsSQL = indirect.Reference
406414
bindings = append(bindings, indirect.Bindings...)
407415
} else {
408-
leftAsSQL = "?"
409416
bindings = append(bindings, array.Left)
410417
}
411418

412-
switch array.Right.(type) {
419+
switch right := array.Right.(type) {
413420
case string:
414421
rightAsSQL = fmt.Sprintf("%v", array.Right)
415-
default:
416-
rightAsSQL = "?"
422+
case []int:
423+
var values []string
424+
for _, n := range right {
425+
values = append(values, strconv.Itoa(n))
426+
}
417427

428+
binds := fmt.Sprintf("'{%s}'", strings.Join(values, ","))
429+
bindings = append(bindings, binds)
430+
default:
418431
bindings = append(bindings, array.Right)
419432
}
420433

0 commit comments

Comments
 (0)