sqlboiler icon indicating copy to clipboard operation
sqlboiler copied to clipboard

Call of `reflect.Value.Field` on zero `Value`

Open eliaperantoni opened this issue 2 years ago • 2 comments

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.

eliaperantoni avatar Jul 25 '22 08:07 eliaperantoni

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.

eliaperantoni avatar Jul 25 '22 09:07 eliaperantoni

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.

stephenafamo avatar Jul 26 '22 03:07 stephenafamo