From 4c8c918c4394d43b3c94de3f6b37b5b776fc98e4 Mon Sep 17 00:00:00 2001 From: YangKeao Date: Thu, 25 Aug 2022 05:20:22 -0400 Subject: [PATCH] executor: add conversion to opaque value for json_objectagg and json_arrayagg (#37337) close pingcap/tidb#25053 --- executor/aggfuncs/func_json_arrayagg.go | 5 +- executor/aggfuncs/func_json_objectagg.go | 64 +++++++++++++------ executor/aggfuncs/func_json_objectagg_test.go | 62 +++++++++++++----- expression/aggregation/base_func.go | 12 +++- 4 files changed, 104 insertions(+), 39 deletions(-) diff --git a/executor/aggfuncs/func_json_arrayagg.go b/executor/aggfuncs/func_json_arrayagg.go index 9d7bbfdce4..5cd0f15d5b 100644 --- a/executor/aggfuncs/func_json_arrayagg.go +++ b/executor/aggfuncs/func_json_arrayagg.go @@ -85,9 +85,10 @@ func (e *jsonArrayagg) UpdatePartialResult(sctx sessionctx.Context, rowsInGroup return 0, errors.Trace(err) } - realItem := item.Clone().GetValue() + realItem := getRealJSONValue(item, e.args[0].GetType()) + switch x := realItem.(type) { - case nil, bool, int64, uint64, float64, string, json.BinaryJSON, *types.MyDecimal, []uint8, types.Time, types.Duration: + case nil, bool, int64, uint64, float64, string, json.BinaryJSON, json.Opaque, *types.MyDecimal, []uint8, types.Time, types.Duration: p.entries = append(p.entries, realItem) memDelta += getValMemDelta(realItem) default: diff --git a/executor/aggfuncs/func_json_objectagg.go b/executor/aggfuncs/func_json_objectagg.go index 099e4ca3a1..c324f6dd8e 100644 --- a/executor/aggfuncs/func_json_objectagg.go +++ b/executor/aggfuncs/func_json_objectagg.go @@ -15,15 +15,17 @@ package aggfuncs import ( + "strings" "unsafe" "github.com/pingcap/errors" + "github.com/pingcap/tidb/parser/charset" + "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/types/json" "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/hack" - "github.com/pingcap/tidb/util/stringutil" ) const ( @@ -85,38 +87,33 @@ func (e *jsonObjectAgg) AppendFinalResult2Chunk(sctx sessionctx.Context, pr Part func (e *jsonObjectAgg) UpdatePartialResult(sctx sessionctx.Context, rowsInGroup []chunk.Row, pr PartialResult) (memDelta int64, err error) { p := (*partialResult4JsonObjectAgg)(pr) for _, row := range rowsInGroup { - key, err := e.args[0].Eval(row) + key, keyIsNull, err := e.args[0].EvalString(sctx, row) if err != nil { return 0, errors.Trace(err) } + key = strings.Clone(key) + + if keyIsNull { + return 0, json.ErrJSONDocumentNULLKey + } value, err := e.args[1].Eval(row) if err != nil { return 0, errors.Trace(err) } - if key.IsNull() { - return 0, json.ErrJSONDocumentNULLKey - } - - // the result json's key is string, so it needs to convert the first arg to string - keyString, err := key.ToString() - if err != nil { - return 0, errors.Trace(err) - } - keyString = stringutil.Copy(keyString) - - realVal := value.Clone().GetValue() + realVal := getRealJSONValue(value, e.args[1].GetType()) switch x := realVal.(type) { - case nil, bool, int64, uint64, float64, string, json.BinaryJSON, *types.MyDecimal, []uint8, types.Time, types.Duration: - if _, ok := p.entries[keyString]; !ok { - memDelta += int64(len(keyString)) + getValMemDelta(realVal) + case nil, bool, int64, uint64, float64, string, json.BinaryJSON, json.Opaque, *types.MyDecimal, types.Time, types.Duration: + if _, ok := p.entries[key]; !ok { + memDelta += int64(len(key)) + getValMemDelta(realVal) if len(p.entries)+1 > (1<