summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Botchkov <holyfoot@askmonty.org>2017-01-26 16:35:05 +0400
committerAlexey Botchkov <holyfoot@askmonty.org>2017-01-26 16:35:05 +0400
commitd96ee168a1f87c090421fb593930515ae8db3d7f (patch)
tree7eb78889644c1bc4eb32ab4274a0840a1622cfd4
parent71495a1748784a887f42888a2a7b8cac5e088ff6 (diff)
downloadmariadb-git-d96ee168a1f87c090421fb593930515ae8db3d7f.tar.gz
MDEV-11557 port MySQL-5.7 JSON tests to MariaDB.
paths ending on [0]..[0] should be handled in conforming manner.
-rw-r--r--mysql-test/r/func_json.result50
-rw-r--r--mysql-test/suite/json/r/json_no_table.result62
-rw-r--r--mysql-test/t/func_json.test18
-rw-r--r--sql/item_jsonfunc.cc24
-rw-r--r--strings/json_lib.c43
5 files changed, 147 insertions, 50 deletions
diff --git a/mysql-test/r/func_json.result b/mysql-test/r/func_json.result
index 47993ae9a32..6968cf79d7d 100644
--- a/mysql-test/r/func_json.result
+++ b/mysql-test/r/func_json.result
@@ -444,3 +444,53 @@ json CREATE TABLE `json` (
`j` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table json;
+select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2]' );
+json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2]' )
+1
+select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0]' );
+json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0]' )
+1
+select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0]' );
+json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0]' )
+1
+select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0][0]' );
+json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0][0]' )
+1
+select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2]' );
+json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2]' )
+2
+select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0]' );
+json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0]' )
+2
+select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0]' );
+json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0]' )
+2
+select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0][0]' );
+json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0][0]' )
+2
+select json_length( '{"a":{"b":{"d":1}}, "a":{"c":{"d":1, "j":2}}}', '$.a[0][0][0].c' );
+json_length( '{"a":{"b":{"d":1}}, "a":{"c":{"d":1, "j":2}}}', '$.a[0][0][0].c' )
+2
+select json_set('1', '$[0]', 100);
+json_set('1', '$[0]', 100)
+100
+select json_set('1', '$[0][0]', 100);
+json_set('1', '$[0][0]', 100)
+100
+select json_set('1', '$[1]', 100);
+json_set('1', '$[1]', 100)
+[1, 100]
+select json_set('{"a":12}', '$[0]', 100);
+json_set('{"a":12}', '$[0]', 100)
+100
+select json_set('{"a":12}', '$[0].a', 100);
+json_set('{"a":12}', '$[0].a', 100)
+{"a":100}
+select json_set('{"a":12}', '$[0][0].a', 100);
+json_set('{"a":12}', '$[0][0].a', 100)
+{"a":100}
+select json_set('{"a":12}', '$[0][1].a', 100);
+json_set('{"a":12}', '$[0][1].a', 100)
+NULL
+Warnings:
+Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_set'
diff --git a/mysql-test/suite/json/r/json_no_table.result b/mysql-test/suite/json/r/json_no_table.result
index 88016ebfd19..97148bdad43 100644
--- a/mysql-test/suite/json/r/json_no_table.result
+++ b/mysql-test/suite/json/r/json_no_table.result
@@ -420,10 +420,10 @@ json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2]' )
1
select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0]' );
json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0]' )
-NULL
+1
select json_length( '[ 1, [ 2, 3, 4 ], {"a": 1} ]', '$[2][0]' );
json_length( '[ 1, [ 2, 3, 4 ], {"a": 1} ]', '$[2][0]' )
-NULL
+1
select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][1]' );
json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][1]' )
NULL
@@ -1694,13 +1694,13 @@ JSON_ARRAY_APPEND
# ----------------------------------------------------------------------
select json_array_append('{"a":1}', '$[0]', 100);
json_array_append('{"a":1}', '$[0]', 100)
-NULL
+[{"a":1}, 100]
select json_array_append('3', '$[0]', 100);
json_array_append('3', '$[0]', 100)
-NULL
+[3, 100]
select json_array_append('3', '$[0][0][0][0]', 100);
json_array_append('3', '$[0][0][0][0]', 100)
-NULL
+[3, 100]
# ----------------------------------------------------------------------
# Test of JSON_INSERT function.
# ----------------------------------------------------------------------
@@ -2118,7 +2118,7 @@ json_set('1', '$', 4)
4
select json_set('1', '$[0]', 4);
json_set('1', '$[0]', 4)
-[1, 4]
+4
select json_set('1', '$[1]', 4);
json_set('1', '$[1]', 4)
[1, 4]
@@ -2127,13 +2127,13 @@ json_set('1', '$[10]', '4', '$[11]', 5)
[1, "4", 5]
select json_set('[1,2,3]', '$[2][0]', 4);
json_set('[1,2,3]', '$[2][0]', 4)
-[1,2,[3, 4]]
+[1,2,4]
select json_set('[1,2,3]', '$[2][2]', 4);
json_set('[1,2,3]', '$[2][2]', 4)
[1,2,[3, 4]]
select json_set('{"a": 3}', '$.a[0]', 4);
json_set('{"a": 3}', '$.a[0]', 4)
-{"a": [3, 4]}
+{"a": 4}
select json_set('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5');
json_set('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5')
{"a": [3, 4, "5"]}
@@ -2280,7 +2280,7 @@ json_replace('1', '$', 4)
4
select json_replace('1', '$[0]', 4);
json_replace('1', '$[0]', 4)
-1
+4
select json_replace('1', '$[1]', 4);
json_replace('1', '$[1]', 4)
1
@@ -2289,13 +2289,13 @@ json_replace('1', '$[10]', '4', '$[11]', 5)
1
select json_replace('[1,2,3]', '$[2][0]', 4);
json_replace('[1,2,3]', '$[2][0]', 4)
-[1,2,3]
+[1,2,4]
select json_replace('[1,2,3]', '$[2][2]', 4);
json_replace('[1,2,3]', '$[2][2]', 4)
[1,2,3]
select json_replace('{"a": 3}', '$.a[0]', 4);
json_replace('{"a": 3}', '$.a[0]', 4)
-{"a": 3}
+{"a": 4}
select json_replace('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5');
json_replace('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5')
{"a": 3}
@@ -2312,7 +2312,7 @@ true);
JSON_REPLACE('{ "a" : "foo", "b" : [ 1, 2, 3 ] }',
'$.a[0]',
true)
-{ "a" : "foo", "b" : [ 1, 2, 3 ] }
+{ "a" : true, "b" : [ 1, 2, 3 ] }
SELECT JSON_REPLACE('{ "a" : "foo", "b" : [ 1, 2, 3 ] }',
'$.b[5]',
true);
@@ -3489,23 +3489,19 @@ JSON_SET('1', '$', 100)
100
SELECT JSON_SET('1', '$[0]', 100);
JSON_SET('1', '$[0]', 100)
-[1, 100]
+100
SELECT JSON_SET('1', '$[0][0]', 100);
JSON_SET('1', '$[0][0]', 100)
-NULL
-Warnings:
-Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_set'
+100
SELECT JSON_SET('1', '$[0][0][0]', 100);
JSON_SET('1', '$[0][0][0]', 100)
-NULL
-Warnings:
-Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_set'
+100
SELECT JSON_SET('[]', '$', 100);
JSON_SET('[]', '$', 100)
100
SELECT JSON_SET('[]', '$[0]', 100);
JSON_SET('[]', '$[0]', 100)
-[, 100]
+[100]
SELECT JSON_SET('[]', '$[0][0]', 100);
JSON_SET('[]', '$[0][0]', 100)
NULL
@@ -3524,12 +3520,10 @@ JSON_SET('[1]', '$[0]', 100)
[100]
SELECT JSON_SET('[1]', '$[0][0]', 100);
JSON_SET('[1]', '$[0][0]', 100)
-[[1, 100]]
+[100]
SELECT JSON_SET('[1]', '$[0][0][0]', 100);
JSON_SET('[1]', '$[0][0][0]', 100)
-NULL
-Warnings:
-Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_set'
+[100]
SELECT JSON_SET('[[1]]', '$', 100);
JSON_SET('[[1]]', '$', 100)
100
@@ -3541,7 +3535,7 @@ JSON_SET('[[1]]', '$[0][0]', 100)
[[100]]
SELECT JSON_SET('[[1]]', '$[0][0][0]', 100);
JSON_SET('[[1]]', '$[0][0][0]', 100)
-[[[1, 100]]]
+[[100]]
SELECT JSON_SET('[[[1]]]', '$', 100);
JSON_SET('[[[1]]]', '$', 100)
100
@@ -3559,17 +3553,13 @@ JSON_REPLACE('1', '$', 100)
100
SELECT JSON_REPLACE('1', '$[0]', 100);
JSON_REPLACE('1', '$[0]', 100)
-1
+100
SELECT JSON_REPLACE('1', '$[0][0]', 100);
JSON_REPLACE('1', '$[0][0]', 100)
-NULL
-Warnings:
-Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_update'
+100
SELECT JSON_REPLACE('1', '$[0][0][0]', 100);
JSON_REPLACE('1', '$[0][0][0]', 100)
-NULL
-Warnings:
-Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_update'
+100
SELECT JSON_REPLACE('[]', '$', 100);
JSON_REPLACE('[]', '$', 100)
100
@@ -3594,12 +3584,10 @@ JSON_REPLACE('[1]', '$[0]', 100)
[100]
SELECT JSON_REPLACE('[1]', '$[0][0]', 100);
JSON_REPLACE('[1]', '$[0][0]', 100)
-[1]
+[100]
SELECT JSON_REPLACE('[1]', '$[0][0][0]', 100);
JSON_REPLACE('[1]', '$[0][0][0]', 100)
-NULL
-Warnings:
-Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_update'
+[100]
SELECT JSON_REPLACE('[[1]]', '$', 100);
JSON_REPLACE('[[1]]', '$', 100)
100
@@ -3611,7 +3599,7 @@ JSON_REPLACE('[[1]]', '$[0][0]', 100)
[[100]]
SELECT JSON_REPLACE('[[1]]', '$[0][0][0]', 100);
JSON_REPLACE('[[1]]', '$[0][0][0]', 100)
-[[1]]
+[[100]]
SELECT JSON_REPLACE('[[[1]]]', '$', 100);
JSON_REPLACE('[[[1]]]', '$', 100)
100
diff --git a/mysql-test/t/func_json.test b/mysql-test/t/func_json.test
index 455f1a722ea..b9b4ab3726a 100644
--- a/mysql-test/t/func_json.test
+++ b/mysql-test/t/func_json.test
@@ -179,3 +179,21 @@ create table json (j INT);
show create table json;
drop table json;
+select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2]' );
+select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0]' );
+select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0]' );
+select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0][0]' );
+select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2]' );
+select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0]' );
+select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0]' );
+select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0][0]' );
+select json_length( '{"a":{"b":{"d":1}}, "a":{"c":{"d":1, "j":2}}}', '$.a[0][0][0].c' );
+
+select json_set('1', '$[0]', 100);
+select json_set('1', '$[0][0]', 100);
+select json_set('1', '$[1]', 100);
+select json_set('{"a":12}', '$[0]', 100);
+select json_set('{"a":12}', '$[0].a', 100);
+select json_set('{"a":12}', '$[0][0].a', 100);
+select json_set('{"a":12}', '$[0][1].a', 100);
+
diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc
index fc146427bc1..4731bada6ab 100644
--- a/sql/item_jsonfunc.cc
+++ b/sql/item_jsonfunc.cc
@@ -1983,13 +1983,22 @@ String *Item_func_json_insert::val_str(String *str)
if (je.value_type != JSON_VALUE_ARRAY)
{
const uchar *v_from= je.value_begin;
- if (!mode_insert)
- continue;
+ int do_array_autowrap;
+
+ if (mode_insert)
+ do_array_autowrap= !mode_replace || lp->n_item;
+ else
+ {
+ if (lp->n_item)
+ continue;
+ do_array_autowrap= 0;
+ }
+
str->length(0);
/* Wrap the value as an array. */
if (append_simple(str, js->ptr(), (const char *) v_from - js->ptr()) ||
- str->append("[", 1))
+ (do_array_autowrap && str->append("[", 1)))
goto js_error; /* Out of memory. */
if (je.value_type == JSON_VALUE_OBJECT)
@@ -1998,10 +2007,11 @@ String *Item_func_json_insert::val_str(String *str)
goto js_error;
}
- if (append_simple(str, v_from, je.s.c_str - v_from) ||
- str->append(", ", 2) ||
+ if ((do_array_autowrap &&
+ (append_simple(str, v_from, je.s.c_str - v_from) ||
+ str->append(", ", 2))) ||
append_json_value(str, args[n_arg+1], &tmp_val) ||
- str->append("]", 1) ||
+ (do_array_autowrap && str->append("]", 1)) ||
append_simple(str, je.s.c_str, js->end()-(const char *) je.s.c_str))
goto js_error; /* Out of memory. */
@@ -2033,7 +2043,7 @@ String *Item_func_json_insert::val_str(String *str)
v_to= (const char *) (je.s.c_str - je.sav_c_len);
str->length(0);
if (append_simple(str, js->ptr(), v_to - js->ptr()) ||
- str->append(", ", 2) ||
+ (n_item > 0 && str->append(", ", 2)) ||
append_json_value(str, args[n_arg+1], &tmp_val) ||
append_simple(str, v_to, js->end() - v_to))
goto js_error; /* Out of memory. */
diff --git a/strings/json_lib.c b/strings/json_lib.c
index 66b075a997b..18bdce2613f 100644
--- a/strings/json_lib.c
+++ b/strings/json_lib.c
@@ -1187,6 +1187,8 @@ int json_skip_key(json_engine_t *j)
}
+#define SKIPPED_STEP_MARK ((uint) ~0)
+
/*
Current step of the patch matches the JSON construction.
Now we should either stop the search or go to the next
@@ -1195,24 +1197,48 @@ int json_skip_key(json_engine_t *j)
static int handle_match(json_engine_t *je, json_path_t *p,
json_path_step_t **p_cur_step, uint *array_counters)
{
+ json_path_step_t *next_step= *p_cur_step + 1;
+
DBUG_ASSERT(*p_cur_step < p->last_step);
if (json_read_value(je))
return 1;
if (json_value_scalar(je))
+ {
+ while (next_step->type == JSON_PATH_ARRAY && next_step->n_item == 0)
+ {
+ if (++next_step > p->last_step)
+ {
+ je->s.c_str= je->value_begin;
+ return 1;
+ }
+ }
return 0;
+ }
+
+ if (next_step->type == JSON_PATH_ARRAY && next_step->n_item == 0 &&
+ je->value_type & JSON_VALUE_OBJECT)
+ {
+ do
+ {
+ array_counters[next_step - p->steps]= SKIPPED_STEP_MARK;
+ if (++next_step > p->last_step)
+ {
+ je->s.c_str= je->value_begin;
+ return 1;
+ }
+ } while (next_step->type == JSON_PATH_ARRAY && next_step->n_item == 0);
+ }
- (*p_cur_step)++;
- array_counters[*p_cur_step - p->steps]= 0;
+
+ array_counters[next_step - p->steps]= 0;
if ((int) je->value_type !=
- (int) ((*p_cur_step)->type & JSON_PATH_KEY_OR_ARRAY))
- {
- (*p_cur_step)--;
+ (int) (next_step->type & JSON_PATH_KEY_OR_ARRAY))
return json_skip_level(je);
- }
+ *p_cur_step= next_step;
return 0;
}
@@ -1277,6 +1303,11 @@ int json_find_path(json_engine_t *je,
json_skip_array_item(je);
break;
case JST_OBJ_END:
+ do
+ {
+ (*p_cur_step)--;
+ } while (array_counters[(*p_cur_step) - p->steps] == SKIPPED_STEP_MARK);
+ break;
case JST_ARRAY_END:
(*p_cur_step)--;
break;