Skip to content
This repository has been archived by the owner on Feb 15, 2023. It is now read-only.

Commit

Permalink
go fields: explicity support non-pointer marshalers
Browse files Browse the repository at this point in the history
  • Loading branch information
berfarah committed Oct 9, 2018
1 parent 29e1b32 commit 0ff8421
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 12 deletions.
15 changes: 15 additions & 0 deletions internal/fields/sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ type Valuer struct {
value reflect.Value
}

var marshalerType = reflect.TypeOf((*marshaler)(nil)).Elem()

func nonPointerMarshal(d *Descriptor, val reflect.Value) (reflect.Value, bool) {
if !d.Ptr && reflect.PtrTo(d.Type).Implements(marshalerType) {
fmt.Printf("typ: %+v, intf %v, intftyp: %T\n", d, val.Interface(), val.Interface())
v := reflect.New(d.Type)
v.Elem().Set(val)
return v, true
}
return val, false
}

// Value satisfies the sql/driver.Valuer interface.
// The value should be one of the following:
// int64
Expand Down Expand Up @@ -62,6 +74,9 @@ func (f Valuer) Value() (driver.Value, error) {
// }
switch {
case f.Tags.Contains("binary"):
if v, ok := nonPointerMarshal(f.Descriptor, f.value); ok {
return v.Interface().(marshaler).Marshal()
}
if iface, ok := i.(marshaler); ok {
return iface.Marshal()
}
Expand Down
39 changes: 27 additions & 12 deletions internal/fields/sql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,7 @@ func TestField_ValidateSQLType(t *testing.T) {
{In: ifaceBinaryMarshal{}, Error: true},
{In: ifaceBinaryMarshal{}, Tags: []string{"binary"}, Error: false},
{In: &ifaceBinaryMarshal{}, Tags: []string{"binary"}, Error: false},
// Non-pointer proto does not work because the Marshal() method has a pointer receiver.
{In: proto.ExampleEvent{}, Tags: []string{"binary"}, Error: true},
{In: proto.ExampleEvent{}, Tags: []string{"binary"}, Error: false},
{In: &proto.ExampleEvent{}, Tags: []string{"binary"}, Error: false},
}

Expand All @@ -246,15 +245,31 @@ func TestField_ValidateSQLType(t *testing.T) {
}

func TestField_SupportsProtobuf(t *testing.T) {
event := &proto.ExampleEvent{Table: "users"}
descriptor := fields.New(reflect.TypeOf(event), []string{"binary"})
valuer := descriptor.Valuer(reflect.ValueOf(event))
b, err := valuer.Value()
assert.NoError(t, err)
t.Run("pointer", func(t *testing.T) {
event := &proto.ExampleEvent{Table: "users"}
descriptor := fields.New(reflect.TypeOf(event), []string{"binary"})
valuer := descriptor.Valuer(reflect.ValueOf(event))
b, err := valuer.Value()
assert.NoError(t, err)

got := reflect.New(reflect.TypeOf(event)).Elem()
scanner := descriptor.Scanner()
scanner.Target(got)
scanner.Scan(b)
assert.Equal(t, event, got.Interface())
})

t.Run("pointer", func(t *testing.T) {
event := proto.ExampleEvent{Table: "users"}
descriptor := fields.New(reflect.TypeOf(event), []string{"binary"})
valuer := descriptor.Valuer(reflect.ValueOf(event))
b, err := valuer.Value()
assert.NoError(t, err)

got := reflect.New(reflect.TypeOf(event)).Elem()
scanner := descriptor.Scanner()
scanner.Target(got)
scanner.Scan(b)
assert.Equal(t, event, got.Interface())
got := reflect.New(reflect.TypeOf(event))
scanner := descriptor.Scanner()
scanner.Target(got)
scanner.Scan(b)
assert.Equal(t, event, got.Elem().Interface())
})
}

0 comments on commit 0ff8421

Please sign in to comment.