sqlboiler icon indicating copy to clipboard operation
sqlboiler copied to clipboard

Allocate struct pointers fields with "bind" tag

Open eliaperantoni opened this issue 2 years ago • 1 comments

Hello, this is an attempt to fix #1164.

If I were to do something like:

var slice []*struct{
    User *models.User `boil:",bind"`
}
models.Users().BindG(nil, &slice)

It wouldn't have worked prior to this PR because bind would've created a zeroed instance of the struct and then attempted to get a reflect.Value by dereferencing the User field. But in a zeroed struct the pointer is nil, and so you get this panic:

panic: reflect: call of reflect.Value.Field on zero Value

A workaround would be to embed models.User without a pointer. But this is not always feasible or performant, depending on how the resulting slice is going to be used afterward.

This PR makes it so that bind also allocates any pointer field provided that the target is []*Struct and the bind tag is set.


Implementation wise, I simply enumerate the struct fields after the call to reflect.New and allocate any pointer with the bind tag.

When the bind target is []Struct (instead of []*Struct) the behavior remains unchanged as the structs are copied-by-value anyways and the documentation already warns about not using structs with references when binding like that.

eliaperantoni avatar Jul 26 '22 08:07 eliaperantoni

@stephenafamo

eliaperantoni avatar Aug 03 '22 05:08 eliaperantoni