From e66ad1bcecedaa3032a16f0f71b1878502f9cb8b Mon Sep 17 00:00:00 2001 From: Jack Christensen Date: Fri, 23 Dec 2022 13:44:09 -0600 Subject: [PATCH] Fix encode to json ignoring driver.Valuer https://github.com/jackc/pgx/issues/1430 --- extended_query_builder.go | 14 ++++++++++++++ pgtype/json.go | 6 ++++++ pgtype/json_test.go | 3 +++ 3 files changed, 23 insertions(+) diff --git a/extended_query_builder.go b/extended_query_builder.go index b0c0e02b..0bbdfbb5 100644 --- a/extended_query_builder.go +++ b/extended_query_builder.go @@ -1,6 +1,7 @@ package pgx import ( + "database/sql/driver" "fmt" "github.com/jackc/pgx/v5/internal/anynil" @@ -181,6 +182,19 @@ func (eqb *ExtendedQueryBuilder) appendParamsForQueryExecModeExec(m *pgtype.Map, } } } + if !ok { + var dv driver.Valuer + if dv, ok = arg.(driver.Valuer); ok { + v, err := dv.Value() + if err != nil { + return err + } + dt, ok = m.TypeForValue(v) + if ok { + arg = v + } + } + } if !ok { var str fmt.Stringer if str, ok = arg.(fmt.Stringer); ok { diff --git a/pgtype/json.go b/pgtype/json.go index 63338bac..9fef2fb6 100644 --- a/pgtype/json.go +++ b/pgtype/json.go @@ -24,6 +24,12 @@ func (c JSONCodec) PlanEncode(m *Map, oid uint32, format int16, value any) Encod return encodePlanJSONCodecEitherFormatString{} case []byte: return encodePlanJSONCodecEitherFormatByteSlice{} + + // Cannot rely on driver.Valuer being handled later because anything can be marshalled. + // + // https://github.com/jackc/pgx/issues/1430 + case driver.Valuer: + return &encodePlanDriverValuer{m: m, oid: oid, formatCode: format} } // Because anything can be marshalled the normal wrapping in Map.PlanScan doesn't get a chance to run. So try the diff --git a/pgtype/json_test.go b/pgtype/json_test.go index 00dbbc5c..8ef6fb31 100644 --- a/pgtype/json_test.go +++ b/pgtype/json_test.go @@ -52,6 +52,9 @@ func TestJSONCodec(t *testing.T) { // Test sql.Scanner. (https://github.com/jackc/pgx/issues/1418) {"42", new(sql.NullInt64), isExpectedEq(sql.NullInt64{Int64: 42, Valid: true})}, + + // Test driver.Valuer. (https://github.com/jackc/pgx/issues/1430) + {sql.NullInt64{Int64: 42, Valid: true}, new(sql.NullInt64), isExpectedEq(sql.NullInt64{Int64: 42, Valid: true})}, }) pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, pgxtest.KnownOIDQueryExecModes, "json", []pgxtest.ValueRoundTripTest{