Skip to content

Commit

Permalink
Fix hstore NULL versus empty
Browse files Browse the repository at this point in the history
When running queries with the hstore type registered, and with simple
mode queries, the scan implementation does not correctly distinguish
between NULL and empty. Fix the implementation and add a test to
verify this.
  • Loading branch information
evanj authored and jackc committed May 13, 2023
1 parent f59e8bf commit 2a86501
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 2 deletions.
4 changes: 2 additions & 2 deletions pgtype/hstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ func (scanPlanBinaryHstoreToHstoreScanner) Scan(src []byte, dst any) error {
scanner := (dst).(HstoreScanner)

if src == nil {
return scanner.ScanHstore(Hstore{})
return scanner.ScanHstore(Hstore(nil))
}

rp := 0
Expand Down Expand Up @@ -234,7 +234,7 @@ func (scanPlanTextAnyToHstoreScanner) Scan(src []byte, dst any) error {
scanner := (dst).(HstoreScanner)

if src == nil {
return scanner.ScanHstore(Hstore{})
return scanner.ScanHstore(Hstore(nil))
}

keys, values, err := parseHstore(string(src))
Expand Down
23 changes: 23 additions & 0 deletions pgtype/hstore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package pgtype_test

import (
"context"
"reflect"
"testing"

"github.com/jackc/pgx/v5"
Expand Down Expand Up @@ -179,4 +180,26 @@ func TestHstoreCodec(t *testing.T) {
}

pgxtest.RunValueRoundTripTests(context.Background(), t, ctr, pgxtest.KnownOIDQueryExecModes, "hstore", tests)

// scan empty and NULL: should be different
pgxtest.RunWithQueryExecModes(context.Background(), t, ctr, pgxtest.AllQueryExecModes, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
h := pgtype.Hstore{"should_be_erased": nil}
err := conn.QueryRow(ctx, `select cast(null as hstore)`).Scan(&h)
if err != nil {
t.Fatal(err)
}
expectedNil := pgtype.Hstore(nil)
if !reflect.DeepEqual(h, expectedNil) {
t.Errorf("plain conn.Scan failed expectedNil=%#v actual=%#v", expectedNil, h)
}

err = conn.QueryRow(ctx, `select cast('' as hstore)`).Scan(&h)
if err != nil {
t.Fatal(err)
}
expectedEmpty := pgtype.Hstore{}
if !reflect.DeepEqual(h, expectedEmpty) {
t.Errorf("plain conn.Scan failed expectedEmpty=%#v actual=%#v", expectedEmpty, h)
}
})
}

0 comments on commit 2a86501

Please sign in to comment.