Use wrapper to treat fmt.String as pgtype.TextValuer

query-exec-mode
Jack Christensen 2022-01-20 20:22:53 -06:00
parent 06f4e47750
commit b10eb89fe4
5 changed files with 27 additions and 4 deletions

View File

@ -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
}

View File

@ -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{}
}

View File

@ -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.

View File

@ -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{}
}

View File

@ -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'))},
})
}