Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XMLCodec: fix DecodeValue to return a []byte #2228

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion pgtype/pgtype_default.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,25 @@ func initDefaultMap() {
defaultMap.RegisterType(&Type{Name: "varchar", OID: VarcharOID, Codec: TextCodec{}})
defaultMap.RegisterType(&Type{Name: "xid", OID: XIDOID, Codec: Uint32Codec{}})
defaultMap.RegisterType(&Type{Name: "xid8", OID: XID8OID, Codec: Uint64Codec{}})
defaultMap.RegisterType(&Type{Name: "xml", OID: XMLOID, Codec: &XMLCodec{Marshal: xml.Marshal, Unmarshal: xml.Unmarshal}})
defaultMap.RegisterType(&Type{Name: "xml", OID: XMLOID, Codec: &XMLCodec{
Marshal: xml.Marshal,
// xml.Unmarshal does not support unmarshalling into *any. However, XMLCodec.DecodeValue calls Unmarshal with a
// *any. Wrap xml.Marshal with a function that copies the data into a new byte slice in this case. Not implementing
// directly in XMLCodec.DecodeValue to allow for the unlikely possibility that someone uses an alternative XML
// unmarshaler that does support unmarshalling into *any.
//
// https://github.com/jackc/pgx/issues/2227
// https://github.com/jackc/pgx/pull/2228
Unmarshal: func(data []byte, v any) error {
if v, ok := v.(*any); ok {
dstBuf := make([]byte, len(data))
copy(dstBuf, data)
*v = dstBuf
return nil
}
return xml.Unmarshal(data, v)
},
}})

// Range types
defaultMap.RegisterType(&Type{Name: "daterange", OID: DaterangeOID, Codec: &RangeCodec{ElementType: defaultMap.oidToType[DateOID]}})
Expand Down
29 changes: 29 additions & 0 deletions pgtype/xml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,32 @@ func TestXMLCodecPointerToPointerToString(t *testing.T) {
require.Nil(t, s)
})
}

func TestXMLCodecDecodeValue(t *testing.T) {
skipCockroachDB(t, "CockroachDB does not support XML.")
defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, _ testing.TB, conn *pgx.Conn) {
for _, tt := range []struct {
sql string
expected any
}{
{
sql: `select '<foo>bar</foo>'::xml`,
expected: []byte("<foo>bar</foo>"),
},
} {
t.Run(tt.sql, func(t *testing.T) {
rows, err := conn.Query(ctx, tt.sql)
require.NoError(t, err)

for rows.Next() {
values, err := rows.Values()
require.NoError(t, err)
require.Len(t, values, 1)
require.Equal(t, tt.expected, values[0])
}

require.NoError(t, rows.Err())
})
}
})
}