diff --git a/pgtype/hstore.go b/pgtype/hstore.go index ca0c3f6f7..e4695819a 100644 --- a/pgtype/hstore.go +++ b/pgtype/hstore.go @@ -42,7 +42,7 @@ func (h *Hstore) Scan(src any) error { switch src := src.(type) { case string: - return scanPlanTextAnyToHstoreScanner{}.Scan([]byte(src), h) + return scanPlanTextAnyToHstoreScanner{}.scanString(src, h) } return fmt.Errorf("cannot scan %T", src) @@ -236,14 +236,18 @@ func (scanPlanBinaryHstoreToHstoreScanner) Scan(src []byte, dst any) error { type scanPlanTextAnyToHstoreScanner struct{} -func (scanPlanTextAnyToHstoreScanner) Scan(src []byte, dst any) error { +func (s scanPlanTextAnyToHstoreScanner) Scan(src []byte, dst any) error { scanner := (dst).(HstoreScanner) if src == nil { return scanner.ScanHstore(Hstore(nil)) } + return s.scanString(string(src), scanner) +} - keys, values, err := parseHstore(string(src)) +// scanString does not return nil hstore values because string cannot be nil. +func (scanPlanTextAnyToHstoreScanner) scanString(src string, scanner HstoreScanner) error { + keys, values, err := parseHstore(src) if err != nil { return err } diff --git a/pgtype/hstore_test.go b/pgtype/hstore_test.go index e2b6bb4ef..4f93a94d9 100644 --- a/pgtype/hstore_test.go +++ b/pgtype/hstore_test.go @@ -288,3 +288,22 @@ func BenchmarkHstoreEncode(b *testing.B) { }) } } + +func BenchmarkHstoreScan(b *testing.B) { + strs := []string{ + "", + `"a"=>"b"`, + `"a"=>"100", "b"=>"200", "c"=>"300", "d"=>"400", "e"=>"500"`, + } + + var h pgtype.Hstore + b.ReportAllocs() + for i := 0; i < b.N; i++ { + for _, str := range strs { + err := h.Scan(str) + if err != nil { + b.Fatal(err) + } + } + } +}