From 25d1c8376994a29e053cc773eeabe9240213b7ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20van=20Eeden?= Date: Thu, 13 Jun 2024 03:04:30 +0200 Subject: [PATCH] expression: Fix JSON quote (#53961) close pingcap/tidb#37294 --- go.mod | 2 +- pkg/expression/builtin_json.go | 10 ++++++++-- pkg/expression/builtin_json_vec.go | 10 ++++++++-- tests/integrationtest/r/expression/json.result | 12 ++++++++++++ tests/integrationtest/t/expression/json.test | 6 ++++++ 5 files changed, 35 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index dec96d2522a24..95b1d8a278fc7 100644 --- a/go.mod +++ b/go.mod @@ -309,7 +309,7 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291 // indirect google.golang.org/protobuf v1.34.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect + gopkg.in/natefinch/lumberjack.v2 v2.2.1 gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apimachinery v0.28.6 // indirect k8s.io/klog/v2 v2.120.1 // indirect diff --git a/pkg/expression/builtin_json.go b/pkg/expression/builtin_json.go index 85a21f5f6c757..727aeb85440f9 100644 --- a/pkg/expression/builtin_json.go +++ b/pkg/expression/builtin_json.go @@ -18,7 +18,6 @@ import ( "bytes" "context" goJSON "encoding/json" - "strconv" "strings" "github.com/pingcap/errors" @@ -1414,7 +1413,14 @@ func (b *builtinJSONQuoteSig) evalString(ctx EvalContext, row chunk.Row) (string if isNull || err != nil { return "", isNull, err } - return strconv.Quote(str), false, nil + buffer := &bytes.Buffer{} + encoder := goJSON.NewEncoder(buffer) + encoder.SetEscapeHTML(false) + err = encoder.Encode(str) + if err != nil { + return "", isNull, err + } + return string(bytes.TrimSuffix(buffer.Bytes(), []byte("\n"))), false, nil } type jsonSearchFunctionClass struct { diff --git a/pkg/expression/builtin_json_vec.go b/pkg/expression/builtin_json_vec.go index b174bdc2df2e3..eda8d66bceae9 100644 --- a/pkg/expression/builtin_json_vec.go +++ b/pkg/expression/builtin_json_vec.go @@ -17,7 +17,6 @@ package expression import ( "bytes" goJSON "encoding/json" - "strconv" "strings" "github.com/pingcap/errors" @@ -477,7 +476,14 @@ func (b *builtinJSONQuoteSig) vecEvalString(ctx EvalContext, input *chunk.Chunk, result.AppendNull() continue } - result.AppendString(strconv.Quote(buf.GetString(i))) + buffer := &bytes.Buffer{} + encoder := goJSON.NewEncoder(buffer) + encoder.SetEscapeHTML(false) + err = encoder.Encode(buf.GetString(i)) + if err != nil { + return err + } + result.AppendString(string(bytes.TrimSuffix(buffer.Bytes(), []byte("\n")))) } return nil } diff --git a/tests/integrationtest/r/expression/json.result b/tests/integrationtest/r/expression/json.result index 07f27454deea1..a9da5cfd2438b 100644 --- a/tests/integrationtest/r/expression/json.result +++ b/tests/integrationtest/r/expression/json.result @@ -703,3 +703,15 @@ JSON_SCHEMA_VALID('{"properties": {"a": {"pattern": "^a"}}}', '{"a": "abc"}') SELECT JSON_SCHEMA_VALID('{"properties": {"a": {"pattern": "^a"}}}', '{"a": "cba"}'); JSON_SCHEMA_VALID('{"properties": {"a": {"pattern": "^a"}}}', '{"a": "cba"}') 0 +SELECT JSON_QUOTE(""); +JSON_QUOTE("") +"" +SELECT JSON_QUOTE("&"); +JSON_QUOTE("&") +"&" +SELECT JSON_QUOTE(CONVERT(0x10 USING utf8mb4)); +JSON_QUOTE(CONVERT(0x10 USING utf8mb4)) +"\u0010" +SELECT JSON_QUOTE("O'Neil"); +JSON_QUOTE("O'Neil") +"O'Neil" diff --git a/tests/integrationtest/t/expression/json.test b/tests/integrationtest/t/expression/json.test index ed0a96533b3c6..055142a364202 100644 --- a/tests/integrationtest/t/expression/json.test +++ b/tests/integrationtest/t/expression/json.test @@ -417,3 +417,9 @@ SELECT JSON_SCHEMA_VALID('{"properties": {"a": {"type": "number", "minimum": 5}} SELECT JSON_SCHEMA_VALID('{"properties": {"a": {"type": "number", "minimum": 5}}}', '{"a": 6}'); SELECT JSON_SCHEMA_VALID('{"properties": {"a": {"pattern": "^a"}}}', '{"a": "abc"}'); SELECT JSON_SCHEMA_VALID('{"properties": {"a": {"pattern": "^a"}}}', '{"a": "cba"}'); + +# TestJSONQuote +SELECT JSON_QUOTE(""); +SELECT JSON_QUOTE("&"); +SELECT JSON_QUOTE(CONVERT(0x10 USING utf8mb4)); +SELECT JSON_QUOTE("O'Neil");