From 6b4e33d9085bbd04a5e6852af7919a0ec44ec7c4 Mon Sep 17 00:00:00 2001 From: Justin Jaffray Date: Fri, 15 Feb 2019 14:19:26 -0500 Subject: [PATCH] sql: fix semantics of JSON ? operator on strings Fixes #35001. Release note (sql change): The semantics of the JSON '?' operator when applied to JSON strings has been changed to match Postgres. Now, a JSON string '?'s a string when the two are equal. --- pkg/sql/logictest/testdata/logic_test/json | 22 ++++++++++++++++++++++ pkg/util/json/encoded.go | 7 ++++++- pkg/util/json/json.go | 6 +++++- pkg/util/json/json_test.go | 2 +- 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/pkg/sql/logictest/testdata/logic_test/json b/pkg/sql/logictest/testdata/logic_test/json index 486d1c137c19..60bda282806d 100644 --- a/pkg/sql/logictest/testdata/logic_test/json +++ b/pkg/sql/logictest/testdata/logic_test/json @@ -133,6 +133,28 @@ SELECT bar FROM foo WHERE bar ? 'a' ---- {"a": "b"} +query BBBBBBB +VALUES ( + '"hello"'::JSONB ? 'hello', + '"hello"'::JSONB ? 'goodbye', + '"hello"'::JSONB ? 'ello', + '"hello"'::JSONB ? 'h', + 'true'::JSONB ? 'true', + '1'::JSONB ? '1', + 'null'::JSONB ? 'null' +) +---- +true false false false false false false + +query T +SELECT bar FROM foo WHERE bar ? 'hello' +---- +"hello" + +query T +SELECT bar FROM foo WHERE bar ? 'goodbye' +---- + query T SELECT bar FROM foo WHERE bar ?| ARRAY['a','b'] ---- diff --git a/pkg/util/json/encoded.go b/pkg/util/json/encoded.go index f58bd2f9a906..7c660f01758e 100644 --- a/pkg/util/json/encoded.go +++ b/pkg/util/json/encoded.go @@ -606,8 +606,13 @@ func (j *jsonEncoded) Exists(key string) (bool, error) { return true, nil } } + default: + s, err := j.decode() + if err != nil { + return false, err + } + return s.Exists(key) } - return false, nil } func (j *jsonEncoded) FetchValKeyOrIdx(key string) (JSON, error) { diff --git a/pkg/util/json/json.go b/pkg/util/json/json.go index c2ec7c7de2d6..7929a5d48494 100644 --- a/pkg/util/json/json.go +++ b/pkg/util/json/json.go @@ -1458,7 +1458,11 @@ func (jsonNull) Exists(string) (bool, error) { return false, nil } func (jsonTrue) Exists(string) (bool, error) { return false, nil } func (jsonFalse) Exists(string) (bool, error) { return false, nil } func (jsonNumber) Exists(string) (bool, error) { return false, nil } -func (jsonString) Exists(string) (bool, error) { return false, nil } + +func (j jsonString) Exists(s string) (bool, error) { + return string(j) == s, nil +} + func (j jsonArray) Exists(s string) (bool, error) { for i := 0; i < len(j); i++ { if elem, ok := j[i].(jsonString); ok && string(elem) == s { diff --git a/pkg/util/json/json_test.go b/pkg/util/json/json_test.go index b4e6dd6a5310..9acc7bbb3189 100644 --- a/pkg/util/json/json_test.go +++ b/pkg/util/json/json_test.go @@ -695,7 +695,7 @@ func TestJSONExists(t *testing.T) { {`baz`, false}, }, `["a"]`: {{``, false}, {`0`, false}, {`a`, true}}, - `"a"`: {{``, false}, {`0`, false}, {`a`, false}}, + `"a"`: {{``, false}, {`0`, false}, {`a`, true}}, `1`: {{``, false}, {`0`, false}, {`a`, false}}, `true`: {{``, false}, {`0`, false}, {`a`, false}}, }