sqlboiler
sqlboiler copied to clipboard
Call of `reflect.Value.Field` on zero `Value`
What version of SQLBoiler are you using (sqlboiler --version)?
SQLBoiler v3.7.1
What is your database and version (eg. Postgresql 10)
Postgres 10.6
If this happened at runtime what code produced the issue? (if not applicable leave blank)
var u struct {
User *models.User `boil:",bind"`
}
err = models.Users().Bind(nil, db, &u)
if err != nil {
panic(err)
}
Please provide a relevant database schema so we can replicate your issue (Provided you are comfortable sharing this)
CREATE TABLE "user" (
id SERIAL PRIMARY KEY
);
Further information. What did you do, what did you expect?
I expected the u variable to be filled but instead I get this panic:
panic: reflect: call of reflect.Value.Field on zero Value
goroutine 1 [running]:
reflect.Value.Field({0x0?, 0x0?, 0xc000143bc0?}, 0x44b9f2?)
/usr/lib/go/src/reflect/value.go:1220 +0xef
github.com/volatiletech/sqlboiler/queries.ptrFromMapping({0x7063e0?, 0xc0000b0de0?, 0x7d7938?}, 0xff0000, 0x1)
/home/elia/go/pkg/mod/github.com/volatiletech/[email protected]+incompatible/queries/reflect.go:378 +0x129
github.com/volatiletech/sqlboiler/queries.PtrsFromMapping({0x7063e0?, 0xc0000b0de0?, 0xc0000a0480?}, {0xc0000a3270, 0x1, 0x0?})
/home/elia/go/pkg/mod/github.com/volatiletech/[email protected]+incompatible/queries/reflect.go:344 +0x94
github.com/volatiletech/sqlboiler/queries.bind(0x6e5e40?, {0x6e5e40?, 0xc0000b0de0}, {0x7d9360, 0x7063e0}, {0x6ecca0?, 0xc000098e90?}, 0x0)
/home/elia/go/pkg/mod/github.com/volatiletech/[email protected]+incompatible/queries/reflect.go:280 +0x62b
github.com/volatiletech/sqlboiler/queries.(*Query).Bind(0xc0000fb600, {0x0, 0x0}, {0x7d7d98?, 0xc00009fee0}, {0x6e5e40, 0xc0000b0de0})
/home/elia/go/pkg/mod/github.com/volatiletech/[email protected]+incompatible/queries/reflect.go:147 +0x147
main.main()
/home/elia/dump/sqlboilertest/main.go:18 +0xfa
exit status 2
The panic is not caused by the if err != nil { panic(err) } but by the call to .Bind itself.
When I change the type of the field from *models.User to models.User the issue disappears. But I'd like to use a pointer for performance reasons.
As a workaround, you can allocate the field so that the pointer is not nil but points to an zeroed models.User instead:
u.User = new(models.User)
I'm not exactly sure why this works though.
My best guess is that SQLBoiler uses reflect to recursively inspect the structure of the bound variable and needs actual non-nil values in order to do so.
This remains an issue when binding to a slice since I can't pre-allocate the pointers without knowing how many rows will be returned.
This is sort of working as intended. If you send in a PR that addresses this, I will review but I will not work on this myself.