Skip to content

Commit

Permalink
Merge pull request #1338 from volatiletech/fix/panic-struct-ptr
Browse files Browse the repository at this point in the history
Fix panic with nil pointers in structs to bind
  • Loading branch information
stephenafamo authored Jan 2, 2024
2 parents f10c023 + f0c6c11 commit 71f1195
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 31 deletions.
48 changes: 25 additions & 23 deletions queries/reflect.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,27 +83,27 @@ func (q *Query) BindG(ctx context.Context, obj interface{}) error {
//
// Example usage:
//
// type JoinStruct struct {
// // User1 can have it's struct fields bound to since it specifies
// // ,bind in the struct tag, it will look specifically for
// // fields that are prefixed with "user." returning from the query.
// // For example "user.id" column name will bind to User1.ID
// User1 *models.User `boil:"user,bind"`
// // User2 will follow the same rules as noted above except it will use
// // "friend." as the prefix it's looking for.
// User2 *models.User `boil:"friend,bind"`
// // RandomData will not be recursed into to look for fields to
// // bind and will not be bound to because of the - for the name.
// RandomData myStruct `boil:"-"`
// // Date will not be recursed into to look for fields to bind because
// // it does not specify ,bind in the struct tag. But it can be bound to
// // as it does not specify a - for the name.
// Date time.Time
// }
// type JoinStruct struct {
// // User1 can have it's struct fields bound to since it specifies
// // ,bind in the struct tag, it will look specifically for
// // fields that are prefixed with "user." returning from the query.
// // For example "user.id" column name will bind to User1.ID
// User1 *models.User `boil:"user,bind"`
// // User2 will follow the same rules as noted above except it will use
// // "friend." as the prefix it's looking for.
// User2 *models.User `boil:"friend,bind"`
// // RandomData will not be recursed into to look for fields to
// // bind and will not be bound to because of the - for the name.
// RandomData myStruct `boil:"-"`
// // Date will not be recursed into to look for fields to bind because
// // it does not specify ,bind in the struct tag. But it can be bound to
// // as it does not specify a - for the name.
// Date time.Time
// }
//
// models.Users(
// qm.InnerJoin("users as friend on users.friend_id = friend.id")
// ).Bind(&joinStruct)
// models.Users(
// qm.InnerJoin("users as friend on users.friend_id = friend.id")
// ).Bind(&joinStruct)
//
// For custom objects that want to use eager loading, please see the
// loadRelationships function.
Expand Down Expand Up @@ -368,6 +368,9 @@ func ptrFromMapping(val reflect.Value, mapping uint64, addressOf bool) reflect.V

val = val.Field(int(v))
if val.Kind() == reflect.Ptr {
if val.IsNil() {
val = reflect.New(val.Type().Elem())
}
val = reflect.Indirect(val)
}
}
Expand Down Expand Up @@ -606,8 +609,7 @@ func parseNumeric(s string, t reflect.Type) interface{} {
reflect.Uint32,
reflect.Uint64:
res, err = strconv.ParseUint(s, 0, t.Bits())
case reflect.Float32,
reflect.Float64:
case reflect.Float32, reflect.Float64:
res, err = strconv.ParseFloat(s, t.Bits())
}
if err != nil {
Expand Down Expand Up @@ -803,7 +805,7 @@ var specialWordReplacer = strings.NewReplacer(

// unTitleCase attempts to undo a title-cased string.
//
// DO NOT USE THIS METHOD IF YOU CAN AVOID IT
// # DO NOT USE THIS METHOD IF YOU CAN AVOID IT
//
// Normally this would be easy but we have to deal with uppercased words
// of varying lengths. We almost never use this function so it
Expand Down
14 changes: 6 additions & 8 deletions queries/reflect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import (
"testing"
"time"

"github.com/volatiletech/sqlboiler/v4/drivers"
"github.com/volatiletech/null/v8"
"github.com/volatiletech/sqlboiler/v4/drivers"

"github.com/DATA-DOG/go-sqlmock"
)
Expand Down Expand Up @@ -193,7 +193,7 @@ func testMakeMapping(byt ...byte) uint64 {
func TestMakeStructMapping(t *testing.T) {
t.Parallel()

var testStruct = struct {
testStruct := struct {
LastName string `boil:"different"`
AwesomeName string `boil:"awesome_name"`
Face string `boil:"-"`
Expand Down Expand Up @@ -249,8 +249,7 @@ func TestPtrFromMapping(t *testing.T) {
Int: 5,
IntP: new(int),
NestedPtrsP: &NestedPtrs{
Int: 6,
IntP: new(int),
Int: 6,
},
}

Expand Down Expand Up @@ -399,10 +398,9 @@ func TestGetBoilTag(t *testing.T) {
func TestBindChecks(t *testing.T) {
t.Parallel()

type useless struct {
}
type useless struct{}

var tests = []struct {
tests := []struct {
BKind bindKind
Fail bool
Obj interface{}
Expand Down Expand Up @@ -623,7 +621,7 @@ func TestAssignBytes(t *testing.T) {
t.Parallel()

var dst []byte
var src = []byte("hello")
src := []byte("hello")

Assign(&dst, src)
if !bytes.Equal(dst, src) {
Expand Down

0 comments on commit 71f1195

Please sign in to comment.