Skip to content

Commit 3118aeb

Browse files
committed
fix the verify args of JSON_TYPE
Signed-off-by: Yang Keao <[email protected]>
1 parent cfa52d0 commit 3118aeb

File tree

3 files changed

+146
-63
lines changed

3 files changed

+146
-63
lines changed

pkg/expression/builtin_json.go

Lines changed: 61 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"bytes"
1919
"context"
2020
goJSON "encoding/json"
21+
"strconv"
2122
"strings"
2223

2324
"github.com/pingcap/errors"
@@ -108,7 +109,7 @@ func (b *builtinJSONTypeSig) Clone() builtinFunc {
108109
}
109110

110111
func (c *jsonTypeFunctionClass) getFunction(ctx BuildContext, args []Expression) (builtinFunc, error) {
111-
if err := c.verifyArgs(args); err != nil {
112+
if err := c.verifyArgs(ctx.GetEvalCtx(), args); err != nil {
112113
return nil, err
113114
}
114115
bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETJson)
@@ -125,6 +126,51 @@ func (c *jsonTypeFunctionClass) getFunction(ctx BuildContext, args []Expression)
125126
return sig, nil
126127
}
127128

129+
func (c *jsonTypeFunctionClass) verifyArgs(ctx EvalContext, args []Expression) error {
130+
if err := c.baseFunctionClass.verifyArgs(args); err != nil {
131+
return err
132+
}
133+
return verifyJSONArgsType(ctx, c.funcName, true, args, 0)
134+
}
135+
136+
// verifyJSONArgsType verifies that all args specified in `jsonArgsIndex` are JSON or non-binary string or NULL.
137+
// the `useJSONErr` specifies to use `ErrIncorrectType` or `ErrInvalidTypeForJSON`. If it's true, the error will be `ErrInvalidTypeForJSON`
138+
func verifyJSONArgsType(ctx EvalContext, funcName string, useJSONErr bool, args []Expression, jsonArgsIndex ...int) error {
139+
if jsonArgsIndex == nil {
140+
// if no index is specified, verify all args
141+
jsonArgsIndex = make([]int, len(args))
142+
for i := 0; i < len(args); i++ {
143+
jsonArgsIndex[i] = i
144+
}
145+
}
146+
for _, argIndex := range jsonArgsIndex {
147+
arg := args[argIndex]
148+
149+
typ := arg.GetType(ctx)
150+
if typ.GetType() == mysql.TypeNull {
151+
continue
152+
}
153+
154+
evalType := typ.EvalType()
155+
switch evalType {
156+
case types.ETString:
157+
cs := typ.GetCharset()
158+
if cs == charset.CharsetBin {
159+
return types.ErrInvalidJSONCharset.GenWithStackByArgs(cs)
160+
}
161+
continue
162+
case types.ETJson:
163+
continue
164+
default:
165+
if useJSONErr {
166+
return ErrInvalidTypeForJSON.GenWithStackByArgs(argIndex+1, funcName)
167+
}
168+
return ErrIncorrectType.GenWithStackByArgs(strconv.Itoa(argIndex+1), funcName)
169+
}
170+
}
171+
return nil
172+
}
173+
128174
func (b *builtinJSONTypeSig) evalString(ctx EvalContext, row chunk.Row) (val string, isNull bool, err error) {
129175
var j types.BinaryJSON
130176
j, isNull, err = b.args[0].EvalJSON(ctx, row)
@@ -155,10 +201,7 @@ func (c *jsonExtractFunctionClass) verifyArgs(ctx EvalContext, args []Expression
155201
if err := c.baseFunctionClass.verifyArgs(args); err != nil {
156202
return err
157203
}
158-
if evalType := args[0].GetType(ctx).EvalType(); evalType != types.ETString && evalType != types.ETJson {
159-
return ErrInvalidTypeForJSON.GenWithStackByArgs(1, "json_extract")
160-
}
161-
return nil
204+
return verifyJSONArgsType(ctx, c.funcName, true, args, 0)
162205
}
163206

164207
func (c *jsonExtractFunctionClass) getFunction(ctx BuildContext, args []Expression) (builtinFunc, error) {
@@ -225,10 +268,7 @@ func (c *jsonUnquoteFunctionClass) verifyArgs(ctx EvalContext, args []Expression
225268
if err := c.baseFunctionClass.verifyArgs(args); err != nil {
226269
return err
227270
}
228-
if evalType := args[0].GetType(ctx).EvalType(); evalType != types.ETString && evalType != types.ETJson {
229-
return ErrIncorrectType.GenWithStackByArgs("1", "json_unquote")
230-
}
231-
return nil
271+
return verifyJSONArgsType(ctx, c.funcName, false, args, 0)
232272
}
233273

234274
func (c *jsonUnquoteFunctionClass) getFunction(ctx BuildContext, args []Expression) (builtinFunc, error) {
@@ -469,12 +509,7 @@ func (c *jsonMergeFunctionClass) verifyArgs(ctx EvalContext, args []Expression)
469509
if err := c.baseFunctionClass.verifyArgs(args); err != nil {
470510
return err
471511
}
472-
for i, arg := range args {
473-
if evalType := arg.GetType(ctx).EvalType(); evalType != types.ETString && evalType != types.ETJson {
474-
return ErrInvalidTypeForJSON.GenWithStackByArgs(i+1, "json_merge")
475-
}
476-
}
477-
return nil
512+
return verifyJSONArgsType(ctx, c.funcName, true, args)
478513
}
479514

480515
type builtinJSONMergeSig struct {
@@ -682,10 +717,7 @@ func (c *jsonContainsPathFunctionClass) verifyArgs(ctx EvalContext, args []Expre
682717
if err := c.baseFunctionClass.verifyArgs(args); err != nil {
683718
return err
684719
}
685-
if evalType := args[0].GetType(ctx).EvalType(); evalType != types.ETString && evalType != types.ETJson {
686-
return ErrInvalidTypeForJSON.GenWithStackByArgs(1, "json_contains_path")
687-
}
688-
return nil
720+
return verifyJSONArgsType(ctx, c.funcName, true, args, 0)
689721
}
690722

691723
func (c *jsonContainsPathFunctionClass) getFunction(ctx BuildContext, args []Expression) (builtinFunc, error) {
@@ -801,10 +833,7 @@ func (c *jsonMemberOfFunctionClass) verifyArgs(ctx EvalContext, args []Expressio
801833
if err := c.baseFunctionClass.verifyArgs(args); err != nil {
802834
return err
803835
}
804-
if evalType := args[1].GetType(ctx).EvalType(); evalType != types.ETJson && evalType != types.ETString {
805-
return ErrInvalidTypeForJSON.GenWithStackByArgs(2, "member of")
806-
}
807-
return nil
836+
return verifyJSONArgsType(ctx, c.funcName, true, args, 1)
808837
}
809838

810839
func (c *jsonMemberOfFunctionClass) getFunction(ctx BuildContext, args []Expression) (builtinFunc, error) {
@@ -867,13 +896,7 @@ func (c *jsonContainsFunctionClass) verifyArgs(ctx EvalContext, args []Expressio
867896
if err := c.baseFunctionClass.verifyArgs(args); err != nil {
868897
return err
869898
}
870-
if evalType := args[0].GetType(ctx).EvalType(); evalType != types.ETJson && evalType != types.ETString {
871-
return ErrInvalidTypeForJSON.GenWithStackByArgs(1, "json_contains")
872-
}
873-
if evalType := args[1].GetType(ctx).EvalType(); evalType != types.ETJson && evalType != types.ETString {
874-
return ErrInvalidTypeForJSON.GenWithStackByArgs(2, "json_contains")
875-
}
876-
return nil
899+
return verifyJSONArgsType(ctx, c.funcName, true, args, 0, 1)
877900
}
878901

879902
func (c *jsonContainsFunctionClass) getFunction(ctx BuildContext, args []Expression) (builtinFunc, error) {
@@ -950,13 +973,7 @@ func (c *jsonOverlapsFunctionClass) verifyArgs(ctx EvalContext, args []Expressio
950973
if err := c.baseFunctionClass.verifyArgs(args); err != nil {
951974
return err
952975
}
953-
if evalType := args[0].GetType(ctx).EvalType(); evalType != types.ETJson && evalType != types.ETString {
954-
return ErrInvalidTypeForJSON.GenWithStackByArgs(1, "json_overlaps")
955-
}
956-
if evalType := args[1].GetType(ctx).EvalType(); evalType != types.ETJson && evalType != types.ETString {
957-
return ErrInvalidTypeForJSON.GenWithStackByArgs(2, "json_overlaps")
958-
}
959-
return nil
976+
return verifyJSONArgsType(ctx, c.funcName, true, args, 0, 1)
960977
}
961978

962979
func (c *jsonOverlapsFunctionClass) getFunction(ctx BuildContext, args []Expression) (builtinFunc, error) {
@@ -1283,12 +1300,7 @@ func (c *jsonMergePatchFunctionClass) verifyArgs(ctx EvalContext, args []Express
12831300
if err := c.baseFunctionClass.verifyArgs(args); err != nil {
12841301
return err
12851302
}
1286-
for i, arg := range args {
1287-
if evalType := arg.GetType(ctx).EvalType(); evalType != types.ETString && evalType != types.ETJson {
1288-
return ErrInvalidTypeForJSON.GenWithStackByArgs(i+1, "json_merge_patch")
1289-
}
1290-
}
1291-
return nil
1303+
return verifyJSONArgsType(ctx, c.funcName, true, args)
12921304
}
12931305

12941306
func (c *jsonMergePatchFunctionClass) getFunction(ctx BuildContext, args []Expression) (builtinFunc, error) {
@@ -1355,12 +1367,7 @@ func (c *jsonMergePreserveFunctionClass) verifyArgs(ctx EvalContext, args []Expr
13551367
if err := c.baseFunctionClass.verifyArgs(args); err != nil {
13561368
return err
13571369
}
1358-
for i, arg := range args {
1359-
if evalType := arg.GetType(ctx).EvalType(); evalType != types.ETString && evalType != types.ETJson {
1360-
return ErrInvalidTypeForJSON.GenWithStackByArgs(i+1, "json_merge_preserve")
1361-
}
1362-
}
1363-
return nil
1370+
return verifyJSONArgsType(ctx, c.funcName, true, args)
13641371
}
13651372

13661373
func (c *jsonMergePreserveFunctionClass) getFunction(ctx BuildContext, args []Expression) (builtinFunc, error) {
@@ -1509,10 +1516,7 @@ func (c *jsonSearchFunctionClass) verifyArgs(ctx EvalContext, args []Expression)
15091516
if err := c.baseFunctionClass.verifyArgs(args); err != nil {
15101517
return err
15111518
}
1512-
if evalType := args[0].GetType(ctx).EvalType(); evalType != types.ETString && evalType != types.ETJson {
1513-
return ErrInvalidTypeForJSON.GenWithStackByArgs(1, "json_search")
1514-
}
1515-
return nil
1519+
return verifyJSONArgsType(ctx, c.funcName, true, args, 0)
15161520
}
15171521

15181522
func (c *jsonSearchFunctionClass) getFunction(ctx BuildContext, args []Expression) (builtinFunc, error) {
@@ -1727,10 +1731,7 @@ func (c *jsonKeysFunctionClass) verifyArgs(ctx EvalContext, args []Expression) e
17271731
if err := c.baseFunctionClass.verifyArgs(args); err != nil {
17281732
return err
17291733
}
1730-
if evalType := args[0].GetType(ctx).EvalType(); evalType != types.ETString && evalType != types.ETJson {
1731-
return ErrInvalidTypeForJSON.GenWithStackByArgs(1, "json_keys")
1732-
}
1733-
return nil
1734+
return verifyJSONArgsType(ctx, c.funcName, true, args, 0)
17341735
}
17351736

17361737
func (c *jsonKeysFunctionClass) getFunction(ctx BuildContext, args []Expression) (builtinFunc, error) {
@@ -1902,11 +1903,9 @@ func (c *jsonSchemaValidFunctionClass) verifyArgs(ctx EvalContext, args []Expres
19021903
if err := c.baseFunctionClass.verifyArgs(args); err != nil {
19031904
return err
19041905
}
1905-
if evalType := args[0].GetType(ctx).EvalType(); evalType != types.ETString && evalType != types.ETJson {
1906-
return ErrInvalidTypeForJSON.GenWithStackByArgs(1, "json_schema_valid")
1907-
}
1908-
if evalType := args[1].GetType(ctx).EvalType(); evalType != types.ETString && evalType != types.ETJson {
1909-
return ErrInvalidTypeForJSON.GenWithStackByArgs(2, "json_schema_valid")
1906+
1907+
if err := verifyJSONArgsType(ctx, c.funcName, true, args, 0, 1); err != nil {
1908+
return err
19101909
}
19111910
if c, ok := args[0].(*Constant); ok {
19121911
// If args[0] is NULL, then don't check the length of *both* arguments.

tests/integrationtest/r/expression/json.result

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ Error 3146 (22032): Invalid data type for JSON data in argument 1 to function js
727727
SELECT JSON_OVERLAPS('{}', 123);
728728
Error 3146 (22032): Invalid data type for JSON data in argument 2 to function json_overlaps; a JSON string or JSON type is required.
729729
SELECT 'abc' MEMBER OF(123);
730-
Error 3146 (22032): Invalid data type for JSON data in argument 2 to function member of; a JSON string or JSON type is required.
730+
Error 3146 (22032): Invalid data type for JSON data in argument 2 to function json_memberof; a JSON string or JSON type is required.
731731
SELECT JSON_SEARCH('{}',3,4);
732732
Error 3154 (42000): The oneOrAll argument to json_search may take these values: 'one' or 'all'.
733733
SELECT JSON_ARRAY_APPEND('[]','abc','def');
@@ -765,3 +765,44 @@ Error 3853 (22032): Invalid JSON type in argument 1 to function json_schema_vali
765765
select json_type(cast(cast('2024' as year) as json));
766766
json_type(cast(cast('2024' as year) as json))
767767
UNSIGNED INTEGER
768+
DROP TABLE IF EXISTS t1;
769+
CREATE TABLE t1(id INT PRIMARY KEY, d1 DATE, d2 DATETIME, t1 TIME, t2 TIMESTAMP, b1 BIT, b2 BINARY);
770+
INSERT INTO t1 VALUES (1, '2024-06-14', '2024-06-14 09:37:00', '09:37:00', '2024-06-14 09:37:00', b'0', 0x41);
771+
SELECT JSON_TYPE(d1) FROM t1;
772+
Error 3146 (22032): Invalid data type for JSON data in argument 1 to function json_type; a JSON string or JSON type is required.
773+
SELECT JSON_TYPE(d2) FROM t1;
774+
Error 3146 (22032): Invalid data type for JSON data in argument 1 to function json_type; a JSON string or JSON type is required.
775+
SELECT JSON_TYPE(t1) FROM t1;
776+
Error 3146 (22032): Invalid data type for JSON data in argument 1 to function json_type; a JSON string or JSON type is required.
777+
SELECT JSON_TYPE(t2) FROM t1;
778+
Error 3146 (22032): Invalid data type for JSON data in argument 1 to function json_type; a JSON string or JSON type is required.
779+
SELECT JSON_TYPE(b1) FROM t1;
780+
Error 3146 (22032): Invalid data type for JSON data in argument 1 to function json_type; a JSON string or JSON type is required.
781+
SELECT JSON_TYPE(b2) FROM t1;
782+
Error 3144 (HY000): Cannot create a JSON value from a string with CHARACTER SET 'binary'.
783+
SELECT JSON_EXTRACT(b2, '$') FROM t1;
784+
Error 3144 (HY000): Cannot create a JSON value from a string with CHARACTER SET 'binary'.
785+
SELECT JSON_MERGE(b2, '{a:"b"}') FROM t1;
786+
Error 3144 (HY000): Cannot create a JSON value from a string with CHARACTER SET 'binary'.
787+
SELECT JSON_CONTAINS_PATH(b2, 'one', '$.a') FROM t1;
788+
Error 3144 (HY000): Cannot create a JSON value from a string with CHARACTER SET 'binary'.
789+
SELECT '1' member of(b2) FROM t1;
790+
Error 3144 (HY000): Cannot create a JSON value from a string with CHARACTER SET 'binary'.
791+
SELECT JSON_CONTAINS(b2, '{a:"b"}') FROM t1;
792+
Error 3144 (HY000): Cannot create a JSON value from a string with CHARACTER SET 'binary'.
793+
SELECT JSON_OVERLAPS(b2, '{a:"b"}') FROM t1;
794+
Error 3144 (HY000): Cannot create a JSON value from a string with CHARACTER SET 'binary'.
795+
SELECT JSON_MERGE_PATCH(b2, '{a:"b"}') FROM t1;
796+
Error 3144 (HY000): Cannot create a JSON value from a string with CHARACTER SET 'binary'.
797+
SELECT JSON_MERGE_PATCH('{a:"b"}', b2) FROM t1;
798+
Error 3144 (HY000): Cannot create a JSON value from a string with CHARACTER SET 'binary'.
799+
SELECT JSON_MERGE_PRESERVE(b2, '{a:"b"}') FROM t1;
800+
Error 3144 (HY000): Cannot create a JSON value from a string with CHARACTER SET 'binary'.
801+
SELECT JSON_MERGE_PRESERVE('{a:"b"}', b2) FROM t1;
802+
Error 3144 (HY000): Cannot create a JSON value from a string with CHARACTER SET 'binary'.
803+
SELECT JSON_SEARCH(b2, 'one', '1') FROM t1;
804+
Error 3144 (HY000): Cannot create a JSON value from a string with CHARACTER SET 'binary'.
805+
SELECT JSON_KEYS(b2) FROM t1;
806+
Error 3144 (HY000): Cannot create a JSON value from a string with CHARACTER SET 'binary'.
807+
SELECT JSON_SCHEMA_VALID(b2, '{}') FROM t1;
808+
Error 3144 (HY000): Cannot create a JSON value from a string with CHARACTER SET 'binary'.

tests/integrationtest/t/expression/json.test

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,3 +484,46 @@ SELECT JSON_SCHEMA_VALID('{"properties": {"a": {"exclusiveMinimum": true}}}', '{
484484
# TestIssue54494
485485
# https://github.com/pingcap/tidb/issues/54494
486486
select json_type(cast(cast('2024' as year) as json));
487+
488+
# TestIssue54029
489+
DROP TABLE IF EXISTS t1;
490+
CREATE TABLE t1(id INT PRIMARY KEY, d1 DATE, d2 DATETIME, t1 TIME, t2 TIMESTAMP, b1 BIT, b2 BINARY);
491+
INSERT INTO t1 VALUES (1, '2024-06-14', '2024-06-14 09:37:00', '09:37:00', '2024-06-14 09:37:00', b'0', 0x41);
492+
-- error 3146
493+
SELECT JSON_TYPE(d1) FROM t1;
494+
-- error 3146
495+
SELECT JSON_TYPE(d2) FROM t1;
496+
-- error 3146
497+
SELECT JSON_TYPE(t1) FROM t1;
498+
-- error 3146
499+
SELECT JSON_TYPE(t2) FROM t1;
500+
-- error 3146
501+
SELECT JSON_TYPE(b1) FROM t1;
502+
-- error 3144
503+
SELECT JSON_TYPE(b2) FROM t1;
504+
-- error 3144
505+
SELECT JSON_EXTRACT(b2, '$') FROM t1;
506+
-- error 3144
507+
SELECT JSON_MERGE(b2, '{a:"b"}') FROM t1;
508+
-- error 3144
509+
SELECT JSON_CONTAINS_PATH(b2, 'one', '$.a') FROM t1;
510+
-- error 3144
511+
SELECT '1' member of(b2) FROM t1;
512+
-- error 3144
513+
SELECT JSON_CONTAINS(b2, '{a:"b"}') FROM t1;
514+
-- error 3144
515+
SELECT JSON_OVERLAPS(b2, '{a:"b"}') FROM t1;
516+
-- error 3144
517+
SELECT JSON_MERGE_PATCH(b2, '{a:"b"}') FROM t1;
518+
-- error 3144
519+
SELECT JSON_MERGE_PATCH('{a:"b"}', b2) FROM t1;
520+
-- error 3144
521+
SELECT JSON_MERGE_PRESERVE(b2, '{a:"b"}') FROM t1;
522+
-- error 3144
523+
SELECT JSON_MERGE_PRESERVE('{a:"b"}', b2) FROM t1;
524+
-- error 3144
525+
SELECT JSON_SEARCH(b2, 'one', '1') FROM t1;
526+
-- error 3144
527+
SELECT JSON_KEYS(b2) FROM t1;
528+
-- error 3144
529+
SELECT JSON_SCHEMA_VALID(b2, '{}') FROM t1;

0 commit comments

Comments
 (0)