Skip to content

Commit 49d74cb

Browse files
committed
Select statement has invalid NULL check syntax when using implicit nil value #272
1 parent e40b45c commit 49d74cb

File tree

4 files changed

+27
-9
lines changed

4 files changed

+27
-9
lines changed

exp/bool.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package exp
33
import (
44
"reflect"
55
"regexp"
6+
7+
"github.com/doug-martin/goqu/v9/internal/util"
68
)
79

810
type boolean struct {
@@ -155,7 +157,7 @@ func checkLikeExp(op BooleanOperation, lhs Expression, val interface{}, invert b
155157

156158
// checks a boolean operation normalizing the operation based on the RHS (e.g. "a" = true vs "a" IS TRUE
157159
func checkBoolExpType(op BooleanOperation, lhs Expression, rhs interface{}, invert bool) BooleanExpression {
158-
if rhs == nil {
160+
if rhs == nil || util.IsNil(rhs) {
159161
op = IsOp
160162
} else {
161163
switch reflect.Indirect(reflect.ValueOf(rhs)).Kind() {

expressions_example_test.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,7 @@ func ExampleOr_withAnd() {
10081008
}
10091009

10101010
func ExampleOr_withExMap() {
1011+
var val *int
10111012
ds := goqu.From("test").Where(
10121013
goqu.Or(
10131014
// Ex will be anded together
@@ -1018,6 +1019,7 @@ func ExampleOr_withExMap() {
10181019
goqu.Ex{
10191020
"col3": nil,
10201021
"col4": "foo",
1022+
"col5": val,
10211023
},
10221024
),
10231025
)
@@ -1028,8 +1030,8 @@ func ExampleOr_withExMap() {
10281030
fmt.Println(sql, args)
10291031

10301032
// Output:
1031-
// SELECT * FROM "test" WHERE ((("col1" = 1) AND ("col2" IS TRUE)) OR (("col3" IS NULL) AND ("col4" = 'foo'))) []
1032-
// SELECT * FROM "test" WHERE ((("col1" = ?) AND ("col2" IS TRUE)) OR (("col3" IS NULL) AND ("col4" = ?))) [1 foo]
1033+
// SELECT * FROM "test" WHERE ((("col1" = 1) AND ("col2" IS TRUE)) OR (("col3" IS NULL) AND ("col4" = 'foo') AND ("col5" IS NULL))) []
1034+
// SELECT * FROM "test" WHERE ((("col1" = ?) AND ("col2" IS TRUE)) OR (("col3" IS NULL) AND ("col4" = ?) AND ("col5" IS NULL))) [1 foo]
10331035
}
10341036

10351037
func ExampleRange_numbers() {

internal/util/reflect.go

+12
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,18 @@ func IsEmptyValue(v reflect.Value) bool {
8383
}
8484
}
8585

86+
func IsNil(i interface{}) bool {
87+
if i == nil {
88+
return true
89+
}
90+
switch reflect.TypeOf(i).Kind() {
91+
case reflect.Ptr, reflect.Map, reflect.Array, reflect.Chan, reflect.Slice:
92+
return reflect.ValueOf(i).IsNil()
93+
default:
94+
return false
95+
}
96+
}
97+
8698
var (
8799
structMapCache = make(map[interface{}]ColumnMap)
88100
structMapCacheLock = sync.Mutex{}

sqlgen/expression_sql_generator.go

+8-6
Original file line numberDiff line numberDiff line change
@@ -405,13 +405,15 @@ func (esg *expressionSQLGenerator) booleanExpressionSQL(b sb.SQLBuilder, operato
405405

406406
if (operatorOp == exp.IsOp || operatorOp == exp.IsNotOp) && esg.dialectOptions.UseLiteralIsBools {
407407
// these values must be interpolated because preparing them generates invalid SQL
408-
switch rhs {
409-
case true:
410-
rhs = TrueLiteral
411-
case false:
412-
rhs = FalseLiteral
413-
case nil:
408+
if util.IsNil(rhs) {
414409
rhs = exp.NewLiteralExpression(string(esg.dialectOptions.Null))
410+
} else {
411+
switch rhs {
412+
case true:
413+
rhs = TrueLiteral
414+
case false:
415+
rhs = FalseLiteral
416+
}
415417
}
416418
}
417419
b.WriteRunes(esg.dialectOptions.SpaceRune)

0 commit comments

Comments
 (0)