diff --git a/pkg/expression/builtin_json.go b/pkg/expression/builtin_json.go index 86961ee19e179..32f21d788998b 100644 --- a/pkg/expression/builtin_json.go +++ b/pkg/expression/builtin_json.go @@ -1770,10 +1770,6 @@ func (b *builtinJSONLengthSig) evalInt(ctx EvalContext, row chunk.Row) (res int6 return res, isNull, err } - if obj.TypeCode != types.JSONTypeCodeObject && obj.TypeCode != types.JSONTypeCodeArray { - return 1, false, nil - } - if len(b.args) == 2 { path, isNull, err := b.args[1].EvalString(ctx, row) if isNull || err != nil { @@ -1793,9 +1789,10 @@ func (b *builtinJSONLengthSig) evalInt(ctx EvalContext, row chunk.Row) (res int6 if !exists { return res, true, nil } - if obj.TypeCode != types.JSONTypeCodeObject && obj.TypeCode != types.JSONTypeCodeArray { - return 1, false, nil - } + } + + if obj.TypeCode != types.JSONTypeCodeObject && obj.TypeCode != types.JSONTypeCodeArray { + return 1, false, nil } return int64(obj.GetElemCount()), false, nil } diff --git a/pkg/expression/builtin_json_test.go b/pkg/expression/builtin_json_test.go index 95ce9414a7afa..60561566730f7 100644 --- a/pkg/expression/builtin_json_test.go +++ b/pkg/expression/builtin_json_test.go @@ -647,8 +647,8 @@ func TestJSONLength(t *testing.T) { {[]any{`-1`}, 1, true}, {[]any{`1.1`}, 1, true}, {[]any{`"1"`}, 1, true}, - {[]any{`"1"`, "$.a"}, 1, true}, - {[]any{`null`, "$.a"}, 1, true}, + {[]any{`"1"`, "$.a"}, nil, true}, + {[]any{`null`, "$.a"}, nil, true}, // Tests nil arguments {[]any{nil}, nil, true}, {[]any{nil, "a"}, nil, true}, diff --git a/pkg/expression/builtin_json_vec.go b/pkg/expression/builtin_json_vec.go index 84dab07ef6e29..dbb4d443d26b4 100644 --- a/pkg/expression/builtin_json_vec.go +++ b/pkg/expression/builtin_json_vec.go @@ -814,6 +814,9 @@ func (b *builtinJSONLengthSig) vectorized() bool { func (b *builtinJSONLengthSig) vecEvalInt(ctx EvalContext, input *chunk.Chunk, result *chunk.Column) error { nr := input.NumRows() + result.ResizeInt64(nr, false) + resI64s := result.Int64s() + jsonBuf, err := b.bufAllocator.get() if err != nil { return err @@ -822,8 +825,7 @@ func (b *builtinJSONLengthSig) vecEvalInt(ctx EvalContext, input *chunk.Chunk, r if err := b.args[0].VecEvalJSON(ctx, input, jsonBuf); err != nil { return err } - result.ResizeInt64(nr, false) - resI64s := result.Int64s() + result.MergeNulls(jsonBuf) if len(b.args) == 2 { pathBuf, err := b.bufAllocator.get() @@ -834,23 +836,12 @@ func (b *builtinJSONLengthSig) vecEvalInt(ctx EvalContext, input *chunk.Chunk, r if err := b.args[1].VecEvalString(ctx, input, pathBuf); err != nil { return err } + result.MergeNulls(pathBuf) - result.MergeNulls(jsonBuf) for i := 0; i < nr; i++ { if result.IsNull(i) { continue } - jsonItem := jsonBuf.GetJSON(i) - - if jsonItem.TypeCode != types.JSONTypeCodeObject && jsonItem.TypeCode != types.JSONTypeCodeArray { - resI64s[i] = 1 - continue - } - - if pathBuf.IsNull(i) { - result.SetNull(i, true) - continue - } pathExpr, err := types.ParseJSONPathExpr(pathBuf.GetString(i)) if err != nil { @@ -860,6 +851,7 @@ func (b *builtinJSONLengthSig) vecEvalInt(ctx EvalContext, input *chunk.Chunk, r return types.ErrInvalidJSONPathMultipleSelection } + jsonItem := jsonBuf.GetJSON(i) obj, exists := jsonItem.Extract([]types.JSONPathExpression{pathExpr}) if !exists { result.SetNull(i, true) @@ -872,7 +864,6 @@ func (b *builtinJSONLengthSig) vecEvalInt(ctx EvalContext, input *chunk.Chunk, r resI64s[i] = int64(obj.GetElemCount()) } } else { - result.MergeNulls(jsonBuf) for i := 0; i < nr; i++ { if result.IsNull(i) { continue diff --git a/tests/integrationtest/r/expression/json.result b/tests/integrationtest/r/expression/json.result index 243a8388b0ab9..a2092ffe22376 100644 --- a/tests/integrationtest/r/expression/json.result +++ b/tests/integrationtest/r/expression/json.result @@ -429,9 +429,20 @@ json_length('{}'), json_length('[]'), json_length('{"a": 1}'), json_length('{"a": 1, "b": 2}'), -json_length('[1, 2, 3]'); -json_length('1') json_length('{}') json_length('[]') json_length('{"a": 1}') json_length('{"a": 1, "b": 2}') json_length('[1, 2, 3]') -1 0 0 1 2 3 +json_length('[1, 2, 3]'), +json_length('{}', '$'), +json_length('1', '$'), +json_length(null, '$'), +json_length(null, 'fdfd'), +json_length('{}', null), +json_length('1', '$.a'), +json_length('{}', '$.a'); +json_length('1') json_length('{}') json_length('[]') json_length('{"a": 1}') json_length('{"a": 1, "b": 2}') json_length('[1, 2, 3]') json_length('{}', '$') json_length('1', '$') json_length(null, '$') json_length(null, 'fdfd') json_length('{}', null) json_length('1', '$.a') json_length('{}', '$.a') +1 0 0 1 2 3 0 1 NULL NULL NULL NULL NULL +select json_length('{}', 'fsdfds'); +Error 3143 (42000): Invalid JSON path expression. The error is around character position 1. +select json_length('1', 'fsdfds'); +Error 3143 (42000): Invalid JSON path expression. The error is around character position 1. select json_array(922337203685477580) = json_array(922337203685477581); json_array(922337203685477580) = json_array(922337203685477581) 0 diff --git a/tests/integrationtest/t/expression/json.test b/tests/integrationtest/t/expression/json.test index 6d6a0f6b250e0..005b3754d2553 100644 --- a/tests/integrationtest/t/expression/json.test +++ b/tests/integrationtest/t/expression/json.test @@ -248,7 +248,18 @@ select json_length('[]'), json_length('{"a": 1}'), json_length('{"a": 1, "b": 2}'), - json_length('[1, 2, 3]'); + json_length('[1, 2, 3]'), + json_length('{}', '$'), + json_length('1', '$'), + json_length(null, '$'), + json_length(null, 'fdfd'), + json_length('{}', null), + json_length('1', '$.a'), + json_length('{}', '$.a'); +-- error 3143 +select json_length('{}', 'fsdfds'); +-- error 3143 +select json_length('1', 'fsdfds'); # issue 16267 select json_array(922337203685477580) = json_array(922337203685477581);