From 50831b0f197fd1edb98aa56085e391e5033e2a54 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Tue, 24 Jan 2017 17:34:44 +0400 Subject: [PATCH] MDEV-11557 port MySQL-5.7 JSON tests to MariaDB. json_no_table.test ported. --- include/json_lib.h | 25 +- mysql-test/mysql-test-run.pl | 1 + mysql-test/r/func_json.result | 6 + mysql-test/suite/json/r/json_no_table.result | 3634 ++++++++++++++++++ mysql-test/suite/json/t/json_no_table.test | 2288 +++++++++++ mysql-test/t/func_json.test | 2 + sql/item_jsonfunc.cc | 376 +- sql/item_jsonfunc.h | 1 + sql/share/errmsg-utf8.txt | 2 + strings/json_lib.c | 166 +- 10 files changed, 6293 insertions(+), 208 deletions(-) create mode 100644 mysql-test/suite/json/r/json_no_table.result create mode 100644 mysql-test/suite/json/t/json_no_table.test diff --git a/include/json_lib.h b/include/json_lib.h index ce7f27317bc..ddba571ac59 100644 --- a/include/json_lib.h +++ b/include/json_lib.h @@ -219,7 +219,7 @@ typedef struct st_json_engine_t /* string constants. */ int stack[JSON_DEPTH_LIMIT]; /* Keeps the stack of nested JSON structures. */ - int *stack_p; /* The 'stack' pointer. */ + int stack_p; /* The 'stack' pointer. */ } json_engine_t; @@ -308,7 +308,7 @@ typedef const int *json_level_t; */ #define json_get_level(j) (j->stack_p) -int json_skip_to_level(json_engine_t *j, json_level_t level); +int json_skip_to_level(json_engine_t *j, int level); /* json_skip_level() works as above with just current structre. @@ -391,6 +391,27 @@ int json_append_ascii(CHARSET_INFO *json_cs, uchar *json, uchar *json_end, const uchar *ascii, const uchar *ascii_end); + +/* + Scan the JSON and return paths met one-by-one. + json_get_path_start(&p) + while (json_get_path_next(&p)) + { + handle_the_next_path(); + } +*/ + +int json_get_path_start(json_engine_t *je, CHARSET_INFO *i_cs, + const uchar *str, const uchar *end, + json_path_t *p); + + +int json_get_path_next(json_engine_t *je, json_path_t *p); + + +int json_path_compare(const json_path_t *a, const json_path_t *b); + + #ifdef __cplusplus } #endif diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index b3fe2d2f20a..1b6802e6b49 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -182,6 +182,7 @@ my @DEFAULT_SUITES= qw( innodb_fts- innodb_gis- innodb_zip- + json- maria- multi_source- optimizer_unfixed_bugs- diff --git a/mysql-test/r/func_json.result b/mysql-test/r/func_json.result index 6c1987cc3e7..47993ae9a32 100644 --- a/mysql-test/r/func_json.result +++ b/mysql-test/r/func_json.result @@ -212,6 +212,12 @@ json_extract('1', '$') select json_extract('[10, 20, [30, 40], 1, 10]', '$[1]'); json_extract('[10, 20, [30, 40], 1, 10]', '$[1]') 20 +select json_extract('[10, 20, [30, 40], 1, 10]', '$[1]', '$[25]'); +json_extract('[10, 20, [30, 40], 1, 10]', '$[1]', '$[25]') +[20] +select json_extract( '[{"a": [3, 4]}, {"b": 2}]', '$[0].a', '$[1].a'); +json_extract( '[{"a": [3, 4]}, {"b": 2}]', '$[0].a', '$[1].a') +[[3, 4]] select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.k1', 'word'); json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.k1', 'word') {"a":1, "b":{"c":1, "k1":"word"}, "d":[1, 2]} diff --git a/mysql-test/suite/json/r/json_no_table.result b/mysql-test/suite/json/r/json_no_table.result new file mode 100644 index 00000000000..514b6a775d4 --- /dev/null +++ b/mysql-test/suite/json/r/json_no_table.result @@ -0,0 +1,3634 @@ +SELECT CAST(0.0e0 AS JSON) = -0.0e0; +CAST(0.0e0 AS JSON) = -0.0e0 +1 +SELECT CAST(CAST(0 AS DECIMAL) AS JSON) = CAST(-0.0e0 AS DECIMAL); +CAST(CAST(0 AS DECIMAL) AS JSON) = CAST(-0.0e0 AS DECIMAL) +1 +SELECT CAST(0.0e0 AS JSON) = CAST(-0.0e0 AS DECIMAL); +CAST(0.0e0 AS JSON) = CAST(-0.0e0 AS DECIMAL) +1 +SELECT CAST(CAST(0 AS DECIMAL) AS JSON) = -0.0e0; +CAST(CAST(0 AS DECIMAL) AS JSON) = -0.0e0 +1 +SELECT CAST(CAST(0 AS SIGNED) AS JSON) = -0.0e0; +CAST(CAST(0 AS SIGNED) AS JSON) = -0.0e0 +1 +SELECT CAST(CAST(0 AS SIGNED) AS JSON) = CAST(-0.0e0 AS DECIMAL); +CAST(CAST(0 AS SIGNED) AS JSON) = CAST(-0.0e0 AS DECIMAL) +1 +SELECT CAST(CAST(0 AS UNSIGNED) AS JSON) = -0.0e0; +CAST(CAST(0 AS UNSIGNED) AS JSON) = -0.0e0 +1 +SELECT CAST(CAST(0 AS UNSIGNED) AS JSON) = CAST(-0.0e0 AS DECIMAL); +CAST(CAST(0 AS UNSIGNED) AS JSON) = CAST(-0.0e0 AS DECIMAL) +1 +select cast('"abc"' as json); +cast('"abc"' as json) +"abc" +error ER_INVALID_JSON_TEXT_IN_PARAM +select cast('abc' as json); +cast('abc' as json) +abc + +# String literal - valid JSON +select JSON_VALID('123'); +JSON_VALID('123') +1 +select JSON_VALID('-123'); +JSON_VALID('-123') +1 +select JSON_VALID('5000000000'); +JSON_VALID('5000000000') +1 +select JSON_VALID('-5000000000'); +JSON_VALID('-5000000000') +1 +select JSON_VALID('1.23'); +JSON_VALID('1.23') +1 +select JSON_VALID('"123"'); +JSON_VALID('"123"') +1 +select JSON_VALID('true'); +JSON_VALID('true') +1 +select JSON_VALID('false'); +JSON_VALID('false') +1 +select JSON_VALID('null'); +JSON_VALID('null') +1 +select JSON_VALID('{"address": "Trondheim"}'); +JSON_VALID('{"address": "Trondheim"}') +1 + +# String literal - not valid JSON +select JSON_VALID('12 3'); +JSON_VALID('12 3') +0 + +# String literal not in UTF-8 +set names 'ascii'; +select JSON_VALID('123'); +JSON_VALID('123') +1 +set names 'utf8'; + +# Json expression +select JSON_VALID(cast('[123]' as JSON )); +JSON_VALID(cast('[123]' as JSON )) +1 + +# Json expression NULL +select JSON_VALID(cast(NULL as JSON )); +JSON_VALID(cast(NULL as JSON )) +NULL + +# Bare NULL +select JSON_VALID( NULL ); +JSON_VALID( NULL ) +NULL + +# Function result - string +select JSON_VALID( UPPER('"abc"') ); +JSON_VALID( UPPER('"abc"') ) +1 +set names 'latin1'; + +# Function result - string +select JSON_VALID( UPPER('"abc"') ); +JSON_VALID( UPPER('"abc"') ) +1 +set names 'utf8'; + +# Function result - date, not valid as JSON without CAST +select JSON_VALID( CAST('2015-01-15' AS DATE) ); +JSON_VALID( CAST('2015-01-15' AS DATE) ) +0 + +# The date string doesn't parse as JSON text, so wrong: +select JSON_VALID( CAST(CAST('2015-01-15' AS DATE) as CHAR CHARACTER SET 'utf8') ); +JSON_VALID( CAST(CAST('2015-01-15' AS DATE) as CHAR CHARACTER SET 'utf8') ) +0 +# OK, though: +select JSON_VALID( CAST(CURDATE() as JSON) ); +JSON_VALID( CAST(CURDATE() as JSON) ) +0 + +# Function result - NULL +select JSON_VALID( UPPER(NULL) ); +JSON_VALID( UPPER(NULL) ) +NULL +select JSON_VALID( UPPER(CAST(NULL as CHAR)) ); +JSON_VALID( UPPER(CAST(NULL as CHAR)) ) +NULL +SELECT JSON_VALID( '{ "firstName" : "Fred", "lastName" : "Flintstone" }' ); +JSON_VALID( '{ "firstName" : "Fred", "lastName" : "Flintstone" }' ) +1 +SELECT JSON_VALID( '3' ); +JSON_VALID( '3' ) +1 +SELECT JSON_VALID( null ); +JSON_VALID( null ) +NULL +# ---------------------------------------------------------------------- +# Test of JSON_CONTAINS_PATH function. +# ---------------------------------------------------------------------- +select json_contains_path(); +ERROR 42000: Incorrect parameter count in the call to native function 'json_contains_path' +select json_contains_path('{ "a": true }' ); +ERROR 42000: Incorrect parameter count in the call to native function 'json_contains_path' +select json_contains_path('{ "a": true }', 'all' ); +ERROR 42000: Incorrect parameter count in the call to native function 'json_contains_path' +error ER_INVALID_JSON_TEXT_IN_PARAM +select json_contains_path('{ "a": tru }', 'all', '$' ); +json_contains_path('{ "a": tru }', 'all', '$' ) +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_contains_path' at position 10 +error ER_INVALID_JSON_PATH +select json_contains_path('{ "a": true }', 'all', '$[' ); +json_contains_path('{ "a": true }', 'all', '$[' ) +NULL +Warnings: +Warning 4041 Unexpected end of JSON path in argument 3 to function 'json_contains_path' +error ER_INVALID_JSON_PATH +select json_contains_path('{ "a": true }', 'all', '$a.***[3]' ); +json_contains_path('{ "a": true }', 'all', '$a.***[3]' ) +NULL +Warnings: +Warning 4042 Syntax error in JSON path in argument 3 to function 'json_contains_path' at position 2 +error ER_JSON_BAD_ONE_OR_ALL_ARG +select json_contains_path('{ "a": true }', 'foo', '$.a' ); +json_contains_path('{ "a": true }', 'foo', '$.a' ) +NULL +Warnings: +Warning 4046 Argument 2 to function 'json_contains_path' must be "one" or "all". +error ER_INVALID_JSON_CHARSET +select json_contains_path('{}', 'all', cast('$' as binary)); +json_contains_path('{}', 'all', cast('$' as binary)) +1 +select json_contains_path(null, 'all', '$.a' ); +json_contains_path(null, 'all', '$.a' ) +NULL +select json_contains_path('{ "a": true }', null, '$.a' ); +json_contains_path('{ "a": true }', null, '$.a' ) +NULL +select json_contains_path('{ "a": true }', 'all', null ); +json_contains_path('{ "a": true }', 'all', null ) +NULL +select json_contains_path('{ "a": true }', 'all', '$' ); +json_contains_path('{ "a": true }', 'all', '$' ) +1 +select json_contains_path('{ "a": true }', 'all', '$.a' ); +json_contains_path('{ "a": true }', 'all', '$.a' ) +1 +select json_contains_path('{ "a": true }', 'one', '$.a' ); +json_contains_path('{ "a": true }', 'one', '$.a' ) +1 +select json_contains_path('{ "a": true }', 'all', '$.b' ); +json_contains_path('{ "a": true }', 'all', '$.b' ) +0 +select json_contains_path('{ "a": true }', 'one', '$.b' ); +json_contains_path('{ "a": true }', 'one', '$.b' ) +0 +select json_contains_path('{ "a": true }', 'all', '$.a', '$.b' ); +json_contains_path('{ "a": true }', 'all', '$.a', '$.b' ) +0 +select json_contains_path('{ "a": true }', 'all', '$.b', '$.a' ); +json_contains_path('{ "a": true }', 'all', '$.b', '$.a' ) +0 +select json_contains_path('{ "a": true }', 'ALL', '$.a', '$.b' ); +json_contains_path('{ "a": true }', 'ALL', '$.a', '$.b' ) +0 +select json_contains_path('{ "a": true }', 'aLl', '$.a', '$.b' ); +json_contains_path('{ "a": true }', 'aLl', '$.a', '$.b' ) +0 +select json_contains_path('{ "a": true }', 'one', '$.a', '$.b' ); +json_contains_path('{ "a": true }', 'one', '$.a', '$.b' ) +1 +select json_contains_path('{ "a": true }', 'one', '$.b', '$.a' ); +json_contains_path('{ "a": true }', 'one', '$.b', '$.a' ) +1 +select json_contains_path('{ "a": true }', 'ONE', '$.a', '$.b' ); +json_contains_path('{ "a": true }', 'ONE', '$.a', '$.b' ) +1 +select json_contains_path('{ "a": true }', 'oNe', '$.a', '$.b' ); +json_contains_path('{ "a": true }', 'oNe', '$.a', '$.b' ) +1 +select json_contains_path('{ "a": true, "b": [ 1, 2, { "c": [ 4, 5, { "d": [ 6, 7, 8, 9, 10 ]} ] } ] }', 'all', '$**[4]' ); +json_contains_path('{ "a": true, "b": [ 1, 2, { "c": [ 4, 5, { "d": [ 6, 7, 8, 9, 10 ]} ] } ] }', 'all', '$**[4]' ) +1 +select json_contains_path('{ "a": true, "b": [ 1, 2, { "c": [ 4, 5, { "d": [ 6, 7, 8, 9, 10 ]} ] } ] }', 'all', '$**[4]', '$**[5]' ); +json_contains_path('{ "a": true, "b": [ 1, 2, { "c": [ 4, 5, { "d": [ 6, 7, 8, 9, 10 ]} ] } ] }', 'all', '$**[4]', '$**[5]' ) +0 +select json_contains_path('{ "a": true, "b": [ 1, 2, { "c": [ 4, 5, { "d": [ 6, 7, 8, 9, 10 ]} ] } ] }', 'all', '$**.c[2]' ); +json_contains_path('{ "a": true, "b": [ 1, 2, { "c": [ 4, 5, { "d": [ 6, 7, 8, 9, 10 ]} ] } ] }', 'all', '$**.c[2]' ) +1 +select json_contains_path('{ "a": true, "b": [ 1, 2, { "c": [ 4, 5, { "d": [ 6, 7, 8, 9, 10 ]} ] } ] }', 'all', '$**.c[3]' ); +json_contains_path('{ "a": true, "b": [ 1, 2, { "c": [ 4, 5, { "d": [ 6, 7, 8, 9, 10 ]} ] } ] }', 'all', '$**.c[3]' ) +0 +select json_contains_path('{"a":1, "b":2}', 'one', '$.*'); +json_contains_path('{"a":1, "b":2}', 'one', '$.*') +1 +select json_contains_path('[1,2,3]', 'one', '$.*'); +json_contains_path('[1,2,3]', 'one', '$.*') +0 +select json_contains_path('{}', 'one', '$[*]'); +json_contains_path('{}', 'one', '$[*]') +0 +SELECT JSON_CONTAINS_PATH('[1, [[{"x": [{"a":{"b":{"c":42}}}]}]]]', +'one', '$**.a.*'); +JSON_CONTAINS_PATH('[1, [[{"x": [{"a":{"b":{"c":42}}}]}]]]', +'one', '$**.a.*') +1 +SELECT JSON_CONTAINS_PATH('[1, [[{"x": [{"a":{"b":{"c":42}}}]}]]]', +'all', '$**.a.*'); +JSON_CONTAINS_PATH('[1, [[{"x": [{"a":{"b":{"c":42}}}]}]]]', +'all', '$**.a.*') +1 +SELECT JSON_CONTAINS_PATH('[1,2,3]', 'one', '$**[*]'); +JSON_CONTAINS_PATH('[1,2,3]', 'one', '$**[*]') +1 +SELECT JSON_CONTAINS_PATH('[1,2,3]', 'all', '$**[*]'); +JSON_CONTAINS_PATH('[1,2,3]', 'all', '$**[*]') +1 +select json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'all', '$**[1]', '$.b[0]', '$.c' ); +json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'all', '$**[1]', '$.b[0]', '$.c' ) +0 +select json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'all', '$.c', '$**[1]', '$.b[0]' ); +json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'all', '$.c', '$**[1]', '$.b[0]' ) +0 +select json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'all', '$.b[0]', '$.c', '$**[1]' ); +json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'all', '$.b[0]', '$.c', '$**[1]' ) +0 +select json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'one', '$**[1]', '$.b[0]', '$.c' ); +json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'one', '$**[1]', '$.b[0]', '$.c' ) +1 +select json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'one', '$.c', '$**[1]', '$.b[0]' ); +json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'one', '$.c', '$**[1]', '$.b[0]' ) +1 +select json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'one', '$.b[0]', '$.c', '$**[1]' ); +json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'one', '$.b[0]', '$.c', '$**[1]' ) +1 +SELECT JSON_CONTAINS_PATH +( +'{ "a" : 123, "b" : [ 123, 456 ] }', +'all', +'$.a.c', +'$.b[1]' +); +JSON_CONTAINS_PATH +( +'{ "a" : 123, "b" : [ 123, 456 ] }', +'all', +'$.a.c', +'$.b[1]' +) +0 +SELECT JSON_CONTAINS_PATH +( +'{ "a" : 123, "b" : [ 123, 456 ] }', +'one', +'$.a.c', +'$.b[1]' +); +JSON_CONTAINS_PATH +( +'{ "a" : 123, "b" : [ 123, 456 ] }', +'one', +'$.a.c', +'$.b[1]' +) +1 +SELECT JSON_CONTAINS_PATH +( +'{ "a" : 123, "b" : [ 123, 456 ] }', +'all', +'$.c' +); +JSON_CONTAINS_PATH +( +'{ "a" : 123, "b" : [ 123, 456 ] }', +'all', +'$.c' +) +0 +SELECT JSON_CONTAINS_PATH +( +'{ "a" : 123, "b" : [ 123, { "c" : { "d" : true } } ] }', +'all', +'$.b[1].c.d' +); +JSON_CONTAINS_PATH +( +'{ "a" : 123, "b" : [ 123, { "c" : { "d" : true } } ] }', +'all', +'$.b[1].c.d' +) +1 +select json_length( null ); +json_length( null ) +NULL +select json_length( '1' ); +json_length( '1' ) +1 + +# invalid json text +error ER_INVALID_JSON_TEXT_IN_PARAM +select json_length( 'abc' ); +json_length( 'abc' ) +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_length' at position 1 +select json_length( '"abc"' ); +json_length( '"abc"' ) +1 +select json_length( 'true' ); +json_length( 'true' ) +1 +select json_length( 'false' ); +json_length( 'false' ) +1 +select json_length( 'null' ); +json_length( 'null' ) +1 +select json_length( '{}' ); +json_length( '{}' ) +0 +select json_length( '{ "a" : 100, "b" : 200 }' ); +json_length( '{ "a" : 100, "b" : 200 }' ) +2 +select json_length( '{ "a" : 100, "b" : [ 300, 400, 500 ] }' ); +json_length( '{ "a" : 100, "b" : [ 300, 400, 500 ] }' ) +2 +select json_length( '[]' ); +json_length( '[]' ) +0 +select json_length( '[ null, "foo", true, 1.1 ]' ); +json_length( '[ null, "foo", true, 1.1 ]' ) +4 +select json_length( '[ null, "foo", true, { "a" : "b", "c" : "d" } ]' ); +json_length( '[ null, "foo", true, { "a" : "b", "c" : "d" } ]' ) +4 +select json_length( '"foo"' ); +json_length( '"foo"' ) +1 +select json_length( '1.2' ); +json_length( '1.2' ) +1 + +# invalid json path +error ER_INVALID_JSON_PATH +select json_length( 'true', 'c$' ); +json_length( 'true', 'c$' ) +NULL +Warnings: +Warning 4042 Syntax error in JSON path in argument 2 to function 'json_length' at position 1 + +# invalid json path +error ER_INVALID_JSON_PATH +select json_length( '{ "foo" : [ true, false ] }', '$.foo[bar]' ); +json_length( '{ "foo" : [ true, false ] }', '$.foo[bar]' ) +NULL +Warnings: +Warning 4042 Syntax error in JSON path in argument 2 to function 'json_length' at position 7 + +# wildcards not allowed in path expressions for this function +error ER_INVALID_JSON_PATH_WILDCARD +select json_length( 'true', '$.*' ); +json_length( 'true', '$.*' ) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_length' + +# wildcards not allowed in path expressions for this function +error ER_INVALID_JSON_PATH_WILDCARD +select json_length( 'true', '$.foo**.bar' ); +json_length( 'true', '$.foo**.bar' ) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_length' +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[0]' ); +json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[0]' ) +1 +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[1]' ); +json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[1]' ) +3 +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]' ) +NULL +select json_length( '[ 1, [ 2, 3, 4 ], {"a": 1} ]', '$[2][0]' ); +json_length( '[ 1, [ 2, 3, 4 ], {"a": 1} ]', '$[2][0]' ) +NULL +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][1]' ); +json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][1]' ) +NULL +select json_length( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]' ); +json_length( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]' ) +3 +SELECT JSON_LENGTH +( +'{}' +); +JSON_LENGTH +( +'{}' +) +0 +SELECT JSON_LENGTH +( +'3' +); +JSON_LENGTH +( +'3' +) +1 +SELECT JSON_LENGTH +( +'{ "a" : 123, "b" : [ 123, 456, 789 ] }' +); +JSON_LENGTH +( +'{ "a" : 123, "b" : [ 123, 456, 789 ] }' +) +2 +SELECT JSON_LENGTH +( +'{ "a" : 123, "b" : [ 123, 456, 789 ] }', +'$.b' +); +JSON_LENGTH +( +'{ "a" : 123, "b" : [ 123, 456, 789 ] }', +'$.b' +) +3 +SELECT JSON_LENGTH +( +'{ "a" : 123, "b" : [ 123, 456, 789 ] }', +'$.c' +); +JSON_LENGTH +( +'{ "a" : 123, "b" : [ 123, 456, 789 ] }', +'$.c' +) +NULL +# ---------------------------------------------------------------------- +# Test of JSON_DEPTH function. +# ---------------------------------------------------------------------- +select json_depth(null); +json_depth(null) +NULL +select json_depth(cast(null as json)); +json_depth(cast(null as json)) +NULL +select json_depth(cast('[]' as json)), +json_depth(cast('{}' as json)), +json_depth(cast('null' as json)), +json_depth(json_quote('foo')); +json_depth(cast('[]' as json)) json_depth(cast('{}' as json)) json_depth(cast('null' as json)) json_depth(json_quote('foo')) +1 1 1 1 +select json_depth(cast('[[2], 3, [[[4]]]]' as json)); +json_depth(cast('[[2], 3, [[[4]]]]' as json)) +5 +select json_depth(cast('{"a": {"a1": [3]}, "b": {"b1": {"c": {"d": [5]}}}}' as json)); +json_depth(cast('{"a": {"a1": [3]}, "b": {"b1": {"c": {"d": [5]}}}}' as json)) +6 +SELECT JSON_DEPTH +( +'{}' +); +JSON_DEPTH +( +'{}' +) +1 +SELECT JSON_DEPTH +( +'[]' +); +JSON_DEPTH +( +'[]' +) +1 +SELECT JSON_DEPTH( '"abc"' ); +JSON_DEPTH( '"abc"' ) +1 +SELECT JSON_DEPTH( CAST( '"abc"' AS JSON ) ); +JSON_DEPTH( CAST( '"abc"' AS JSON ) ) +1 +error ER_INVALID_TYPE_FOR_JSON +SELECT JSON_DEPTH( 1 ); +JSON_DEPTH( 1 ) +1 +error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_DEPTH( 'abc' ); +JSON_DEPTH( 'abc' ) +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_depth' at position 1 +SELECT JSON_DEPTH( CAST( 1 AS JSON ) ); +JSON_DEPTH( CAST( 1 AS JSON ) ) +1 +SELECT JSON_DEPTH +( +'{ "a" : true, "b" : false, "c" : null }' +); +JSON_DEPTH +( +'{ "a" : true, "b" : false, "c" : null }' +) +2 +SELECT JSON_DEPTH +( +'[ "a", true, "b" , false, "c" , null ]' +); +JSON_DEPTH +( +'[ "a", true, "b" , false, "c" , null ]' +) +2 +SELECT JSON_DEPTH +( +'{ "a" : true, "b" : {}, "c" : null }' +); +JSON_DEPTH +( +'{ "a" : true, "b" : {}, "c" : null }' +) +2 +SELECT JSON_DEPTH +( +'[ "a", true, "b" , {}, "c" , null ]' +); +JSON_DEPTH +( +'[ "a", true, "b" , {}, "c" , null ]' +) +2 +SELECT JSON_DEPTH +( +'{ "a" : true, "b" : { "e" : false }, "c" : null }' +); +JSON_DEPTH +( +'{ "a" : true, "b" : { "e" : false }, "c" : null }' +) +3 +SELECT JSON_DEPTH +( +'[ "a", true, "b" , { "e" : false }, "c" , null ]' +); +JSON_DEPTH +( +'[ "a", true, "b" , { "e" : false }, "c" , null ]' +) +3 +error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_DEPTH +( +'[ "a", true, "b" , { "e" : false }, "c" , null' +); +JSON_DEPTH +( +'[ "a", true, "b" , { "e" : false }, "c" , null' +) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_depth' +# ---------------------------------------------------------------------- +# Test of JSON_REMOVE function. +# ---------------------------------------------------------------------- +select json_remove( null, '$[1]' ); +json_remove( null, '$[1]' ) +NULL +select json_remove( null, '$[1]' ) is null; +json_remove( null, '$[1]' ) is null +1 +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', null ); +json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', null ) +NULL +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', null ) is null; +json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', null ) is null +1 +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]', null ); +json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]', null ) +NULL +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]', null ) is null; +json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]', null ) is null +1 + +# not enough args +select json_remove(); +ERROR 42000: Incorrect parameter count in the call to native function 'json_remove' + +# not enough args +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]' ); +ERROR 42000: Incorrect parameter count in the call to native function 'json_remove' + +# not enough args +select json_remove( '$[1]' ); +ERROR 42000: Incorrect parameter count in the call to native function 'json_remove' + +# invalid json text +error ER_INVALID_JSON_TEXT_IN_PARAM +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ', '$[1]', '$[2]' ); +json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ', '$[1]', '$[2]' ) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_remove' + +# invalid json path +error ER_INVALID_JSON_PATH +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1', '$[2]' ); +json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1', '$[2]' ) +NULL +Warnings: +Warning 4041 Unexpected end of JSON path in argument 2 to function 'json_remove' + +# invalid json path +error ER_INVALID_JSON_PATH +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]', '$[2' ); +json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]', '$[2' ) +NULL +Warnings: +Warning 4041 Unexpected end of JSON path in argument 3 to function 'json_remove' + +# Vacuous path expression +error ER_JSON_VACUOUS_PATH +select json_remove( '[ 1, 2, 3 ]', '$' ); +json_remove( '[ 1, 2, 3 ]', '$' ) +NULL +Warnings: +Warning 4051 Path expression '$' is not allowed in argument 2 to function 'json_remove'. + +# Vacuous path expression +error ER_JSON_VACUOUS_PATH +select json_remove( '[ 1, 2, 3 ]', '$', '$[2]' ); +json_remove( '[ 1, 2, 3 ]', '$', '$[2]' ) +NULL +Warnings: +Warning 4051 Path expression '$' is not allowed in argument 2 to function 'json_remove'. + +# Vacuous path expression +error ER_JSON_VACUOUS_PATH +select json_remove( '[ 1, 2, 3 ]', '$[1]', '$' ); +json_remove( '[ 1, 2, 3 ]', '$[1]', '$' ) +NULL +Warnings: +Warning 4051 Path expression '$' is not allowed in argument 3 to function 'json_remove'. +error ER_INVALID_JSON_PATH_WILDCARD +select json_remove( '[ 1, 2, 3 ]', '$[*]' ); +json_remove( '[ 1, 2, 3 ]', '$[*]' ) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_remove' +error ER_INVALID_JSON_PATH_WILDCARD +select json_remove( '[ 1, 2, 3 ]', '$**[2]' ); +json_remove( '[ 1, 2, 3 ]', '$**[2]' ) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_remove' +error ER_INVALID_JSON_PATH_WILDCARD +select json_remove( '[ 1, 2, 3 ]', '$[2]', '$[*]' ); +json_remove( '[ 1, 2, 3 ]', '$[2]', '$[*]' ) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 3 to function 'json_remove' +error ER_INVALID_JSON_PATH_WILDCARD +select json_remove( '[ 1, 2, 3 ]', '$[2]', '$**[2]' ); +json_remove( '[ 1, 2, 3 ]', '$[2]', '$**[2]' ) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 3 to function 'json_remove' +select json_remove( '[ 1, 2, 3 ]', '$[0]' ); +json_remove( '[ 1, 2, 3 ]', '$[0]' ) +[ 2, 3 ] +select json_remove( '[ 1, 2, 3 ]', '$[1]' ); +json_remove( '[ 1, 2, 3 ]', '$[1]' ) +[ 1, 3 ] +select json_remove( '[ 1, 2, 3 ]', '$[2]' ); +json_remove( '[ 1, 2, 3 ]', '$[2]' ) +[ 1, 2] +select json_remove( '[ 1, 2, 3 ]', '$[3]' ); +json_remove( '[ 1, 2, 3 ]', '$[3]' ) +[ 1, 2, 3 ] +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]' ); +json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]' ) +[ 1, 5 ] +error ER_INVALID_JSON_PATH_WILDCARD +select json_remove( '[ { "a": { "a": true } } ]', '$**.a' ); +json_remove( '[ { "a": { "a": true } } ]', '$**.a' ) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_remove' +select json_remove( '[ { "a": true }, { "b": false }, { "c": null }, { "a": null } ]', '$[0].a', '$[2].c' ); +json_remove( '[ { "a": true }, { "b": false }, { "c": null }, { "a": null } ]', '$[0].a', '$[2].c' ) +[ { }, { "b": false }, { }, { "a": null } ] +error ER_INVALID_JSON_PATH_WILDCARD +select json_remove( '[ { "a": true }, { "b": [ { "c": { "a": true } } ] }, { "c": null }, { "a": null } ]', '$**.a' ); +json_remove( '[ { "a": true }, { "b": [ { "c": { "a": true } } ] }, { "c": null }, { "a": null } ]', '$**.a' ) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_remove' +select json_remove( '{"id": 123, "name": "systemQA", "array": [1, 2, 3]}', '$[0]' ); +json_remove( '{"id": 123, "name": "systemQA", "array": [1, 2, 3]}', '$[0]' ) +{"id": 123, "name": "systemQA", "array": [1, 2, 3]} +SELECT JSON_REMOVE +( +'{"a" : "foo", "b" : [true, {"c" : 123}]}', +'$.b[ 1 ]' +); +JSON_REMOVE +( +'{"a" : "foo", "b" : [true, {"c" : 123}]}', +'$.b[ 1 ]' +) +{"a" : "foo", "b" : [true, {"c" : 123}]} +SELECT JSON_REMOVE +( +'{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.b[ 1 ].c' +); +JSON_REMOVE +( +'{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.b[ 1 ].c' +) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_remove' +SELECT JSON_REMOVE +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c' +); +JSON_REMOVE +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c' +) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_remove' +SELECT JSON_REMOVE +( +'{ "a" : "foo", "b" : [ true, { "c" : 123, "d" : 456 } ] }', +'$.b[ 1 ].e' +); +JSON_REMOVE +( +'{ "a" : "foo", "b" : [ true, { "c" : 123, "d" : 456 } ] }', +'$.b[ 1 ].e' +) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_remove' +# ---------------------------------------------------------------------- +# Test of JSON_MERGE function. +# ---------------------------------------------------------------------- + +# not enough args +select json_merge(); +ERROR 42000: Incorrect parameter count in the call to native function 'json_merge' + +# not enough args +select json_merge( '[ 1, 2, 3 ]' ); +ERROR 42000: Incorrect parameter count in the call to native function 'json_merge' +select json_merge( null, null ); +json_merge( null, null ) +NULL +select json_merge( null, '[ 1, 2, 3 ]' ); +json_merge( null, '[ 1, 2, 3 ]' ) +NULL +select json_merge( '[ 1, 2, 3 ]', null ); +json_merge( '[ 1, 2, 3 ]', null ) +NULL +select json_merge( null, '[ 1, 2, 3 ]', '[ 4, 5, 6 ]' ); +json_merge( null, '[ 1, 2, 3 ]', '[ 4, 5, 6 ]' ) +NULL +select json_merge( '[ 1, 2, 3 ]', null, '[ 4, 5, 6 ]' ); +json_merge( '[ 1, 2, 3 ]', null, '[ 4, 5, 6 ]' ) +NULL +select json_merge( '[ 1, 2, 3 ]', '[ 4, 5, 6 ]', null ); +json_merge( '[ 1, 2, 3 ]', '[ 4, 5, 6 ]', null ) +NULL +error ER_INVALID_JSON_TEXT_IN_PARAM +select json_merge( '[1, 2]', '[3, 4' ); +json_merge( '[1, 2]', '[3, 4' ) +[1, 2, 3, 4 +error ER_INVALID_JSON_TEXT_IN_PARAM +select json_merge( '[1, 2', '[3, 4]' ); +json_merge( '[1, 2', '[3, 4]' ) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_merge' +select json_merge( '1', '2' ); +json_merge( '1', '2' ) +[1, 2] +select json_merge( '1', '[2, 3]' ); +json_merge( '1', '[2, 3]' ) +[1, 2, 3] +select json_merge( '[1, 2]', '3' ); +json_merge( '[1, 2]', '3' ) +[1, 2, 3] +select json_merge( '1', '{ "a": 2 }' ); +json_merge( '1', '{ "a": 2 }' ) +[1, { "a": 2 }] +select json_merge( '{ "a": 2 }', '1' ); +json_merge( '{ "a": 2 }', '1' ) +[{ "a": 2 }, 1] +select json_merge( '[1, 2]', '[3, 4]' ); +json_merge( '[1, 2]', '[3, 4]' ) +[1, 2, 3, 4] +select json_merge( '{ "a": 2 }', '{ "b": 3}' ); +json_merge( '{ "a": 2 }', '{ "b": 3}' ) +{ "a": 2 , "b": 3} +select json_merge( '[1, 2]', '{ "a": 2 }' ); +json_merge( '[1, 2]', '{ "a": 2 }' ) +[1, 2, { "a": 2 }] +select json_merge( '{ "a": 2 }', '[1, 2]' ); +json_merge( '{ "a": 2 }', '[1, 2]' ) +[{ "a": 2 }, 1, 2] +select json_merge( '{"a": 1, "b": 2 }', '{"b": 3, "d": 4 }' ); +json_merge( '{"a": 1, "b": 2 }', '{"b": 3, "d": 4 }' ) +{"a": 1, "b": 2 , "b": 3, "d": 4 } +select json_merge( '{"a": 1, "b": 2 }', '{"b": [3, 4], "d": 4 }' ); +json_merge( '{"a": 1, "b": 2 }', '{"b": [3, 4], "d": 4 }' ) +{"a": 1, "b": 2 , "b": [3, 4], "d": 4 } +select json_merge( '{"a": 1, "b": [2, 3] }', '{"b": 4, "d": 4 }' ); +json_merge( '{"a": 1, "b": [2, 3] }', '{"b": 4, "d": 4 }' ) +{"a": 1, "b": [2, 3] , "b": 4, "d": 4 } +select json_merge( '{"a": 1, "b": 2 }', '{"b": {"e": 7, "f": 8}, "d": 4 }' ); +json_merge( '{"a": 1, "b": 2 }', '{"b": {"e": 7, "f": 8}, "d": 4 }' ) +{"a": 1, "b": 2 , "b": {"e": 7, "f": 8}, "d": 4 } +select json_merge( '{"b": {"e": 7, "f": 8}, "d": 4 }', '{"a": 1, "b": 2 }' ); +json_merge( '{"b": {"e": 7, "f": 8}, "d": 4 }', '{"a": 1, "b": 2 }' ) +{"b": {"e": 7, "f": 8}, "d": 4 , "a": 1, "b": 2 } +select json_merge( '{"a": 1, "b": [2, 9] }', '{"b": [10, 11], "d": 4 }' ); +json_merge( '{"a": 1, "b": [2, 9] }', '{"b": [10, 11], "d": 4 }' ) +{"a": 1, "b": [2, 9] , "b": [10, 11], "d": 4 } +select json_merge( '{"a": 1, "b": [2, 9] }', '{"b": {"e": 7, "f": 8}, "d": 4 }' ); +json_merge( '{"a": 1, "b": [2, 9] }', '{"b": {"e": 7, "f": 8}, "d": 4 }' ) +{"a": 1, "b": [2, 9] , "b": {"e": 7, "f": 8}, "d": 4 } +select json_merge( '{"b": {"e": 7, "f": 8}, "d": 4 }', '{"a": 1, "b": [2, 9] }' ); +json_merge( '{"b": {"e": 7, "f": 8}, "d": 4 }', '{"a": 1, "b": [2, 9] }' ) +{"b": {"e": 7, "f": 8}, "d": 4 , "a": 1, "b": [2, 9] } +select json_merge( '{"b": {"e": 7, "f": 8}, "d": 4 }', '{ "a": 1, "b": {"e": 20, "g": 21 } }' ); +json_merge( '{"b": {"e": 7, "f": 8}, "d": 4 }', '{ "a": 1, "b": {"e": 20, "g": 21 } }' ) +{"b": {"e": 7, "f": 8}, "d": 4 , "a": 1, "b": {"e": 20, "g": 21 } } +select json_merge( '1', '2', '3' ); +json_merge( '1', '2', '3' ) +[1, 2, 3] +select json_merge( '[1, 2 ]', '3', '[4, 5]' ); +json_merge( '[1, 2 ]', '3', '[4, 5]' ) +[1, 2 , 3, 4, 5] +select json_merge +( +'{ "a": true, "b": { "c": 3, "d": 4 }, "e": [ 1, 2 ] }', +'{ "d": false, "b": { "g": 3, "d": 5 }, "f": [ 1, 2 ] }', +'{ "m": true, "b": { "h": 8, "d": 4 }, "e": [ 3, 4 ] }' +); +json_merge +( +'{ "a": true, "b": { "c": 3, "d": 4 }, "e": [ 1, 2 ] }', +'{ "d": false, "b": { "g": 3, "d": 5 }, "f": [ 1, 2 ] }', +'{ "m": true, "b": { "h": 8, "d": 4 }, "e": [ 3, 4 ] }' +) +{ "a": true, "b": { "c": 3, "d": 4 }, "e": [ 1, 2 ] , "d": false, "b": { "g": 3, "d": 5 }, "f": [ 1, 2 ] , "m": true, "b": { "h": 8, "d": 4 }, "e": [ 3, 4 ] } +SELECT JSON_MERGE +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'[ 5, 6]' +); +JSON_MERGE +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'[ 5, 6]' +) +[{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }, 5, 6] +SELECT JSON_MERGE +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'{ "b": [ false, 34 ] }' +); +JSON_MERGE +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'{ "b": [ false, 34 ] }' +) +{ "a" : "foo", "b" : [ true, { "c" : 123 } ] , "b": [ false, 34 ] } +SELECT JSON_MERGE +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'{ "b": "bar" }' +); +JSON_MERGE +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'{ "b": "bar" }' +) +{ "a" : "foo", "b" : [ true, { "c" : 123 } ] , "b": "bar" } +SELECT JSON_MERGE +( +'{ "a" : { "b" : 1 } }', +'{ "a" : { "c" : 1 } }' +); +JSON_MERGE +( +'{ "a" : { "b" : 1 } }', +'{ "a" : { "c" : 1 } }' +) +{ "a" : { "b" : 1 } , "a" : { "c" : 1 } } +# ---------------------------------------------------------------------- +# Test of JSON_TYPE function. +# ---------------------------------------------------------------------- +error ER_INVALID_JSON_TEXT_IN_PARAM +select json_type('abc'); +json_type('abc') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_type' at position 1 +select json_type('{"a": 2}'); +json_type('{"a": 2}') +OBJECT +select json_type('[1,2]'); +json_type('[1,2]') +ARRAY +select json_type('"scalar string"'); +json_type('"scalar string"') +STRING +select json_type('true'); +json_type('true') +BOOLEAN +select json_type('false'); +json_type('false') +BOOLEAN +select json_type('null'); +json_type('null') +NULL +select json_type('1'); +json_type('1') +INTEGER +select json_type('-0'); +json_type('-0') +INTEGER +select json_type('-0.0'); +json_type('-0.0') +DOUBLE +error ER_INVALID_TYPE_FOR_JSON +select json_type(-1); +json_type(-1) +INTEGER +error ER_INVALID_TYPE_FOR_JSON +select json_type(CAST(1 AS UNSIGNED)); +json_type(CAST(1 AS UNSIGNED)) +INTEGER +select json_type('32767'); +json_type('32767') +INTEGER +error ER_INVALID_TYPE_FOR_JSON +select json_type(PI()); +json_type(PI()) +DOUBLE +select json_type('3.14'); +json_type('3.14') +DOUBLE +error ER_INVALID_JSON_TEXT_IN_PARAM +select json_type(CAST(CAST('2015-01-15' AS DATE) as CHAR CHARACTER SET 'utf8')); +json_type(CAST(CAST('2015-01-15' AS DATE) as CHAR CHARACTER SET 'utf8')) +INTEGER +# ---------------------------------------------------------------------- +# Test of CAST(literal AS JSON) +# ---------------------------------------------------------------------- +select json_type(cast(cast('2014-11-25 18:00' as datetime) as json)); +json_type(cast(cast('2014-11-25 18:00' as datetime) as json)) +INTEGER +select json_type(cast(cast('2014-11-25' as date) as json)); +json_type(cast(cast('2014-11-25' as date) as json)) +INTEGER +select json_type(cast(cast('18:00:59' as time) as json)); +json_type(cast(cast('18:00:59' as time) as json)) +INTEGER +select json_type(cast(127 as json)); +json_type(cast(127 as json)) +INTEGER +select json_type(cast(255 as json)); +json_type(cast(255 as json)) +INTEGER +select json_type(cast(32767 as json)); +json_type(cast(32767 as json)) +INTEGER +select json_type(cast(65535 as json)); +json_type(cast(65535 as json)) +INTEGER +select json_type(cast(8388607 as json)); +json_type(cast(8388607 as json)) +INTEGER +select json_type(cast(16777215 as json)); +json_type(cast(16777215 as json)) +INTEGER +select json_type(cast(2147483647 as json)); +json_type(cast(2147483647 as json)) +INTEGER +select json_type(cast(4294967295 as json)); +json_type(cast(4294967295 as json)) +INTEGER +select json_type(cast(9223372036854775807 as json)); +json_type(cast(9223372036854775807 as json)) +INTEGER +select json_type(cast(18446744073709551615 as json)); +json_type(cast(18446744073709551615 as json)) +INTEGER +select json_type(cast(true as json)); +json_type(cast(true as json)) +INTEGER +select json_type(cast(b'10101' as json)); +json_type(cast(b'10101' as json)) +NULL +Warnings: +Warning 4036 Character disallowd in JSON in argument 1 to function 'json_type' at position 1 +select json_type(cast(cast(3.14 as decimal(5,2)) as json)); +json_type(cast(cast(3.14 as decimal(5,2)) as json)) +DOUBLE +select json_type(cast(3.14 as json)); +json_type(cast(3.14 as json)) +DOUBLE +select json_type(cast(3.14E30 as json)); +json_type(cast(3.14E30 as json)) +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_type' at position 7 +select json_type(cast(cast('10101abcde' as binary) as json)); +json_type(cast(cast('10101abcde' as binary) as json)) +INTEGER +select json_type(cast(ST_GeomFromText('POINT(1 1)') as json)); +json_type(cast(ST_GeomFromText('POINT(1 1)') as json)) +NULL +Warnings: +Warning 4036 Character disallowd in JSON in argument 1 to function 'json_type' at position 1 +select json_type(cast(ST_GeomFromText('LINESTRING(0 0,1 1,2 2)') as json)); +json_type(cast(ST_GeomFromText('LINESTRING(0 0,1 1,2 2)') as json)) +NULL +Warnings: +Warning 4036 Character disallowd in JSON in argument 1 to function 'json_type' at position 1 +select json_type(cast(ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0), + (5 5,7 5,7 7,5 7, 5 5))') as json)); +json_type(cast(ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0), + (5 5,7 5,7 7,5 7, 5 5))') as json)) +NULL +Warnings: +Warning 4036 Character disallowd in JSON in argument 1 to function 'json_type' at position 1 +select json_type(cast(null as json)); +json_type(cast(null as json)) +NULL +select json_type(cast(null as json)) is null; +json_type(cast(null as json)) is null +1 +select json_type(null) is null; +json_type(null) is null +1 +select cast(cast('2014-11-25 18:00' as datetime) as json); +cast(cast('2014-11-25 18:00' as datetime) as json) +2014-11-25 18:00:00 +select cast(cast('2014-11-25' as date) as json); +cast(cast('2014-11-25' as date) as json) +2014-11-25 +select cast(cast('18:00:59' as time) as json); +cast(cast('18:00:59' as time) as json) +18:00:59 +select cast(127 as json); +cast(127 as json) +127 +select cast(255 as json); +cast(255 as json) +255 +select cast(32767 as json); +cast(32767 as json) +32767 +select cast(65535 as json); +cast(65535 as json) +65535 +select cast(8388607 as json); +cast(8388607 as json) +8388607 +select cast(16777215 as json); +cast(16777215 as json) +16777215 +select cast(2147483647 as json); +cast(2147483647 as json) +2147483647 +select cast(4294967295 as json); +cast(4294967295 as json) +4294967295 +select cast(9223372036854775807 as json); +cast(9223372036854775807 as json) +9223372036854775807 +select cast(18446744073709551615 as json); +cast(18446744073709551615 as json) +18446744073709551615 +select cast(true as json); +cast(true as json) +1 +select cast(b'10101' as json); +cast(b'10101' as json) + +select cast(cast(3.14 as decimal(5,2)) as json); +cast(cast(3.14 as decimal(5,2)) as json) +3.14 +select cast(3.14 as json); +cast(3.14 as json) +3.14 +select cast(3.14e0 as json); +cast(3.14e0 as json) +3.14 +select cast(cast('10101abcde' as binary) as json); +cast(cast('10101abcde' as binary) as json) +10101abcde +select cast(ST_GeomFromText('POINT(1 1)') as json); +cast(ST_GeomFromText('POINT(1 1)') as json) +ð?ð? +select cast(ST_GeomFromText('LINESTRING(0 0,1 1,2 2)') as json); +cast(ST_GeomFromText('LINESTRING(0 0,1 1,2 2)') as json) +ð?ð?@@ +select cast(ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0), + (5 5,7 5,7 7,5 7, 5 5))') as json); +cast(ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0), + (5 5,7 5,7 7,5 7, 5 5))') as json) +$@$@$@$@@@@@@@@@@@ +select cast(null as json); +cast(null as json) +NULL +select cast(null as json) is null; +cast(null as json) is null +1 +# ---------------------------------------------------------------------- +# Test of JSON_KEYS function. +# ---------------------------------------------------------------------- +select json_keys(NULL); +json_keys(NULL) +NULL +select json_keys(NULL, '$.b'); +json_keys(NULL, '$.b') +NULL +select json_keys(NULL, NULL); +json_keys(NULL, NULL) +NULL +select json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a'); +json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a') +NULL +select json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', NULL); +json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', NULL) +NULL +select json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}'); +json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}') +["a", "b"] +select json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.b'); +json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.b') +["e", "b"] +error ER_INVALID_JSON_PATH_WILDCARD +select json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.*.b'); +json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.*.b') +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_keys' +# returns [ "a", "b" ] +SELECT JSON_KEYS('{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }'); +JSON_KEYS('{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }') +["a", "b"] +# returns [] +SELECT JSON_KEYS('{ "a" : "foo", "b" : [ true, { "c" : {} } ] }', +'$.b[1].c'); +JSON_KEYS('{ "a" : "foo", "b" : [ true, { "c" : {} } ] }', +'$.b[1].c') +[] +# returns NULL +SELECT JSON_KEYS('{ "a" : "foo", "b" : [ true, { "c" : {} } ] }', +'$.a.b[2]'); +JSON_KEYS('{ "a" : "foo", "b" : [ true, { "c" : {} } ] }', +'$.a.b[2]') +NULL +error ER_INVALID_JSON_PATH +SELECT JSON_KEYS('{"a":1}', '1010'); +JSON_KEYS('{"a":1}', '1010') +NULL +Warnings: +Warning 4042 Syntax error in JSON path in argument 2 to function 'json_keys' at position 1 +error ER_INVALID_JSON_PATH +SELECT JSON_KEYS('{"a":1}', '1010') IS NULL; +JSON_KEYS('{"a":1}', '1010') IS NULL +0 +SELECT JSON_KEYS +( +'{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }' +); +JSON_KEYS +( +'{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }' +) +["a", "b"] +SELECT JSON_KEYS +( +'{ "a" : "foo", "b" : [ true, { "c" : {} } ] }', +'$.b[1].c' +); +JSON_KEYS +( +'{ "a" : "foo", "b" : [ true, { "c" : {} } ] }', +'$.b[1].c' +) +[] +SELECT JSON_KEYS +( +'{ "a" : "foo", "b" : [ true, { "c" : {} } ] }', +'$.a.b[2]' +); +JSON_KEYS +( +'{ "a" : "foo", "b" : [ true, { "c" : {} } ] }', +'$.a.b[2]' +) +NULL +SELECT JSON_KEYS(); +ERROR 42000: Incorrect parameter count in the call to native function 'JSON_KEYS' +SELECT JSON_KEYS('{}', '$', '$'); +ERROR 42000: Incorrect parameter count in the call to native function 'JSON_KEYS' +# ---------------------------------------------------------------------- +# CAST( AS CHAR). See also 'json_conversions.test' for other +# conversion tests. +# ---------------------------------------------------------------------- +select cast(json_keys('{"a": 1}') as char); +cast(json_keys('{"a": 1}') as char) +["a"] +select cast(cast(1 as json) as char); +cast(cast(1 as json) as char) +1 +select cast(json_keys(NULL) as char); +cast(json_keys(NULL) as char) +NULL +# ---------------------------------------------------------------------- +# Path matching with double-quotes +# ---------------------------------------------------------------------- +select json_extract( '{ "one potato" : 1 }', '$."one potato"' ); +json_extract( '{ "one potato" : 1 }', '$."one potato"' ) +NULL +select json_extract( '{ "a.b" : 1 }', '$."a.b"' ); +json_extract( '{ "a.b" : 1 }', '$."a.b"' ) +NULL +select json_extract( '{ "\\"a\\"": 1}', '$."a"' ); +json_extract( '{ "\\"a\\"": 1}', '$."a"' ) +NULL +select json_extract( '{ "\\"a\\"": 1}', '$."\\"a\\""' ); +json_extract( '{ "\\"a\\"": 1}', '$."\\"a\\""' ) +NULL +Warnings: +Warning 4042 Syntax error in JSON path in argument 2 to function 'json_extract' at position 7 +select json_extract( '{ "a": 1}', '$."a"' ); +json_extract( '{ "a": 1}', '$."a"' ) +NULL +select json_extract( '{ "a": 1}', '$.a' ); +json_extract( '{ "a": 1}', '$.a' ) +1 +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[0]' ); +json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[0]' ) +[ 3, 2 ] +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[0][1]' ); +json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[0][1]' ) +2 +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[1]' ); +json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[1]' ) +[ { "c" : "d" }, 1 ] +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[1][0]' ); +json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[1][0]' ) +{ "c" : "d" } +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[1][0].c' ); +json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[1][0].c' ) +"d" +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$."one potato"' ); +json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$."one potato"' ) +NULL +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.b.c' ); +json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.b.c' ) +6 +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$."b.c"' ); +json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$."b.c"' ) +NULL +# ---------------------------------------------------------------------- +# Test of JSON_EXTRACT function. +# ---------------------------------------------------------------------- +select json_extract(NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_extract' +select json_extract('$.b'); +ERROR 42000: Incorrect parameter count in the call to native function 'json_extract' +select json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}'); +ERROR 42000: Incorrect parameter count in the call to native function 'json_extract' +error ER_INVALID_JSON_TEXT_IN_PARAM +select json_extract('$.a', '{"a": 1, "b": {"e": "foo", "b": 3}}'); +json_extract('$.a', '{"a": 1, "b": {"e": "foo", "b": 3}}') +NULL +Warnings: +Warning 4042 Syntax error in JSON path in argument 2 to function 'json_extract' at position 1 +select json_extract(NULL, '$.b'); +json_extract(NULL, '$.b') +NULL +select json_extract(NULL, NULL); +json_extract(NULL, NULL) +NULL +select json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a'); +json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a') +1 +select json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.*'); +json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.*') +[1, {"e": "foo", "b": 3}] +select json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a', '$.b.e'); +json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a', '$.b.e') +[1, "foo"] +select json_extract('{"a": 1, "b": [1,2,3]}', '$.b[2]'); +json_extract('{"a": 1, "b": [1,2,3]}', '$.b[2]') +3 +select json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a', NULL); +json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a', NULL) +[1] +# returns a JSON value containing just the string "123" +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }', +'$.b[ 1 ].c'); +JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }', +'$.b[ 1 ].c') +NULL +# returns a JSON value containing just the number 123 +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c'); +JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c') +NULL +# raises an error because the document is not valid +error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_EXTRACT('{ "a" : [ }', +'$.b[ 1 ].c'); +JSON_EXTRACT('{ "a" : [ }', +'$.b[ 1 ].c') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 11 +# raises an error because the path is invalid +error ER_INVALID_JSON_PATH +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].'); +JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].') +NULL +Warnings: +Warning 4041 Unexpected end of JSON path in argument 2 to function 'json_extract' +# returns a JSON value containing the number 123 (because of +# auto-wrapping the scalar) +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c[ 0 ]'); +JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c[ 0 ]') +NULL +# returns a JSON value containing the object because of auto-wrapping +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : {"not array": 4} } ] }', +'$.b[ 1 ].c[ 0 ]'); +JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : {"not array": 4} } ] }', +'$.b[ 1 ].c[ 0 ]') +NULL +# returns null because the path, although valid, does not identify a value +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c[ 1 ]'); +JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c[ 1 ]') +NULL +# returns a JSON value containing the number 123 (due to normalization) +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.b[ 1 ].c'); +JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.b[ 1 ].c') +NULL +# returns a JSON array [ "foo", true ] +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.a', '$.b[0]'); +JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.a', '$.b[0]') +["foo", true] +# returns a JSON array [ true ] +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.d', '$.b[0]'); +JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.d', '$.b[0]') +[true] +select json_extract( '[1]', '$[0][0]' ); +json_extract( '[1]', '$[0][0]' ) +NULL +select json_extract( '[1]', '$**[0]' ); +json_extract( '[1]', '$**[0]' ) +[1] +select json_extract( '{ "a": 1 }', '$.a[0]' ); +json_extract( '{ "a": 1 }', '$.a[0]' ) +NULL +select json_extract( '{ "a": 1 }', '$**[0]' ); +json_extract( '{ "a": 1 }', '$**[0]' ) +NULL +select json_extract( '{ "a": 1 }', '$[0].a' ); +json_extract( '{ "a": 1 }', '$[0].a' ) +NULL +select json_extract( '{ "a": 1 }', '$**.a' ); +json_extract( '{ "a": 1 }', '$**.a' ) +[1] +select json_extract( '{ "a": 1 }', '$[0].a[0]' ); +json_extract( '{ "a": 1 }', '$[0].a[0]' ) +NULL +select json_extract( '{ "a": 1 }', '$**[0]' ); +json_extract( '{ "a": 1 }', '$**[0]' ) +NULL +select json_extract( '{ "a": 1 }', '$[0].a' ); +json_extract( '{ "a": 1 }', '$[0].a' ) +NULL +select json_extract( '{ "a": 1 }', '$**.a' ); +json_extract( '{ "a": 1 }', '$**.a' ) +[1] +select json_extract( '{ "a": 1 }', '$[0][0].a' ); +json_extract( '{ "a": 1 }', '$[0][0].a' ) +NULL +select json_extract( '{ "a": 1 }', '$[0][0][0].a' ); +json_extract( '{ "a": 1 }', '$[0][0][0].a' ) +NULL +SELECT JSON_EXTRACT('[1, [[{"x": [{"a":{"b":{"c":42}}}]}]]]', '$**.a.*'); +JSON_EXTRACT('[1, [[{"x": [{"a":{"b":{"c":42}}}]}]]]', '$**.a.*') +[{"c":42}] +SELECT JSON_EXTRACT('[1, [[{"x": [{"a":{"b":{"c":42}}}]}]]]', +'$[1][0][0].x[0].a.*'); +JSON_EXTRACT('[1, [[{"x": [{"a":{"b":{"c":42}}}]}]]]', +'$[1][0][0].x[0].a.*') +[{"c":42}] +SELECT JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }', +'$.b[ 1 ].c' +); +JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }', +'$.b[ 1 ].c' +) +NULL +SELECT JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c' +); +JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c' +) +NULL +error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_EXTRACT +( +'{ "a" : [ }', +'$.b[ 1 ].c' +); +JSON_EXTRACT +( +'{ "a" : [ }', +'$.b[ 1 ].c' +) +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 11 +error ER_INVALID_JSON_PATH +SELECT JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].' +); +JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].' +) +NULL +Warnings: +Warning 4041 Unexpected end of JSON path in argument 2 to function 'json_extract' +SELECT JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c[ 0 ]' +); +JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c[ 0 ]' +) +NULL +SELECT JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c[ 1 ]' +); +JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c[ 1 ]' +) +NULL +SELECT JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.b[ 1 ].c' +); +JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.b[ 1 ].c' +) +NULL +SELECT JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.a', '$.b[0]' +); +JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.a', '$.b[0]' +) +["foo", true] +SELECT JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.d', '$.b[0]' +); +JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.d', '$.b[0]' +) +[true] +select json_extract( '[ { "a": 1 }, { "a": 2 } ]', '$[*].b' ) jdoc; +jdoc +NULL +select json_extract( '[ { "a": 1 }, { "a": 2 } ]', '$[0].b' ) jdoc; +jdoc +NULL +select json_extract( '[ { "a": 1 }, { "a": 2 } ]', '$[0].a' ) jdoc; +jdoc +1 +select json_extract( '[ { "a": 1 }, { "a": 2 } ]', '$[*].a' ) jdoc; +jdoc +[1, 2] +select json_extract( '[ { "a": 1 }, { "b": 2 } ]', '$[*].a' ) jdoc; +jdoc +[1] +select json_extract( '[ { "a": [3,4] }, { "b": 2 } ]', '$[0].a' ) jdoc; +jdoc +[3,4] +select json_extract( '[ { "a": [3,4] }, { "b": 2 } ]', '$[*].a' ) jdoc; +jdoc +[[3,4]] +select json_extract( '[ { "a": [3,4] }, { "b": 2 } ]', '$[0].a', '$[1].a' ) jdoc; +jdoc +[[3,4]] +# ---------------------------------------------------------------------- +# Test of JSON_ARRAY_APPEND function. +# ---------------------------------------------------------------------- +select json_array_append(NULL, '$.b', cast(1 as json)); +json_array_append(NULL, '$.b', cast(1 as json)) +NULL +select json_array_append('[1,2,3]', NULL, cast(1 as json)); +json_array_append('[1,2,3]', NULL, cast(1 as json)) +NULL +select json_array_append('[1,2,3]', '$', NULL); +json_array_append('[1,2,3]', '$', NULL) +[1,2,3, null] +select json_array_append(NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_array_append' +select json_array_append(NULL, NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_array_append' +select json_array_append(NULL, NULL, NULL, NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_array_append' +SELECT JSON_ARRAY_APPEND(cast('1' as json), '$', 3); +JSON_ARRAY_APPEND(cast('1' as json), '$', 3) +[1, 3] +SELECT JSON_ARRAY_APPEND(cast('{"a": 3}' as json), '$', 3); +JSON_ARRAY_APPEND(cast('{"a": 3}' as json), '$', 3) +[{"a": 3}, 3] +error ER_INVALID_JSON_PATH_WILDCARD +select json_array_append(cast('{"a": {"b": [3]}}' as json), '$**[0]', 6); +json_array_append(cast('{"a": {"b": [3]}}' as json), '$**[0]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_array_append' +# Auto-wrapping, since because the paths identify scalars. +# should return {"a": "foo", "b": ["bar", 4], "c": ["wibble", "grape"]} +SELECT JSON_ARRAY_APPEND('{"a": "foo", "b": "bar", "c": "wibble"}', +'$.b', cast(4 as json), +'$.c', cast('"grape"' as json)); +JSON_ARRAY_APPEND('{"a": "foo", "b": "bar", "c": "wibble"}', +'$.b', cast(4 as json), +'$.c', cast('"grape"' as json)) +{"a": "foo", "b": ["bar", 4], "c": ["wibble", "grape"]} +# should return {"a": "foo", "b": [1, 2, 3, 4], +# "c": ["apple", "pear", "grape"]} +SELECT JSON_ARRAY_APPEND('{"a" : "foo","b": [1, 2, 3], "c": ["apple", "pear"]}', +'$.b', cast(4 as json), +'$.c', cast('"grape"' as json)); +JSON_ARRAY_APPEND('{"a" : "foo","b": [1, 2, 3], "c": ["apple", "pear"]}', +'$.b', cast(4 as json), +'$.c', cast('"grape"' as json)) +{"a" : "foo","b": [1, 2, 3, 4], "c": ["apple", "pear", "grape"]} +SELECT JSON_ARRAY_APPEND('{"a" : "foo","b": [1, 2, 3], "c": ["apple", "pear"]}', +'$.b', 4, +'$.c', 'grape'); +JSON_ARRAY_APPEND('{"a" : "foo","b": [1, 2, 3], "c": ["apple", "pear"]}', +'$.b', 4, +'$.c', 'grape') +{"a" : "foo","b": [1, 2, 3, 4], "c": ["apple", "pear", "grape"]} +error ER_INVALID_JSON_PATH_WILDCARD +select json_array_append( '[[], [], []]', '$[*]', 3, '$[*]', 4); +json_array_append( '[[], [], []]', '$[*]', 3, '$[*]', 4) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_array_append' +error ER_INVALID_JSON_PATH_WILDCARD +select json_array_append( '[[], "not array", []]', '$[*]', 3, '$[*]', 4); +json_array_append( '[[], "not array", []]', '$[*]', 3, '$[*]', 4) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_array_append' +SELECT JSON_ARRAY_APPEND +( +'{ "a" : "foo", "b" : "bar", "c" : "wibble" }', +'$.b', 4, +'$.c', "grape" +); +JSON_ARRAY_APPEND +( +'{ "a" : "foo", "b" : "bar", "c" : "wibble" }', +'$.b', 4, +'$.c', "grape" +) +{ "a" : "foo", "b" : ["bar", 4], "c" : ["wibble", "grape"] } +SELECT JSON_ARRAY_APPEND +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ], "c" : [ "apple", "pear" ] }', +'$.b', 4, +'$.c', "grape" +); +JSON_ARRAY_APPEND +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ], "c" : [ "apple", "pear" ] }', +'$.b', 4, +'$.c', "grape" +) +{ "a" : "foo", "b" : [ 1, 2, 3 , 4], "c" : [ "apple", "pear" , "grape"] } +# ---------------------------------------------------------------------- +# Bug#21373874 ASSERTION `PARENT' FAILED +# ---------------------------------------------------------------------- +select json_array_append('{"a":1}', '$[0]', 100); +json_array_append('{"a":1}', '$[0]', 100) +NULL +select json_array_append('3', '$[0]', 100); +json_array_append('3', '$[0]', 100) +NULL +select json_array_append('3', '$[0][0][0][0]', 100); +json_array_append('3', '$[0][0][0][0]', 100) +NULL +# ---------------------------------------------------------------------- +# Test of JSON_INSERT function. +# ---------------------------------------------------------------------- +select json_insert(NULL, '$.b', cast(1 as json)); +json_insert(NULL, '$.b', cast(1 as json)) +NULL +select json_insert('[1,2,3]', NULL, cast(1 as json)); +json_insert('[1,2,3]', NULL, cast(1 as json)) +NULL +select json_insert('[1,2,3]', '$[3]', NULL); +json_insert('[1,2,3]', '$[3]', NULL) +[1,2,3, null] +select json_insert(NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_insert' +select json_insert(NULL, NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_insert' +select json_insert(NULL, NULL, NULL, NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_insert' +select json_insert('[1,2,3]', '$[2]', 4); +json_insert('[1,2,3]', '$[2]', 4) +[1,2,3] +select json_insert('[1,2,3]', '$[3]', 4); +json_insert('[1,2,3]', '$[3]', 4) +[1,2,3, 4] +select json_insert('[1,2,3]', '$[10]', 4); +json_insert('[1,2,3]', '$[10]', 4) +[1,2,3, 4] +select json_insert('{"c":4}', '$.c', 4); +json_insert('{"c":4}', '$.c', 4) +{"c":4} +select json_insert('{"c":4}', '$.a', 4); +json_insert('{"c":4}', '$.a', 4) +{"c":4, "a":4} +select json_insert('1', '$', 4); +json_insert('1', '$', 4) +[1, 4] +select json_insert('1', '$[0]', 4); +json_insert('1', '$[0]', 4) +[1, 4] +select json_insert('1', '$[1]', 4); +json_insert('1', '$[1]', 4) +[1, 4] +select json_insert('1', '$[10]', '4', '$[11]', 5); +json_insert('1', '$[10]', '4', '$[11]', 5) +[1, "4", 5] +select json_insert('[1,2,3]', '$[2][0]', 4); +json_insert('[1,2,3]', '$[2][0]', 4) +[1,2,[3, 4]] +select json_insert('[1,2,3]', '$[2][2]', 4); +json_insert('[1,2,3]', '$[2][2]', 4) +[1,2,[3, 4]] +select json_insert('{"a": 3}', '$.a[0]', 4); +json_insert('{"a": 3}', '$.a[0]', 4) +{"a": [3, 4]} +select json_insert('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5'); +json_insert('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5') +{"a": [3, 4, "5"]} +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('{"a": [1], "b": 2}' as json), '$.*[1]', 6); +json_insert(cast('{"a": [1], "b": 2}' as json), '$.*[1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('{"a": 1, "b": 2}' as json), '$.*[1]', 6); +json_insert(cast('{"a": 1, "b": 2}' as json), '$.*[1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('{"a": {"b": 3}}' as json), '$.a.*[1]', 6); +json_insert(cast('{"a": {"b": 3}}' as json), '$.a.*[1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('{"a": {"b": [3]}}' as json), '$.a.*[1]', 6); +json_insert(cast('{"a": {"b": [3]}}' as json), '$.a.*[1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('{"a": {"b": 3}}' as json), '$**[1]', 6); +json_insert(cast('{"a": {"b": 3}}' as json), '$**[1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('{"a": {"b": [3]}}' as json), '$**[1]', 6); +json_insert(cast('{"a": {"b": [3]}}' as json), '$**[1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('[1]' as json), '$[*][1]', 6); +json_insert(cast('[1]' as json), '$[*][1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('[1]' as json), '$**[1]', 6); +json_insert(cast('[1]' as json), '$**[1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('[1, [2], 3]' as json), '$[*][1]', 6); +json_insert(cast('[1, [2], 3]' as json), '$[*][1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('[1, [2], 3]' as json), '$**[1]', 6); +json_insert(cast('[1, [2], 3]' as json), '$**[1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('[[1]]' as json), '$[*][1]', 6); +json_insert(cast('[[1]]' as json), '$[*][1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('[[1]]' as json), '$**[1]', 6); +json_insert(cast('[[1]]' as json), '$**[1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +select json_insert(cast('{"a": 3}' as json), '$[1]', 6); +json_insert(cast('{"a": 3}' as json), '$[1]', 6) +[{"a": 3}, 6] +SELECT JSON_INSERT('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.a', true); +JSON_INSERT('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.a', true) +{ "a" : "foo", "b" : [ 1, 2, 3 ] } +SELECT JSON_INSERT('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.c', 123); +JSON_INSERT('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.c', 123) +{ "a" : "foo", "b" : [ 1, 2, 3 ] , "c":123} +SELECT JSON_INSERT('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.c', '123'); +JSON_INSERT('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.c', '123') +{ "a" : "foo", "b" : [ 1, 2, 3 ] , "c":"123"} +SELECT JSON_INSERT('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.a[1]', true); +JSON_INSERT('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.a[1]', true) +{ "a" : ["foo", true], "b" : [ 1, 2, 3 ] } +SELECT JSON_INSERT('{ "a" : "foo"}', '$.b', true, '$.b', false); +JSON_INSERT('{ "a" : "foo"}', '$.b', true, '$.b', false) +{ "a" : "foo", "b":true} +SELECT JSON_INSERT +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.a', +true +); +JSON_INSERT +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.a', +true +) +{ "a" : "foo", "b" : [ 1, 2, 3 ] } +SELECT JSON_INSERT +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.c', +123 +); +JSON_INSERT +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.c', +123 +) +{ "a" : "foo", "b" : [ 1, 2, 3 ] , "c":123} +SELECT JSON_INSERT +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.c', +'123' +); +JSON_INSERT +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.c', +'123' +) +{ "a" : "foo", "b" : [ 1, 2, 3 ] , "c":"123"} +SELECT JSON_INSERT +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.a[1]', +true +); +JSON_INSERT +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.a[1]', +true +) +{ "a" : ["foo", true], "b" : [ 1, 2, 3 ] } +SELECT JSON_INSERT +( +'{ "a" : "foo"}', +'$.b', true, +'$.b', false +); +JSON_INSERT +( +'{ "a" : "foo"}', +'$.b', true, +'$.b', false +) +{ "a" : "foo", "b":true} +# ---------------------------------------------------------------------- +# Test of JSON_ARRAY_INSERT function. +# ---------------------------------------------------------------------- +select json_array_insert(NULL, '$.b[1]', 1); +json_array_insert(NULL, '$.b[1]', 1) +NULL +select json_array_insert('[1,2,3]', NULL, 1); +json_array_insert('[1,2,3]', NULL, 1) +NULL +select json_array_insert('[1,2,3]', '$[3]', NULL); +json_array_insert('[1,2,3]', '$[3]', NULL) +[1,2,3, null] +select json_array_insert(NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_array_insert' +select json_array_insert(NULL, NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_array_insert' +select json_array_insert(NULL, NULL, NULL, NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_array_insert' +error ER_INVALID_JSON_PATH_ARRAY_CELL +select json_array_insert('true', '$', 1); +json_array_insert('true', '$', 1) +NULL +error ER_INVALID_JSON_PATH_ARRAY_CELL +select json_array_insert('true', '$.a', 1); +json_array_insert('true', '$.a', 1) +NULL +error ER_INVALID_JSON_PATH_ARRAY_CELL +select json_array_insert('true', '$.a[1].b', 1); +json_array_insert('true', '$.a[1].b', 1) +NULL +select json_array_insert( 'true', '$[0]', false ); +json_array_insert( 'true', '$[0]', false ) +true +select json_array_insert( 'true', '$[1]', false ); +json_array_insert( 'true', '$[1]', false ) +true +select json_array_insert( '{ "a": true }', '$.a[0]', false ); +json_array_insert( '{ "a": true }', '$.a[0]', false ) +{ "a": true } +select json_array_insert( '{ "a": true }', '$.a[1]', false ); +json_array_insert( '{ "a": true }', '$.a[1]', false ) +{ "a": true } +select json_array_insert( '[]', '$[0]', false ); +json_array_insert( '[]', '$[0]', false ) +[false] +select json_array_insert( '[]', '$[1]', false ); +json_array_insert( '[]', '$[1]', false ) +[false] +select json_array_insert( '[true]', '$[0]', false ); +json_array_insert( '[true]', '$[0]', false ) +[false, true] +select json_array_insert( '[true]', '$[1]', false ); +json_array_insert( '[true]', '$[1]', false ) +[true, false] +select json_array_insert( '[true]', '$[2]', false ); +json_array_insert( '[true]', '$[2]', false ) +[true, false] +select json_array_insert( '{ "a": [] }', '$.a[0]', false ); +json_array_insert( '{ "a": [] }', '$.a[0]', false ) +{ "a": [false] } +select json_array_insert( '{ "a": [] }', '$.a[1]', false ); +json_array_insert( '{ "a": [] }', '$.a[1]', false ) +{ "a": [false] } +select json_array_insert( '{ "a": [true] }', '$.a[0]', false ); +json_array_insert( '{ "a": [true] }', '$.a[0]', false ) +{ "a": [false, true] } +select json_array_insert( '{ "a": [true] }', '$.a[1]', false ); +json_array_insert( '{ "a": [true] }', '$.a[1]', false ) +{ "a": [true, false] } +select json_array_insert( '{ "a": [true] }', '$.a[2]', false ); +json_array_insert( '{ "a": [true] }', '$.a[2]', false ) +{ "a": [true, false] } +select json_array_insert( '[1, 2, 3, 4]', '$[0]', false ); +json_array_insert( '[1, 2, 3, 4]', '$[0]', false ) +[false, 1, 2, 3, 4] +select json_array_insert( '[1, 2, 3, 4]', '$[1]', false ); +json_array_insert( '[1, 2, 3, 4]', '$[1]', false ) +[1, false, 2, 3, 4] +select json_array_insert( '[1, 2, 3, 4]', '$[2]', false ); +json_array_insert( '[1, 2, 3, 4]', '$[2]', false ) +[1, 2, false, 3, 4] +select json_array_insert( '[1, 2, 3, 4]', '$[3]', false ); +json_array_insert( '[1, 2, 3, 4]', '$[3]', false ) +[1, 2, 3, false, 4] +select json_array_insert( '[1, 2, 3, 4]', '$[4]', false ); +json_array_insert( '[1, 2, 3, 4]', '$[4]', false ) +[1, 2, 3, 4, false] +select json_array_insert( '[1, 2, 3, 4]', '$[5]', false ); +json_array_insert( '[1, 2, 3, 4]', '$[5]', false ) +[1, 2, 3, 4, false] +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[0]', false ); +json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[0]', false ) +{ "a": [false, 1, 2, 3, 4] } +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[1]', false ); +json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[1]', false ) +{ "a": [1, false, 2, 3, 4] } +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[2]', false ); +json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[2]', false ) +{ "a": [1, 2, false, 3, 4] } +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[3]', false ); +json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[3]', false ) +{ "a": [1, 2, 3, false, 4] } +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[4]', false ); +json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[4]', false ) +{ "a": [1, 2, 3, 4, false] } +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[5]', false ); +json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[5]', false ) +{ "a": [1, 2, 3, 4, false] } +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.b[0]', false ); +json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.b[0]', false ) +{ "a": [1, 2, 3, 4] } +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.b[1]', false ); +json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.b[1]', false ) +{ "a": [1, 2, 3, 4] } +select json_array_insert( '"a"', '$[0]', true ); +json_array_insert( '"a"', '$[0]', true ) +"a" +select json_array_insert( '[ "a" ]', '$[0][0]', true ); +json_array_insert( '[ "a" ]', '$[0][0]', true ) +[ "a" ] +select json_array_insert( '"a"', '$[1]', true ); +json_array_insert( '"a"', '$[1]', true ) +"a" +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert('[]', '$.a.*[1]', 6); +json_insert('[]', '$.a.*[1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert('[]', '$**[1]', 6); +json_insert('[]', '$**[1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert('[]', '$[*][1]', 6); +json_insert('[]', '$[*][1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +select json_array_insert( '[ 1, 2, 3 ]', '$[1]', true, '$[1]', false ); +json_array_insert( '[ 1, 2, 3 ]', '$[1]', true, '$[1]', false ) +[ 1, false, true, 2, 3 ] +select json_array_insert( '[ 1, 2, 3 ]', '$[1]', +cast( '[ "a", "b", "c", "d" ]' as json ), '$[1][2]', false ); +json_array_insert( '[ 1, 2, 3 ]', '$[1]', +cast( '[ "a", "b", "c", "d" ]' as json ), '$[1][2]', false ) +[ 1, [ "a", "b", false, "c", "d" ], 2, 3 ] +error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_ARRAY_INSERT(JSON_EXTRACT('[1', '$'), '$[0]', 1); +JSON_ARRAY_INSERT(JSON_EXTRACT('[1', '$'), '$[0]', 1) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_extract' +error ER_INVALID_JSON_TEXT_IN_PARAM +select json_array_insert( '[ 1, 2, 3 ]', '$[1]', json_extract( '[', '$' ) ); +json_array_insert( '[ 1, 2, 3 ]', '$[1]', json_extract( '[', '$' ) ) +[ 1, null, 2, 3 ] +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_extract' +# ---------------------------------------------------------------------- +# Test of JSON_SET function. +# ---------------------------------------------------------------------- +select json_set(NULL, '$.b', cast(1 as json)); +json_set(NULL, '$.b', cast(1 as json)) +NULL +select json_set('[1,2,3]', NULL, cast(1 as json)); +json_set('[1,2,3]', NULL, cast(1 as json)) +NULL +select json_set('[1,2,3]', '$[3]', NULL); +json_set('[1,2,3]', '$[3]', NULL) +[1,2,3, null] +select json_set(NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_set' +select json_set(NULL, NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_set' +select json_set(NULL, NULL, NULL, NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_set' +error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_SET('{}', '$.name', JSON_EXTRACT('', '$')); +JSON_SET('{}', '$.name', JSON_EXTRACT('', '$')) +{, "name":null} +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_extract' +select json_set('[1,2,3]', '$[2]', 4); +json_set('[1,2,3]', '$[2]', 4) +[1,2,4] +select json_set('[1,2,3]', '$[3]', 4); +json_set('[1,2,3]', '$[3]', 4) +[1,2,3, 4] +select json_set('[1,2,3]', '$[10]', 4); +json_set('[1,2,3]', '$[10]', 4) +[1,2,3, 4] +select json_set('{"c":4}', '$.c', 5); +json_set('{"c":4}', '$.c', 5) +{"c":5} +select json_set('{"c":4}', '$.a', 5); +json_set('{"c":4}', '$.a', 5) +{"c":4, "a":5} +select json_set('1', '$', 4); +json_set('1', '$', 4) +[1, 4] +select json_set('1', '$[0]', 4); +json_set('1', '$[0]', 4) +[1, 4] +select json_set('1', '$[1]', 4); +json_set('1', '$[1]', 4) +[1, 4] +select json_set('1', '$[10]', '4', '$[11]', 5); +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]] +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]} +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"]} +error ER_INVALID_JSON_PATH_WILDCARD +select json_set(cast('{"a": {"b": [3]}}' as json), '$**[1]', 6); +json_set(cast('{"a": {"b": [3]}}' as json), '$**[1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_set' +SELECT JSON_SET('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.a', +JSON_OBJECT()); +JSON_SET('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.a', +JSON_OBJECT()) +{ "a" : {}, "b" : [ 1, 2, 3 ] } +SELECT JSON_SET('{ "a" : "foo"}', '$.a', +JSON_OBJECT( 'b', false ), '$.a.c', true); +JSON_SET('{ "a" : "foo"}', '$.a', +JSON_OBJECT( 'b', false ), '$.a.c', true) +{ "a" : {"b": false, "c":true}} +select json_set('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.a', +cast('{}' as json)); +json_set('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.a', +cast('{}' as json)) +{ "a" : {}, "b" : [ 1, 2, 3 ] } +select json_set('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.c', +cast('[true, false]' as json)); +json_set('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.c', +cast('[true, false]' as json)) +{ "a" : "foo", "b" : [ 1, 2, 3 ] , "c":[true, false]} +select json_set('1', '$[3]', 2); +json_set('1', '$[3]', 2) +[1, 2] +select json_set('{ "a" : "foo"}', '$.a', +cast('{"b": false}' as json), '$.a.c', true); +json_set('{ "a" : "foo"}', '$.a', +cast('{"b": false}' as json), '$.a.c', true) +{ "a" : {"b": false, "c":true}} +SELECT JSON_SET +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.a', +JSON_OBJECT() +); +JSON_SET +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.a', +JSON_OBJECT() +) +{ "a" : {}, "b" : [ 1, 2, 3 ] } +SELECT JSON_SET +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.c', +JSON_ARRAY( true, false ) +); +JSON_SET +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.c', +JSON_ARRAY( true, false ) +) +{ "a" : "foo", "b" : [ 1, 2, 3 ] , "c":[true, false]} +SELECT JSON_SET +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.c', +JSON_ARRAY( CAST( 'true' AS JSON ), CAST( 'false' AS JSON ) ) +); +JSON_SET +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.c', +JSON_ARRAY( CAST( 'true' AS JSON ), CAST( 'false' AS JSON ) ) +) +{ "a" : "foo", "b" : [ 1, 2, 3 ] , "c":[true, false]} +SELECT JSON_SET +( +'1', +'$[3]', +2 +); +JSON_SET +( +'1', +'$[3]', +2 +) +[1, 2] +SELECT JSON_SET +( +'{ "a" : "foo"}', +'$.a', JSON_OBJECT( 'b', false ), +'$.a.c', true +); +JSON_SET +( +'{ "a" : "foo"}', +'$.a', JSON_OBJECT( 'b', false ), +'$.a.c', true +) +{ "a" : {"b": false, "c":true}} +# ---------------------------------------------------------------------- +# Test of JSON_REPLACE function. +# ---------------------------------------------------------------------- +select json_replace(NULL, '$.b', cast(1 as json)); +json_replace(NULL, '$.b', cast(1 as json)) +NULL +select json_replace('[1,2,3]', NULL, cast(1 as json)); +json_replace('[1,2,3]', NULL, cast(1 as json)) +NULL +select json_replace('[1,2,3]', '$[2]', NULL); +json_replace('[1,2,3]', '$[2]', NULL) +[1,2,null] +select json_replace(NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_replace' +select json_replace(NULL, NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_replace' +select json_replace(NULL, NULL, NULL, NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_replace' +select json_replace('[1,2,3]', '$[2]', 4); +json_replace('[1,2,3]', '$[2]', 4) +[1,2,4] +select json_replace('[1,2,3]', '$[3]', 4); +json_replace('[1,2,3]', '$[3]', 4) +[1,2,3] +select json_replace('[1,2,3]', '$[10]', 4); +json_replace('[1,2,3]', '$[10]', 4) +[1,2,3] +select json_replace('{"c":4}', '$.c', 5); +json_replace('{"c":4}', '$.c', 5) +{"c":5} +select json_replace('{"c":4}', '$.a', 5); +json_replace('{"c":4}', '$.a', 5) +{"c":4} +select json_replace('1', '$', 4); +json_replace('1', '$', 4) +1 +select json_replace('1', '$[0]', 4); +json_replace('1', '$[0]', 4) +1 +select json_replace('1', '$[1]', 4); +json_replace('1', '$[1]', 4) +1 +select json_replace('1', '$[10]', '4', '$[11]', 5); +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] +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} +select json_replace('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5'); +json_replace('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5') +{"a": 3} +SELECT JSON_REPLACE('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.c', +true); +JSON_REPLACE('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.c', +true) +{ "a" : "foo", "b" : [ 1, 2, 3 ] } +SELECT JSON_REPLACE('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.a[0]', +true); +JSON_REPLACE('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.a[0]', +true) +{ "a" : "foo", "b" : [ 1, 2, 3 ] } +SELECT JSON_REPLACE('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.b[5]', +true); +JSON_REPLACE('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.b[5]', +true) +{ "a" : "foo", "b" : [ 1, 2, 3 ] } +# ---------------------------------------------------------------------- +# Test of JSON_ARRAY function. +# ---------------------------------------------------------------------- +select json_array(NULL, '$.b', cast(1 as json)); +json_array(NULL, '$.b', cast(1 as json)) +[null, "$.b", 1] +select json_array('[1,2,3]', NULL, cast(1 as json)); +json_array('[1,2,3]', NULL, cast(1 as json)) +["[1,2,3]", null, 1] +select json_array('[1,2,3]', '$[3]', NULL); +json_array('[1,2,3]', '$[3]', NULL) +["[1,2,3]", "$[3]", null] +select json_array(); +json_array() +[] +select json_array(3.14); +json_array(3.14) +[3.14] +select json_array('[1,2,3]'); +json_array('[1,2,3]') +["[1,2,3]"] +select json_array(cast('[1,2,3]' as json)); +json_array(cast('[1,2,3]' as json)) +[[1,2,3]] +select json_array(1,2,3); +json_array(1,2,3) +[1, 2, 3] +select json_array(b'0', b'1', b'10'); +json_array(b'0', b'1', b'10') +["\u0000", "\u0001", "\u0002"] +SELECT JSON_ARRAY(); +JSON_ARRAY() +[] +# ---------------------------------------------------------------------- +# Test of JSON_OBJECT function. +# ---------------------------------------------------------------------- +select json_object( 'a' ); +ERROR 42000: Incorrect parameter count in the call to native function 'json_object' +select json_object( 'a', 1, 'b' ); +ERROR 42000: Incorrect parameter count in the call to native function 'json_object' +error ER_JSON_DOCUMENT_NULL_KEY +select json_object( null, 1 ); +json_object( null, 1 ) +{"": 1} +select json_object(); +json_object() +{} +select json_object( 'a', null ); +json_object( 'a', null ) +{"a": null} +select json_object( 'a', 1 ); +json_object( 'a', 1 ) +{"a": 1} +select json_object( 'a', 1, 'b', 'foo' ); +json_object( 'a', 1, 'b', 'foo' ) +{"a": 1, "b": "foo"} +select json_object( 'a', 1, 'b', 'foo', 'c', cast( '{ "d": "wibble" }' as json ) ); +json_object( 'a', 1, 'b', 'foo', 'c', cast( '{ "d": "wibble" }' as json ) ) +{"a": 1, "b": "foo", "c": { "d": "wibble" }} +select json_object( 'a', true, 'b', false, 'c', cast( 'null' as json) ); +json_object( 'a', true, 'b', false, 'c', cast( 'null' as json) ) +{"a": true, "b": false, "c": null} +select json_valid( json_object( '"a"', 1 ) ); +json_valid( json_object( '"a"', 1 ) ) +0 +select json_object( REPEAT('a', 64 * 1024), 1 ); +json_object( REPEAT('a', 64 * 1024), 1 ) +{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa": 1} +select json_object(json_array(), json_array()); +json_object(json_array(), json_array()) +{"[]": []} +select json_object( cast(json_array() as char), json_array()); +json_object( cast(json_array() as char), json_array()) +{"[]": []} +select json_object( 1, json_array()); +json_object( 1, json_array()) +{"1": []} +select json_object( cast(1 as char), json_array()); +json_object( cast(1 as char), json_array()) +{"1": []} +SELECT JSON_OBJECT(); +JSON_OBJECT() +{} +# ---------------------------------------------------------------------- +# Test of JSON_SEARCH function. +# ---------------------------------------------------------------------- +select json_search(); +ERROR 42000: Incorrect parameter count in the call to native function 'json_search' +select json_search( '{ "a": true }' ); +ERROR 42000: Incorrect parameter count in the call to native function 'json_search' +select json_search( '{ "a": true }', 'one' ); +ERROR 42000: Incorrect parameter count in the call to native function 'json_search' +select json_search( null, 'one', 'foo' ); +json_search( null, 'one', 'foo' ) +NULL +select json_search( '{ "a": "foo" }', null, 'foo' ); +json_search( '{ "a": "foo" }', null, 'foo' ) +NULL +select json_search( '{ "a": "foo" }', 'one', 'foo', null, null ); +json_search( '{ "a": "foo" }', 'one', 'foo', null, null ) +NULL +select json_search( '{ "a": "foo" }', 'one', 'foo', null, '$.a', null ); +json_search( '{ "a": "foo" }', 'one', 'foo', null, '$.a', null ) +NULL +error ER_JSON_BAD_ONE_OR_ALL_ARG +select json_search( '{ "a": "foo" }', 'twof', 'foo' ); +json_search( '{ "a": "foo" }', 'twof', 'foo' ) +NULL +Warnings: +Warning 4046 Argument 2 to function 'json_search' must be "one" or "all". +error ER_JSON_BAD_ONE_OR_ALL_ARG +select json_search( '{ "a": "foo" }', 'two', 'foo' ); +json_search( '{ "a": "foo" }', 'two', 'foo' ) +NULL +Warnings: +Warning 4046 Argument 2 to function 'json_search' must be "one" or "all". +select json_search( '{ "a": "foo" }', 'one', 'foo', 'ab' ); +ERROR HY000: Incorrect arguments to ESCAPE +error ER_INVALID_JSON_PATH +select json_search( '{ "a": "foo" }', 'one', 'foo', null, '$a' ); +json_search( '{ "a": "foo" }', 'one', 'foo', null, '$a' ) +NULL +Warnings: +Warning 4042 Syntax error in JSON path in argument 5 to function 'json_search' at position 2 +error ER_INVALID_JSON_PATH +select json_search( '{ "a": "foo" }', 'all', 'foo', null, '$.a', '$b' ); +json_search( '{ "a": "foo" }', 'all', 'foo', null, '$.a', '$b' ) +NULL +Warnings: +Warning 4042 Syntax error in JSON path in argument 6 to function 'json_search' at position 2 +select json_search(a, b, c); +ERROR 42S22: Unknown column 'a' in 'field list' +select json_search( '{ "a": "foobar" }', 'one', 'foo%' ); +json_search( '{ "a": "foobar" }', 'one', 'foo%' ) +"$.a" +select json_search( '{ "a": "foobar", "b": "focus", "c": [ "arm", "foot", "shoulder" ] }', 'one', 'foo%' ); +json_search( '{ "a": "foobar", "b": "focus", "c": [ "arm", "foot", "shoulder" ] }', 'one', 'foo%' ) +"$.a" +select json_search( '{ "a": "foobar", "b": "focus", "c": [ "arm", "foot", "shoulder" ] }', 'all', 'foo%' ); +json_search( '{ "a": "foobar", "b": "focus", "c": [ "arm", "foot", "shoulder" ] }', 'all', 'foo%' ) +["$.a", "$.c[1]"] +select json_search( '{ "a": "foobar", "b": "focus", "c": [ "arm", "foot", "shoulder" ] }', 'all', 'f__us' ); +json_search( '{ "a": "foobar", "b": "focus", "c": [ "arm", "foot", "shoulder" ] }', 'all', 'f__us' ) +"$.b" +select json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'all', 'foo%', null, '$.a' ); +json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'all', 'foo%', null, '$.a' ) +["$.a[0]", "$.a[2]"] +select json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'all', 'foo%', null, '$.a', '$.b' ); +json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'all', 'foo%', null, '$.a', '$.b' ) +["$.a[0]", "$.a[2]", "$.b"] +select json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'one', 'foo%', null, '$.a', '$.b' ); +json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'one', 'foo%', null, '$.a', '$.b' ) +"$.a[0]" +select json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'ALL', 'foo%', null, '$.a' ); +json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'ALL', 'foo%', null, '$.a' ) +["$.a[0]", "$.a[2]"] +select json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'aLl', 'foo%', null, '$.a', '$.b' ); +json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'aLl', 'foo%', null, '$.a', '$.b' ) +["$.a[0]", "$.a[2]", "$.b"] +select json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'ONE', 'foo%', null, '$.a', '$.b' ); +json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'ONE', 'foo%', null, '$.a', '$.b' ) +"$.a[0]" +select json_search +( +'[ { "a": { "b": { "c": "fool" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "food"} } ]', +'all', +'foo%', +null, +'$**.c' +); +json_search +( +'[ { "a": { "b": { "c": "fool" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "food"} } ]', +'all', +'foo%', +null, +'$**.c' +) +["$[0].a.b.c", "$[2].c.c"] +select json_search +( +'[ { "a": { "b": { "c": "showtime" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "shoe"} } ]', +'all', +'sho%', +null, +'$**.c' +); +json_search +( +'[ { "a": { "b": { "c": "showtime" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "shoe"} } ]', +'all', +'sho%', +null, +'$**.c' +) +["$[0].a.b.c", "$[1].b.c", "$[2].c.c"] +select json_search +( +'[ { "a": { "b": { "c": "showtime" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "shoe"} } ]', +'all', +'sho%e', +null, +'$**.c' +); +json_search +( +'[ { "a": { "b": { "c": "showtime" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "shoe"} } ]', +'all', +'sho%e', +null, +'$**.c' +) +["$[0].a.b.c", "$[2].c.c"] +select json_search +( +'[ { "a": { "b": { "c": "showtime" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "shoe"} } ]', +'all', +'sho%', +null, +'$[*].c' +); +json_search +( +'[ { "a": { "b": { "c": "showtime" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "shoe"} } ]', +'all', +'sho%', +null, +'$[*].c' +) +"$[2].c.c" +select json_search +( +'[ { "a": { "b": { "c": "showtime" } } }, [ { "b": { "c": "shout" } }, { "c": { "c": "shoe"} } ] ]', +'all', +'sho%', +null, +'$[1]**.c' +); +json_search +( +'[ { "a": { "b": { "c": "showtime" } } }, [ { "b": { "c": "shout" } }, { "c": { "c": "shoe"} } ] ]', +'all', +'sho%', +null, +'$[1]**.c' +) +["$[1][0].b.c", "$[1][1].c.c"] +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo%bar' ); +json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo%bar' ) +["$[0]", "$[1]"] +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo\%bar' ); +json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo\%bar' ) +NULL +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|' ); +json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|' ) +"$[1]" +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[0]' ); +json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[0]' ) +NULL +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[0]', '$[1]' ); +json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[0]', '$[1]' ) +"$[1]" +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[0]', '$[1]', '$[2]' ); +json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[0]', '$[1]', '$[2]' ) +"$[1]" +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo\%bar', null ); +json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo\%bar', null ) +"$[1]" +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo\%bar', null, '$[0]' ); +json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo\%bar', null, '$[0]' ) +NULL +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo\%bar', null, '$[1]' ); +json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo\%bar', null, '$[1]' ) +"$[1]" +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[0]' ); +json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[0]' ) +NULL +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[1]' ); +json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[1]' ) +"$[1]" +select json_search( '[ "abc", "ABC" ]', 'all', 'aBc' ); +json_search( '[ "abc", "ABC" ]', 'all', 'aBc' ) +["$[0]", "$[1]"] +select json_search( '[ "abc", "ABC" ]', 'all', 'abc' ); +json_search( '[ "abc", "ABC" ]', 'all', 'abc' ) +["$[0]", "$[1]"] +select json_search( '[ "abc", "ABC" ]', 'all', 'ABC' ); +json_search( '[ "abc", "ABC" ]', 'all', 'ABC' ) +["$[0]", "$[1]"] +select json_search( '[ 10, "10", 1.0, "1.0" ]', 'all', '1%' ); +json_search( '[ 10, "10", 1.0, "1.0" ]', 'all', '1%' ) +["$[0]", "$[1]", "$[2]", "$[3]"] +SELECT JSON_SEARCH +( +'{ "a" : 123, "b" : [ 123, 456 ] }', +'one', +'123' +); +JSON_SEARCH +( +'{ "a" : 123, "b" : [ 123, 456 ] }', +'one', +'123' +) +"$.a" +SELECT JSON_SEARCH +( +'{ "a" : "123", "b" : [ 123, "789", "123", "456", "123" ] }', +'one', +'123', +null, +'$.b' +); +JSON_SEARCH +( +'{ "a" : "123", "b" : [ 123, "789", "123", "456", "123" ] }', +'one', +'123', +null, +'$.b' +) +"$.b[0]" +SELECT JSON_SEARCH +( +'{ "a" : "123", "b" : { "key" : "123" } }', +'one', +'123' +); +JSON_SEARCH +( +'{ "a" : "123", "b" : { "key" : "123" } }', +'one', +'123' +) +"$.a" +SELECT JSON_SEARCH +( +'{ "a" : "1243", "b" : { "key" : "1234" } }', +'one', +'123%' +); +JSON_SEARCH +( +'{ "a" : "1243", "b" : { "key" : "1234" } }', +'one', +'123%' +) +"$.b.key" +SELECT JSON_SEARCH +( +'{ "a" : "1243", "b" : { "key" : "1234", "c": "directorysub%directoryabc" } }', +'one', +'dir%torysub@%dir%', +'@' +); +JSON_SEARCH +( +'{ "a" : "1243", "b" : { "key" : "1234", "c": "directorysub%directoryabc" } }', +'one', +'dir%torysub@%dir%', +'@' +) +"$.b.c" +SELECT JSON_SEARCH +( +'{ "a" : "1243", "b" : { "key" : "1234" } }', +'one', +'123%', +null, +'$.c' +); +JSON_SEARCH +( +'{ "a" : "1243", "b" : { "key" : "1234" } }', +'one', +'123%', +null, +'$.c' +) +NULL +SELECT JSON_UNQUOTE +( +JSON_SEARCH +( +'{ "onepotato": "foot", "one potato": "food" , "one \\"potato": "fool" }', +'all', +'food' + ) +); +JSON_UNQUOTE +( +JSON_SEARCH +( +'{ "onepotato": "foot", "one potato": "food" , "one \\"potato": "fool" }', +'all', +'food' + ) +) +$.one potato +select json_type(case (null is null) when 1 then +cast('null' as json) else +cast('[1,2,3]' as json) end); +json_type(case (null is null) when 1 then +cast('null' as json) else +cast('[1,2,3]' as json) end) +NULL +select json_type(case (null is not null) when 1 then +cast('null' as json) else +cast('[1,2,3]' as json) end); +json_type(case (null is not null) when 1 then +cast('null' as json) else +cast('[1,2,3]' as json) end) +ARRAY +select json_type( if(null is null, +cast('null' as json), +cast('[1,2,3]' as json)) ); +json_type( if(null is null, +cast('null' as json), +cast('[1,2,3]' as json)) ) +NULL +select json_type( if(null is not null, +cast('null' as json), +cast('[1,2,3]' as json))); +json_type( if(null is not null, +cast('null' as json), +cast('[1,2,3]' as json))) +ARRAY +select cast(json_extract(cast(concat('[', cast('["A",2]' as json), ']') as json), +'$[0][1]') as char) = 2; +cast(json_extract(cast(concat('[', cast('["A",2]' as json), ']') as json), +'$[0][1]') as char) = 2 +1 +# ---------------------------------------------------------------------- +# Test of aggregate function MAX, MIN. +# ---------------------------------------------------------------------- +select max(cast('[1,2,3]' as json)); +max(cast('[1,2,3]' as json)) +[1,2,3] +# ---------------------------------------------------------------------- +# Test of JSON_QUOTE, JSON_UNQUOTE +# ---------------------------------------------------------------------- +select json_quote(); +ERROR 42000: Incorrect parameter count in the call to native function 'json_quote' +select json_quote('abc', 'def'); +ERROR 42000: Incorrect parameter count in the call to native function 'json_quote' +select json_quote(NULL, 'def'); +ERROR 42000: Incorrect parameter count in the call to native function 'json_quote' +select json_quote('abc', NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_quote' +select json_unquote(); +ERROR 42000: Incorrect parameter count in the call to native function 'json_unquote' +select json_unquote('"abc"', '"def"'); +ERROR 42000: Incorrect parameter count in the call to native function 'json_unquote' +select json_unquote(NULL, 'def'); +ERROR 42000: Incorrect parameter count in the call to native function 'json_unquote' +select json_unquote('"abc"', NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_unquote' +select json_quote(NULL); +json_quote(NULL) +NULL +select json_unquote(NULL); +json_unquote(NULL) +NULL +select json_quote('abc'); +json_quote('abc') +"abc" +select json_quote(convert('abc' using ascii)); +json_quote(convert('abc' using ascii)) +"abc" +select json_quote(convert('abc' using latin1)); +json_quote(convert('abc' using latin1)) +"abc" +select json_quote(convert('abc' using utf8)); +json_quote(convert('abc' using utf8)) +"abc" +select json_quote(convert('abc' using utf8mb4)); +json_quote(convert('abc' using utf8mb4)) +"abc" +select json_unquote('abc'); +json_unquote('abc') +abc +select json_unquote('"abc"'); +json_unquote('"abc"') +abc +select json_unquote(convert('"abc"' using ascii)); +json_unquote(convert('"abc"' using ascii)) +abc +select json_unquote(convert('"abc"' using latin1)); +json_unquote(convert('"abc"' using latin1)) +abc +select json_unquote(convert('"abc"' using utf8)); +json_unquote(convert('"abc"' using utf8)) +abc +select json_unquote(convert('"abc"' using utf8mb4)); +json_unquote(convert('"abc"' using utf8mb4)) +abc +select json_quote('"'); +json_quote('"') +"\"" +select json_unquote('"'); +json_unquote('"') +" +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_unquote' +error ER_INCORRECT_TYPE +select json_quote(123); +json_quote(123) +NULL +error ER_INCORRECT_TYPE +select json_unquote(123); +json_unquote(123) +123 +select json_unquote('""'); +json_unquote('""') + +select char_length(json_unquote('""')); +char_length(json_unquote('""')) +0 +select json_unquote('"" '); +json_unquote('"" ') + +select json_unquote(cast(json_quote('abc') as json)); +json_unquote(cast(json_quote('abc') as json)) +abc +select cast('{"abc": "foo"}' as json); +cast('{"abc": "foo"}' as json) +{"abc": "foo"} +select json_unquote(cast('{"abc": "foo"}' as json)); +json_unquote(cast('{"abc": "foo"}' as json)) +{"abc": "foo"} +select json_extract(cast('{"abc": "foo"}' as json), '$.abc'); +json_extract(cast('{"abc": "foo"}' as json), '$.abc') +"foo" +select json_unquote(json_extract(cast('{"abc": "foo"}' as json), '$.abc')); +json_unquote(json_extract(cast('{"abc": "foo"}' as json), '$.abc')) +foo +select json_unquote('["a", "b", "c"]'); +json_unquote('["a", "b", "c"]') +["a", "b", "c"] +select json_unquote(cast('["a", "b", "c"]' as json)); +json_unquote(cast('["a", "b", "c"]' as json)) +["a", "b", "c"] +select charset(json_unquote('"abc"')); +charset(json_unquote('"abc"')) +utf8 +select json_quote(convert(X'e68891' using utf8)); +json_quote(convert(X'e68891' using utf8)) +"我" +select json_quote(convert(X'e68891' using utf8mb4)); +json_quote(convert(X'e68891' using utf8mb4)) +"我" +select cast(json_quote(convert(X'e68891' using utf8)) as json); +cast(json_quote(convert(X'e68891' using utf8)) as json) +"我" +select json_unquote(convert(X'e68891' using utf8)); +json_unquote(convert(X'e68891' using utf8)) +我 +select json_quote(json_quote(json_quote('abc'))); +json_quote(json_quote(json_quote('abc'))) +"\"\\\"abc\\\"\"" +select json_unquote(json_unquote(json_unquote( # long round trip of it +json_quote(json_quote(json_quote('abc')))))); +json_unquote(json_unquote(json_unquote( # long round trip of it +json_quote(json_quote(json_quote('abc')))))) +abc +select cast(cast('2015-01-15 23:24:25' as datetime) as json); +cast(cast('2015-01-15 23:24:25' as datetime) as json) +2015-01-15 23:24:25 +select json_unquote(cast(cast('2015-01-15 23:24:25' as datetime) as json)); +json_unquote(cast(cast('2015-01-15 23:24:25' as datetime) as json)) +2015-01-15 23:24:25 +select cast(st_geomfromtext('point(1 1)') as json); +cast(st_geomfromtext('point(1 1)') as json) +ð?ð? +select json_unquote(cast(st_geomfromtext('point(1 1)') as json)); +json_unquote(cast(st_geomfromtext('point(1 1)') as json)) +ð?ð? +SELECT JSON_UNQUOTE( '"abc"' ); +JSON_UNQUOTE( '"abc"' ) +abc +SELECT JSON_UNQUOTE( '"abc' ); +JSON_UNQUOTE( '"abc' ) +"abc +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_unquote' +error ER_INCORRECT_TYPE +SELECT JSON_UNQUOTE( 123 ); +JSON_UNQUOTE( 123 ) +123 +SELECT JSON_UNQUOTE +( CAST( CAST( '"abc"' AS JSON ) AS CHAR ) ); +JSON_UNQUOTE +( CAST( CAST( '"abc"' AS JSON ) AS CHAR ) ) +abc +SELECT JSON_UNQUOTE +( +CAST( +JSON_EXTRACT( '{ "userName" : "fred" }', '$.userName' ) +AS CHAR +) +) = 'fred'; +JSON_UNQUOTE +( +CAST( +JSON_EXTRACT( '{ "userName" : "fred" }', '$.userName' ) +AS CHAR +) +) = 'fred' +1 +SELECT +CAST( +JSON_EXTRACT( '{ "userName" : "fred" }', '$.userName' ) +AS CHAR +) = 'fred'; +CAST( +JSON_EXTRACT( '{ "userName" : "fred" }', '$.userName' ) +AS CHAR +) = 'fred' +0 +SELECT JSON_QUOTE( 'abc' ); +JSON_QUOTE( 'abc' ) +"abc" +error ER_INCORRECT_TYPE +SELECT JSON_QUOTE( 123 ); +JSON_QUOTE( 123 ) +NULL +SELECT CAST( JSON_QUOTE( '123' ) AS JSON ); +CAST( JSON_QUOTE( '123' ) AS JSON ) +"123" +# ---------------------------------------------------------------------- +# Test of JSON_CONTAINS +# ---------------------------------------------------------------------- +# should give NULL +select json_contains(NULL, NULL); +json_contains(NULL, NULL) +NULL +select json_contains(cast('{"a": 1, "b": 2}' as json), NULL); +json_contains(cast('{"a": 1, "b": 2}' as json), NULL) +NULL +select json_contains(NULL, cast('null' as json)); +json_contains(NULL, cast('null' as json)) +NULL +select json_contains(cast('[1]' as json), cast('[1]' as json), NULL); +json_contains(cast('[1]' as json), cast('[1]' as json), NULL) +NULL +# should give 0: +select json_contains(cast(3.14 as json), cast(3 as json)); +json_contains(cast(3.14 as json), cast(3 as json)) +0 +# should give 0: not at top level +select json_contains(cast('{"a": {"b": 7}}' as json), cast('{"b": 7}' as json)); +json_contains(cast('{"a": {"b": 7}}' as json), cast('{"b": 7}' as json)) +0 +# but path argument will fix it: +select json_contains(cast('{"a": {"b": 7}}' as json), cast('{"b": 7}' as json), '$.a'); +json_contains(cast('{"a": {"b": 7}}' as json), cast('{"b": 7}' as json), '$.a') +1 +# but arrays "introspect" +select json_contains(cast('[1,[2.0, 3.0]]' as json), cast('[2.0]' as json)); +json_contains(cast('[1,[2.0, 3.0]]' as json), cast('[2.0]' as json)) +1 +select json_contains(cast('[1, 2, [3, [4, 5]], 6, 7]' as json), cast('5' as json)); +json_contains(cast('[1, 2, [3, [4, 5]], 6, 7]' as json), cast('5' as json)) +1 +# should give 0: just a key +select json_contains(cast('{"a": 1, "b": 2}' as json), cast('"a"' as json)); +json_contains(cast('{"a": 1, "b": 2}' as json), cast('"a"' as json)) +0 +# should give 0: one candidate element doesn't match +select json_contains(cast('[1]' as json), cast('[1,2]' as json)); +json_contains(cast('[1]' as json), cast('[1,2]' as json)) +0 +# should all give 1 +select json_contains(cast('null' as json), cast('null' as json)); +json_contains(cast('null' as json), cast('null' as json)) +1 +# simple object subset +select json_contains(cast('{"a": 1, "b": 2}' as json), cast( '{"a": 1}' as json)); +json_contains(cast('{"a": 1, "b": 2}' as json), cast( '{"a": 1}' as json)) +1 +# simple vector subset +select json_contains(cast('[1, 2, 3]' as json), cast('[1, 3]' as json)); +json_contains(cast('[1, 2, 3]' as json), cast('[1, 3]' as json)) +1 +# auto-wrap, should give 1 +select json_contains(cast('[1, 2, 3]' as json), cast(3 as json)); +json_contains(cast('[1, 2, 3]' as json), cast(3 as json)) +1 +# ok even with nested cast off elements +select json_contains(cast('{"person": {"id": 1, "country": "norway"}}' as json), +cast('{"person": {"country": "norway"}}' as json)); +json_contains(cast('{"person": {"id": 1, "country": "norway"}}' as json), +cast('{"person": {"country": "norway"}}' as json)) +1 +# vector reordering and duplicates is ok +select json_contains(cast('[1,3,5]' as json), cast('[5,3,1,5]' as json)); +json_contains(cast('[1,3,5]' as json), cast('[5,3,1,5]' as json)) +1 +# ok even with more elts in candidate than in doc +select json_contains(cast('[{"b": 4, "a":7}]' as json), cast('[{"a":7},{"b":4}]' as json)); +json_contains(cast('[{"b": 4, "a":7}]' as json), cast('[{"a":7},{"b":4}]' as json)) +1 +select json_contains(cast('[{"b": 4, "a":7}, 5]' as json), cast('[5, {"a":7, "b":4}]' as json)); +json_contains(cast('[{"b": 4, "a":7}, 5]' as json), cast('[5, {"a":7, "b":4}]' as json)) +1 +# ok even with mixed number types that compare equal +select json_contains(cast('[{"b": 4, "a":7}, 5.0]' as json), cast('[5, {"a":7.0E0, "b":4}]' as json)); +json_contains(cast('[{"b": 4, "a":7}, 5.0]' as json), cast('[5, {"a":7.0E0, "b":4}]' as json)) +1 +select json_contains( '{"customer": "cust3"}', '{"customer": "cust1"}' ); +json_contains( '{"customer": "cust3"}', '{"customer": "cust1"}' ) +0 +SELECT JSON_CONTAINS('[null,1,[2,3],true,false]', '[null,1,[3],false]'); +JSON_CONTAINS('[null,1,[2,3],true,false]', '[null,1,[3],false]') +1 +SELECT JSON_CONTAINS('[null,1,[2,3],true,false]', '[null,1,[4],false]'); +JSON_CONTAINS('[null,1,[2,3],true,false]', '[null,1,[4],false]') +0 +SELECT JSON_CONTAINS('[true,false]', '[[true]]'); +JSON_CONTAINS('[true,false]', '[[true]]') +1 +SELECT JSON_CONTAINS('[1,2]', '[[1]]'); +JSON_CONTAINS('[1,2]', '[[1]]') +1 +SELECT JSON_CONTAINS('[1,2]', '1', '$.abc'); +JSON_CONTAINS('[1,2]', '1', '$.abc') +0 +SELECT JSON_CONTAINS('{}', '{}'); +JSON_CONTAINS('{}', '{}') +1 +SELECT JSON_CONTAINS('{}', '{"a":1}'); +JSON_CONTAINS('{}', '{"a":1}') +0 +SELECT JSON_CONTAINS('{"a":1}', '{"a":1,"b":2}'); +JSON_CONTAINS('{"a":1}', '{"a":1,"b":2}') +0 +SELECT JSON_CONTAINS +( +CAST('[1, 4, 6]' AS JSON), +CAST('[1, 6]' AS JSON) +); +JSON_CONTAINS +( +CAST('[1, 4, 6]' AS JSON), +CAST('[1, 6]' AS JSON) +) +1 +SELECT JSON_CONTAINS +( +CAST('{"person": {"id": 1, "country": "norway"}}' AS JSON), +CAST('{"person": {"country": "norway"}}' AS JSON) +); +JSON_CONTAINS +( +CAST('{"person": {"id": 1, "country": "norway"}}' AS JSON), +CAST('{"person": {"country": "norway"}}' AS JSON) +) +1 +SELECT JSON_CONTAINS +( +CAST('[1,3,5]' AS JSON), +CAST('[5,3,1,5]' AS JSON) +); +JSON_CONTAINS +( +CAST('[1,3,5]' AS JSON), +CAST('[5,3,1,5]' AS JSON) +) +1 +SELECT JSON_CONTAINS +( +CAST('[3.14]' AS JSON), +CAST('[3]' AS JSON) +); +JSON_CONTAINS +( +CAST('[3.14]' AS JSON), +CAST('[3]' AS JSON) +) +0 +SELECT JSON_CONTAINS +( +CAST('[1, 2, 3]' AS JSON), +CAST(3 AS JSON) +); +JSON_CONTAINS +( +CAST('[1, 2, 3]' AS JSON), +CAST(3 AS JSON) +) +1 +SELECT JSON_CONTAINS(); +ERROR 42000: Incorrect parameter count in the call to native function 'JSON_CONTAINS' +SELECT JSON_CONTAINS('[1]'); +ERROR 42000: Incorrect parameter count in the call to native function 'JSON_CONTAINS' +SELECT JSON_CONTAINS('[1]', '[1]', '$', '$[0]'); +ERROR 42000: Incorrect parameter count in the call to native function 'JSON_CONTAINS' +# ---------------------------------------------------------------------- +# Wrong collation from JSON_QUOTE caused problems: Set it in +# Item_func_json_quote::fix_length_and_dec. Bug found by Knut. +# Similar issue for JSON_UNQUOTE and JSON_TYPE. +# ---------------------------------------------------------------------- +select json_object("a", ifnull(json_quote('test'), cast('null' as json))); +json_object("a", ifnull(json_quote('test'), cast('null' as json))) +{"a": "\"test\""} +select cast(concat('[', json_quote('ab'), ']') as json); +cast(concat('[', json_quote('ab'), ']') as json) +["ab"] +select cast(concat('[', json_unquote('"12"'), ']') as json); +cast(concat('[', json_unquote('"12"'), ']') as json) +[12] +select cast(concat('["', json_type(cast(1 as json)), '"]') as json); +cast(concat('["', json_type(cast(1 as json)), '"]') as json) +["INTEGER"] +# +# Bug#20912438: ITEM_TYPE_HOLDER::DISPLAY_LENGTH(ITEM*): ASSERTION `0' FAILED +# +(SELECT JSON_KEYS('{ "key80": "2015-04-20 11:53:55"}')) UNION ALL +(SELECT JSON_KEYS('{ "key80": "2015-04-20 11:53:55" }') LIMIT 0); +JSON_KEYS('{ "key80": "2015-04-20 11:53:55"}') +["key80"] +SELECT CAST(1 AS JSON) UNION ALL SELECT CAST(1 AS JSON); +CAST(1 AS JSON) +1 +1 +SELECT COUNT(*), CAST(NULL AS JSON); +COUNT(*) CAST(NULL AS JSON) +1 NULL +error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT COUNT(*), JSON_EXTRACT('not valid json!', '$'); +COUNT(*) JSON_EXTRACT('not valid json!', '$') +1 NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 1 +# ---------------------------------------------------------------------- +# Bug report from John E. +# Crash in Item_copy_json::~Item_copy_json +# ---------------------------------------------------------------------- +EXPLAIN SELECT COUNT(*), JSON_KEYS('{}'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used +select json_search( '{ "a": "foo" }', 'one', 'foo', 'a' ); +json_search( '{ "a": "foo" }', 'one', 'foo', 'a' ) +"$.a" +select json_search( '{ "a": "foo" }', 'one', 'foo', null ); +json_search( '{ "a": "foo" }', 'one', 'foo', null ) +"$.a" +select json_search( '{ "a": "foo" }', 'one', 'foo', convert(x'f8' using latin1) ); +json_search( '{ "a": "foo" }', 'one', 'foo', convert(x'f8' using latin1) ) +"$.a" +select json_search( '{ "a": "foo" }', 'one', 'foo', 'ab' ); +ERROR HY000: Incorrect arguments to ESCAPE +# ---------------------------------------------------------------------- +# Wrong results when Json_path_cache primed is accessed +# during the prepare-phase. +#---------------------------------------------------------------------- +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', null ) is null; +json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', null ) is null +1 +prepare stmt1 from 'select json_remove( ''[ 1, { "a": true, "b": false, "c": null }, 5 ]'', null ) is null'; +execute stmt1; +json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', null ) is null +1 +error ER_INVALID_JSON_PATH +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$.' ) is null; +json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$.' ) is null +0 +error ER_INVALID_JSON_PATH +prepare stmt1 from 'select json_remove( ''[ 1, { "a": true, "b": false, "c": null }, 5 ]'', ''$.'' ) is null'; +# ---------------------------------------------------------------------- +# Bug#20987329 VALUE OF PREPARED STATEMENT PLACEHOLDER FOR PARAMETER +# IN JSON_EXTRACT IS STICKY +#---------------------------------------------------------------------- +prepare json_stmt1 FROM 'select json_contains( ''{ "keyA": [1, 2, 3], "keyB": [4, 5, 6] }'', ''[2]'', ? )'; +set @mypath = '$.keyA'; +execute json_stmt1 USING @mypath; +json_contains( '{ "keyA": [1, 2, 3], "keyB": [4, 5, 6] }', '[2]', ? ) +1 +set @mypath = '$.keyB'; +execute json_stmt1 USING @mypath; +json_contains( '{ "keyA": [1, 2, 3], "keyB": [4, 5, 6] }', '[2]', ? ) +0 +prepare json_stmt2 FROM 'select json_contains_path( ''{ "keyA": [1, 2, 3] }'', ''all'', ? )'; +set @mypath = '$.keyA'; +execute json_stmt2 USING @mypath; +json_contains_path( '{ "keyA": [1, 2, 3] }', 'all', ? ) +1 +set @mypath = '$.keyB'; +execute json_stmt2 USING @mypath; +json_contains_path( '{ "keyA": [1, 2, 3] }', 'all', ? ) +0 +prepare json_stmt3 FROM 'select json_length( ''{ "keyA": [1, 2, 3], "keyB": [1, 2, 3, 4] }'', ? )'; +set @mypath = '$.keyA'; +execute json_stmt3 USING @mypath; +json_length( '{ "keyA": [1, 2, 3], "keyB": [1, 2, 3, 4] }', ? ) +3 +set @mypath = '$.keyB'; +execute json_stmt3 USING @mypath; +json_length( '{ "keyA": [1, 2, 3], "keyB": [1, 2, 3, 4] }', ? ) +4 +prepare json_stmt4 FROM 'select json_keys( ''[ { "keyA": true }, { "keyB": false } ]'', ? )'; +set @mypath = '$[0]'; +execute json_stmt4 USING @mypath; +json_keys( '[ { "keyA": true }, { "keyB": false } ]', ? ) +["keyA"] +set @mypath = '$[1]'; +execute json_stmt4 USING @mypath; +json_keys( '[ { "keyA": true }, { "keyB": false } ]', ? ) +["keyB"] +prepare json_stmt5 FROM 'select json_array_append( ''{ "keyA": [1, 2], "keyB": [3, 4] }'', ?, 5 )'; +set @mypath = '$.keyA'; +execute json_stmt5 USING @mypath; +json_array_append( '{ "keyA": [1, 2], "keyB": [3, 4] }', ?, 5 ) +{ "keyA": [1, 2, 5], "keyB": [3, 4] } +set @mypath = '$.keyB'; +execute json_stmt5 USING @mypath; +json_array_append( '{ "keyA": [1, 2], "keyB": [3, 4] }', ?, 5 ) +{ "keyA": [1, 2], "keyB": [3, 4, 5] } +prepare json_stmt6 FROM 'select json_insert( ''{ "keyA": [1, 2], "keyB": [3, 4] }'', ?, 5 )'; +set @mypath = '$.keyA[2]'; +execute json_stmt6 USING @mypath; +json_insert( '{ "keyA": [1, 2], "keyB": [3, 4] }', ?, 5 ) +{ "keyA": [1, 2, 5], "keyB": [3, 4] } +set @mypath = '$.keyB[2]'; +execute json_stmt6 USING @mypath; +json_insert( '{ "keyA": [1, 2], "keyB": [3, 4] }', ?, 5 ) +{ "keyA": [1, 2], "keyB": [3, 4, 5] } +prepare json_stmt7 FROM 'select json_set( ''{ "keyA": [1, 2], "keyB": [3, 4] }'', ?, 5 )'; +set @mypath = '$.keyA[2]'; +execute json_stmt7 USING @mypath; +json_set( '{ "keyA": [1, 2], "keyB": [3, 4] }', ?, 5 ) +{ "keyA": [1, 2, 5], "keyB": [3, 4] } +set @mypath = '$.keyB[2]'; +execute json_stmt7 USING @mypath; +json_set( '{ "keyA": [1, 2], "keyB": [3, 4] }', ?, 5 ) +{ "keyA": [1, 2], "keyB": [3, 4, 5] } +prepare json_stmt8 FROM 'select json_replace( ''{ "keyA": [1, 2], "keyB": [3, 4] }'', ?, 5 )'; +set @mypath = '$.keyA[1]'; +execute json_stmt8 USING @mypath; +json_replace( '{ "keyA": [1, 2], "keyB": [3, 4] }', ?, 5 ) +{ "keyA": [1, 5], "keyB": [3, 4] } +set @mypath = '$.keyB[1]'; +execute json_stmt8 USING @mypath; +json_replace( '{ "keyA": [1, 2], "keyB": [3, 4] }', ?, 5 ) +{ "keyA": [1, 2], "keyB": [3, 5] } +prepare json_stmt9 FROM 'select json_search( ''{ "keyA": [ "foot" ], "keyB": [ "food" ] }'', ''all'', ''foo%'', null, ? )'; +set @mypath = '$.keyA'; +execute json_stmt9 USING @mypath; +json_search( '{ "keyA": [ "foot" ], "keyB": [ "food" ] }', 'all', 'foo%', null, ? ) +"$.keyA[0]" +set @mypath = '$.keyB'; +execute json_stmt9 USING @mypath; +json_search( '{ "keyA": [ "foot" ], "keyB": [ "food" ] }', 'all', 'foo%', null, ? ) +"$.keyB[0]" +prepare json_stmt10 FROM 'select json_remove( ''{ "keyA": [ "foot" ], "keyB": [ "food" ] }'', ? )'; +set @mypath = '$.keyA'; +execute json_stmt10 USING @mypath; +json_remove( '{ "keyA": [ "foot" ], "keyB": [ "food" ] }', ? ) +{ "keyB": [ "food" ] } +set @mypath = '$.keyB'; +execute json_stmt10 USING @mypath; +json_remove( '{ "keyA": [ "foot" ], "keyB": [ "food" ] }', ? ) +{ "keyA": [ "foot" ]} +prepare json_stmt11 FROM 'select json_contains_path( ''{ "keyA": true }'', ?, ''$.keyA'', ''$.keyB'' )'; +set @mypath = 'one'; +execute json_stmt11 USING @mypath; +json_contains_path( '{ "keyA": true }', ?, '$.keyA', '$.keyB' ) +1 +set @mypath = 'all'; +execute json_stmt11 USING @mypath; +json_contains_path( '{ "keyA": true }', ?, '$.keyA', '$.keyB' ) +0 +prepare json_stmt12 FROM 'select json_search( ''{ "keyA": [ "foot" ], "keyB": [ "food" ] }'', ?, ''foo%'' )'; +set @mypath = 'one'; +execute json_stmt12 USING @mypath; +json_search( '{ "keyA": [ "foot" ], "keyB": [ "food" ] }', ?, 'foo%' ) +"$.keyA[0]" +set @mypath = 'all'; +execute json_stmt12 USING @mypath; +json_search( '{ "keyA": [ "foot" ], "keyB": [ "food" ] }', ?, 'foo%' ) +["$.keyA[0]", "$.keyB[0]"] +# +# Bug#21128632 JSON_QUOTE(JSON_TYPE(...)) GIVES ERROR 3139 ER_INVALID_JSON_CHARSET +# +select json_quote( json_type( json_object() ) ); +json_quote( json_type( json_object() ) ) +"OBJECT" +select json_quote( json_type( cast('{}' as json) ) ); +json_quote( json_type( cast('{}' as json) ) ) +"OBJECT" +# +# Bug#21148020 OUTPUT FROM JSON_TYPE() IS TRUNCATED +# WHEN EXECUTED IN A VIEW OR JOIN +# +SELECT JSON_TYPE(JSON_OBJECT()); +JSON_TYPE(JSON_OBJECT()) +OBJECT +CREATE VIEW v1 AS SELECT JSON_TYPE(JSON_OBJECT()); +SELECT * FROM v1; +JSON_TYPE(JSON_OBJECT()) +OBJE +drop view v1; +# +# Bug#21198333 SIG 6 IN ITEM_CACHE_JSON::CACHE_VALUE AT SQL/ITEM.CC:9470 +# +error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT MIN(JSON_EXTRACT('not json', '$')); +MIN(JSON_EXTRACT('not json', '$')) +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 1 +# +# Bug#21200657 DATA FROM DERIVED TABLE BASED +# ON JSN_QUOTE()/JSN_UNQUOTE() CALL IS TRUNCATED +# +SELECT JSON_QUOTE('This is a string that should not be truncated') AS field1; +field1 +"This is a string that should not be truncated" +SELECT JSON_UNQUOTE(JSON_QUOTE('This is a string that should not be truncated')) AS field1; +field1 +This is a string that should not be truncated +SELECT * FROM (SELECT JSON_QUOTE('This is a string that should not be truncated') AS field1) AS DERIVED_TABLE; +field1 +"This is a string that should not be truncated" +SELECT * FROM (SELECT JSON_UNQUOTE("This is a string that should not be truncated") AS field1) AS DERIVED_TABLE; +field1 +This is a string that should not be truncated +SELECT * FROM (SELECT JSON_UNQUOTE(JSON_QUOTE('This is a string that should not be truncated')) AS field1) AS DERIVED_TABLE; +field1 +This is a string that should not be truncated +# +# Bug#21296173 JSON_OBJECT('KEY', BOOLEAN_LITERAL) USES VALUES 0, 1 +# FOR BOOL WHEN USED VIA VIEW +# +SELECT JSON_OBJECT('key1', false, 'key2', true); +JSON_OBJECT('key1', false, 'key2', true) +{"key1": false, "key2": true} +SELECT JSON_ARRAY('key1', false, 'key2', true); +JSON_ARRAY('key1', false, 'key2', true) +["key1", false, "key2", true] +CREATE VIEW v1 AS SELECT JSON_OBJECT('key1', false, 'key2', true); +SELECT * FROM v1; +JSON_OBJECT('key1', false, 'key2', true) +{"key1": 0, "key2": 1} +CREATE VIEW v2 AS SELECT JSON_ARRAY('key1', false, 'key2', true); +SELECT * FROM v2; +JSON_ARRAY('key1', false, 'key2', true) +["key1", 0, "key2", 1] +drop view v1; +drop view v2; +# +# Bug#21293089 JSON_CONTAINS() RETURNS WRONG RESULT WITH EMPTY JSON ARRAY +# +SELECT JSON_CONTAINS('[]', '{"a" : 1}'); +JSON_CONTAINS('[]', '{"a" : 1}') +0 +SELECT JSON_CONTAINS('[]', '[1, 2, 3, 4, 5]'); +JSON_CONTAINS('[]', '[1, 2, 3, 4, 5]') +0 +SELECT JSON_CONTAINS('[]', '[1, 2, 3, 4, {"a" : 1}]'); +JSON_CONTAINS('[]', '[1, 2, 3, 4, {"a" : 1}]') +0 +SELECT JSON_CONTAINS('[]', '{"a" : [1, 2, 3, 4, 5]}'); +JSON_CONTAINS('[]', '{"a" : [1, 2, 3, 4, 5]}') +0 +SELECT JSON_CONTAINS('[]', '[]'); +JSON_CONTAINS('[]', '[]') +1 +# +# Bug#21377136 STACK OVERFLOW IN RAPIDJSON::GENERICREADER +# +error ER_JSON_DOCUMENT_TOO_DEEP +SELECT JSON_VALID(REPEAT('[', 100000)); +JSON_VALID(REPEAT('[', 100000)) +0 +error ER_JSON_DOCUMENT_TOO_DEEP +SELECT JSON_VALID(REPEAT('{"a":', 100000)); +JSON_VALID(REPEAT('{"a":', 100000)) +0 +error ER_JSON_DOCUMENT_TOO_DEEP +SELECT JSON_VALID(REPEAT('{"a":[', 100000)); +JSON_VALID(REPEAT('{"a":[', 100000)) +0 +error ER_JSON_DOCUMENT_TOO_DEEP +SELECT JSON_VALID(REPEAT('[{"a":', 100000)); +JSON_VALID(REPEAT('[{"a":', 100000)) +0 +# +# Bug#21381806 JSON: ASSERTION FAILED: ARG->NULL_VALUE +# +SELECT JSON_SET(CASE WHEN 1 THEN NULL ELSE NULL END, '{}', '{}'); +JSON_SET(CASE WHEN 1 THEN NULL ELSE NULL END, '{}', '{}') +NULL +SELECT JSON_VALID(CASE WHEN 1 THEN NULL ELSE NULL END); +JSON_VALID(CASE WHEN 1 THEN NULL ELSE NULL END) +NULL +SELECT JSON_ARRAY(CASE WHEN 1 THEN NULL ELSE NULL END); +JSON_ARRAY(CASE WHEN 1 THEN NULL ELSE NULL END) +[null] +# +# Bug#21384048 ASSERTION FAILED: N >= 0 && N <= 308 +# IN RAPIDJSON::INTERNAL::FASTPATH +# +SELECT JSON_EXTRACT('-1E-36181012216111515851075235238', '$'); +JSON_EXTRACT('-1E-36181012216111515851075235238', '$') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 33 +SELECT JSON_EXTRACT('1E-36181012216111515851075235238', '$'); +JSON_EXTRACT('1E-36181012216111515851075235238', '$') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 32 +SELECT JSON_EXTRACT('1E-325', '$'); +JSON_EXTRACT('1E-325', '$') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 6 +SELECT JSON_EXTRACT('1E-324', '$'); +JSON_EXTRACT('1E-324', '$') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 6 +SELECT JSON_EXTRACT('1E-323', '$'); +JSON_EXTRACT('1E-323', '$') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 6 +SELECT JSON_EXTRACT('1E+308', '$'); +JSON_EXTRACT('1E+308', '$') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 6 +error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_EXTRACT('1E+309', '$'); +JSON_EXTRACT('1E+309', '$') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 6 +error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_EXTRACT('1E+36181012216111515851075235238', '$'); +JSON_EXTRACT('1E+36181012216111515851075235238', '$') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 32 +error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_EXTRACT('-1E+36181012216111515851075235238', '$'); +JSON_EXTRACT('-1E+36181012216111515851075235238', '$') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 33 +# +# Bug#21383284: ASSERTION IN SELECT_LEX::SETUP_CONDS +# +SELECT 1 FROM dual WHERE JSON_SEARCH('{}', 'one', 'foo', 'too-long-escape'); +ERROR HY000: Incorrect arguments to ESCAPE +error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT 1 FROM dual WHERE JSON_SEARCH('{}', 'one', 'foo', JSON_EXTRACT('', '$')); +1 +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_extract' +# +# Bug#21442624 INCORRECT RESULT FROM JSON_SET WITH AUTO-WRAPPING +# +SELECT JSON_SET('1', '$', 100); +JSON_SET('1', '$', 100) +[1, 100] +SELECT JSON_SET('1', '$[0]', 100); +JSON_SET('1', '$[0]', 100) +[1, 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' +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' +SELECT JSON_SET('[]', '$', 100); +JSON_SET('[]', '$', 100) +[, 100] +SELECT JSON_SET('[]', '$[0]', 100); +JSON_SET('[]', '$[0]', 100) +[, 100] +SELECT JSON_SET('[]', '$[0][0]', 100); +JSON_SET('[]', '$[0][0]', 100) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_set' +SELECT JSON_SET('[]', '$[0][0][0]', 100); +JSON_SET('[]', '$[0][0][0]', 100) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_set' +SELECT JSON_SET('[1]', '$', 100); +JSON_SET('[1]', '$', 100) +[1, 100] +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) +[[1, 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' +SELECT JSON_SET('[[1]]', '$', 100); +JSON_SET('[[1]]', '$', 100) +[[1], 100] +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]]', '$[0][0][0]', 100); +JSON_SET('[[1]]', '$[0][0][0]', 100) +[[[1, 100]]] +SELECT JSON_SET('[[[1]]]', '$', 100); +JSON_SET('[[[1]]]', '$', 100) +[[[1]], 100] +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]]]', '$[0][0][0]', 100); +JSON_SET('[[[1]]]', '$[0][0][0]', 100) +[[[100]]] +SELECT JSON_REPLACE('1', '$', 100); +JSON_REPLACE('1', '$', 100) +1 +SELECT JSON_REPLACE('1', '$[0]', 100); +JSON_REPLACE('1', '$[0]', 100) +1 +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' +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' +SELECT JSON_REPLACE('[]', '$', 100); +JSON_REPLACE('[]', '$', 100) +[] +SELECT JSON_REPLACE('[]', '$[0]', 100); +JSON_REPLACE('[]', '$[0]', 100) +[] +SELECT JSON_REPLACE('[]', '$[0][0]', 100); +JSON_REPLACE('[]', '$[0][0]', 100) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_update' +SELECT JSON_REPLACE('[]', '$[0][0][0]', 100); +JSON_REPLACE('[]', '$[0][0][0]', 100) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_update' +SELECT JSON_REPLACE('[1]', '$', 100); +JSON_REPLACE('[1]', '$', 100) +[1] +SELECT JSON_REPLACE('[1]', '$[0]', 100); +JSON_REPLACE('[1]', '$[0]', 100) +[100] +SELECT JSON_REPLACE('[1]', '$[0][0]', 100); +JSON_REPLACE('[1]', '$[0][0]', 100) +[1] +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' +SELECT JSON_REPLACE('[[1]]', '$', 100); +JSON_REPLACE('[[1]]', '$', 100) +[[1]] +SELECT JSON_REPLACE('[[1]]', '$[0]', 100); +JSON_REPLACE('[[1]]', '$[0]', 100) +[100] +SELECT JSON_REPLACE('[[1]]', '$[0][0]', 100); +JSON_REPLACE('[[1]]', '$[0][0]', 100) +[[100]] +SELECT JSON_REPLACE('[[1]]', '$[0][0][0]', 100); +JSON_REPLACE('[[1]]', '$[0][0][0]', 100) +[[1]] +SELECT JSON_REPLACE('[[[1]]]', '$', 100); +JSON_REPLACE('[[[1]]]', '$', 100) +[[[1]]] +SELECT JSON_REPLACE('[[[1]]]', '$[0]', 100); +JSON_REPLACE('[[[1]]]', '$[0]', 100) +[100] +SELECT JSON_REPLACE('[[[1]]]', '$[0][0]', 100); +JSON_REPLACE('[[[1]]]', '$[0][0]', 100) +[[100]] +SELECT JSON_REPLACE('[[[1]]]', '$[0][0][0]', 100); +JSON_REPLACE('[[[1]]]', '$[0][0][0]', 100) +[[[100]]] +# +# Bug#21828321: JSON FUNCS CALL DBUG_ABORT OR EXIT() ON WINDOWS! +# +SELECT JSON_ARRAY(LEAST(NULL, NULL), GREATEST(NULL, NULL), LEAST(j1, NULL), +GREATEST(NULL, j2), LEAST(j1, j2), GREATEST(j1, j2)) AS j +FROM (SELECT CAST('1' AS JSON) AS j1, CAST('2' AS JSON) AS j2) t; +j +[null, null, null, null, "1", "2"] diff --git a/mysql-test/suite/json/t/json_no_table.test b/mysql-test/suite/json/t/json_no_table.test new file mode 100644 index 00000000000..584af56a3a9 --- /dev/null +++ b/mysql-test/suite/json/t/json_no_table.test @@ -0,0 +1,2288 @@ +########### suite/json/t/json_notable.test # +# Tests json columns functionality that does not need any tables # +# to be defined (no storage engine functionality) # +# # +# This test copies some tests originally in json.test # +###################################################################### + +# Some extra checks for comparisons between positive and negative zero. +# All should be equal. +SELECT CAST(0.0e0 AS JSON) = -0.0e0; +SELECT CAST(CAST(0 AS DECIMAL) AS JSON) = CAST(-0.0e0 AS DECIMAL); +SELECT CAST(0.0e0 AS JSON) = CAST(-0.0e0 AS DECIMAL); +SELECT CAST(CAST(0 AS DECIMAL) AS JSON) = -0.0e0; +SELECT CAST(CAST(0 AS SIGNED) AS JSON) = -0.0e0; +SELECT CAST(CAST(0 AS SIGNED) AS JSON) = CAST(-0.0e0 AS DECIMAL); +SELECT CAST(CAST(0 AS UNSIGNED) AS JSON) = -0.0e0; +SELECT CAST(CAST(0 AS UNSIGNED) AS JSON) = CAST(-0.0e0 AS DECIMAL); + +# Test that CAST string argument isn't treated as ANY_JSON_ATOM +# in that a MySQL string needs to be parsed to JSON here; it is not +# auto-converted to a JSON string as in ANY_JSON_ATOM contexts. +select cast('"abc"' as json); +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +select cast('abc' as json); + +--echo +--echo # String literal - valid JSON +select JSON_VALID('123'); # uint +select JSON_VALID('-123'); # int +select JSON_VALID('5000000000'); # uint64 +select JSON_VALID('-5000000000'); # int64 +select JSON_VALID('1.23'); # double +select JSON_VALID('"123"'); +select JSON_VALID('true'); +select JSON_VALID('false'); +select JSON_VALID('null'); +select JSON_VALID('{"address": "Trondheim"}'); + +--echo +--echo # String literal - not valid JSON +select JSON_VALID('12 3'); + +--echo +--echo # String literal not in UTF-8 +set names 'ascii'; +# auto-convert to utf-8 +select JSON_VALID('123'); + +set names 'utf8'; + +--echo +--echo # Json expression +select JSON_VALID(cast('[123]' as JSON )); + +--echo +--echo # Json expression NULL +select JSON_VALID(cast(NULL as JSON )); + +--echo +--echo # Bare NULL +select JSON_VALID( NULL ); + +--echo +--echo # Function result - string +select JSON_VALID( UPPER('"abc"') ); + +set names 'latin1'; +--echo +--echo # Function result - string +# auto-convert to utf-8 +select JSON_VALID( UPPER('"abc"') ); + +set names 'utf8'; + +--echo +--echo # Function result - date, not valid as JSON without CAST +select JSON_VALID( CAST('2015-01-15' AS DATE) ); + +--echo +--echo # The date string doesn't parse as JSON text, so wrong: +select JSON_VALID( CAST(CAST('2015-01-15' AS DATE) as CHAR CHARACTER SET 'utf8') ); +--echo # OK, though: +select JSON_VALID( CAST(CURDATE() as JSON) ); + +--echo +--echo # Function result - NULL +select JSON_VALID( UPPER(NULL) ); +select JSON_VALID( UPPER(CAST(NULL as CHAR)) ); + +# examples from wl7909 spec +# returns 1 +SELECT JSON_VALID( '{ "firstName" : "Fred", "lastName" : "Flintstone" }' ); + +# returns 1 +SELECT JSON_VALID( '3' ); + +# returns NULL as IS JSON would +SELECT JSON_VALID( null ); + + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_CONTAINS_PATH function. +--echo # ---------------------------------------------------------------------- + +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_contains_path(); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_contains_path('{ "a": true }' ); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_contains_path('{ "a": true }', 'all' ); +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +select json_contains_path('{ "a": tru }', 'all', '$' ); +--echo error ER_INVALID_JSON_PATH +select json_contains_path('{ "a": true }', 'all', '$[' ); +--echo error ER_INVALID_JSON_PATH +select json_contains_path('{ "a": true }', 'all', '$a.***[3]' ); +--echo error ER_JSON_BAD_ONE_OR_ALL_ARG +select json_contains_path('{ "a": true }', 'foo', '$.a' ); +--echo error ER_INVALID_JSON_CHARSET +select json_contains_path('{}', 'all', cast('$' as binary)); + +select json_contains_path(null, 'all', '$.a' ); +select json_contains_path('{ "a": true }', null, '$.a' ); +select json_contains_path('{ "a": true }', 'all', null ); + +# degenerate path +select json_contains_path('{ "a": true }', 'all', '$' ); + +# positive, one path +select json_contains_path('{ "a": true }', 'all', '$.a' ); +select json_contains_path('{ "a": true }', 'one', '$.a' ); + +# negative, one path +select json_contains_path('{ "a": true }', 'all', '$.b' ); +select json_contains_path('{ "a": true }', 'one', '$.b' ); + +# all +select json_contains_path('{ "a": true }', 'all', '$.a', '$.b' ); +select json_contains_path('{ "a": true }', 'all', '$.b', '$.a' ); +select json_contains_path('{ "a": true }', 'ALL', '$.a', '$.b' ); +select json_contains_path('{ "a": true }', 'aLl', '$.a', '$.b' ); + +# some +select json_contains_path('{ "a": true }', 'one', '$.a', '$.b' ); +select json_contains_path('{ "a": true }', 'one', '$.b', '$.a' ); +select json_contains_path('{ "a": true }', 'ONE', '$.a', '$.b' ); +select json_contains_path('{ "a": true }', 'oNe', '$.a', '$.b' ); + +# some wildcards +select json_contains_path('{ "a": true, "b": [ 1, 2, { "c": [ 4, 5, { "d": [ 6, 7, 8, 9, 10 ]} ] } ] }', 'all', '$**[4]' ); +select json_contains_path('{ "a": true, "b": [ 1, 2, { "c": [ 4, 5, { "d": [ 6, 7, 8, 9, 10 ]} ] } ] }', 'all', '$**[4]', '$**[5]' ); +select json_contains_path('{ "a": true, "b": [ 1, 2, { "c": [ 4, 5, { "d": [ 6, 7, 8, 9, 10 ]} ] } ] }', 'all', '$**.c[2]' ); +select json_contains_path('{ "a": true, "b": [ 1, 2, { "c": [ 4, 5, { "d": [ 6, 7, 8, 9, 10 ]} ] } ] }', 'all', '$**.c[3]' ); +select json_contains_path('{"a":1, "b":2}', 'one', '$.*'); +select json_contains_path('[1,2,3]', 'one', '$.*'); +select json_contains_path('{}', 'one', '$[*]'); + +# combine ellipsis and wildcard +SELECT JSON_CONTAINS_PATH('[1, [[{"x": [{"a":{"b":{"c":42}}}]}]]]', + 'one', '$**.a.*'); +SELECT JSON_CONTAINS_PATH('[1, [[{"x": [{"a":{"b":{"c":42}}}]}]]]', + 'all', '$**.a.*'); +SELECT JSON_CONTAINS_PATH('[1,2,3]', 'one', '$**[*]'); +SELECT JSON_CONTAINS_PATH('[1,2,3]', 'all', '$**[*]'); + +# 3 paths +select json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'all', '$**[1]', '$.b[0]', '$.c' ); +select json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'all', '$.c', '$**[1]', '$.b[0]' ); +select json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'all', '$.b[0]', '$.c', '$**[1]' ); +select json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'one', '$**[1]', '$.b[0]', '$.c' ); +select json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'one', '$.c', '$**[1]', '$.b[0]' ); +select json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'one', '$.b[0]', '$.c', '$**[1]' ); + +# examples from the wl7909 spec +# returns 0 because there is no element at $.a.c +SELECT JSON_CONTAINS_PATH +( + '{ "a" : 123, "b" : [ 123, 456 ] }', + 'all', + '$.a.c', + '$.b[1]' +); + +# returns 1 because there is an element at $.b[1] +SELECT JSON_CONTAINS_PATH +( + '{ "a" : 123, "b" : [ 123, 456 ] }', + 'one', + '$.a.c', + '$.b[1]' +); + +# returns 0 because there is no element at the given path +SELECT JSON_CONTAINS_PATH +( + '{ "a" : 123, "b" : [ 123, 456 ] }', + 'all', + '$.c' +); + +# returns 1 because there is an element at $.b[1].c.d +SELECT JSON_CONTAINS_PATH +( + '{ "a" : 123, "b" : [ 123, { "c" : { "d" : true } } ] }', + 'all', + '$.b[1].c.d' +); + +select json_length( null ); +select json_length( '1' ); +--echo +--echo # invalid json text +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +select json_length( 'abc' ); +select json_length( '"abc"' ); +select json_length( 'true' ); +select json_length( 'false' ); +select json_length( 'null' ); + +select json_length( '{}' ); +select json_length( '{ "a" : 100, "b" : 200 }' ); +select json_length( '{ "a" : 100, "b" : [ 300, 400, 500 ] }' ); +select json_length( '[]' ); +select json_length( '[ null, "foo", true, 1.1 ]' ); +select json_length( '[ null, "foo", true, { "a" : "b", "c" : "d" } ]' ); +select json_length( '"foo"' ); +select json_length( '1.2' ); + + +# bad path expressions +--echo +--echo # invalid json path +--echo error ER_INVALID_JSON_PATH +select json_length( 'true', 'c$' ); +--echo +--echo # invalid json path +--echo error ER_INVALID_JSON_PATH +select json_length( '{ "foo" : [ true, false ] }', '$.foo[bar]' ); +--echo +--echo # wildcards not allowed in path expressions for this function +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_length( 'true', '$.*' ); +--echo +--echo # wildcards not allowed in path expressions for this function +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_length( 'true', '$.foo**.bar' ); + +# json_length() with non-vacuous path expressions + +# 1 +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[0]' ); +# 3 +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[1]' ); +# 1 +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2]' ); +# auto-wrapping: 1 +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0]' ); # auto-wrap scalar +select json_length( '[ 1, [ 2, 3, 4 ], {"a": 1} ]', '$[2][0]' ); # ditto object + +# non-existent path: null +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][1]' ); +# 3 +select json_length( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]' ); + +# examples from the wl7909 spec +# returns 0 +SELECT JSON_LENGTH +( + '{}' +); + +# returns 1 +SELECT JSON_LENGTH +( + '3' +); + +# returns 2 +SELECT JSON_LENGTH +( + '{ "a" : 123, "b" : [ 123, 456, 789 ] }' +); + +# returns 3 +SELECT JSON_LENGTH +( + '{ "a" : 123, "b" : [ 123, 456, 789 ] }', + '$.b' +); + +# returns null because the path does not exist +SELECT JSON_LENGTH +( + '{ "a" : 123, "b" : [ 123, 456, 789 ] }', + '$.c' +); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_DEPTH function. +--echo # ---------------------------------------------------------------------- +select json_depth(null); +select json_depth(cast(null as json)); +#select i, json_depth(j) from t1; +select json_depth(cast('[]' as json)), + json_depth(cast('{}' as json)), + json_depth(cast('null' as json)), + json_depth(json_quote('foo')); +select json_depth(cast('[[2], 3, [[[4]]]]' as json)); +select json_depth(cast('{"a": {"a1": [3]}, "b": {"b1": {"c": {"d": [5]}}}}' as json)); + +# examples from the wl7909 spec +# returns 1 +SELECT JSON_DEPTH +( + '{}' +); + +# returns 1 +SELECT JSON_DEPTH +( + '[]' +); + +# returns 1 +SELECT JSON_DEPTH( '"abc"' ); + +# returns 1 +SELECT JSON_DEPTH( CAST( '"abc"' AS JSON ) ); + +--echo error ER_INVALID_TYPE_FOR_JSON +SELECT JSON_DEPTH( 1 ); + +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_DEPTH( 'abc' ); + +# returns 1 +SELECT JSON_DEPTH( CAST( 1 AS JSON ) ); + +# returns 2 +SELECT JSON_DEPTH +( + '{ "a" : true, "b" : false, "c" : null }' +); + +# returns 2 +SELECT JSON_DEPTH +( + '[ "a", true, "b" , false, "c" , null ]' +); + +# returns 2 +SELECT JSON_DEPTH +( + '{ "a" : true, "b" : {}, "c" : null }' +); + +# returns 2 +SELECT JSON_DEPTH +( + '[ "a", true, "b" , {}, "c" , null ]' +); + +# returns 3 +SELECT JSON_DEPTH +( + '{ "a" : true, "b" : { "e" : false }, "c" : null }' +); + +# returns 3 +SELECT JSON_DEPTH +( + '[ "a", true, "b" , { "e" : false }, "c" , null ]' +); + +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_DEPTH +( + '[ "a", true, "b" , { "e" : false }, "c" , null' +); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_REMOVE function. +--echo # ---------------------------------------------------------------------- + +# null args +select json_remove( null, '$[1]' ); +select json_remove( null, '$[1]' ) is null; +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', null ); +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', null ) is null; +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]', null ); +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]', null ) is null; + +# too few args + +--echo +--echo # not enough args +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_remove(); +--echo +--echo # not enough args +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]' ); +--echo +--echo # not enough args +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_remove( '$[1]' ); + +# malformed args +--echo +--echo # invalid json text +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ', '$[1]', '$[2]' ); +--echo +--echo # invalid json path +--echo error ER_INVALID_JSON_PATH +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1', '$[2]' ); +--echo +--echo # invalid json path +--echo error ER_INVALID_JSON_PATH +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]', '$[2' ); +--echo +--echo # Vacuous path expression +--echo error ER_JSON_VACUOUS_PATH +select json_remove( '[ 1, 2, 3 ]', '$' ); +--echo +--echo # Vacuous path expression +--echo error ER_JSON_VACUOUS_PATH +select json_remove( '[ 1, 2, 3 ]', '$', '$[2]' ); +--echo +--echo # Vacuous path expression +--echo error ER_JSON_VACUOUS_PATH +select json_remove( '[ 1, 2, 3 ]', '$[1]', '$' ); + +# wildcard/ellipsis not allowed in paths +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_remove( '[ 1, 2, 3 ]', '$[*]' ); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_remove( '[ 1, 2, 3 ]', '$**[2]' ); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_remove( '[ 1, 2, 3 ]', '$[2]', '$[*]' ); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_remove( '[ 1, 2, 3 ]', '$[2]', '$**[2]' ); + +# simple matches + +select json_remove( '[ 1, 2, 3 ]', '$[0]' ); +select json_remove( '[ 1, 2, 3 ]', '$[1]' ); +select json_remove( '[ 1, 2, 3 ]', '$[2]' ); +select json_remove( '[ 1, 2, 3 ]', '$[3]' ); +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]' ); + +# one match nested inside another +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_remove( '[ { "a": { "a": true } } ]', '$**.a' ); + +# multiple paths +select json_remove( '[ { "a": true }, { "b": false }, { "c": null }, { "a": null } ]', '$[0].a', '$[2].c' ); + +# ellipsis with matches at different levels +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_remove( '[ { "a": true }, { "b": [ { "c": { "a": true } } ] }, { "c": null }, { "a": null } ]', '$**.a' ); + +# nonsense path +select json_remove( '{"id": 123, "name": "systemQA", "array": [1, 2, 3]}', '$[0]' ); + +# examples from wl7909 spec +# returns the document {"a": "foo", "b": [true]} +SELECT JSON_REMOVE +( + '{"a" : "foo", "b" : [true, {"c" : 123}]}', + '$.b[ 1 ]' +); + +# returns {"a": "foo", "b": [true, {}]} due to normalization +SELECT JSON_REMOVE +( + '{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', + '$.b[ 1 ].c' +); + +# returns {"a": "foo", "b": [true, {}]} +SELECT JSON_REMOVE +( + '{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', + '$.b[ 1 ].c' +); + +# returns the original document because the path doesn't identify an element +SELECT JSON_REMOVE +( + '{ "a" : "foo", "b" : [ true, { "c" : 123, "d" : 456 } ] }', + '$.b[ 1 ].e' +); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_MERGE function. +--echo # ---------------------------------------------------------------------- + +--echo +--echo # not enough args +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_merge(); +--echo +--echo # not enough args +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_merge( '[ 1, 2, 3 ]' ); + +# null args result in NULL value +select json_merge( null, null ); +select json_merge( null, '[ 1, 2, 3 ]' ); +select json_merge( '[ 1, 2, 3 ]', null ); +select json_merge( null, '[ 1, 2, 3 ]', '[ 4, 5, 6 ]' ); +select json_merge( '[ 1, 2, 3 ]', null, '[ 4, 5, 6 ]' ); +select json_merge( '[ 1, 2, 3 ]', '[ 4, 5, 6 ]', null ); + +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +select json_merge( '[1, 2]', '[3, 4' ); +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +select json_merge( '[1, 2', '[3, 4]' ); + +# good json_merge() expressions +select json_merge( '1', '2' ); +select json_merge( '1', '[2, 3]' ); +select json_merge( '[1, 2]', '3' ); +select json_merge( '1', '{ "a": 2 }' ); +select json_merge( '{ "a": 2 }', '1' ); +select json_merge( '[1, 2]', '[3, 4]' ); +select json_merge( '{ "a": 2 }', '{ "b": 3}' ); +select json_merge( '[1, 2]', '{ "a": 2 }' ); +select json_merge( '{ "a": 2 }', '[1, 2]' ); + +select json_merge( '{"a": 1, "b": 2 }', '{"b": 3, "d": 4 }' ); +select json_merge( '{"a": 1, "b": 2 }', '{"b": [3, 4], "d": 4 }' ); +select json_merge( '{"a": 1, "b": [2, 3] }', '{"b": 4, "d": 4 }' ); +select json_merge( '{"a": 1, "b": 2 }', '{"b": {"e": 7, "f": 8}, "d": 4 }' ); +select json_merge( '{"b": {"e": 7, "f": 8}, "d": 4 }', '{"a": 1, "b": 2 }' ); +select json_merge( '{"a": 1, "b": [2, 9] }', '{"b": [10, 11], "d": 4 }' ); +select json_merge( '{"a": 1, "b": [2, 9] }', '{"b": {"e": 7, "f": 8}, "d": 4 }' ); +select json_merge( '{"b": {"e": 7, "f": 8}, "d": 4 }', '{"a": 1, "b": [2, 9] }' ); +select json_merge( '{"b": {"e": 7, "f": 8}, "d": 4 }', '{ "a": 1, "b": {"e": 20, "g": 21 } }' ); + +select json_merge( '1', '2', '3' ); +select json_merge( '[1, 2 ]', '3', '[4, 5]' ); +select json_merge +( + '{ "a": true, "b": { "c": 3, "d": 4 }, "e": [ 1, 2 ] }', + '{ "d": false, "b": { "g": 3, "d": 5 }, "f": [ 1, 2 ] }', + '{ "m": true, "b": { "h": 8, "d": 4 }, "e": [ 3, 4 ] }' +); + +# examples from the wl7909 spec +# returns [{"a": "foo", "b": [true, {"c": 123}]}, 5, 6] +SELECT JSON_MERGE +( + '{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', + '[ 5, 6]' +); + +# returns {"a": "foo", "b": [true, {"c": 123}, false, 34]} +SELECT JSON_MERGE +( + '{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', + '{ "b": [ false, 34 ] }' +); + +# returns {"a": "foo", "b": [true, {"c": 123}, "bar"]} +SELECT JSON_MERGE +( + '{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', + '{ "b": "bar" }' +); + +# returns {"a": {"b": 1, "c": 1}} +SELECT JSON_MERGE +( + '{ "a" : { "b" : 1 } }', + '{ "a" : { "c" : 1 } }' +); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_TYPE function. +--echo # ---------------------------------------------------------------------- + +# negative test +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +select json_type('abc'); + +#select i, json_type(j) from t1; +select json_type('{"a": 2}'); +select json_type('[1,2]'); +select json_type('"scalar string"'); +select json_type('true'); +select json_type('false'); +select json_type('null'); +select json_type('1'); +select json_type('-0'); +select json_type('-0.0'); +--echo error ER_INVALID_TYPE_FOR_JSON +select json_type(-1); +--echo error ER_INVALID_TYPE_FOR_JSON +select json_type(CAST(1 AS UNSIGNED)); +select json_type('32767'); +--echo error ER_INVALID_TYPE_FOR_JSON +select json_type(PI()); +select json_type('3.14'); + +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +select json_type(CAST(CAST('2015-01-15' AS DATE) as CHAR CHARACTER SET 'utf8')); + +--echo # ---------------------------------------------------------------------- +--echo # Test of CAST(literal AS JSON) +--echo # ---------------------------------------------------------------------- +select json_type(cast(cast('2014-11-25 18:00' as datetime) as json)); +select json_type(cast(cast('2014-11-25' as date) as json)); +select json_type(cast(cast('18:00:59' as time) as json)); +# select json_type(cast(cast('2014-11-25 18:00' as timestamp) as json)); -- cast target type not supported + +# select json_type(cast(cast('1999' as year) as json)); -- cast target type not supported +select json_type(cast(127 as json)); +select json_type(cast(255 as json)); +select json_type(cast(32767 as json)); +select json_type(cast(65535 as json)); +select json_type(cast(8388607 as json)); +select json_type(cast(16777215 as json)); +select json_type(cast(2147483647 as json)); +select json_type(cast(4294967295 as json)); +select json_type(cast(9223372036854775807 as json)); +select json_type(cast(18446744073709551615 as json)); +select json_type(cast(true as json)); +select json_type(cast(b'10101' as json)); + +select json_type(cast(cast(3.14 as decimal(5,2)) as json)); +select json_type(cast(3.14 as json)); +select json_type(cast(3.14E30 as json)); +# select json_type(cast(cast(3.14 as numeral(5,2)) as json)); -- cast target type not supported + +# select json_type(cast(cast(3.14 as double) as json)); -- cast target type not supported +# select json_type(cast(cast(3.14 as float) as json)); -- cast target type not supported + +# select json_type(cast(cast(b'10101' as bit(10)) as json)); -- cast target type not supported +# select json_type(cast(cast('10101abcde' as blob) as json)); -- cast target type not supported +select json_type(cast(cast('10101abcde' as binary) as json)); + +# select json_type(cast(cast('a' as enum('a','b','c')) as json)); -- cast target type not supported +# select json_type(cast(cast('a,c' as set('a','b','c')) as json)); -- cast target type not supported + +select json_type(cast(ST_GeomFromText('POINT(1 1)') as json)); +select json_type(cast(ST_GeomFromText('LINESTRING(0 0,1 1,2 2)') as json)); +select json_type(cast(ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0), + (5 5,7 5,7 7,5 7, 5 5))') as json)); +select json_type(cast(null as json)); +select json_type(cast(null as json)) is null; # check that it is an SQL NULL +select json_type(null) is null; # is an SQL NULL + +# +# same, but now show the printable value: +# +select cast(cast('2014-11-25 18:00' as datetime) as json); +select cast(cast('2014-11-25' as date) as json); +select cast(cast('18:00:59' as time) as json); +# select cast(cast('2014-11-25 18:00' as timestamp) as json); -- cast target type not supported + +# select cast(cast('1999' as year) as json); -- cast target type not supported +select cast(127 as json); +select cast(255 as json); +select cast(32767 as json); +select cast(65535 as json); +select cast(8388607 as json); +select cast(16777215 as json); +select cast(2147483647 as json); +select cast(4294967295 as json); +select cast(9223372036854775807 as json); +select cast(18446744073709551615 as json); +select cast(true as json); +select cast(b'10101' as json); + +select cast(cast(3.14 as decimal(5,2)) as json); +select cast(3.14 as json); +select cast(3.14e0 as json); +# select cast(cast(3.14 as numeral(5,2)) as json); -- cast target type not supported + +# select cast(cast(3.14 as double) as json); -- cast target type not supported +# select cast(cast(3.14 as float) as json); -- cast target type not supported + +# select cast(cast(b'10101' as bit(10) as json); -- cast target type not supported +# select cast(cast('10101abcde' as blob) as json); -- cast target type not supported +select cast(cast('10101abcde' as binary) as json); + +# select cast(cast('a' as enum('a','b','c') as json); -- cast target type not supported +# select cast(cast('a,c' as set('a','b','c') as json); -- cast target type not supported + +select cast(ST_GeomFromText('POINT(1 1)') as json); +select cast(ST_GeomFromText('LINESTRING(0 0,1 1,2 2)') as json); +select cast(ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0), + (5 5,7 5,7 7,5 7, 5 5))') as json); +select cast(null as json); +select cast(null as json) is null; # check that it is an SQL NULL + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_KEYS function. +--echo # ---------------------------------------------------------------------- +# should all give NULL: +select json_keys(NULL); +select json_keys(NULL, '$.b'); +select json_keys(NULL, NULL); +select json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a'); +select json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', NULL); + +# non NULL results +select json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}'); +select json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.b'); + +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.*.b'); + +# Examples from the specification +--echo # returns [ "a", "b" ] +SELECT JSON_KEYS('{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }'); + +--echo # returns [] +SELECT JSON_KEYS('{ "a" : "foo", "b" : [ true, { "c" : {} } ] }', + '$.b[1].c'); + +--echo # returns NULL +SELECT JSON_KEYS('{ "a" : "foo", "b" : [ true, { "c" : {} } ] }', + '$.a.b[2]'); + +--echo error ER_INVALID_JSON_PATH +SELECT JSON_KEYS('{"a":1}', '1010'); +--echo error ER_INVALID_JSON_PATH +SELECT JSON_KEYS('{"a":1}', '1010') IS NULL; + +# examples from the wl7909 spec +# returns [ "a", "b" ] +SELECT JSON_KEYS +( + '{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }' +); + +# returns [] +SELECT JSON_KEYS +( + '{ "a" : "foo", "b" : [ true, { "c" : {} } ] }', + '$.b[1].c' +); + +# returns NULL +SELECT JSON_KEYS +( + '{ "a" : "foo", "b" : [ true, { "c" : {} } ] }', + '$.a.b[2]' +); + +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT JSON_KEYS(); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT JSON_KEYS('{}', '$', '$'); + +--echo # ---------------------------------------------------------------------- +--echo # CAST( AS CHAR). See also 'json_conversions.test' for other +--echo # conversion tests. +--echo # ---------------------------------------------------------------------- +select cast(json_keys('{"a": 1}') as char); +select cast(cast(1 as json) as char); +select cast(json_keys(NULL) as char); +#select cast(j as char) from keys1; + +--echo # ---------------------------------------------------------------------- +--echo # Path matching with double-quotes +--echo # ---------------------------------------------------------------------- + +# matches +select json_extract( '{ "one potato" : 1 }', '$."one potato"' ); +# matches +select json_extract( '{ "a.b" : 1 }', '$."a.b"' ); + +# doesn't match +select json_extract( '{ "\\"a\\"": 1}', '$."a"' ); +# matches +select json_extract( '{ "\\"a\\"": 1}', '$."\\"a\\""' ); +# matches +select json_extract( '{ "a": 1}', '$."a"' ); +# matches +select json_extract( '{ "a": 1}', '$.a' ); + +# examples from functional spec section on Path Syntax + +# [3, 2] +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[0]' ); +# 2 +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[0][1]' ); +# [ { "c": "d" }, 1 ] +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[1]' ); +# { "c": "d" } +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[1][0]' ); +# "d" +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[1][0].c' ); +# 7 +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$."one potato"' ); +# 6 +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.b.c' ); +# 8 +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$."b.c"' ); + + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_EXTRACT function. +--echo # ---------------------------------------------------------------------- + +# errors +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_extract(NULL); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_extract('$.b'); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}'); + +# Confused argument order +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +select json_extract('$.a', '{"a": 1, "b": {"e": "foo", "b": 3}}'); + +# NULLs +select json_extract(NULL, '$.b'); +select json_extract(NULL, NULL); + +# non-NULLs +select json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a'); +select json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.*'); +select json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a', '$.b.e'); +select json_extract('{"a": 1, "b": [1,2,3]}', '$.b[2]'); +# one path is NULL +select json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a', NULL); + +# Examples from the specification +--echo # returns a JSON value containing just the string "123" +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }', + '$.b[ 1 ].c'); + +--echo # returns a JSON value containing just the number 123 +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', + '$.b[ 1 ].c'); + +--echo # raises an error because the document is not valid +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_EXTRACT('{ "a" : [ }', + '$.b[ 1 ].c'); + +--echo # raises an error because the path is invalid +--echo error ER_INVALID_JSON_PATH +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', + '$.b[ 1 ].'); + +--echo # returns a JSON value containing the number 123 (because of +--echo # auto-wrapping the scalar) +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', + '$.b[ 1 ].c[ 0 ]'); +--echo # returns a JSON value containing the object because of auto-wrapping +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : {"not array": 4} } ] }', + '$.b[ 1 ].c[ 0 ]'); + +--echo # returns null because the path, although valid, does not identify a value +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', + '$.b[ 1 ].c[ 1 ]'); + +--echo # returns a JSON value containing the number 123 (due to normalization) +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', + '$.b[ 1 ].c'); + +--echo # returns a JSON array [ "foo", true ] +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', + '$.a', '$.b[0]'); + +--echo # returns a JSON array [ true ] +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', + '$.d', '$.b[0]'); + +# some examples verifying ellipsis behavior + +# should have same result +select json_extract( '[1]', '$[0][0]' ); +select json_extract( '[1]', '$**[0]' ); + +# should have same result +select json_extract( '{ "a": 1 }', '$.a[0]' ); +select json_extract( '{ "a": 1 }', '$**[0]' ); + +# should have same result +select json_extract( '{ "a": 1 }', '$[0].a' ); +select json_extract( '{ "a": 1 }', '$**.a' ); + +# should have same result +select json_extract( '{ "a": 1 }', '$[0].a[0]' ); +select json_extract( '{ "a": 1 }', '$**[0]' ); + +# should have the same result +select json_extract( '{ "a": 1 }', '$[0].a' ); +select json_extract( '{ "a": 1 }', '$**.a' ); +select json_extract( '{ "a": 1 }', '$[0][0].a' ); +select json_extract( '{ "a": 1 }', '$[0][0][0].a' ); + +# should have the same result +SELECT JSON_EXTRACT('[1, [[{"x": [{"a":{"b":{"c":42}}}]}]]]', '$**.a.*'); +SELECT JSON_EXTRACT('[1, [[{"x": [{"a":{"b":{"c":42}}}]}]]]', + '$[1][0][0].x[0].a.*'); + +# examples from the wl7909 spec +# returns a JSON value containing just the string "123" +SELECT JSON_EXTRACT +( + '{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }', + '$.b[ 1 ].c' +); + +# returns a JSON value containing just the number 123 +SELECT JSON_EXTRACT +( + '{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', + '$.b[ 1 ].c' +); + +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_EXTRACT +( + '{ "a" : [ }', + '$.b[ 1 ].c' +); + +--echo error ER_INVALID_JSON_PATH +SELECT JSON_EXTRACT +( + '{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', + '$.b[ 1 ].' +); + +# returns a JSON value containing the number 123 (because of auto-wrapping) +SELECT JSON_EXTRACT +( + '{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', + '$.b[ 1 ].c[ 0 ]' +); + +# returns null because the path, although valid, does not identify a value +SELECT JSON_EXTRACT +( + '{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', + '$.b[ 1 ].c[ 1 ]' +); + +# returns a JSON value containing the number 123 (due to normalization) +SELECT JSON_EXTRACT +( + '{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', + '$.b[ 1 ].c' +); + +# returns a JSON array ["foo", true] +SELECT JSON_EXTRACT +( + '{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', + '$.a', '$.b[0]' +); + +# returns a the 'true' literal +SELECT JSON_EXTRACT +( + '{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', + '$.d', '$.b[0]' +); + +# should return NULL +select json_extract( '[ { "a": 1 }, { "a": 2 } ]', '$[*].b' ) jdoc; + +# should return NULL +select json_extract( '[ { "a": 1 }, { "a": 2 } ]', '$[0].b' ) jdoc; + +# should return 1 +select json_extract( '[ { "a": 1 }, { "a": 2 } ]', '$[0].a' ) jdoc; + +# should return [1, 2] +select json_extract( '[ { "a": 1 }, { "a": 2 } ]', '$[*].a' ) jdoc; + +# should return [1] +select json_extract( '[ { "a": 1 }, { "b": 2 } ]', '$[*].a' ) jdoc; + +# should return [3, 4] +select json_extract( '[ { "a": [3,4] }, { "b": 2 } ]', '$[0].a' ) jdoc; + +# should return [[3, 4]] +select json_extract( '[ { "a": [3,4] }, { "b": 2 } ]', '$[*].a' ) jdoc; + +# should return [[3, 4]] +select json_extract( '[ { "a": [3,4] }, { "b": 2 } ]', '$[0].a', '$[1].a' ) jdoc; + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_ARRAY_APPEND function. +--echo # ---------------------------------------------------------------------- + +# NULLs +select json_array_append(NULL, '$.b', cast(1 as json)); +select json_array_append('[1,2,3]', NULL, cast(1 as json)); +select json_array_append('[1,2,3]', '$', NULL); + +# wrong # args +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_array_append(NULL); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_array_append(NULL, NULL); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_array_append(NULL, NULL, NULL, NULL); + +# auto-wrap +SELECT JSON_ARRAY_APPEND(cast('1' as json), '$', 3); +SELECT JSON_ARRAY_APPEND(cast('{"a": 3}' as json), '$', 3); + +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_array_append(cast('{"a": {"b": [3]}}' as json), '$**[0]', 6); + +# Examples from the specification + +--echo # Auto-wrapping, since because the paths identify scalars. +--echo # should return {"a": "foo", "b": ["bar", 4], "c": ["wibble", "grape"]} +SELECT JSON_ARRAY_APPEND('{"a": "foo", "b": "bar", "c": "wibble"}', + '$.b', cast(4 as json), + '$.c', cast('"grape"' as json)); + +--echo # should return {"a": "foo", "b": [1, 2, 3, 4], +--echo # "c": ["apple", "pear", "grape"]} +SELECT JSON_ARRAY_APPEND('{"a" : "foo","b": [1, 2, 3], "c": ["apple", "pear"]}', + '$.b', cast(4 as json), + '$.c', cast('"grape"' as json)); + +# without CAST: cf. not required for ANY_JSON_ATOM arguments in specification +SELECT JSON_ARRAY_APPEND('{"a" : "foo","b": [1, 2, 3], "c": ["apple", "pear"]}', + '$.b', 4, + '$.c', 'grape'); + +# wild cards, multiple pairs +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_array_append( '[[], [], []]', '$[*]', 3, '$[*]', 4); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_array_append( '[[], "not array", []]', '$[*]', 3, '$[*]', 4); + +# examples from wl7909 spec +# should return {"a": "foo", "b": ["bar", 4], "c": ["wibble", "grape"]} due to autowrapping +SELECT JSON_ARRAY_APPEND +( + '{ "a" : "foo", "b" : "bar", "c" : "wibble" }', + '$.b', 4, + '$.c', "grape" +); + +# should return {"a": "foo", "b": [1, 2, 3, 4], "c": ["apple", "pear", "grape"]} +SELECT JSON_ARRAY_APPEND +( + '{ "a" : "foo", "b" : [ 1, 2, 3 ], "c" : [ "apple", "pear" ] }', + '$.b', 4, + '$.c', "grape" +); + +--echo # ---------------------------------------------------------------------- +--echo # Bug#21373874 ASSERTION `PARENT' FAILED +--echo # ---------------------------------------------------------------------- + +select json_array_append('{"a":1}', '$[0]', 100); +select json_array_append('3', '$[0]', 100); +select json_array_append('3', '$[0][0][0][0]', 100); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_INSERT function. +--echo # ---------------------------------------------------------------------- + +# NULLs +select json_insert(NULL, '$.b', cast(1 as json)); +select json_insert('[1,2,3]', NULL, cast(1 as json)); +select json_insert('[1,2,3]', '$[3]', NULL); + +# wrong # args +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_insert(NULL); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_insert(NULL, NULL); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_insert(NULL, NULL, NULL, NULL); + +# positive test cases + +select json_insert('[1,2,3]', '$[2]', 4); +select json_insert('[1,2,3]', '$[3]', 4); +select json_insert('[1,2,3]', '$[10]', 4); + +select json_insert('{"c":4}', '$.c', 4); +select json_insert('{"c":4}', '$.a', 4); + +select json_insert('1', '$', 4); +select json_insert('1', '$[0]', 4); +select json_insert('1', '$[1]', 4); +select json_insert('1', '$[10]', '4', '$[11]', 5); + +select json_insert('[1,2,3]', '$[2][0]', 4); +select json_insert('[1,2,3]', '$[2][2]', 4); + +select json_insert('{"a": 3}', '$.a[0]', 4); +select json_insert('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5'); + +# wild card & auto-wrap (scalars) +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('{"a": [1], "b": 2}' as json), '$.*[1]', 6); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('{"a": 1, "b": 2}' as json), '$.*[1]', 6); + +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('{"a": {"b": 3}}' as json), '$.a.*[1]', 6); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('{"a": {"b": [3]}}' as json), '$.a.*[1]', 6); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('{"a": {"b": 3}}' as json), '$**[1]', 6); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('{"a": {"b": [3]}}' as json), '$**[1]', 6); + +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('[1]' as json), '$[*][1]', 6); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('[1]' as json), '$**[1]', 6); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('[1, [2], 3]' as json), '$[*][1]', 6); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('[1, [2], 3]' as json), '$**[1]', 6); + +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('[[1]]' as json), '$[*][1]', 6); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('[[1]]' as json), '$**[1]', 6); + +# auto-wrap object +select json_insert(cast('{"a": 3}' as json), '$[1]', 6); + + +# Examples from the specification + +# returns the original document because the path does exist +SELECT JSON_INSERT('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.a', true); + +# inserts a number, returns '{ "a" : "foo", "b" : [ 1, 2, 3 ], "c" : 123 } +SELECT JSON_INSERT('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.c', 123); + +# inserts a string, returns '{ "a" : "foo", "b" : [ 1, 2, 3 ], "c" : "123" } +SELECT JSON_INSERT('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.c', '123'); + +# returns '{ "a" : [ "foo", true ], "b" : [ 1, 2, 3 ] }' +SELECT JSON_INSERT('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.a[1]', true); + +# should return { "a" : "foo", "b": true } +SELECT JSON_INSERT('{ "a" : "foo"}', '$.b', true, '$.b', false); + +# examples from the wl7909 spec +# returns the original document because the path does exist +SELECT JSON_INSERT +( + '{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.a', + true +); + +# inserts a number, returns '{"a": "foo", "b": [1, 2, 3], "c": 123} +SELECT JSON_INSERT +( + '{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.c', + 123 +); + +# inserts a string, returns '{"a": "foo", "b": [1, 2, 3], "c": "123"} +SELECT JSON_INSERT +( + '{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.c', + '123' +); + +# returns '{"a": ["foo", true], "b": [1, 2, 3]}' +SELECT JSON_INSERT +( + '{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.a[1]', + true +); + +# returns {"a": "foo", "b": true} +SELECT JSON_INSERT +( + '{ "a" : "foo"}', + '$.b', true, + '$.b', false +); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_ARRAY_INSERT function. +--echo # ---------------------------------------------------------------------- + +# NULLs +select json_array_insert(NULL, '$.b[1]', 1); +select json_array_insert('[1,2,3]', NULL, 1); +select json_array_insert('[1,2,3]', '$[3]', NULL); + +# wrong # args +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_array_insert(NULL); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_array_insert(NULL, NULL); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_array_insert(NULL, NULL, NULL, NULL); + +# path does not indicate a cell position +--echo error ER_INVALID_JSON_PATH_ARRAY_CELL +select json_array_insert('true', '$', 1); +--echo error ER_INVALID_JSON_PATH_ARRAY_CELL +select json_array_insert('true', '$.a', 1); +--echo error ER_INVALID_JSON_PATH_ARRAY_CELL +select json_array_insert('true', '$.a[1].b', 1); + +# nop if there is no array at the path's parent +select json_array_insert( 'true', '$[0]', false ); +select json_array_insert( 'true', '$[1]', false ); +select json_array_insert( '{ "a": true }', '$.a[0]', false ); +select json_array_insert( '{ "a": true }', '$.a[1]', false ); + +# positive tests +select json_array_insert( '[]', '$[0]', false ); +select json_array_insert( '[]', '$[1]', false ); +select json_array_insert( '[true]', '$[0]', false ); +select json_array_insert( '[true]', '$[1]', false ); +select json_array_insert( '[true]', '$[2]', false ); +select json_array_insert( '{ "a": [] }', '$.a[0]', false ); +select json_array_insert( '{ "a": [] }', '$.a[1]', false ); +select json_array_insert( '{ "a": [true] }', '$.a[0]', false ); +select json_array_insert( '{ "a": [true] }', '$.a[1]', false ); +select json_array_insert( '{ "a": [true] }', '$.a[2]', false ); + +# insert into the middle of an array +select json_array_insert( '[1, 2, 3, 4]', '$[0]', false ); +select json_array_insert( '[1, 2, 3, 4]', '$[1]', false ); +select json_array_insert( '[1, 2, 3, 4]', '$[2]', false ); +select json_array_insert( '[1, 2, 3, 4]', '$[3]', false ); +select json_array_insert( '[1, 2, 3, 4]', '$[4]', false ); +select json_array_insert( '[1, 2, 3, 4]', '$[5]', false ); + +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[0]', false ); +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[1]', false ); +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[2]', false ); +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[3]', false ); +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[4]', false ); +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[5]', false ); + +# nop +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.b[0]', false ); +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.b[1]', false ); + +# no auto-wrapping +select json_array_insert( '"a"', '$[0]', true ); +select json_array_insert( '[ "a" ]', '$[0][0]', true ); +select json_array_insert( '"a"', '$[1]', true ); + +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert('[]', '$.a.*[1]', 6); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert('[]', '$**[1]', 6); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert('[]', '$[*][1]', 6); + +# multiple paths, +select json_array_insert( '[ 1, 2, 3 ]', '$[1]', true, '$[1]', false ); +select json_array_insert( '[ 1, 2, 3 ]', '$[1]', + cast( '[ "a", "b", "c", "d" ]' as json ), '$[1][2]', false ); + +# test an error while evaluating the document expression +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_ARRAY_INSERT(JSON_EXTRACT('[1', '$'), '$[0]', 1); + +# error in reading new value +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +select json_array_insert( '[ 1, 2, 3 ]', '$[1]', json_extract( '[', '$' ) ); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_SET function. +--echo # ---------------------------------------------------------------------- + +# NULLs +select json_set(NULL, '$.b', cast(1 as json)); +select json_set('[1,2,3]', NULL, cast(1 as json)); +select json_set('[1,2,3]', '$[3]', NULL); + +# wrong # args +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_set(NULL); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_set(NULL, NULL); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_set(NULL, NULL, NULL, NULL); + +# Detect errors in nested function calls. +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_SET('{}', '$.name', JSON_EXTRACT('', '$')); + +# positive test cases + +select json_set('[1,2,3]', '$[2]', 4); +select json_set('[1,2,3]', '$[3]', 4); +select json_set('[1,2,3]', '$[10]', 4); + +select json_set('{"c":4}', '$.c', 5); +select json_set('{"c":4}', '$.a', 5); + +select json_set('1', '$', 4); +select json_set('1', '$[0]', 4); +select json_set('1', '$[1]', 4); +select json_set('1', '$[10]', '4', '$[11]', 5); + +select json_set('[1,2,3]', '$[2][0]', 4); +select json_set('[1,2,3]', '$[2][2]', 4); + +select json_set('{"a": 3}', '$.a[0]', 4); +select json_set('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5'); + +# auto-wrap plus ellipsis with nested hits should give: {"a": [{"b": [3, 6]}, 6]} +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_set(cast('{"a": {"b": [3]}}' as json), '$**[1]', 6); + +# Examples from the specification: Include when missing functions are +# available. + +# returns { "a" : {}, "b" : [ 1, 2, 3 ] } + SELECT JSON_SET('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.a', + JSON_OBJECT()); + +# # returns { "a" : "foo", "b" : [ 1, 2, 3 ], "c" : [ true, false ] } +# SELECT JSON_SET('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +# '$.c', +# JSON_ARRAY( true, false )); + +# # returns { "a" : "foo", "b" : [ 1, 2, 3 ], "c" : [ true, false ] } +# SELECT JSON_SET('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +# '$.c', +# JSON_ARRAY( CAST( 'true' AS JSON ), CAST( 'false' AS JSON ) )); + +# # returns [ 1, null, null, 2 ] +# SELECT JSON_SET('1', '$[3]', 2); + +# should return { "a": { "b": false, "c": true } } +SELECT JSON_SET('{ "a" : "foo"}', '$.a', + JSON_OBJECT( 'b', false ), '$.a.c', true); + +# returns { "a" : {}, "b" : [ 1, 2, 3 ] } +select json_set('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.a', + cast('{}' as json)); + +# returns { "a" : "foo", "b" : [ 1, 2, 3 ], "c" : [ true, false ] } +select json_set('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.c', + cast('[true, false]' as json)); + +# returns [ 1, null, null, 2 ] +select json_set('1', '$[3]', 2); + +# should return { "a": { "b": false, "c": true } } +select json_set('{ "a" : "foo"}', '$.a', + cast('{"b": false}' as json), '$.a.c', true); + +# examples from wl7909 spec +# returns {"a": {}, "b": [1, 2, 3]} +SELECT JSON_SET +( + '{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.a', + JSON_OBJECT() +); + +# returns {"a": "foo", "b": [1, 2, 3], "c": [true, false]} +SELECT JSON_SET +( + '{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.c', + JSON_ARRAY( true, false ) +); + +# returns {"a": "foo", "b": [1, 2, 3], "c": [true, false]} +SELECT JSON_SET +( + '{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.c', + JSON_ARRAY( CAST( 'true' AS JSON ), CAST( 'false' AS JSON ) ) +); + +# returns [1, 2] +SELECT JSON_SET +( + '1', + '$[3]', + 2 +); + +# returns {"a": {"b": false, "c": true}} +SELECT JSON_SET +( + '{ "a" : "foo"}', + '$.a', JSON_OBJECT( 'b', false ), + '$.a.c', true +); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_REPLACE function. +--echo # ---------------------------------------------------------------------- + +# NULLs +select json_replace(NULL, '$.b', cast(1 as json)); +select json_replace('[1,2,3]', NULL, cast(1 as json)); +select json_replace('[1,2,3]', '$[2]', NULL); + +# wrong # args +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_replace(NULL); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_replace(NULL, NULL); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_replace(NULL, NULL, NULL, NULL); + +# positive test cases + +select json_replace('[1,2,3]', '$[2]', 4); +select json_replace('[1,2,3]', '$[3]', 4); +select json_replace('[1,2,3]', '$[10]', 4); + +select json_replace('{"c":4}', '$.c', 5); +select json_replace('{"c":4}', '$.a', 5); + +select json_replace('1', '$', 4); +select json_replace('1', '$[0]', 4); +select json_replace('1', '$[1]', 4); +select json_replace('1', '$[10]', '4', '$[11]', 5); + +select json_replace('[1,2,3]', '$[2][0]', 4); +select json_replace('[1,2,3]', '$[2][2]', 4); + +select json_replace('{"a": 3}', '$.a[0]', 4); +select json_replace('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5'); + + +# Examples from the specification + +# returns the original document because the path doesn't exist +SELECT JSON_REPLACE('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.c', + true); + +# returns '{ "a" : true, "b" : [ 1, 2, 3 ] }' +SELECT JSON_REPLACE('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.a[0]', + true); + +# returns the original document because the path doesn't exist +SELECT JSON_REPLACE('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.b[5]', + true); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_ARRAY function. +--echo # ---------------------------------------------------------------------- + +# NULLs +select json_array(NULL, '$.b', cast(1 as json)); +select json_array('[1,2,3]', NULL, cast(1 as json)); +select json_array('[1,2,3]', '$[3]', NULL); + + +# positive test cases +select json_array(); +select json_array(3.14); +select json_array('[1,2,3]'); +select json_array(cast('[1,2,3]' as json)); +select json_array(1,2,3); +select json_array(b'0', b'1', b'10'); + +# returns the empty array: [] +SELECT JSON_ARRAY(); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_OBJECT function. +--echo # ---------------------------------------------------------------------- + +# odd number of args +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_object( 'a' ); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_object( 'a', 1, 'b' ); + +# null arg +--echo error ER_JSON_DOCUMENT_NULL_KEY +select json_object( null, 1 ); + +# positive tests +select json_object(); +select json_object( 'a', null ); +select json_object( 'a', 1 ); +select json_object( 'a', 1, 'b', 'foo' ); +select json_object( 'a', 1, 'b', 'foo', 'c', cast( '{ "d": "wibble" }' as json ) ); +select json_object( 'a', true, 'b', false, 'c', cast( 'null' as json) ); +select json_valid( json_object( '"a"', 1 ) ); + +# long key +select json_object( REPEAT('a', 64 * 1024), 1 ); + +# non-string keyNames are cast to CHAR +select json_object(json_array(), json_array()); +select json_object( cast(json_array() as char), json_array()); + +select json_object( 1, json_array()); +select json_object( cast(1 as char), json_array()); + +# returns the empty object: {} +SELECT JSON_OBJECT(); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_SEARCH function. +--echo # ---------------------------------------------------------------------- + +# wrong number of args +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_search(); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_search( '{ "a": true }' ); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_search( '{ "a": true }', 'one' ); + +# null args +select json_search( null, 'one', 'foo' ); +select json_search( '{ "a": "foo" }', null, 'foo' ); +# FIXME. what should happen here? +#select json_search( '{ "a": "foo" }', 'one', null ); +select json_search( '{ "a": "foo" }', 'one', 'foo', null, null ); +select json_search( '{ "a": "foo" }', 'one', 'foo', null, '$.a', null ); + +# bad values for the oneOrAll arg +--echo error ER_JSON_BAD_ONE_OR_ALL_ARG +select json_search( '{ "a": "foo" }', 'twof', 'foo' ); +--echo error ER_JSON_BAD_ONE_OR_ALL_ARG +select json_search( '{ "a": "foo" }', 'two', 'foo' ); + +# bad escape arg +--error ER_WRONG_ARGUMENTS +select json_search( '{ "a": "foo" }', 'one', 'foo', 'ab' ); + +# bad path args +--echo error ER_INVALID_JSON_PATH +select json_search( '{ "a": "foo" }', 'one', 'foo', null, '$a' ); +--echo error ER_INVALID_JSON_PATH +select json_search( '{ "a": "foo" }', 'all', 'foo', null, '$.a', '$b' ); + +--error ER_BAD_FIELD_ERROR +select json_search(a, b, c); + +# simple tests for search without path arguments +select json_search( '{ "a": "foobar" }', 'one', 'foo%' ); +select json_search( '{ "a": "foobar", "b": "focus", "c": [ "arm", "foot", "shoulder" ] }', 'one', 'foo%' ); +select json_search( '{ "a": "foobar", "b": "focus", "c": [ "arm", "foot", "shoulder" ] }', 'all', 'foo%' ); +select json_search( '{ "a": "foobar", "b": "focus", "c": [ "arm", "foot", "shoulder" ] }', 'all', 'f__us' ); + +select json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'all', 'foo%', null, '$.a' ); +select json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'all', 'foo%', null, '$.a', '$.b' ); +select json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'one', 'foo%', null, '$.a', '$.b' ); + +select json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'ALL', 'foo%', null, '$.a' ); +select json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'aLl', 'foo%', null, '$.a', '$.b' ); +select json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'ONE', 'foo%', null, '$.a', '$.b' ); + +# wildcards in the path expression +select json_search +( + '[ { "a": { "b": { "c": "fool" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "food"} } ]', + 'all', + 'foo%', + null, + '$**.c' +); + +select json_search +( + '[ { "a": { "b": { "c": "showtime" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "shoe"} } ]', + 'all', + 'sho%', + null, + '$**.c' +); + +select json_search +( + '[ { "a": { "b": { "c": "showtime" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "shoe"} } ]', + 'all', + 'sho%e', + null, + '$**.c' +); + +select json_search +( + '[ { "a": { "b": { "c": "showtime" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "shoe"} } ]', + 'all', + 'sho%', + null, + '$[*].c' +); + +select json_search +( + '[ { "a": { "b": { "c": "showtime" } } }, [ { "b": { "c": "shout" } }, { "c": { "c": "shoe"} } ] ]', + 'all', + 'sho%', + null, + '$[1]**.c' +); + +# escape character +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo%bar' ); +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo\%bar' ); +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|' ); +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[0]' ); +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[0]', '$[1]' ); +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[0]', '$[1]', '$[2]' ); + +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo\%bar', null ); +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo\%bar', null, '$[0]' ); +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo\%bar', null, '$[1]' ); +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[0]' ); +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[1]' ); + +# search is case-sensitive +select json_search( '[ "abc", "ABC" ]', 'all', 'aBc' ); +select json_search( '[ "abc", "ABC" ]', 'all', 'abc' ); +select json_search( '[ "abc", "ABC" ]', 'all', 'ABC' ); + +# only matches strings, not numerics +select json_search( '[ 10, "10", 1.0, "1.0" ]', 'all', '1%' ); + +# examples from the wl7909 spec +# returns null because numeric values don't match string values +SELECT JSON_SEARCH +( + '{ "a" : 123, "b" : [ 123, 456 ] }', + 'one', + '123' +); + +# returns "$.b[2]" +SELECT JSON_SEARCH +( + '{ "a" : "123", "b" : [ 123, "789", "123", "456", "123" ] }', + 'one', + '123', + null, + '$.b' +); + +# could return either "$.a" or "$.b.key" +SELECT JSON_SEARCH +( + '{ "a" : "123", "b" : { "key" : "123" } }', + 'one', + '123' +); + +# returns "$.b.key" +SELECT JSON_SEARCH +( + '{ "a" : "1243", "b" : { "key" : "1234" } }', + 'one', + '123%' +); + +# returns "$.b.c" +SELECT JSON_SEARCH +( + '{ "a" : "1243", "b" : { "key" : "1234", "c": "directorysub%directoryabc" } }', + 'one', + 'dir%torysub@%dir%', + '@' +); + +# returns null because the path doesn't exist +SELECT JSON_SEARCH +( + '{ "a" : "1243", "b" : { "key" : "1234" } }', + 'one', + '123%', + null, + '$.c' +); + +# returns $."one potato" +SELECT JSON_UNQUOTE +( + JSON_SEARCH + ( + '{ "onepotato": "foot", "one potato": "food" , "one \\"potato": "fool" }', + 'all', + 'food' + ) +); + +select json_type(case (null is null) when 1 then + cast('null' as json) else + cast('[1,2,3]' as json) end); + +select json_type(case (null is not null) when 1 then + cast('null' as json) else + cast('[1,2,3]' as json) end); + +select json_type( if(null is null, + cast('null' as json), + cast('[1,2,3]' as json)) ); + +select json_type( if(null is not null, + cast('null' as json), + cast('[1,2,3]' as json))); + +select cast(json_extract(cast(concat('[', cast('["A",2]' as json), ']') as json), + '$[0][1]') as char) = 2; + +--echo # ---------------------------------------------------------------------- +--echo # Test of aggregate function MAX, MIN. +--echo # ---------------------------------------------------------------------- + +select max(cast('[1,2,3]' as json)); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_QUOTE, JSON_UNQUOTE +--echo # ---------------------------------------------------------------------- + +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_quote(); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_quote('abc', 'def'); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_quote(NULL, 'def'); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_quote('abc', NULL); + +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_unquote(); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_unquote('"abc"', '"def"'); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_unquote(NULL, 'def'); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_unquote('"abc"', NULL); + +select json_quote(NULL); +select json_unquote(NULL); + +select json_quote('abc'); +select json_quote(convert('abc' using ascii)); +select json_quote(convert('abc' using latin1)); +select json_quote(convert('abc' using utf8)); +select json_quote(convert('abc' using utf8mb4)); + +select json_unquote('abc'); # should do nothing + +select json_unquote('"abc"'); +select json_unquote(convert('"abc"' using ascii)); +select json_unquote(convert('"abc"' using latin1)); +select json_unquote(convert('"abc"' using utf8)); +select json_unquote(convert('"abc"' using utf8mb4)); + +select json_quote('"'); +select json_unquote('"'); # should do nothing + +--echo error ER_INCORRECT_TYPE +select json_quote(123); # integer not allowed +--echo error ER_INCORRECT_TYPE +select json_unquote(123); # integer not allowed + +select json_unquote('""'); # empty string +select char_length(json_unquote('""')); # verify empty string +select json_unquote('"" '); # unchanged: no final " +select json_unquote(cast(json_quote('abc') as json)); # round trip + +# No change in this JSON string: it is an object +select cast('{"abc": "foo"}' as json); +select json_unquote(cast('{"abc": "foo"}' as json)); + +# This is a JSON string, so it is actually unquoted +select json_extract(cast('{"abc": "foo"}' as json), '$.abc'); +select json_unquote(json_extract(cast('{"abc": "foo"}' as json), '$.abc')); + +# Bug fix: thse should be the same +select json_unquote('["a", "b", "c"]'); +select json_unquote(cast('["a", "b", "c"]' as json)); + +select charset(json_unquote('"abc"')); + +select json_quote(convert(X'e68891' using utf8)); # chinese "I" (wo3) +select json_quote(convert(X'e68891' using utf8mb4)); # chinese "I" (wo3) + +select cast(json_quote(convert(X'e68891' using utf8)) as json); + +select json_unquote(convert(X'e68891' using utf8)); # chinese "I" (wo3) + +select json_quote(json_quote(json_quote('abc'))); # deep quote +select json_unquote(json_unquote(json_unquote( # long round trip of it + json_quote(json_quote(json_quote('abc')))))); + +# DATE/TIME will lose their quotes, too: +select cast(cast('2015-01-15 23:24:25' as datetime) as json); +select json_unquote(cast(cast('2015-01-15 23:24:25' as datetime) as json)); + +# as well as opaque values: +select cast(st_geomfromtext('point(1 1)') as json); +select json_unquote(cast(st_geomfromtext('point(1 1)') as json)); + +# examples from the wl7909 spec +# returns the SQL string literal abc +SELECT JSON_UNQUOTE( '"abc"' ); + +# returns the SQL string literal "abc +SELECT JSON_UNQUOTE( '"abc' ); + +--echo error ER_INCORRECT_TYPE +SELECT JSON_UNQUOTE( 123 ); + +# returns the SQL string literal abc +SELECT JSON_UNQUOTE +( CAST( CAST( '"abc"' AS JSON ) AS CHAR ) ); + +# returns 1 +SELECT JSON_UNQUOTE +( + CAST( + JSON_EXTRACT( '{ "userName" : "fred" }', '$.userName' ) + AS CHAR + ) +) = 'fred'; + +# returns 0 +SELECT + CAST( + JSON_EXTRACT( '{ "userName" : "fred" }', '$.userName' ) + AS CHAR + ) = 'fred'; + +# returns "abc" +SELECT JSON_QUOTE( 'abc' ); + +--echo error ER_INCORRECT_TYPE +SELECT JSON_QUOTE( 123 ); + +# returns the JSON document consisting of the string scalar "123" +SELECT CAST( JSON_QUOTE( '123' ) AS JSON ); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_CONTAINS +--echo # ---------------------------------------------------------------------- + +--echo # should give NULL +select json_contains(NULL, NULL); +select json_contains(cast('{"a": 1, "b": 2}' as json), NULL); +select json_contains(NULL, cast('null' as json)); +select json_contains(cast('[1]' as json), cast('[1]' as json), NULL); + +--echo # should give 0: +select json_contains(cast(3.14 as json), cast(3 as json)); + +--echo # should give 0: not at top level +select json_contains(cast('{"a": {"b": 7}}' as json), cast('{"b": 7}' as json)); + +--echo # but path argument will fix it: +select json_contains(cast('{"a": {"b": 7}}' as json), cast('{"b": 7}' as json), '$.a'); + +--echo # but arrays "introspect" +select json_contains(cast('[1,[2.0, 3.0]]' as json), cast('[2.0]' as json)); +select json_contains(cast('[1, 2, [3, [4, 5]], 6, 7]' as json), cast('5' as json)); + +--echo # should give 0: just a key +select json_contains(cast('{"a": 1, "b": 2}' as json), cast('"a"' as json)); + +--echo # should give 0: one candidate element doesn't match +select json_contains(cast('[1]' as json), cast('[1,2]' as json)); + +--echo # should all give 1 +select json_contains(cast('null' as json), cast('null' as json)); +--echo # simple object subset +select json_contains(cast('{"a": 1, "b": 2}' as json), cast( '{"a": 1}' as json)); +--echo # simple vector subset +select json_contains(cast('[1, 2, 3]' as json), cast('[1, 3]' as json)); +--echo # auto-wrap, should give 1 +select json_contains(cast('[1, 2, 3]' as json), cast(3 as json)); +--echo # ok even with nested cast off elements +select json_contains(cast('{"person": {"id": 1, "country": "norway"}}' as json), + cast('{"person": {"country": "norway"}}' as json)); +--echo # vector reordering and duplicates is ok +select json_contains(cast('[1,3,5]' as json), cast('[5,3,1,5]' as json)); +--echo # ok even with more elts in candidate than in doc +select json_contains(cast('[{"b": 4, "a":7}]' as json), cast('[{"a":7},{"b":4}]' as json)); +select json_contains(cast('[{"b": 4, "a":7}, 5]' as json), cast('[5, {"a":7, "b":4}]' as json)); +--echo # ok even with mixed number types that compare equal +select json_contains(cast('[{"b": 4, "a":7}, 5.0]' as json), cast('[5, {"a":7.0E0, "b":4}]' as json)); + +# Bug discovered by Rick: used to give 1 (true). +select json_contains( '{"customer": "cust3"}', '{"customer": "cust1"}' ); + +SELECT JSON_CONTAINS('[null,1,[2,3],true,false]', '[null,1,[3],false]'); +SELECT JSON_CONTAINS('[null,1,[2,3],true,false]', '[null,1,[4],false]'); +SELECT JSON_CONTAINS('[true,false]', '[[true]]'); +SELECT JSON_CONTAINS('[1,2]', '[[1]]'); +SELECT JSON_CONTAINS('[1,2]', '1', '$.abc'); +SELECT JSON_CONTAINS('{}', '{}'); +SELECT JSON_CONTAINS('{}', '{"a":1}'); +SELECT JSON_CONTAINS('{"a":1}', '{"a":1,"b":2}'); + +# examples from the wl7909 spec +# returns 1 +SELECT JSON_CONTAINS +( + CAST('[1, 4, 6]' AS JSON), + CAST('[1, 6]' AS JSON) +); + +# returns 1; even with nested cast off elements +SELECT JSON_CONTAINS +( + CAST('{"person": {"id": 1, "country": "norway"}}' AS JSON), + CAST('{"person": {"country": "norway"}}' AS JSON) +); + +# returns 1; reordering and duplicates are ok +SELECT JSON_CONTAINS +( + CAST('[1,3,5]' AS JSON), + CAST('[5,3,1,5]' AS JSON) +); + +# return 0; no type conversion is performed +SELECT JSON_CONTAINS +( + CAST('[3.14]' AS JSON), + CAST('[3]' AS JSON) +); + +# returns 1, due to auto-wrapping +SELECT JSON_CONTAINS +( + CAST('[1, 2, 3]' AS JSON), + CAST(3 AS JSON) +); + +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT JSON_CONTAINS(); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT JSON_CONTAINS('[1]'); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT JSON_CONTAINS('[1]', '[1]', '$', '$[0]'); + +--echo # ---------------------------------------------------------------------- +--echo # Wrong collation from JSON_QUOTE caused problems: Set it in +--echo # Item_func_json_quote::fix_length_and_dec. Bug found by Knut. +--echo # Similar issue for JSON_UNQUOTE and JSON_TYPE. +--echo # ---------------------------------------------------------------------- +select json_object("a", ifnull(json_quote('test'), cast('null' as json))); +select cast(concat('[', json_quote('ab'), ']') as json); +select cast(concat('[', json_unquote('"12"'), ']') as json); +select cast(concat('["', json_type(cast(1 as json)), '"]') as json); + +--echo # +--echo # Bug#20912438: ITEM_TYPE_HOLDER::DISPLAY_LENGTH(ITEM*): ASSERTION `0' FAILED +--echo # +(SELECT JSON_KEYS('{ "key80": "2015-04-20 11:53:55"}')) UNION ALL +(SELECT JSON_KEYS('{ "key80": "2015-04-20 11:53:55" }') LIMIT 0); +SELECT CAST(1 AS JSON) UNION ALL SELECT CAST(1 AS JSON); + +# Exercise NULL handling and error handling in Item_copy_json::copy(). +SELECT COUNT(*), CAST(NULL AS JSON); +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT COUNT(*), JSON_EXTRACT('not valid json!', '$'); + +--echo # ---------------------------------------------------------------------- +--echo # Bug report from John E. +--echo # Crash in Item_copy_json::~Item_copy_json +--echo # ---------------------------------------------------------------------- +EXPLAIN SELECT COUNT(*), JSON_KEYS('{}'); + +select json_search( '{ "a": "foo" }', 'one', 'foo', 'a' ); +select json_search( '{ "a": "foo" }', 'one', 'foo', null ); +select json_search( '{ "a": "foo" }', 'one', 'foo', convert(x'f8' using latin1) ); + +# bad escape arg +--error ER_WRONG_ARGUMENTS +select json_search( '{ "a": "foo" }', 'one', 'foo', 'ab' ); + +--echo # ---------------------------------------------------------------------- +--echo # Wrong results when Json_path_cache primed is accessed +--echo # during the prepare-phase. +--echo #---------------------------------------------------------------------- + +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', null ) is null; + +prepare stmt1 from 'select json_remove( ''[ 1, { "a": true, "b": false, "c": null }, 5 ]'', null ) is null'; +execute stmt1; + +--echo error ER_INVALID_JSON_PATH +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$.' ) is null; + +--echo error ER_INVALID_JSON_PATH +prepare stmt1 from 'select json_remove( ''[ 1, { "a": true, "b": false, "c": null }, 5 ]'', ''$.'' ) is null'; + +--echo # ---------------------------------------------------------------------- +--echo # Bug#20987329 VALUE OF PREPARED STATEMENT PLACEHOLDER FOR PARAMETER +--echo # IN JSON_EXTRACT IS STICKY +--echo #---------------------------------------------------------------------- + +# should get different results with different parameter values + +# json_extract() + +# json_contains() + +prepare json_stmt1 FROM 'select json_contains( ''{ "keyA": [1, 2, 3], "keyB": [4, 5, 6] }'', ''[2]'', ? )'; +set @mypath = '$.keyA'; +execute json_stmt1 USING @mypath; +set @mypath = '$.keyB'; +execute json_stmt1 USING @mypath; + +# json_contains_path() + +prepare json_stmt2 FROM 'select json_contains_path( ''{ "keyA": [1, 2, 3] }'', ''all'', ? )'; +set @mypath = '$.keyA'; +execute json_stmt2 USING @mypath; +set @mypath = '$.keyB'; +execute json_stmt2 USING @mypath; + +# json_length() + +prepare json_stmt3 FROM 'select json_length( ''{ "keyA": [1, 2, 3], "keyB": [1, 2, 3, 4] }'', ? )'; +set @mypath = '$.keyA'; +execute json_stmt3 USING @mypath; +set @mypath = '$.keyB'; +execute json_stmt3 USING @mypath; + +# json_keys() + +prepare json_stmt4 FROM 'select json_keys( ''[ { "keyA": true }, { "keyB": false } ]'', ? )'; +set @mypath = '$[0]'; +execute json_stmt4 USING @mypath; +set @mypath = '$[1]'; +execute json_stmt4 USING @mypath; + +# json_array_append() + +prepare json_stmt5 FROM 'select json_array_append( ''{ "keyA": [1, 2], "keyB": [3, 4] }'', ?, 5 )'; +set @mypath = '$.keyA'; +execute json_stmt5 USING @mypath; +set @mypath = '$.keyB'; +execute json_stmt5 USING @mypath; + +# json_insert() + +prepare json_stmt6 FROM 'select json_insert( ''{ "keyA": [1, 2], "keyB": [3, 4] }'', ?, 5 )'; +set @mypath = '$.keyA[2]'; +execute json_stmt6 USING @mypath; +set @mypath = '$.keyB[2]'; +execute json_stmt6 USING @mypath; + +# json_set() + +prepare json_stmt7 FROM 'select json_set( ''{ "keyA": [1, 2], "keyB": [3, 4] }'', ?, 5 )'; +set @mypath = '$.keyA[2]'; +execute json_stmt7 USING @mypath; +set @mypath = '$.keyB[2]'; +execute json_stmt7 USING @mypath; + +# json_replace() + +prepare json_stmt8 FROM 'select json_replace( ''{ "keyA": [1, 2], "keyB": [3, 4] }'', ?, 5 )'; +set @mypath = '$.keyA[1]'; +execute json_stmt8 USING @mypath; +set @mypath = '$.keyB[1]'; +execute json_stmt8 USING @mypath; + +# json_search() + +prepare json_stmt9 FROM 'select json_search( ''{ "keyA": [ "foot" ], "keyB": [ "food" ] }'', ''all'', ''foo%'', null, ? )'; +set @mypath = '$.keyA'; +execute json_stmt9 USING @mypath; +set @mypath = '$.keyB'; +execute json_stmt9 USING @mypath; + +# json_remove() + +prepare json_stmt10 FROM 'select json_remove( ''{ "keyA": [ "foot" ], "keyB": [ "food" ] }'', ? )'; +set @mypath = '$.keyA'; +execute json_stmt10 USING @mypath; +set @mypath = '$.keyB'; +execute json_stmt10 USING @mypath; + +# similar caching problem for the oneOrAll args + +prepare json_stmt11 FROM 'select json_contains_path( ''{ "keyA": true }'', ?, ''$.keyA'', ''$.keyB'' )'; +set @mypath = 'one'; +execute json_stmt11 USING @mypath; +set @mypath = 'all'; +execute json_stmt11 USING @mypath; + +prepare json_stmt12 FROM 'select json_search( ''{ "keyA": [ "foot" ], "keyB": [ "food" ] }'', ?, ''foo%'' )'; +set @mypath = 'one'; +execute json_stmt12 USING @mypath; +set @mypath = 'all'; +execute json_stmt12 USING @mypath; + +--echo # +--echo # Bug#21128632 JSON_QUOTE(JSON_TYPE(...)) GIVES ERROR 3139 ER_INVALID_JSON_CHARSET +--echo # + +select json_quote( json_type( json_object() ) ); +select json_quote( json_type( cast('{}' as json) ) ); + +--echo # +--echo # Bug#21148020 OUTPUT FROM JSON_TYPE() IS TRUNCATED +--echo # WHEN EXECUTED IN A VIEW OR JOIN +--echo # + +SELECT JSON_TYPE(JSON_OBJECT()); +CREATE VIEW v1 AS SELECT JSON_TYPE(JSON_OBJECT()); +SELECT * FROM v1; +drop view v1; + +# SELECT JSON_TYPE(CAST(CAST('2015-05-25 11:23:55' AS DATETIME) AS JSON)); +# CREATE VIEW v2 AS SELECT JSON_TYPE(CAST(CAST('2015-05-25 11:23:55' AS +# DATETIME) AS JSON)); +# SELECT * FROM v2; +# drop view v2; + +--echo # +--echo # Bug#21198333 SIG 6 IN ITEM_CACHE_JSON::CACHE_VALUE AT SQL/ITEM.CC:9470 +--echo # +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT MIN(JSON_EXTRACT('not json', '$')); + +--echo # +--echo # Bug#21200657 DATA FROM DERIVED TABLE BASED +--echo # ON JSN_QUOTE()/JSN_UNQUOTE() CALL IS TRUNCATED +--echo # +SELECT JSON_QUOTE('This is a string that should not be truncated') AS field1; +SELECT JSON_UNQUOTE(JSON_QUOTE('This is a string that should not be truncated')) AS field1; + +SELECT * FROM (SELECT JSON_QUOTE('This is a string that should not be truncated') AS field1) AS DERIVED_TABLE; +SELECT * FROM (SELECT JSON_UNQUOTE("This is a string that should not be truncated") AS field1) AS DERIVED_TABLE; +SELECT * FROM (SELECT JSON_UNQUOTE(JSON_QUOTE('This is a string that should not be truncated')) AS field1) AS DERIVED_TABLE; + +--echo # +--echo # Bug#21296173 JSON_OBJECT('KEY', BOOLEAN_LITERAL) USES VALUES 0, 1 +--echo # FOR BOOL WHEN USED VIA VIEW +--echo # + +SELECT JSON_OBJECT('key1', false, 'key2', true); +SELECT JSON_ARRAY('key1', false, 'key2', true); +CREATE VIEW v1 AS SELECT JSON_OBJECT('key1', false, 'key2', true); +SELECT * FROM v1; +CREATE VIEW v2 AS SELECT JSON_ARRAY('key1', false, 'key2', true); +SELECT * FROM v2; + +drop view v1; +drop view v2; + +--echo # +--echo # Bug#21293089 JSON_CONTAINS() RETURNS WRONG RESULT WITH EMPTY JSON ARRAY +--echo # +SELECT JSON_CONTAINS('[]', '{"a" : 1}'); +SELECT JSON_CONTAINS('[]', '[1, 2, 3, 4, 5]'); +SELECT JSON_CONTAINS('[]', '[1, 2, 3, 4, {"a" : 1}]'); +SELECT JSON_CONTAINS('[]', '{"a" : [1, 2, 3, 4, 5]}'); +SELECT JSON_CONTAINS('[]', '[]'); + +--echo # +--echo # Bug#21377136 STACK OVERFLOW IN RAPIDJSON::GENERICREADER +--echo # +--echo error ER_JSON_DOCUMENT_TOO_DEEP +SELECT JSON_VALID(REPEAT('[', 100000)); +--echo error ER_JSON_DOCUMENT_TOO_DEEP +SELECT JSON_VALID(REPEAT('{"a":', 100000)); +--echo error ER_JSON_DOCUMENT_TOO_DEEP +SELECT JSON_VALID(REPEAT('{"a":[', 100000)); +--echo error ER_JSON_DOCUMENT_TOO_DEEP +SELECT JSON_VALID(REPEAT('[{"a":', 100000)); + +--echo # +--echo # Bug#21381806 JSON: ASSERTION FAILED: ARG->NULL_VALUE +--echo # +SELECT JSON_SET(CASE WHEN 1 THEN NULL ELSE NULL END, '{}', '{}'); +SELECT JSON_VALID(CASE WHEN 1 THEN NULL ELSE NULL END); +SELECT JSON_ARRAY(CASE WHEN 1 THEN NULL ELSE NULL END); + +--echo # +--echo # Bug#21384048 ASSERTION FAILED: N >= 0 && N <= 308 +--echo # IN RAPIDJSON::INTERNAL::FASTPATH +--echo # +SELECT JSON_EXTRACT('-1E-36181012216111515851075235238', '$'); +SELECT JSON_EXTRACT('1E-36181012216111515851075235238', '$'); +SELECT JSON_EXTRACT('1E-325', '$'); +SELECT JSON_EXTRACT('1E-324', '$'); +SELECT JSON_EXTRACT('1E-323', '$'); +SELECT JSON_EXTRACT('1E+308', '$'); +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_EXTRACT('1E+309', '$'); +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_EXTRACT('1E+36181012216111515851075235238', '$'); +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_EXTRACT('-1E+36181012216111515851075235238', '$'); + +--echo # +--echo # Bug#21383284: ASSERTION IN SELECT_LEX::SETUP_CONDS +--echo # +--error ER_WRONG_ARGUMENTS +SELECT 1 FROM dual WHERE JSON_SEARCH('{}', 'one', 'foo', 'too-long-escape'); +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT 1 FROM dual WHERE JSON_SEARCH('{}', 'one', 'foo', JSON_EXTRACT('', '$')); + +--echo # +--echo # Bug#21442624 INCORRECT RESULT FROM JSON_SET WITH AUTO-WRAPPING +--echo # + +SELECT JSON_SET('1', '$', 100); +SELECT JSON_SET('1', '$[0]', 100); +SELECT JSON_SET('1', '$[0][0]', 100); +SELECT JSON_SET('1', '$[0][0][0]', 100); + +SELECT JSON_SET('[]', '$', 100); +SELECT JSON_SET('[]', '$[0]', 100); +SELECT JSON_SET('[]', '$[0][0]', 100); +SELECT JSON_SET('[]', '$[0][0][0]', 100); + +SELECT JSON_SET('[1]', '$', 100); +SELECT JSON_SET('[1]', '$[0]', 100); +SELECT JSON_SET('[1]', '$[0][0]', 100); +SELECT JSON_SET('[1]', '$[0][0][0]', 100); + +SELECT JSON_SET('[[1]]', '$', 100); +SELECT JSON_SET('[[1]]', '$[0]', 100); +SELECT JSON_SET('[[1]]', '$[0][0]', 100); +SELECT JSON_SET('[[1]]', '$[0][0][0]', 100); + +SELECT JSON_SET('[[[1]]]', '$', 100); +SELECT JSON_SET('[[[1]]]', '$[0]', 100); +SELECT JSON_SET('[[[1]]]', '$[0][0]', 100); +SELECT JSON_SET('[[[1]]]', '$[0][0][0]', 100); + +SELECT JSON_REPLACE('1', '$', 100); +SELECT JSON_REPLACE('1', '$[0]', 100); +SELECT JSON_REPLACE('1', '$[0][0]', 100); +SELECT JSON_REPLACE('1', '$[0][0][0]', 100); + +SELECT JSON_REPLACE('[]', '$', 100); +SELECT JSON_REPLACE('[]', '$[0]', 100); +SELECT JSON_REPLACE('[]', '$[0][0]', 100); +SELECT JSON_REPLACE('[]', '$[0][0][0]', 100); + +SELECT JSON_REPLACE('[1]', '$', 100); +SELECT JSON_REPLACE('[1]', '$[0]', 100); +SELECT JSON_REPLACE('[1]', '$[0][0]', 100); +SELECT JSON_REPLACE('[1]', '$[0][0][0]', 100); + +SELECT JSON_REPLACE('[[1]]', '$', 100); +SELECT JSON_REPLACE('[[1]]', '$[0]', 100); +SELECT JSON_REPLACE('[[1]]', '$[0][0]', 100); +SELECT JSON_REPLACE('[[1]]', '$[0][0][0]', 100); + +SELECT JSON_REPLACE('[[[1]]]', '$', 100); +SELECT JSON_REPLACE('[[[1]]]', '$[0]', 100); +SELECT JSON_REPLACE('[[[1]]]', '$[0][0]', 100); +SELECT JSON_REPLACE('[[[1]]]', '$[0][0][0]', 100); + + +--echo # +--echo # Bug#21828321: JSON FUNCS CALL DBUG_ABORT OR EXIT() ON WINDOWS! +--echo # +# LEAST and GREATEST treat JSON arguments as strings for now. They used to hit +# an assertion if used in a JSON context and all arguments were JSON values, or +# a mix of NULLs and JSON values. +SELECT JSON_ARRAY(LEAST(NULL, NULL), GREATEST(NULL, NULL), LEAST(j1, NULL), + GREATEST(NULL, j2), LEAST(j1, j2), GREATEST(j1, j2)) AS j +FROM (SELECT CAST('1' AS JSON) AS j1, CAST('2' AS JSON) AS j2) t; + diff --git a/mysql-test/t/func_json.test b/mysql-test/t/func_json.test index 7ab136f177c..455f1a722ea 100644 --- a/mysql-test/t/func_json.test +++ b/mysql-test/t/func_json.test @@ -78,6 +78,8 @@ select json_extract('[10, 20, [30, 40]]', '$[2][*]'); select json_extract('[10, 20, [{"a":3}, 30, 40]]', '$[2][*]'); select json_extract('1', '$'); select json_extract('[10, 20, [30, 40], 1, 10]', '$[1]'); +select json_extract('[10, 20, [30, 40], 1, 10]', '$[1]', '$[25]'); +select json_extract( '[{"a": [3, 4]}, {"b": 2}]', '$[0].a', '$[1].a'); select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.k1', 'word'); select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.d[3]', 3); diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index b0576fbdaba..e97f00dae8e 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -168,6 +168,7 @@ void report_json_error_ex(String *js, json_engine_t *je, #define NO_WILDCARD_ALLOWED 1 #define SHOULD_END_WITH_ARRAY 2 +#define TRIVIAL_PATH_NOT_ALLOWED 3 #define report_path_error(js, je, n_param) \ report_path_error_ex(js, je, func_name(), n_param,\ @@ -205,6 +206,11 @@ static void report_path_error_ex(String *ps, json_path_t *p, code= ER_JSON_PATH_NO_WILDCARD; break; + case TRIVIAL_PATH_NOT_ALLOWED: + code= ER_JSON_PATH_EMPTY; + break; + + default: return; } @@ -547,22 +553,43 @@ void Item_func_json_extract::fix_length_and_dec() } +static bool path_exact(const json_path_with_flags *paths_list, int n_paths, + const json_path_t *p) +{ + for (; n_paths > 0; n_paths--, paths_list++) + { + if (json_path_compare(&paths_list->p, p) == 0) + return TRUE; + } + return FALSE; +} + + +static bool path_ok(const json_path_with_flags *paths_list, int n_paths, + const json_path_t *p) +{ + for (; n_paths > 0; n_paths--, paths_list++) + { + if (json_path_compare(&paths_list->p, p) >= 0) + return TRUE; + } + return FALSE; +} + + String *Item_func_json_extract::val_str(String *str) { String *js= args[0]->val_str(&tmp_js); - json_engine_t je; - bool multiple_values_found= FALSE; + json_engine_t je, sav_je; + json_path_t p; const uchar *value; - const char *first_value= NULL; - uint n_arg, v_len, first_len; - uint array_counters[JSON_DEPTH_LIMIT]; + int not_first_value= 0; + uint n_arg, v_len; + int possible_multiple_values; if ((null_value= args[0]->null_value)) return 0; - str->set_charset(js->charset()); - str->length(0); - for (n_arg=1; n_arg < arg_count; n_arg++) { json_path_with_flags *c_path= paths + n_arg - 1; @@ -572,76 +599,66 @@ String *Item_func_json_extract::val_str(String *str) if (s_p && json_path_setup(&c_path->p,s_p->charset(),(const uchar *) s_p->ptr(), (const uchar *) s_p->ptr() + s_p->length())) + { + report_path_error(s_p, &c_path->p, n_arg); goto return_null; + } c_path->parsed= c_path->constant; } + } - if (args[n_arg]->null_value) - goto return_null; + possible_multiple_values= arg_count > 2 || + (paths[0].p.types_used & (JSON_PATH_WILD | JSON_PATH_DOUBLE_WILD)); - json_scan_start(&je, js->charset(),(const uchar *) js->ptr(), - (const uchar *) js->ptr() + js->length()); + str->set_charset(js->charset()); + str->length(0); - c_path->cur_step= c_path->p.steps; + if (possible_multiple_values && str->append("[", 1)) + goto error; - while (!json_find_path(&je, &c_path->p, &c_path->cur_step, array_counters)) + json_get_path_start(&je, js->charset(),(const uchar *) js->ptr(), + (const uchar *) js->ptr() + js->length(), &p); + + while (json_get_path_next(&je, &p) == 0) + { + if (!path_exact(paths, arg_count-1, &p)) + continue; + + value= je.value_begin; + + if (json_value_scalar(&je)) + v_len= je.value_end - value; + else { - if (json_read_value(&je)) + if (possible_multiple_values) + sav_je= je; + if (json_skip_level(&je)) goto error; - - value= je.value_begin; - if (json_value_scalar(&je)) - v_len= je.value_end - value; - else - { - if (json_skip_level(&je)) - goto error; - v_len= je.s.c_str - value; - } - - if (!multiple_values_found) - { - if (first_value == NULL) - { - /* - Just remember the first value as we don't know yet - if we need to create an array out of it or not. - */ - first_value= (const char *) value; - first_len= v_len; - } - else - { - multiple_values_found= TRUE; /* We have to make an JSON array. */ - if (str->append("[", 1) || - str->append(first_value, first_len)) - goto error; /* Out of memory. */ - } - - } - if (multiple_values_found && - (str->append(", ", 2) || - str->append((const char *) value, v_len))) - goto error; /* Out of memory. */ - - if (json_scan_next(&je)) - break; - + v_len= je.s.c_str - value; + if (possible_multiple_values) + je= sav_je; } + + if ((not_first_value && str->append(", ", 2)) || + str->append((const char *) value, v_len)) + goto error; /* Out of memory. */ + + not_first_value= 1; + + if (!possible_multiple_values) + break; } if (je.s.error) goto error; - if (first_value == NULL) + if (!not_first_value) { /* Nothing was found. */ goto return_null; } - if (multiple_values_found ? - str->append("]") : - str->append(first_value, first_len)) + if (possible_multiple_values && str->append("]")) goto error; /* Out of memory. */ return str; @@ -796,12 +813,14 @@ static int check_contains(json_engine_t *js, json_engine_t *value) { while (json_scan_next(js) == 0 && js->state != JST_ARRAY_END) { - json_level_t c_level; + int c_level, v_scalar; DBUG_ASSERT(js->state == JST_VALUE); if (json_read_value(js)) return FALSE; - c_level= json_value_scalar(js) ? NULL : json_get_level(js); + if (!(v_scalar= json_value_scalar(js))) + c_level= json_get_level(js); + if (check_contains(js, value)) { if (json_skip_level(js)) @@ -809,7 +828,7 @@ static int check_contains(json_engine_t *js, json_engine_t *value) return TRUE; } if (value->s.error || js->s.error || - (c_level && json_skip_to_level(js, c_level))) + (!v_scalar && json_skip_to_level(js, c_level))) return FALSE; } return FALSE; @@ -955,6 +974,8 @@ return_null: bool Item_func_json_contains_path::fix_fields(THD *thd, Item **ref) { return alloc_tmp_paths(thd, arg_count-2, &paths, &tmp_paths) || + (p_found= (bool *) alloc_root(thd->mem_root, + (arg_count-2)*sizeof(bool))) == NULL || Item_int_func::fix_fields(thd, ref); } @@ -1010,6 +1031,7 @@ static int parse_one_or_all(const Item_func *f, Item *ooa_arg, } +#ifdef DUMMY longlong Item_func_json_contains_path::val_int() { String *js= args[0]->val_str(&tmp_js); @@ -1076,6 +1098,87 @@ return_null: null_value= 1; return 0; } +#endif /*DUMMY*/ + +longlong Item_func_json_contains_path::val_int() +{ + String *js= args[0]->val_str(&tmp_js); + json_engine_t je; + uint n_arg; + longlong result; + json_path_t p; + int n_found; + + if ((null_value= args[0]->null_value)) + return 0; + + if (parse_one_or_all(this, args[1], &ooa_parsed, ooa_constant, &mode_one)) + goto null_return;; + + for (n_arg=2; n_arg < arg_count; n_arg++) + { + json_path_with_flags *c_path= paths + n_arg - 2; + if (!c_path->parsed) + { + String *s_p= args[n_arg]->val_str(tmp_paths + (n_arg-2)); + if (s_p && + json_path_setup(&c_path->p,s_p->charset(),(const uchar *) s_p->ptr(), + (const uchar *) s_p->ptr() + s_p->length())) + { + report_path_error(s_p, &c_path->p, n_arg); + goto null_return; + } + c_path->parsed= c_path->constant; + } + if (args[n_arg]->null_value) + goto null_return; + } + + json_get_path_start(&je, js->charset(),(const uchar *) js->ptr(), + (const uchar *) js->ptr() + js->length(), &p); + + + if (!mode_one) + { + bzero(p_found, (arg_count-2) * sizeof(bool)); + n_found= arg_count - 2; + } + + result= 0; + while (json_get_path_next(&je, &p) == 0) + { + int n_path= arg_count - 2; + json_path_with_flags *c_path= paths; + for (; n_path > 0; n_path--, c_path++) + { + if (json_path_compare(&c_path->p, &p) >= 0) + { + if (mode_one) + { + result= 1; + break; + } + /* mode_all */ + if (p_found[n_path-1]) + continue; /* already found */ + if (--n_found == 0) + { + result= 1; + break; + } + p_found[n_path-1]= TRUE; + } + } + } + + if (je.s.error == 0) + return result; + + report_json_error(js, &je, 0); +null_return: + null_value= 1; + return 0; +} static int append_json_value(String *str, Item *item, String *tmp_val) @@ -1626,10 +1729,10 @@ longlong Item_func_json_length::val_int() { String *s_p= args[1]->val_str(&tmp_path); if (s_p && - json_path_setup(&path.p, s_p->charset(), (const uchar *) s_p->ptr(), - (const uchar *) s_p->ptr() + s_p->length())) + path_setup_nwc(&path.p, s_p->charset(), (const uchar *) s_p->ptr(), + (const uchar *) s_p->ptr() + s_p->length())) { - report_path_error(s_p, &path.p, 2); + report_path_error(s_p, &path.p, 1); goto null_return; } path.parsed= path.constant; @@ -2040,7 +2143,7 @@ String *Item_func_json_remove::val_str(String *str) str->set_charset(js->charset()); json_string_set_cs(&key_name, js->charset()); - for (n_arg=1, n_path=0; n_arg < arg_count; n_arg+=2, n_path++) + for (n_arg=1, n_path=0; n_arg < arg_count; n_arg++, n_path++) { uint array_counters[JSON_DEPTH_LIMIT]; json_path_with_flags *c_path= paths + n_path; @@ -2064,7 +2167,11 @@ String *Item_func_json_remove::val_str(String *str) /* We search to the last step. */ c_path->p.last_step--; if (c_path->p.last_step < c_path->p.steps) + { + c_path->p.s.error= TRIVIAL_PATH_NOT_ALLOWED; + report_path_error(s_p, &c_path->p, n_arg); goto null_return; + } } c_path->parsed= c_path->constant; } @@ -2371,60 +2478,6 @@ static int append_json_path(String *str, const json_path_t *p) } -static int json_path_compare(const json_path_t *a, const json_path_t *b) -{ - const json_path_step_t *sa= a->steps + 1; - const json_path_step_t *sb= b->steps + 1; - - if (a->last_step - sa > b->last_step - sb) - return -2; - - while (sa <= a->last_step) - { - if (sb > b->last_step) - return -2; - - if (!((sa->type & sb->type) & JSON_PATH_KEY_OR_ARRAY)) - goto step_failed; - - if (sa->type & JSON_PATH_ARRAY) - { - if (!(sa->type & JSON_PATH_WILD) && sa->n_item != sb->n_item) - goto step_failed; - } - else /* JSON_PATH_KEY */ - { - if (!(sa->type & JSON_PATH_WILD) && - (sa->key_end - sa->key != sb->key_end - sb->key || - memcmp(sa->key, sb->key, sa->key_end - sa->key) != 0)) - goto step_failed; - } - sb++; - sa++; - continue; - -step_failed: - if (!(sa->type & JSON_PATH_DOUBLE_WILD)) - return -1; - sb++; - } - - return sb <= b->last_step; -} - - -static bool path_ok(const json_path_with_flags *paths_list, int n_paths, - const json_path_t *p) -{ - for (; n_paths > 0; n_paths--, paths_list++) - { - if (json_path_compare(&paths_list->p, p) >= 0) - return TRUE; - } - return FALSE; -} - - String *Item_func_json_search::val_str(String *str) { String *js= args[0]->val_str(&tmp_js); @@ -2462,75 +2515,38 @@ String *Item_func_json_search::val_str(String *str) goto null_return; } - json_scan_start(&je, js->charset(),(const uchar *) js->ptr(), - (const uchar *) js->ptr() + js->length()); + json_get_path_start(&je, js->charset(),(const uchar *) js->ptr(), + (const uchar *) js->ptr() + js->length(), &p); - p.last_step= p.steps; - p.steps[0].type= JSON_PATH_ARRAY_WILD; - p.steps[0].n_item= 0; - - do + while (json_get_path_next(&je, &p) == 0) { - switch (je.state) + if (json_value_scalar(&je)) { - case JST_KEY: - p.last_step->key= je.s.c_str; - while (json_read_keyname_chr(&je) == 0) - p.last_step->key_end= je.s.c_str; - if (je.s.error) - goto js_error; - /* Now we have je.state == JST_VALUE, so let's handle it. */ - - case JST_VALUE: - if (json_read_value(&je)) - goto js_error; - if (json_value_scalar(&je)) + if ((arg_count < 5 || path_ok(paths, arg_count - 4, &p)) && + compare_json_value_wild(&je, s_str) != 0) { - if ((arg_count < 5 || path_ok(paths, n_arg - 4, &p)) && - compare_json_value_wild(&je, s_str) != 0) + ++n_path_found; + if (n_path_found == 1) { - ++n_path_found; - if (n_path_found == 1) - { - sav_path= p; - sav_path.last_step= sav_path.steps + (p.last_step - p.steps); - } - else - { - if (n_path_found == 2) - { - if (str->append("[", 1) || - append_json_path(str, &sav_path)) - goto js_error; - } - if (str->append(", ", 2) || append_json_path(str, &p)) - goto js_error; - } - - if (mode_one) - goto end; + sav_path= p; + sav_path.last_step= sav_path.steps + (p.last_step - p.steps); } - if (p.last_step->type & JSON_PATH_ARRAY) - p.last_step->n_item++; - + else + { + if (n_path_found == 2) + { + if (str->append("[", 1) || + append_json_path(str, &sav_path)) + goto js_error; + } + if (str->append(", ", 2) || append_json_path(str, &p)) + goto js_error; + } + if (mode_one) + goto end; } - else - { - p.last_step++; - p.last_step->type= (enum json_path_step_types) je.value_type; - p.last_step->n_item= 0; - } - break; - case JST_OBJ_END: - case JST_ARRAY_END: - p.last_step--; - if (p.last_step->type & JSON_PATH_ARRAY) - p.last_step->n_item++; - break; - default: - break; } - } while (json_scan_next(&je) == 0); + } if (je.s.error) goto js_error; diff --git a/sql/item_jsonfunc.h b/sql/item_jsonfunc.h index 07741536f55..2ce94985a00 100644 --- a/sql/item_jsonfunc.h +++ b/sql/item_jsonfunc.h @@ -197,6 +197,7 @@ protected: String *tmp_paths; bool mode_one; bool ooa_constant, ooa_parsed; + bool *p_found; public: Item_func_json_contains_path(THD *thd, List &list): diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 7f5df13ad97..b526760b8de 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -7446,3 +7446,5 @@ ER_GEOJSON_TOO_FEW_POINTS eng "Incorrect GeoJSON format - too few points for linestring specified." ER_GEOJSON_NOT_CLOSED eng "Incorrect GeoJSON format - polygon not closed." +ER_JSON_PATH_EMPTY + eng "Path expression '$' is not allowed in argument %d to function '%s'." diff --git a/strings/json_lib.c b/strings/json_lib.c index 16d7436ab6e..66b075a997b 100644 --- a/strings/json_lib.c +++ b/strings/json_lib.c @@ -1,4 +1,5 @@ #include +#include #include @@ -126,9 +127,9 @@ static int syntax_error(json_engine_t *j) static int mark_object(json_engine_t *j) { j->state= JST_OBJ_START; - if ((++j->stack_p) - j->stack < JSON_DEPTH_LIMIT) + if (++j->stack_p < JSON_DEPTH_LIMIT) { - *j->stack_p= JST_OBJ_CONT; + j->stack[j->stack_p]= JST_OBJ_CONT; return 0; } j->s.error= JE_DEPTH; @@ -142,9 +143,9 @@ static int read_obj(json_engine_t *j) j->state= JST_OBJ_START; j->value_type= JSON_VALUE_OBJECT; j->value= j->value_begin; - if ((++j->stack_p) - j->stack < JSON_DEPTH_LIMIT) + if (++j->stack_p < JSON_DEPTH_LIMIT) { - *j->stack_p= JST_OBJ_CONT; + j->stack[j->stack_p]= JST_OBJ_CONT; return 0; } j->s.error= JE_DEPTH; @@ -156,9 +157,9 @@ static int read_obj(json_engine_t *j) static int mark_array(json_engine_t *j) { j->state= JST_ARRAY_START; - if ((++j->stack_p) - j->stack < JSON_DEPTH_LIMIT) + if (++j->stack_p < JSON_DEPTH_LIMIT) { - *j->stack_p= JST_ARRAY_CONT; + j->stack[j->stack_p]= JST_ARRAY_CONT; j->value= j->value_begin; return 0; } @@ -172,9 +173,9 @@ static int read_array(json_engine_t *j) j->state= JST_ARRAY_START; j->value_type= JSON_VALUE_ARRAY; j->value= j->value_begin; - if ((++j->stack_p) - j->stack < JSON_DEPTH_LIMIT) + if (++j->stack_p < JSON_DEPTH_LIMIT) { - *j->stack_p= JST_ARRAY_CONT; + j->stack[j->stack_p]= JST_ARRAY_CONT; return 0; } j->s.error= JE_DEPTH; @@ -376,7 +377,7 @@ static int skip_str_constant(json_engine_t *j) return j->s.error= json_eos(&j->s) ? JE_EOS : JE_BAD_CHR; } - j->state= *j->stack_p; + j->state= j->stack[j->stack_p]; return 0; } @@ -397,7 +398,7 @@ static int read_strn(json_engine_t *j) if (skip_str_constant(j)) return 1; - j->state= *j->stack_p; + j->state= j->stack[j->stack_p]; j->value_len= (j->s.c_str - j->value) - 1; return 0; } @@ -469,7 +470,7 @@ static int json_num_states[NS_NUM_STATES][N_NUM_CLASSES]= /*GO*/ { NS_GO1, JE_SYN, NS_Z, NS_INT, JE_SYN, JE_SYN, JE_SYN, JE_BAD_CHR }, /*GO1*/ { JE_SYN, JE_SYN, NS_Z1, NS_INT, JE_SYN, JE_SYN, JE_SYN, JE_BAD_CHR }, /*ZERO*/ { JE_SYN, JE_SYN, JE_SYN, JE_SYN, NS_FRAC, JE_SYN, NS_OK, JE_BAD_CHR }, -/*ZE1*/ { JE_SYN, JE_SYN, JE_SYN, JE_SYN, NS_FRAC, JE_SYN, JE_SYN, JE_BAD_CHR }, +/*ZE1*/ { JE_SYN, JE_SYN, JE_SYN, JE_SYN, NS_FRAC, JE_SYN, NS_OK, JE_BAD_CHR }, /*INT*/ { JE_SYN, JE_SYN, NS_INT, NS_INT, NS_FRAC, NS_EX, NS_OK, JE_BAD_CHR }, /*FRAC*/ { JE_SYN, JE_SYN, NS_FRAC, NS_FRAC,JE_SYN, NS_EX, NS_OK, JE_BAD_CHR }, /*EX*/ { NS_EX1, NS_EX1, NS_EX1, NS_EX1, JE_SYN, JE_SYN, JE_SYN, JE_BAD_CHR }, @@ -517,7 +518,7 @@ static int skip_num_constant(json_engine_t *j) break; } - j->state= *j->stack_p; + j->state= j->stack[j->stack_p]; return 0; } @@ -570,7 +571,7 @@ static int v_false(json_engine_t *j) { if (skip_string_verbatim(&j->s, "alse")) return 1; - j->state= *j->stack_p; + j->state= j->stack[j->stack_p]; return json_scan_next(j); } @@ -580,7 +581,7 @@ static int v_null(json_engine_t *j) { if (skip_string_verbatim(&j->s, "ull")) return 1; - j->state= *j->stack_p; + j->state= j->stack[j->stack_p]; return json_scan_next(j); } @@ -590,7 +591,7 @@ static int v_true(json_engine_t *j) { if (skip_string_verbatim(&j->s, "rue")) return 1; - j->state= *j->stack_p; + j->state= j->stack[j->stack_p]; return json_scan_next(j); } @@ -600,7 +601,7 @@ static int read_false(json_engine_t *j) { j->value_type= JSON_VALUE_FALSE; j->value= j->value_begin; - j->state= *j->stack_p; + j->state= j->stack[j->stack_p]; j->value_len= 5; return skip_string_verbatim(&j->s, "alse"); } @@ -611,7 +612,7 @@ static int read_null(json_engine_t *j) { j->value_type= JSON_VALUE_NULL; j->value= j->value_begin; - j->state= *j->stack_p; + j->state= j->stack[j->stack_p]; j->value_len= 4; return skip_string_verbatim(&j->s, "ull"); } @@ -622,7 +623,7 @@ static int read_true(json_engine_t *j) { j->value_type= JSON_VALUE_TRUE; j->value= j->value_begin; - j->state= *j->stack_p; + j->state= j->stack[j->stack_p]; j->value_len= 4; return skip_string_verbatim(&j->s, "rue"); } @@ -791,7 +792,7 @@ int json_scan_start(json_engine_t *je, { json_string_setup(&je->s, i_cs, str, end); je->stack[0]= JST_DONE; - je->stack_p= je->stack; + je->stack_p= 0; je->state= JST_VALUE; return 0; } @@ -839,7 +840,7 @@ static int skip_key(json_engine_t *j) run our 'state machine' accordingly. */ static int struct_end_eos(json_engine_t *j) -{ return json_actions[*j->stack_p][C_EOS](j); } +{ return json_actions[j->stack[j->stack_p]][C_EOS](j); } /* @@ -849,7 +850,7 @@ static int struct_end_eos(json_engine_t *j) run our 'state machine' accordingly. */ static int struct_end_cb(json_engine_t *j) -{ return json_actions[*j->stack_p][C_RCURB](j); } +{ return json_actions[j->stack[j->stack_p]][C_RCURB](j); } /* @@ -859,7 +860,7 @@ static int struct_end_cb(json_engine_t *j) run our 'state machine' accordingly. */ static int struct_end_qb(json_engine_t *j) -{ return json_actions[*j->stack_p][C_RSQRB](j); } +{ return json_actions[j->stack[j->stack_p]][C_RSQRB](j); } /* @@ -869,7 +870,7 @@ static int struct_end_qb(json_engine_t *j) run our 'state machine' accordingly. */ static int struct_end_cm(json_engine_t *j) -{ return json_actions[*j->stack_p][C_COMMA](j); } +{ return json_actions[j->stack[j->stack_p]][C_COMMA](j); } int json_read_keyname_chr(json_engine_t *j) @@ -1107,8 +1108,6 @@ int json_path_setup(json_path_t *p, continue; case PS_KWD: case PS_AWD: - if (p->last_step->type & JSON_PATH_DOUBLE_WILD) - return p->s.error= JE_SYN; p->last_step->type|= JSON_PATH_WILD; p->types_used|= JSON_PATH_WILD; continue; @@ -1158,7 +1157,7 @@ int json_path_setup(json_path_t *p, } -int json_skip_to_level(json_engine_t *j, json_level_t level) +int json_skip_to_level(json_engine_t *j, int level) { do { if (j->stack_p < level) @@ -1595,3 +1594,118 @@ int json_escape(CHARSET_INFO *str_cs, return json - json_start; } + + +int json_get_path_start(json_engine_t *je, CHARSET_INFO *i_cs, + const uchar *str, const uchar *end, + json_path_t *p) +{ + json_scan_start(je, i_cs, str, end); + p->last_step= p->steps - 1; + return 0; +} + + +int json_get_path_next(json_engine_t *je, json_path_t *p) +{ + if (p->last_step < p->steps) + { + if (json_read_value(je)) + return 1; + + p->last_step= p->steps; + p->steps[0].type= JSON_PATH_ARRAY_WILD; + p->steps[0].n_item= 0; + return 0; + } + else + { + if (json_value_scalar(je)) + { + if (p->last_step->type & JSON_PATH_ARRAY) + p->last_step->n_item++; + } + else + { + p->last_step++; + p->last_step->type= (enum json_path_step_types) je->value_type; + p->last_step->n_item= 0; + } + + if (json_scan_next(je)) + return 1; + } + + do + { + switch (je->state) + { + case JST_KEY: + p->last_step->key= je->s.c_str; + while (json_read_keyname_chr(je) == 0) + p->last_step->key_end= je->s.c_str; + if (je->s.error) + return 1; + /* Now we have je.state == JST_VALUE, so let's handle it. */ + + case JST_VALUE: + if (json_read_value(je)) + return 1; + return 0; + case JST_OBJ_END: + case JST_ARRAY_END: + p->last_step--; + if (p->last_step->type & JSON_PATH_ARRAY) + p->last_step->n_item++; + break; + default: + break; + } + } while (json_scan_next(je) == 0); + + return 1; +} + + +int json_path_compare(const json_path_t *a, const json_path_t *b) +{ + const json_path_step_t *sa= a->steps + 1; + const json_path_step_t *sb= b->steps + 1; + + if (a->last_step - sa > b->last_step - sb) + return -2; + + while (sa <= a->last_step) + { + if (sb > b->last_step) + return -2; + + if (!((sa->type & sb->type) & JSON_PATH_KEY_OR_ARRAY)) + goto step_failed; + + if (sa->type & JSON_PATH_ARRAY) + { + if (!(sa->type & JSON_PATH_WILD) && sa->n_item != sb->n_item) + goto step_failed; + } + else /* JSON_PATH_KEY */ + { + if (!(sa->type & JSON_PATH_WILD) && + (sa->key_end - sa->key != sb->key_end - sb->key || + memcmp(sa->key, sb->key, sa->key_end - sa->key) != 0)) + goto step_failed; + } + sb++; + sa++; + continue; + +step_failed: + if (!(sa->type & JSON_PATH_DOUBLE_WILD)) + return -1; + sb++; + } + + return sb <= b->last_step; +} + +