From b10eb89fe4631ac56de742168ffb08be559e2ddd Mon Sep 17 00:00:00 2001 From: Jack Christensen Date: Thu, 20 Jan 2022 20:22:53 -0600 Subject: [PATCH] Use wrapper to treat fmt.String as pgtype.TextValuer --- pgtype/builtin_wrappers.go | 8 ++++++++ pgtype/enum_codec.go | 2 -- pgtype/pgtype.go | 12 ++++++++++++ pgtype/text.go | 2 -- pgtype/text_test.go | 7 +++++++ 5 files changed, 27 insertions(+), 4 deletions(-) diff --git a/pgtype/builtin_wrappers.go b/pgtype/builtin_wrappers.go index 873afe53..5b6a032a 100644 --- a/pgtype/builtin_wrappers.go +++ b/pgtype/builtin_wrappers.go @@ -491,3 +491,11 @@ func (w mapStringToStringWrapper) HstoreValue() (Hstore, error) { } return hstore, nil } + +type fmtStringerWrapper struct { + s fmt.Stringer +} + +func (w fmtStringerWrapper) TextValue() (Text, error) { + return Text{String: w.s.String(), Valid: true}, nil +} diff --git a/pgtype/enum_codec.go b/pgtype/enum_codec.go index 9a37f1dd..d405245f 100644 --- a/pgtype/enum_codec.go +++ b/pgtype/enum_codec.go @@ -30,8 +30,6 @@ func (EnumCodec) PlanEncode(ci *ConnInfo, oid uint32, format int16, value interf return encodePlanTextCodecByteSlice{} case rune: return encodePlanTextCodecRune{} - case fmt.Stringer: - return encodePlanTextCodecStringer{} case TextValuer: return encodePlanTextCodecTextValuer{} } diff --git a/pgtype/pgtype.go b/pgtype/pgtype.go index 7c1b6c07..bcbb9f97 100644 --- a/pgtype/pgtype.go +++ b/pgtype/pgtype.go @@ -1421,6 +1421,8 @@ func tryWrapBuiltinTypeEncodePlan(value interface{}) (plan WrappedEncodePlanNext return &wrapMapStringToPointerStringEncodePlan{}, mapStringToPointerStringWrapper(value), true case map[string]string: return &wrapMapStringToStringEncodePlan{}, mapStringToStringWrapper(value), true + case fmt.Stringer: + return &wrapFmtStringerEncodePlan{}, fmtStringerWrapper{value}, true } return nil, nil, false @@ -1616,6 +1618,16 @@ func (plan *wrapMapStringToStringEncodePlan) Encode(value interface{}, buf []byt return plan.next.Encode(mapStringToStringWrapper(value.(map[string]string)), buf) } +type wrapFmtStringerEncodePlan struct { + next EncodePlan +} + +func (plan *wrapFmtStringerEncodePlan) SetNext(next EncodePlan) { plan.next = next } + +func (plan *wrapFmtStringerEncodePlan) Encode(value interface{}, buf []byte) (newBuf []byte, err error) { + return plan.next.Encode(fmtStringerWrapper{value.(fmt.Stringer)}, buf) +} + // Encode appends the encoded bytes of value to buf. If value is the SQL value NULL then append nothing and return // (nil, nil). The caller of Encode is responsible for writing the correct NULL value or the length of the data // written. diff --git a/pgtype/text.go b/pgtype/text.go index 3cb1cfa3..3c73cc15 100644 --- a/pgtype/text.go +++ b/pgtype/text.go @@ -100,8 +100,6 @@ func (TextCodec) PlanEncode(ci *ConnInfo, oid uint32, format int16, value interf return encodePlanTextCodecByteSlice{} case rune: return encodePlanTextCodecRune{} - case fmt.Stringer: - return encodePlanTextCodecStringer{} case TextValuer: return encodePlanTextCodecTextValuer{} } diff --git a/pgtype/text_test.go b/pgtype/text_test.go index 27b01c15..f45978a7 100644 --- a/pgtype/text_test.go +++ b/pgtype/text_test.go @@ -9,6 +9,12 @@ import ( "github.com/stretchr/testify/require" ) +type someFmtStringer struct{} + +func (someFmtStringer) String() string { + return "some fmt.Stringer" +} + func TestTextCodec(t *testing.T) { for _, pgTypeName := range []string{"text", "varchar"} { testPgxCodec(t, pgTypeName, []PgxTranscodeTestCase{ @@ -24,6 +30,7 @@ func TestTextCodec(t *testing.T) { }, {nil, new(pgtype.Text), isExpectedEq(pgtype.Text{})}, {"foo", new(string), isExpectedEq("foo")}, + {someFmtStringer{}, new(string), isExpectedEq("some fmt.Stringer")}, {rune('R'), new(rune), isExpectedEq(rune('R'))}, }) }