Fix RowToStructByPos on structs with multiple anonymous sub-structs

Fixes 
pull/1363/head
Baptiste Fontaine 2022-10-18 17:20:47 +00:00 committed by Jack Christensen
parent ba100785cc
commit 3e825ec898
2 changed files with 30 additions and 2 deletions

View File

@ -533,9 +533,9 @@ func (rs *positionalStructRowScanner) appendScanTargets(dstElemValue reflect.Val
for i := 0; i < dstElemType.NumField(); i++ {
sf := dstElemType.Field(i)
if sf.PkgPath == "" {
// Handle anoymous struct embedding, but do not try to handle embedded pointers.
// Handle anonymous struct embedding, but do not try to handle embedded pointers.
if sf.Anonymous && sf.Type.Kind() == reflect.Struct {
scanTargets = append(scanTargets, rs.appendScanTargets(dstElemValue.Field(i), scanTargets)...)
scanTargets = rs.appendScanTargets(dstElemValue.Field(i), scanTargets)
} else {
scanTargets = append(scanTargets, dstElemValue.Field(i).Addr().Interface())
}

View File

@ -383,6 +383,34 @@ func TestRowToStructByPosEmbeddedStruct(t *testing.T) {
})
}
func TestRowToStructByPosMultipleEmbeddedStruct(t *testing.T) {
type Sandwich struct {
Bread string
Salad string
}
type Drink struct {
Ml int
}
type meal struct {
Sandwich
Drink
}
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
rows, _ := conn.Query(ctx, `select 'Baguette' as bread, 'Lettuce' as salad, drink_ml from generate_series(0, 9) drink_ml`)
slice, err := pgx.CollectRows(rows, pgx.RowToStructByPos[meal])
require.NoError(t, err)
assert.Len(t, slice, 10)
for i := range slice {
assert.Equal(t, "Baguette", slice[i].Sandwich.Bread)
assert.Equal(t, "Lettuce", slice[i].Sandwich.Salad)
assert.EqualValues(t, i, slice[i].Drink.Ml)
}
})
}
// Pointer to struct is not supported. But check that we don't panic.
func TestRowToStructByPosEmbeddedPointerToStruct(t *testing.T) {
type Name struct {