Skip to content

Commit

Permalink
pgtype.Hstore: Fix quoting of whitespace; Add test
Browse files Browse the repository at this point in the history
Before this change, the Hstore text protocol did not quote keys or
values containing non-space whitespace ("\r\n\v\t"). This causes
inserts with these values to fail with errors like:

    ERROR: Syntax error near "r" at position 17 (SQLSTATE XX000)

The previous version also quoted curly braces ("{}"), but they don't
seem to require quoting.

It is possible that it would be easier to just always quote the
values, which is what Postgres does when encoding its text protocol,
but this is a smaller change.
  • Loading branch information
evanj authored and jackc committed May 16, 2023
1 parent 8ceef73 commit eab316e
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 1 deletion.
8 changes: 7 additions & 1 deletion pgtype/hstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,9 +272,15 @@ func (c HstoreCodec) DecodeValue(m *Map, oid uint32, format int16, src []byte) (
}

func quoteHstoreElementIfNeeded(src string) string {
if src == "" || (len(src) == 4 && strings.ToLower(src) == "null") || strings.ContainsAny(src, ` {},"\=>`) {
// Double-quote keys and values that include whitespace, commas, =s or >s. To include a double
// quote or a backslash in a key or value, escape it with a backslash.
// From: https://www.postgresql.org/docs/current/hstore.html
// whitespace appears to be defined as the isspace() C function: \t\n\v\f\r\n and space
const quoteRequiredChars = `,"\=> ` + "\t\n\v\f\r"
if src == "" || (len(src) == 4 && strings.ToLower(src) == "null") || strings.ContainsAny(src, quoteRequiredChars) {
return quoteArrayElement(src)
}

return src
}

Expand Down
6 changes: 6 additions & 0 deletions pgtype/hstore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ func TestHstoreCodec(t *testing.T) {
`=>`,
` `,
`\ / / \\ => " ' " '`,
"line1\nline2",
"tab\tafter",
"vtab\vafter",
"form\\ffeed",
"carriage\rreturn",
"curly{}braces",
}
for _, s := range specialStrings {
// Special key values
Expand Down

0 comments on commit eab316e

Please sign in to comment.