When calling sqlx.In on a pointer to var that implements driver.Valuer interface, the function panics for nil pointer dereference.
Current behaviour
type Valuer struct {
Val string
}
func (v Valuer) Value() (driver.Value, error) {
return v.Val, nil
}
query := `SELECT * FROM foo WHERE x = ? or y IN (?)`
_, _, err := In(query,
(*Valuer)(nil), // a non-inited pointer to valuer
[]interface{}{
"a", // a usual value
nil, // a nil value
Valuer{Val: "foo"}, // a Valuer
&Valuer{Val: "foo"}, // a pointer to valuer
(*Valuer)(nil), // a non-inited pointer to valuer
},
)
--- FAIL: TestIn (0.00s)
--- FAIL: TestIn/with_nil_driver.Valuer (0.00s)
panic: value method github.com/jmoiron/sqlx.Valuer.Value called using nil *Valuer pointer [recovered]
panic: value method github.com/jmoiron/sqlx.Valuer.Value called using nil *Valuer pointer
goroutine 13 [running]:
testing.tRunner.func1.2({0x8452a0, 0xc0001d5320})
/usr/local/go/src/testing/testing.go:1632 +0x230
testing.tRunner.func1()
/usr/local/go/src/testing/testing.go:1635 +0x35e
panic({0x8452a0?, 0xc0001d5320?})
/usr/local/go/src/runtime/panic.go:785 +0x132
github.com/jmoiron/sqlx.(*Valuer).Value(0xb48390?)
<autogenerated>:1 +0x45
github.com/jmoiron/sqlx.In({0x8af3e6, 0x29}, {0xc0000d9f30, 0x2, 0x2})
/home/athomas/Work/sqlx/bind.go:166 +0x157
github.com/jmoiron/sqlx.TestIn.func1(0xc0000aad00)
/home/athomas/Work/sqlx/sqlx_test.go:1552 +0x154
testing.tRunner(0xc0000aad00, 0x8d1b60)
/usr/local/go/src/testing/testing.go:1690 +0xf4
created by testing.(*T).Run in goroutine 12
/usr/local/go/src/testing/testing.go:1743 +0x390
FAIL github.com/jmoiron/sqlx 0.006s
expected behaviour
The call should not panic. In stdlib, the resolution of a driver.Valuer returns nil in the special case of a nil value, as decribed in this snippet. I would expect sqlx to behave like stdlib on this matter.
// callValuerValue returns vr.Value(), with one exception:
// If vr.Value is an auto-generated method on a pointer type and the
// pointer is nil, it would panic at runtime in the panicwrap
// method. Treat it like nil instead.
// Issue 8415.
//
// This is so people can implement driver.Value on value types and
// still use nil pointers to those types to mean nil/NULL, just like
// string/*string.
//
// This function is mirrored in the database/sql package.
func callValuerValue(vr Valuer) (v Value, err error) {
if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Pointer &&
rv.IsNil() &&
rv.Type().Elem().Implements(valuerReflectType) {
return nil, nil
}
return vr.Value()
}
Description
When calling
sqlx.In
on a pointer to var that implementsdriver.Valuer
interface, the function panics for nil pointer dereference.Current behaviour
expected behaviour
The call should not panic. In stdlib, the resolution of a driver.Valuer returns nil in the special case of a nil value, as decribed in this snippet. I would expect sqlx to behave like stdlib on this matter.