Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Call to sqlx.In on driver.Value with nil value panics #953

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

moxar
Copy link

@moxar moxar commented Oct 18, 2024

Description

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()
}
--- PASS: TestIn (0.00s)
    --- PASS: TestIn/with_nil_driver.Valuer (0.00s)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant