Skip to content

Commit a2757a6

Browse files
Rick Hillegasdahlerlend
authored andcommitted
Bug#21450084 LET JSON_INSERT() INSERT INTO THE MIDDLE OF JSON ARRAYS.
(cherry picked from commit 27368364403e241c86650f635c72664b4c11d7ff)
1 parent c49c678 commit a2757a6

File tree

6 files changed

+460
-0
lines changed

6 files changed

+460
-0
lines changed

mysql-test/r/json.result

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7262,6 +7262,167 @@ JSON_INSERT
72627262
)
72637263
{"a": "foo", "b": true}
72647264
# ----------------------------------------------------------------------
7265+
# Test of JSON_ARRAY_INSERT function.
7266+
# ----------------------------------------------------------------------
7267+
select json_array_insert(NULL, '$.b[1]', 1);
7268+
json_array_insert(NULL, '$.b[1]', 1)
7269+
NULL
7270+
select json_array_insert('[1,2,3]', NULL, 1);
7271+
json_array_insert('[1,2,3]', NULL, 1)
7272+
NULL
7273+
select json_array_insert('[1,2,3]', '$[3]', NULL);
7274+
json_array_insert('[1,2,3]', '$[3]', NULL)
7275+
NULL
7276+
select json_array_insert(NULL);
7277+
ERROR 42000: Incorrect parameter count in the call to native function 'json_array_insert'
7278+
select json_array_insert(NULL, NULL);
7279+
ERROR 42000: Incorrect parameter count in the call to native function 'json_array_insert'
7280+
select json_array_insert(NULL, NULL, NULL, NULL);
7281+
ERROR 42000: Incorrect parameter count in the call to native function 'json_array_insert'
7282+
select json_array_insert('true', '$', 1);
7283+
ERROR 42000: A path expression is not a path to a cell in an array.
7284+
select json_array_insert('true', '$.a', 1);
7285+
ERROR 42000: A path expression is not a path to a cell in an array.
7286+
select json_array_insert('true', '$.a[1].b', 1);
7287+
ERROR 42000: A path expression is not a path to a cell in an array.
7288+
select json_array_insert( 'true', '$[0]', false );
7289+
json_array_insert( 'true', '$[0]', false )
7290+
true
7291+
select json_array_insert( 'true', '$[1]', false );
7292+
json_array_insert( 'true', '$[1]', false )
7293+
true
7294+
select json_array_insert( '{ "a": true }', '$.a[0]', false );
7295+
json_array_insert( '{ "a": true }', '$.a[0]', false )
7296+
{"a": true}
7297+
select json_array_insert( '{ "a": true }', '$.a[1]', false );
7298+
json_array_insert( '{ "a": true }', '$.a[1]', false )
7299+
{"a": true}
7300+
select json_array_insert( '[]', '$[0]', false );
7301+
json_array_insert( '[]', '$[0]', false )
7302+
[false]
7303+
select json_array_insert( '[]', '$[1]', false );
7304+
json_array_insert( '[]', '$[1]', false )
7305+
[false]
7306+
select json_array_insert( '[true]', '$[0]', false );
7307+
json_array_insert( '[true]', '$[0]', false )
7308+
[false, true]
7309+
select json_array_insert( '[true]', '$[1]', false );
7310+
json_array_insert( '[true]', '$[1]', false )
7311+
[true, false]
7312+
select json_array_insert( '[true]', '$[2]', false );
7313+
json_array_insert( '[true]', '$[2]', false )
7314+
[true, false]
7315+
select json_array_insert( '{ "a": [] }', '$.a[0]', false );
7316+
json_array_insert( '{ "a": [] }', '$.a[0]', false )
7317+
{"a": [false]}
7318+
select json_array_insert( '{ "a": [] }', '$.a[1]', false );
7319+
json_array_insert( '{ "a": [] }', '$.a[1]', false )
7320+
{"a": [false]}
7321+
select json_array_insert( '{ "a": [true] }', '$.a[0]', false );
7322+
json_array_insert( '{ "a": [true] }', '$.a[0]', false )
7323+
{"a": [false, true]}
7324+
select json_array_insert( '{ "a": [true] }', '$.a[1]', false );
7325+
json_array_insert( '{ "a": [true] }', '$.a[1]', false )
7326+
{"a": [true, false]}
7327+
select json_array_insert( '{ "a": [true] }', '$.a[2]', false );
7328+
json_array_insert( '{ "a": [true] }', '$.a[2]', false )
7329+
{"a": [true, false]}
7330+
select json_array_insert( '[1, 2, 3, 4]', '$[0]', false );
7331+
json_array_insert( '[1, 2, 3, 4]', '$[0]', false )
7332+
[false, 1, 2, 3, 4]
7333+
select json_array_insert( '[1, 2, 3, 4]', '$[1]', false );
7334+
json_array_insert( '[1, 2, 3, 4]', '$[1]', false )
7335+
[1, false, 2, 3, 4]
7336+
select json_array_insert( '[1, 2, 3, 4]', '$[2]', false );
7337+
json_array_insert( '[1, 2, 3, 4]', '$[2]', false )
7338+
[1, 2, false, 3, 4]
7339+
select json_array_insert( '[1, 2, 3, 4]', '$[3]', false );
7340+
json_array_insert( '[1, 2, 3, 4]', '$[3]', false )
7341+
[1, 2, 3, false, 4]
7342+
select json_array_insert( '[1, 2, 3, 4]', '$[4]', false );
7343+
json_array_insert( '[1, 2, 3, 4]', '$[4]', false )
7344+
[1, 2, 3, 4, false]
7345+
select json_array_insert( '[1, 2, 3, 4]', '$[5]', false );
7346+
json_array_insert( '[1, 2, 3, 4]', '$[5]', false )
7347+
[1, 2, 3, 4, false]
7348+
select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[0]', false );
7349+
json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[0]', false )
7350+
{"a": [false, 1, 2, 3, 4]}
7351+
select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[1]', false );
7352+
json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[1]', false )
7353+
{"a": [1, false, 2, 3, 4]}
7354+
select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[2]', false );
7355+
json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[2]', false )
7356+
{"a": [1, 2, false, 3, 4]}
7357+
select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[3]', false );
7358+
json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[3]', false )
7359+
{"a": [1, 2, 3, false, 4]}
7360+
select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[4]', false );
7361+
json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[4]', false )
7362+
{"a": [1, 2, 3, 4, false]}
7363+
select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[5]', false );
7364+
json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[5]', false )
7365+
{"a": [1, 2, 3, 4, false]}
7366+
select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.b[0]', false );
7367+
json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.b[0]', false )
7368+
{"a": [1, 2, 3, 4]}
7369+
select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.b[1]', false );
7370+
json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.b[1]', false )
7371+
{"a": [1, 2, 3, 4]}
7372+
create table jdoc( id int, doc json );
7373+
insert into jdoc values
7374+
( 1, '[ [ true ], [ false ] ]' ),
7375+
( 2, '[ [ 0 ], [ 1 ] ]' ),
7376+
( 3, '[ [ "abc" ], [ "def" ] ]' );
7377+
select id, json_array_insert( doc, '$[0][1]', 'fred' )
7378+
from jdoc order by id;
7379+
id json_array_insert( doc, '$[0][1]', 'fred' )
7380+
1 [[true, "fred"], [false]]
7381+
2 [[0, "fred"], [1]]
7382+
3 [["abc", "fred"], ["def"]]
7383+
select id, json_array_insert( doc, '$[1][0]', 'fred' )
7384+
from jdoc order by id;
7385+
id json_array_insert( doc, '$[1][0]', 'fred' )
7386+
1 [[true], ["fred", false]]
7387+
2 [[0], ["fred", 1]]
7388+
3 [["abc"], ["fred", "def"]]
7389+
drop table jdoc;
7390+
create table t( id int, v varchar(10));
7391+
insert into t values (1, 'a'), (2, null), (3, 'a');
7392+
select id v, json_array_insert('[[1]]', '$[0][0]', v) from t order by id;
7393+
v json_array_insert('[[1]]', '$[0][0]', v)
7394+
1 [["a", 1]]
7395+
2 NULL
7396+
3 [["a", 1]]
7397+
drop table t;
7398+
select json_array_insert( '"a"', '$[0]', true );
7399+
json_array_insert( '"a"', '$[0]', true )
7400+
"a"
7401+
select json_array_insert( '[ "a" ]', '$[0][0]', true );
7402+
json_array_insert( '[ "a" ]', '$[0][0]', true )
7403+
["a"]
7404+
select json_array_insert( '"a"', '$[1]', true );
7405+
json_array_insert( '"a"', '$[1]', true )
7406+
"a"
7407+
select json_insert('[]', '$.a.*[1]', 6);
7408+
ERROR 42000: In this situation, path expressions may not contain the * and ** tokens.
7409+
select json_insert('[]', '$**[1]', 6);
7410+
ERROR 42000: In this situation, path expressions may not contain the * and ** tokens.
7411+
select json_insert('[]', '$[*][1]', 6);
7412+
ERROR 42000: In this situation, path expressions may not contain the * and ** tokens.
7413+
select json_array_insert( '[ 1, 2, 3 ]', '$[1]', true, '$[1]', false );
7414+
json_array_insert( '[ 1, 2, 3 ]', '$[1]', true, '$[1]', false )
7415+
[1, false, true, 2, 3]
7416+
select json_array_insert( '[ 1, 2, 3 ]', '$[1]',
7417+
cast( '[ "a", "b", "c", "d" ]' as json ), '$[1][2]', false );
7418+
json_array_insert( '[ 1, 2, 3 ]', '$[1]',
7419+
cast( '[ "a", "b", "c", "d" ]' as json ), '$[1][2]', false )
7420+
[1, ["a", "b", false, "c", "d"], 2, 3]
7421+
SELECT JSON_ARRAY_INSERT(JSON_EXTRACT('[1', '$'), '$[0]', 1);
7422+
ERROR 22032: Invalid JSON text in argument 1 to function json_extract: "Missing a comma or ']' after an array element." at position 2 in '[1'.
7423+
select json_array_insert( '[ 1, 2, 3 ]', '$[1]', json_extract( '[', '$' ) );
7424+
ERROR 22032: Invalid JSON text in argument 1 to function json_extract: "Invalid value." at position 1 in '['.
7425+
# ----------------------------------------------------------------------
72657426
# Test of JSON_SET function.
72667427
# ----------------------------------------------------------------------
72677428
select json_set(NULL, '$.b', cast(1 as json));

mysql-test/t/json.test

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2182,6 +2182,113 @@ SELECT JSON_INSERT
21822182
'$.b', false
21832183
);
21842184

2185+
--echo # ----------------------------------------------------------------------
2186+
--echo # Test of JSON_ARRAY_INSERT function.
2187+
--echo # ----------------------------------------------------------------------
2188+
2189+
# NULLs
2190+
select json_array_insert(NULL, '$.b[1]', 1);
2191+
select json_array_insert('[1,2,3]', NULL, 1);
2192+
select json_array_insert('[1,2,3]', '$[3]', NULL);
2193+
2194+
# wrong # args
2195+
--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
2196+
select json_array_insert(NULL);
2197+
--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
2198+
select json_array_insert(NULL, NULL);
2199+
--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
2200+
select json_array_insert(NULL, NULL, NULL, NULL);
2201+
2202+
# path does not indicate a cell position
2203+
--error ER_INVALID_JSON_PATH_ARRAY_CELL
2204+
select json_array_insert('true', '$', 1);
2205+
--error ER_INVALID_JSON_PATH_ARRAY_CELL
2206+
select json_array_insert('true', '$.a', 1);
2207+
--error ER_INVALID_JSON_PATH_ARRAY_CELL
2208+
select json_array_insert('true', '$.a[1].b', 1);
2209+
2210+
# nop if there is no array at the path's parent
2211+
select json_array_insert( 'true', '$[0]', false );
2212+
select json_array_insert( 'true', '$[1]', false );
2213+
select json_array_insert( '{ "a": true }', '$.a[0]', false );
2214+
select json_array_insert( '{ "a": true }', '$.a[1]', false );
2215+
2216+
# positive tests
2217+
select json_array_insert( '[]', '$[0]', false );
2218+
select json_array_insert( '[]', '$[1]', false );
2219+
select json_array_insert( '[true]', '$[0]', false );
2220+
select json_array_insert( '[true]', '$[1]', false );
2221+
select json_array_insert( '[true]', '$[2]', false );
2222+
select json_array_insert( '{ "a": [] }', '$.a[0]', false );
2223+
select json_array_insert( '{ "a": [] }', '$.a[1]', false );
2224+
select json_array_insert( '{ "a": [true] }', '$.a[0]', false );
2225+
select json_array_insert( '{ "a": [true] }', '$.a[1]', false );
2226+
select json_array_insert( '{ "a": [true] }', '$.a[2]', false );
2227+
2228+
# insert into the middle of an array
2229+
select json_array_insert( '[1, 2, 3, 4]', '$[0]', false );
2230+
select json_array_insert( '[1, 2, 3, 4]', '$[1]', false );
2231+
select json_array_insert( '[1, 2, 3, 4]', '$[2]', false );
2232+
select json_array_insert( '[1, 2, 3, 4]', '$[3]', false );
2233+
select json_array_insert( '[1, 2, 3, 4]', '$[4]', false );
2234+
select json_array_insert( '[1, 2, 3, 4]', '$[5]', false );
2235+
2236+
select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[0]', false );
2237+
select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[1]', false );
2238+
select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[2]', false );
2239+
select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[3]', false );
2240+
select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[4]', false );
2241+
select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[5]', false );
2242+
2243+
# nop
2244+
select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.b[0]', false );
2245+
select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.b[1]', false );
2246+
2247+
# path caching and leg popping
2248+
create table jdoc( id int, doc json );
2249+
insert into jdoc values
2250+
( 1, '[ [ true ], [ false ] ]' ),
2251+
( 2, '[ [ 0 ], [ 1 ] ]' ),
2252+
( 3, '[ [ "abc" ], [ "def" ] ]' );
2253+
2254+
select id, json_array_insert( doc, '$[0][1]', 'fred' )
2255+
from jdoc order by id;
2256+
2257+
select id, json_array_insert( doc, '$[1][0]', 'fred' )
2258+
from jdoc order by id;
2259+
2260+
drop table jdoc;
2261+
2262+
create table t( id int, v varchar(10));
2263+
insert into t values (1, 'a'), (2, null), (3, 'a');
2264+
select id v, json_array_insert('[[1]]', '$[0][0]', v) from t order by id;
2265+
drop table t;
2266+
2267+
# no auto-wrapping
2268+
select json_array_insert( '"a"', '$[0]', true );
2269+
select json_array_insert( '[ "a" ]', '$[0][0]', true );
2270+
select json_array_insert( '"a"', '$[1]', true );
2271+
2272+
--error ER_INVALID_JSON_PATH_WILDCARD
2273+
select json_insert('[]', '$.a.*[1]', 6);
2274+
--error ER_INVALID_JSON_PATH_WILDCARD
2275+
select json_insert('[]', '$**[1]', 6);
2276+
--error ER_INVALID_JSON_PATH_WILDCARD
2277+
select json_insert('[]', '$[*][1]', 6);
2278+
2279+
# multiple paths,
2280+
select json_array_insert( '[ 1, 2, 3 ]', '$[1]', true, '$[1]', false );
2281+
select json_array_insert( '[ 1, 2, 3 ]', '$[1]',
2282+
cast( '[ "a", "b", "c", "d" ]' as json ), '$[1][2]', false );
2283+
2284+
# test an error while evaluating the document expression
2285+
--error ER_INVALID_JSON_TEXT_IN_PARAM
2286+
SELECT JSON_ARRAY_INSERT(JSON_EXTRACT('[1', '$'), '$[0]', 1);
2287+
2288+
# error in reading new value
2289+
--error ER_INVALID_JSON_TEXT_IN_PARAM
2290+
select json_array_insert( '[ 1, 2, 3 ]', '$[1]', json_extract( '[', '$' ) );
2291+
21852292
--echo # ----------------------------------------------------------------------
21862293
--echo # Test of JSON_SET function.
21872294
--echo # ----------------------------------------------------------------------

sql/item_create.cc

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2546,6 +2546,20 @@ class Create_func_json_insert : public Create_native_func
25462546

25472547
};
25482548

2549+
class Create_func_json_array_insert : public Create_native_func
2550+
{
2551+
public:
2552+
virtual Item *create_native(THD *thd, LEX_STRING name,
2553+
PT_item_list *item_list);
2554+
2555+
static Create_func_json_array_insert s_singleton;
2556+
2557+
protected:
2558+
Create_func_json_array_insert() {}
2559+
virtual ~Create_func_json_array_insert() {}
2560+
2561+
};
2562+
25492563
class Create_func_json_row_object : public Create_native_func
25502564
{
25512565
public:
@@ -5923,6 +5937,39 @@ Create_func_json_insert::create_native(THD *thd, LEX_STRING name,
59235937
return func;
59245938
}
59255939

5940+
Create_func_json_array_insert Create_func_json_array_insert::s_singleton;
5941+
5942+
Item*
5943+
Create_func_json_array_insert::create_native(THD *thd,
5944+
LEX_STRING name,
5945+
PT_item_list *item_list)
5946+
{
5947+
Item *func= NULL;
5948+
int arg_count= 0;
5949+
5950+
if (item_list != NULL)
5951+
arg_count= item_list->elements();
5952+
5953+
if (arg_count < 3)
5954+
{
5955+
my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
5956+
return NULL;
5957+
}
5958+
5959+
if (arg_count % 2 == 0) // 3,5,7, ..., (k*2)+1 args allowed
5960+
{
5961+
my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
5962+
}
5963+
else
5964+
{
5965+
func= new (thd->mem_root) Item_func_json_array_insert(thd,
5966+
POS(),
5967+
item_list);
5968+
}
5969+
5970+
return func;
5971+
}
5972+
59265973
Create_func_json_row_object Create_func_json_row_object::s_singleton;
59275974

59285975
Item*
@@ -7484,6 +7531,7 @@ static Native_func_registry func_array[] =
74847531
{ { C_STRING_WITH_LEN("JSON_EXTRACT") }, BUILDER(Create_func_json_extract)},
74857532
{ { C_STRING_WITH_LEN("JSON_APPEND") }, BUILDER(Create_func_json_append)},
74867533
{ { C_STRING_WITH_LEN("JSON_INSERT") }, BUILDER(Create_func_json_insert)},
7534+
{ { C_STRING_WITH_LEN("JSON_ARRAY_INSERT") }, BUILDER(Create_func_json_array_insert)},
74877535
{ { C_STRING_WITH_LEN("JSON_OBJECT") }, BUILDER(Create_func_json_row_object)},
74887536
{ { C_STRING_WITH_LEN("JSON_SEARCH") }, BUILDER(Create_func_json_search)},
74897537
{ { C_STRING_WITH_LEN("JSON_SET") }, BUILDER(Create_func_json_set)},

0 commit comments

Comments
 (0)