From 2e73d1e8eeccb2882ca43d09345c6d0c1048b406 Mon Sep 17 00:00:00 2001 From: Jack Christensen <jack@jackchristensen.com> Date: Mon, 22 Aug 2022 20:56:36 -0500 Subject: [PATCH] Improve error message when failing to scan a NULL::json --- pgtype/json.go | 3 +++ pgtype/json_test.go | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/pgtype/json.go b/pgtype/json.go index de2f08df..51f2509f 100644 --- a/pgtype/json.go +++ b/pgtype/json.go @@ -3,6 +3,7 @@ package pgtype import ( "database/sql/driver" "encoding/json" + "fmt" "reflect" ) @@ -129,6 +130,8 @@ func (scanPlanJSONToJSONUnmarshal) Scan(src []byte, dst any) error { return nil } } + + return fmt.Errorf("cannot scan null into %T", dst) } return json.Unmarshal(src, dst) diff --git a/pgtype/json_test.go b/pgtype/json_test.go index c349fa24..04964e8c 100644 --- a/pgtype/json_test.go +++ b/pgtype/json_test.go @@ -4,7 +4,9 @@ import ( "context" "testing" + pgx "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxtest" + "github.com/stretchr/testify/require" ) func isExpectedEqMap(a any) func(any) bool { @@ -58,3 +60,36 @@ func TestJSONCodec(t *testing.T) { {jsonStruct{Name: "Adam", Age: 10}, new(jsonStruct), isExpectedEq(jsonStruct{Name: "Adam", Age: 10})}, }) } + +// https://github.com/jackc/pgx/issues/1273#issuecomment-1221414648 +func TestJSONCodecUnmarshalSQLNull(t *testing.T) { + defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { + // Slices are nilified + slice := []string{"foo", "bar", "baz"} + err := conn.QueryRow(ctx, "select null::json").Scan(&slice) + require.NoError(t, err) + require.Nil(t, slice) + + // Maps are nilified + m := map[string]any{"foo": "bar"} + err = conn.QueryRow(ctx, "select null::json").Scan(&m) + require.NoError(t, err) + require.Nil(t, m) + + // Pointer to pointer are nilified + n := 42 + p := &n + err = conn.QueryRow(ctx, "select null::json").Scan(&p) + require.NoError(t, err) + require.Nil(t, p) + + // A string cannot scan a NULL. + str := "foobar" + err = conn.QueryRow(ctx, "select null::json").Scan(&str) + require.EqualError(t, err, "can't scan into dest[0]: cannot scan null into *string") + + // A non-string cannot scan a NULL. + err = conn.QueryRow(ctx, "select null::json").Scan(&n) + require.EqualError(t, err, "can't scan into dest[0]: cannot scan null into *int") + }) +}