1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-01 03:47:19 +03:00

MDEV-9143 JSON_xxx functions.

The rest of mysql/json functions implemented.
        CAST AS JSON implemented.
This commit is contained in:
Alexey Botchkov
2016-11-15 17:04:31 +04:00
parent 1122c1f0c2
commit ebe5ebba16
15 changed files with 1619 additions and 59 deletions

View File

@ -226,6 +226,13 @@ int json_scan_next(json_engine_t *j);
int json_read_keyname_chr(json_engine_t *j); int json_read_keyname_chr(json_engine_t *j);
/*
Check if the name of the current JSON key matches
the step of the path.
*/
int json_key_matches(json_engine_t *je, json_string_t *k);
/* /*
json_read_value() function parses the JSON value syntax, json_read_value() function parses the JSON value syntax,
so that we can handle the value of a key or an array item. so that we can handle the value of a key or an array item.

View File

@ -1731,36 +1731,36 @@ column_json(column_create(1, "val", 2, column_create(3, "val2")))
# Time encoding # Time encoding
# #
select hex(column_create("t", "800:46:06.23434" AS time)) as hex, select hex(column_create("t", "800:46:06.23434" AS time)) as hex,
column_json(column_create("t", "800:46:06.23434" AS time)) as json; column_json(column_create("t", "800:46:06.23434" AS time)) as js;
hex json hex js
04010001000000070074649363B82003 {"t":"800:46:06.234340"} 04010001000000070074649363B82003 {"t":"800:46:06.234340"}
select hex(column_create(1, "800:46:06.23434" AS time)) as hex, select hex(column_create(1, "800:46:06.23434" AS time)) as hex,
column_json(column_create(1, "800:46:06.23434" AS time)) as json; column_json(column_create(1, "800:46:06.23434" AS time)) as js;
hex json hex js
000100010007649363B82003 {"1":"800:46:06.234340"} 000100010007649363B82003 {"1":"800:46:06.234340"}
select hex(column_create("t", "800:46:06" AS time)) as hex, select hex(column_create("t", "800:46:06" AS time)) as hex,
column_json(column_create("t", "800:46:06" AS time)) as json; column_json(column_create("t", "800:46:06" AS time)) as js;
hex json hex js
04010001000000070074860B32 {"t":"800:46:06"} 04010001000000070074860B32 {"t":"800:46:06"}
select hex(column_create(1, "800:46:06" AS time)) as hex, select hex(column_create(1, "800:46:06" AS time)) as hex,
column_json(column_create(1, "800:46:06" AS time)) as json; column_json(column_create(1, "800:46:06" AS time)) as js;
hex json hex js
000100010007000060B82003 {"1":"800:46:06"} 000100010007000060B82003 {"1":"800:46:06"}
select hex(column_create("t", "2012-12-21 10:46:06.23434" AS datetime)) as hex, select hex(column_create("t", "2012-12-21 10:46:06.23434" AS datetime)) as hex,
column_json(column_create("t", "2012-12-21 10:46:06.23434" AS datetime)) as json; column_json(column_create("t", "2012-12-21 10:46:06.23434" AS datetime)) as js;
hex json hex js
0401000100000005007495B90F649363B80A00 {"t":"2012-12-21 10:46:06.234340"} 0401000100000005007495B90F649363B80A00 {"t":"2012-12-21 10:46:06.234340"}
select hex(column_create(1, "2012-12-21 10:46:06.23434" AS datetime)) as hex, select hex(column_create(1, "2012-12-21 10:46:06.23434" AS datetime)) as hex,
column_json(column_create(1, "2012-12-21 10:46:06.23434" AS datetime)) as json; column_json(column_create(1, "2012-12-21 10:46:06.23434" AS datetime)) as js;
hex json hex js
00010001000595B90F649363B80A00 {"1":"2012-12-21 10:46:06.234340"} 00010001000595B90F649363B80A00 {"1":"2012-12-21 10:46:06.234340"}
select hex(column_create("t", "2012-12-21 10:46:06" AS datetime)) as hex, select hex(column_create("t", "2012-12-21 10:46:06" AS datetime)) as hex,
column_json(column_create("t", "2012-12-21 10:46:06" AS datetime)) as json; column_json(column_create("t", "2012-12-21 10:46:06" AS datetime)) as js;
hex json hex js
0401000100000005007495B90F86AB00 {"t":"2012-12-21 10:46:06"} 0401000100000005007495B90F86AB00 {"t":"2012-12-21 10:46:06"}
select hex(column_create(1, "2012-12-21 10:46:06" AS datetime)) as hex, select hex(column_create(1, "2012-12-21 10:46:06" AS datetime)) as hex,
column_json(column_create(1, "2012-12-21 10:46:06" AS datetime)) as json; column_json(column_create(1, "2012-12-21 10:46:06" AS datetime)) as js;
hex json hex js
00010001000595B90F000060B80A00 {"1":"2012-12-21 10:46:06"} 00010001000595B90F000060B80A00 {"1":"2012-12-21 10:46:06"}
# #
# MDEV-4849: Out of memory error and valgrind warnings on COLUMN_ADD # MDEV-4849: Out of memory error and valgrind warnings on COLUMN_ADD

View File

@ -46,6 +46,18 @@ json_array_append('["a", "b"]', '$', FALSE)
select json_array_append('{"k1":1, "k2":["a", "b"]}', '$.k2', 2); select json_array_append('{"k1":1, "k2":["a", "b"]}', '$.k2', 2);
json_array_append('{"k1":1, "k2":["a", "b"]}', '$.k2', 2) json_array_append('{"k1":1, "k2":["a", "b"]}', '$.k2', 2)
{"k1":1, "k2":["a", "b", 2]} {"k1":1, "k2":["a", "b", 2]}
SELECT JSON_ARRAY_INSERT('["a", {"b": [1, 2]}, [3, 4]]', '$[1]', 'x');
JSON_ARRAY_INSERT('["a", {"b": [1, 2]}, [3, 4]]', '$[1]', 'x')
["a", "x", {"b": [1, 2]}, [3, 4]]
SELECT JSON_ARRAY_INSERT('["a", {"b": [1, 2]}, [3, 4]]', '$[2]', 'x');
JSON_ARRAY_INSERT('["a", {"b": [1, 2]}, [3, 4]]', '$[2]', 'x')
["a", {"b": [1, 2]}, "x", [3, 4]]
SELECT JSON_ARRAY_INSERT('["a", {"b": [1, 2]}, [3, 4]]', '$[3]', 'x');
JSON_ARRAY_INSERT('["a", {"b": [1, 2]}, [3, 4]]', '$[3]', 'x')
["a", {"b": [1, 2]}, [3, 4], "x"]
SELECT JSON_ARRAY_INSERT('["a", {"b": [1, 2]}, [3, 4]]', '$[4]', 'x');
JSON_ARRAY_INSERT('["a", {"b": [1, 2]}, [3, 4]]', '$[4]', 'x')
["a", {"b": [1, 2]}, [3, 4], "x"]
select json_contains('{"k1":123, "k2":345}', '123', '$.k1'); select json_contains('{"k1":123, "k2":345}', '123', '$.k1');
json_contains('{"k1":123, "k2":345}', '123', '$.k1') json_contains('{"k1":123, "k2":345}', '123', '$.k1')
1 1
@ -91,6 +103,44 @@ json_extract('{"key1":5, "key2":[2,3]}', "$.key1", "$.key2")
select json_extract('{"key0":true, "key1":"qwe"}', "$.key1"); select json_extract('{"key0":true, "key1":"qwe"}', "$.key1");
json_extract('{"key0":true, "key1":"qwe"}', "$.key1") json_extract('{"key0":true, "key1":"qwe"}', "$.key1")
qwe qwe
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]}
select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.d[3]', 3);
json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.d[3]', 3)
{"a":1, "b":{"c":1}, "d":[1, 2, 3]}
select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.a[2]', 2);
json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.a[2]', 2)
{"a":[1, 2], "b":{"c":1}, "d":[1, 2]}
select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.c', 'word');
json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.c', 'word')
{"a":1, "b":{"c":1}, "d":[1, 2]}
select json_set('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]');
json_set('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]')
{ "a": 10, "b": [2, 3], "c":"[true, false]"}
select json_replace('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]');
json_replace('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]')
{ "a": 10, "b": [2, 3]}
select json_replace('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.b', '[true, false]');
json_replace('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.b', '[true, false]')
{ "a": 10, "b": "[true, false]"}
set @j = '["a", ["b", "c"], "d"]';
select json_remove(@j, '$[0]');
json_remove(@j, '$[0]')
[ ["b", "c"], "d"]
select json_remove(@j, '$[1]');
json_remove(@j, '$[1]')
["a" "d"]
select json_remove(@j, '$[2]');
json_remove(@j, '$[2]')
["a", ["b", "c"]]
set @j = '{"a": 1, "b": [2, 3]}';
select json_remove(@j, '$.b');
json_remove(@j, '$.b')
{"a": 1}
select json_remove(@j, '$.a');
json_remove(@j, '$.a')
{"b": [2, 3]}
select json_object("ki", 1, "mi", "ya"); select json_object("ki", 1, "mi", "ya");
json_object("ki", 1, "mi", "ya") json_object("ki", 1, "mi", "ya")
{"ki": 1, "mi": "ya"} {"ki": 1, "mi": "ya"}
@ -121,3 +171,46 @@ BOOLEAN
select json_type('123'); select json_type('123');
json_type('123') json_type('123')
NUMBER NUMBER
select json_keys('{"a":{"c":1, "d":2}, "b":2}');
json_keys('{"a":{"c":1, "d":2}, "b":2}')
["a", "b"]
select json_keys('{"a":{"c":1, "d":2}, "b":2}', "$.a");
json_keys('{"a":{"c":1, "d":2}, "b":2}', "$.a")
["c", "d"]
select json_keys('{"a":{"c":1, "d":2}, "b":2}', "$.b");
json_keys('{"a":{"c":1, "d":2}, "b":2}', "$.b")
NULL
SET @j = '["abc", [{"k": "10"}, "def"], {"x":"abc"}, {"y":"bcd"}]';
select json_search(@j, 'one', 'abc');
json_search(@j, 'one', 'abc')
"$[0]"
select json_search(@j, 'all', 'abc');
json_search(@j, 'all', 'abc')
["$[0]", "$[2].x"]
select json_search(@j, 'all', 'abc', NULL, '$[2]');
json_search(@j, 'all', 'abc', NULL, '$[2]')
"$[2].x"
select json_search(@j, 'all', 'abc', NULL, '$');
json_search(@j, 'all', 'abc', NULL, '$')
["$[0]", "$[2].x"]
select json_search(@j, 'all', '10', NULL, '$');
json_search(@j, 'all', '10', NULL, '$')
"$[1][0].k"
select json_search(@j, 'all', '10', NULL, '$[*]');
json_search(@j, 'all', '10', NULL, '$[*]')
"$[1][0].k"
select json_search(@j, 'all', '10', NULL, '$[*][0].k');
json_search(@j, 'all', '10', NULL, '$[*][0].k')
"$[1][0].k"
select json_unquote('"abc"');
json_unquote('"abc"')
abc
select json_object("a", json_object("b", "abcd"));
json_object("a", json_object("b", "abcd"))
{"a": {"b": "abcd"}}
select json_object("a", '{"b": "abcd"}');
json_object("a", '{"b": "abcd"}')
{"a": "{\"b\": \"abcd\"}"}
select json_object("a", cast('{"b": "abcd"}' as json));
json_object("a", cast('{"b": "abcd"}' as json))
{"a": {"b": "abcd"}}

View File

@ -805,24 +805,24 @@ select column_json(column_create(1, "val", 2, column_create(3, "val2")));
--echo # Time encoding --echo # Time encoding
--echo # --echo #
select hex(column_create("t", "800:46:06.23434" AS time)) as hex, select hex(column_create("t", "800:46:06.23434" AS time)) as hex,
column_json(column_create("t", "800:46:06.23434" AS time)) as json; column_json(column_create("t", "800:46:06.23434" AS time)) as js;
select hex(column_create(1, "800:46:06.23434" AS time)) as hex, select hex(column_create(1, "800:46:06.23434" AS time)) as hex,
column_json(column_create(1, "800:46:06.23434" AS time)) as json; column_json(column_create(1, "800:46:06.23434" AS time)) as js;
select hex(column_create("t", "800:46:06" AS time)) as hex, select hex(column_create("t", "800:46:06" AS time)) as hex,
column_json(column_create("t", "800:46:06" AS time)) as json; column_json(column_create("t", "800:46:06" AS time)) as js;
select hex(column_create(1, "800:46:06" AS time)) as hex, select hex(column_create(1, "800:46:06" AS time)) as hex,
column_json(column_create(1, "800:46:06" AS time)) as json; column_json(column_create(1, "800:46:06" AS time)) as js;
select hex(column_create("t", "2012-12-21 10:46:06.23434" AS datetime)) as hex, select hex(column_create("t", "2012-12-21 10:46:06.23434" AS datetime)) as hex,
column_json(column_create("t", "2012-12-21 10:46:06.23434" AS datetime)) as json; column_json(column_create("t", "2012-12-21 10:46:06.23434" AS datetime)) as js;
select hex(column_create(1, "2012-12-21 10:46:06.23434" AS datetime)) as hex, select hex(column_create(1, "2012-12-21 10:46:06.23434" AS datetime)) as hex,
column_json(column_create(1, "2012-12-21 10:46:06.23434" AS datetime)) as json; column_json(column_create(1, "2012-12-21 10:46:06.23434" AS datetime)) as js;
select hex(column_create("t", "2012-12-21 10:46:06" AS datetime)) as hex, select hex(column_create("t", "2012-12-21 10:46:06" AS datetime)) as hex,
column_json(column_create("t", "2012-12-21 10:46:06" AS datetime)) as json; column_json(column_create("t", "2012-12-21 10:46:06" AS datetime)) as js;
select hex(column_create(1, "2012-12-21 10:46:06" AS datetime)) as hex, select hex(column_create(1, "2012-12-21 10:46:06" AS datetime)) as hex,
column_json(column_create(1, "2012-12-21 10:46:06" AS datetime)) as json; column_json(column_create(1, "2012-12-21 10:46:06" AS datetime)) as js;
--echo # --echo #
--echo # MDEV-4849: Out of memory error and valgrind warnings on COLUMN_ADD --echo # MDEV-4849: Out of memory error and valgrind warnings on COLUMN_ADD

View File

@ -19,6 +19,11 @@ select json_array(1, "text", false, null);
select json_array_append('["a", "b"]', '$', FALSE); select json_array_append('["a", "b"]', '$', FALSE);
select json_array_append('{"k1":1, "k2":["a", "b"]}', '$.k2', 2); select json_array_append('{"k1":1, "k2":["a", "b"]}', '$.k2', 2);
SELECT JSON_ARRAY_INSERT('["a", {"b": [1, 2]}, [3, 4]]', '$[1]', 'x');
SELECT JSON_ARRAY_INSERT('["a", {"b": [1, 2]}, [3, 4]]', '$[2]', 'x');
SELECT JSON_ARRAY_INSERT('["a", {"b": [1, 2]}, [3, 4]]', '$[3]', 'x');
SELECT JSON_ARRAY_INSERT('["a", {"b": [1, 2]}, [3, 4]]', '$[4]', 'x');
select json_contains('{"k1":123, "k2":345}', '123', '$.k1'); select json_contains('{"k1":123, "k2":345}', '123', '$.k1');
select json_contains('"you"', '"you"'); select json_contains('"you"', '"you"');
select json_contains('"youth"', '"you"'); select json_contains('"youth"', '"you"');
@ -37,6 +42,24 @@ select json_extract('{"key1":"asd", "key2":[2,3]}', "$.key1", "$.key2");
select json_extract('{"key1":5, "key2":[2,3]}', "$.key1", "$.key2"); select json_extract('{"key1":5, "key2":[2,3]}', "$.key1", "$.key2");
select json_extract('{"key0":true, "key1":"qwe"}', "$.key1"); select json_extract('{"key0":true, "key1":"qwe"}', "$.key1");
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);
select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.a[2]', 2);
select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.c', 'word');
select json_set('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]');
select json_replace('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]');
select json_replace('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.b', '[true, false]');
set @j = '["a", ["b", "c"], "d"]';
select json_remove(@j, '$[0]');
select json_remove(@j, '$[1]');
select json_remove(@j, '$[2]');
set @j = '{"a": 1, "b": [2, 3]}';
select json_remove(@j, '$.b');
select json_remove(@j, '$.a');
select json_object("ki", 1, "mi", "ya"); select json_object("ki", 1, "mi", "ya");
select json_exists('{"key1":"xxxx", "key2":[1, 2, 3]}', "$.key2"); select json_exists('{"key1":"xxxx", "key2":[1, 2, 3]}', "$.key2");
@ -52,3 +75,23 @@ select json_type('[123, "k2", 345]');
select json_type("true"); select json_type("true");
select json_type('123'); select json_type('123');
select json_keys('{"a":{"c":1, "d":2}, "b":2}');
select json_keys('{"a":{"c":1, "d":2}, "b":2}', "$.a");
select json_keys('{"a":{"c":1, "d":2}, "b":2}', "$.b");
SET @j = '["abc", [{"k": "10"}, "def"], {"x":"abc"}, {"y":"bcd"}]';
select json_search(@j, 'one', 'abc');
select json_search(@j, 'all', 'abc');
select json_search(@j, 'all', 'abc', NULL, '$[2]');
select json_search(@j, 'all', 'abc', NULL, '$');
select json_search(@j, 'all', '10', NULL, '$');
select json_search(@j, 'all', '10', NULL, '$[*]');
select json_search(@j, 'all', '10', NULL, '$[*][0].k');
select json_unquote('"abc"');
select json_object("a", json_object("b", "abcd"));
select json_object("a", '{"b": "abcd"}');
select json_object("a", cast('{"b": "abcd"}' as json));

View File

@ -1457,6 +1457,7 @@ public:
virtual void set_result_field(Field *field) {} virtual void set_result_field(Field *field) {}
virtual bool is_result_field() { return 0; } virtual bool is_result_field() { return 0; }
virtual bool is_bool_type() { return false; } virtual bool is_bool_type() { return false; }
virtual bool is_json_type() { return false; }
/* This is to handle printing of default values */ /* This is to handle printing of default values */
virtual bool need_parentheses_in_default() { return false; } virtual bool need_parentheses_in_default() { return false; }
virtual void save_in_result_field(bool no_conversions) {} virtual void save_in_result_field(bool no_conversions) {}
@ -5763,4 +5764,15 @@ public:
void close() {} void close() {}
}; };
/*
It's used in ::fix_fields() methods of LIKE and JSON_SEARCH
functions to handle the ESCAPE parameter.
This parameter is quite non-standard so the specific function.
*/
bool fix_escape_item(THD *thd, Item *escape_item, String *tmp_str,
bool escape_used_in_parsing, CHARSET_INFO *cmp_cs,
int *escape);
#endif /* SQL_ITEM_INCLUDED */ #endif /* SQL_ITEM_INCLUDED */

View File

@ -5124,13 +5124,10 @@ bool Item_func_like::with_sargable_pattern() const
} }
bool Item_func_like::fix_fields(THD *thd, Item **ref) bool fix_escape_item(THD *thd, Item *escape_item, String *tmp_str,
bool escape_used_in_parsing, CHARSET_INFO *cmp_cs,
int *escape)
{ {
DBUG_ASSERT(fixed == 0);
if (Item_bool_func2::fix_fields(thd, ref) ||
escape_item->fix_fields(thd, &escape_item))
return TRUE;
if (!escape_item->const_during_execution()) if (!escape_item->const_during_execution())
{ {
my_error(ER_WRONG_ARGUMENTS,MYF(0),"ESCAPE"); my_error(ER_WRONG_ARGUMENTS,MYF(0),"ESCAPE");
@ -5140,7 +5137,7 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref)
if (escape_item->const_item()) if (escape_item->const_item())
{ {
/* If we are on execution stage */ /* If we are on execution stage */
String *escape_str= escape_item->val_str(&cmp_value1); String *escape_str= escape_item->val_str(tmp_str);
if (escape_str) if (escape_str)
{ {
const char *escape_str_ptr= escape_str->ptr(); const char *escape_str_ptr= escape_str->ptr();
@ -5153,7 +5150,7 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref)
return TRUE; return TRUE;
} }
if (use_mb(cmp_collation.collation)) if (use_mb(cmp_cs))
{ {
CHARSET_INFO *cs= escape_str->charset(); CHARSET_INFO *cs= escape_str->charset();
my_wc_t wc; my_wc_t wc;
@ -5161,7 +5158,7 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref)
(const uchar*) escape_str_ptr, (const uchar*) escape_str_ptr,
(const uchar*) escape_str_ptr + (const uchar*) escape_str_ptr +
escape_str->length()); escape_str->length());
escape= (int) (rc > 0 ? wc : '\\'); *escape= (int) (rc > 0 ? wc : '\\');
} }
else else
{ {
@ -5170,25 +5167,40 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref)
code instead of Unicode code as "escape" argument. code instead of Unicode code as "escape" argument.
Convert to "cs" if charset of escape differs. Convert to "cs" if charset of escape differs.
*/ */
CHARSET_INFO *cs= cmp_collation.collation;
uint32 unused; uint32 unused;
if (escape_str->needs_conversion(escape_str->length(), if (escape_str->needs_conversion(escape_str->length(),
escape_str->charset(), cs, &unused)) escape_str->charset(),cmp_cs,&unused))
{ {
char ch; char ch;
uint errors; uint errors;
uint32 cnvlen= copy_and_convert(&ch, 1, cs, escape_str_ptr, uint32 cnvlen= copy_and_convert(&ch, 1, cmp_cs, escape_str_ptr,
escape_str->length(), escape_str->length(),
escape_str->charset(), &errors); escape_str->charset(), &errors);
escape= cnvlen ? ch : '\\'; *escape= cnvlen ? ch : '\\';
} }
else else
escape= escape_str_ptr ? *escape_str_ptr : '\\'; *escape= escape_str_ptr ? *escape_str_ptr : '\\';
} }
} }
else else
escape= '\\'; *escape= '\\';
}
return FALSE;
}
bool Item_func_like::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
if (Item_bool_func2::fix_fields(thd, ref) ||
escape_item->fix_fields(thd, &escape_item) ||
fix_escape_item(thd, escape_item, &cmp_value1, escape_used_in_parsing,
cmp_collation.collation, &escape))
return TRUE;
if (escape_item->const_item())
{
/* /*
We could also do boyer-more for non-const items, but as we would have to We could also do boyer-more for non-const items, but as we would have to
recompute the tables for each row it's not worth it. recompute the tables for each row it's not worth it.

View File

@ -1786,6 +1786,19 @@ protected:
}; };
class Create_func_json_keys: public Create_native_func
{
public:
virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_json_keys s_singleton;
protected:
Create_func_json_keys() {}
virtual ~Create_func_json_keys() {}
};
class Create_func_json_contains: public Create_native_func class Create_func_json_contains: public Create_native_func
{ {
public: public:
@ -1825,6 +1838,19 @@ protected:
}; };
class Create_func_json_search : public Create_native_func
{
public:
virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_json_search s_singleton;
protected:
Create_func_json_search() {}
virtual ~Create_func_json_search() {}
};
class Create_func_json_array : public Create_native_func class Create_func_json_array : public Create_native_func
{ {
public: public:
@ -1851,6 +1877,71 @@ protected:
}; };
class Create_func_json_array_insert : public Create_native_func
{
public:
virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_json_array_insert s_singleton;
protected:
Create_func_json_array_insert() {}
virtual ~Create_func_json_array_insert() {}
};
class Create_func_json_insert : public Create_native_func
{
public:
virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_json_insert s_singleton;
protected:
Create_func_json_insert() {}
virtual ~Create_func_json_insert() {}
};
class Create_func_json_set : public Create_native_func
{
public:
virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_json_set s_singleton;
protected:
Create_func_json_set() {}
virtual ~Create_func_json_set() {}
};
class Create_func_json_replace : public Create_native_func
{
public:
virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_json_replace s_singleton;
protected:
Create_func_json_replace() {}
virtual ~Create_func_json_replace() {}
};
class Create_func_json_remove : public Create_native_func
{
public:
virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_json_remove s_singleton;
protected:
Create_func_json_remove() {}
virtual ~Create_func_json_remove() {}
};
class Create_func_json_object : public Create_native_func class Create_func_json_object : public Create_native_func
{ {
public: public:
@ -1903,6 +1994,19 @@ protected:
}; };
class Create_func_json_unquote : public Create_func_arg1
{
public:
virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_json_unquote s_singleton;
protected:
Create_func_json_unquote() {}
virtual ~Create_func_json_unquote() {}
};
class Create_func_last_day : public Create_func_arg1 class Create_func_last_day : public Create_func_arg1
{ {
public: public:
@ -4830,6 +4934,15 @@ Create_func_json_quote::create_1_arg(THD *thd, Item *arg1)
} }
Create_func_json_unquote Create_func_json_unquote::s_singleton;
Item*
Create_func_json_unquote::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_json_unquote(thd, arg1);
}
Create_func_last_day Create_func_last_day::s_singleton; Create_func_last_day Create_func_last_day::s_singleton;
Item* Item*
@ -4885,6 +4998,134 @@ Create_func_json_array_append::create_native(THD *thd, LEX_STRING name,
} }
Create_func_json_array_insert Create_func_json_array_insert::s_singleton;
Item*
Create_func_json_array_insert::create_native(THD *thd, LEX_STRING name,
List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
if (item_list != NULL)
arg_count= item_list->elements;
if (arg_count < 3 || (arg_count & 1) == 0 /*is even*/)
{
my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
}
else
{
func= new (thd->mem_root) Item_func_json_array_insert(thd, *item_list);
}
return func;
}
Create_func_json_insert Create_func_json_insert::s_singleton;
Item*
Create_func_json_insert::create_native(THD *thd, LEX_STRING name,
List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
if (item_list != NULL)
arg_count= item_list->elements;
if (arg_count < 3 || (arg_count & 1) == 0 /*is even*/)
{
my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
}
else
{
func= new (thd->mem_root) Item_func_json_insert(true, false,
thd, *item_list);
}
return func;
}
Create_func_json_set Create_func_json_set::s_singleton;
Item*
Create_func_json_set::create_native(THD *thd, LEX_STRING name,
List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
if (item_list != NULL)
arg_count= item_list->elements;
if (arg_count < 3 || (arg_count & 1) == 0 /*is even*/)
{
my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
}
else
{
func= new (thd->mem_root) Item_func_json_insert(true, true,
thd, *item_list);
}
return func;
}
Create_func_json_replace Create_func_json_replace::s_singleton;
Item*
Create_func_json_replace::create_native(THD *thd, LEX_STRING name,
List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
if (item_list != NULL)
arg_count= item_list->elements;
if (arg_count < 3 || (arg_count & 1) == 0 /*is even*/)
{
my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
}
else
{
func= new (thd->mem_root) Item_func_json_insert(false, true,
thd, *item_list);
}
return func;
}
Create_func_json_remove Create_func_json_remove::s_singleton;
Item*
Create_func_json_remove::create_native(THD *thd, LEX_STRING name,
List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
if (item_list != NULL)
arg_count= item_list->elements;
if (arg_count < 2 /*json_doc, path [,path]*/)
{
my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
}
else
{
func= new (thd->mem_root) Item_func_json_remove(thd, *item_list);
}
return func;
}
Create_func_json_object Create_func_json_object::s_singleton; Create_func_json_object Create_func_json_object::s_singleton;
Item* Item*
@ -4990,6 +5231,31 @@ Create_func_json_contains::create_native(THD *thd, LEX_STRING name,
} }
Create_func_json_keys Create_func_json_keys::s_singleton;
Item*
Create_func_json_keys::create_native(THD *thd, LEX_STRING name,
List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
if (item_list != NULL)
arg_count= item_list->elements;
if (arg_count < 1 || arg_count > 2 /* json_doc, [path]...*/)
{
my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
}
else
{
func= new (thd->mem_root) Item_func_json_keys(thd, *item_list);
}
return func;
}
Create_func_json_contains_path Create_func_json_contains_path::s_singleton; Create_func_json_contains_path Create_func_json_contains_path::s_singleton;
Item* Item*
@ -5040,6 +5306,31 @@ Create_func_json_extract::create_native(THD *thd, LEX_STRING name,
} }
Create_func_json_search Create_func_json_search::s_singleton;
Item*
Create_func_json_search::create_native(THD *thd, LEX_STRING name,
List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
if (item_list != NULL)
arg_count= item_list->elements;
if (arg_count < 3 /* json_doc, one_or_all, search_str, [escape_char[, path]...*/)
{
my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
}
else
{
func= new (thd->mem_root) Item_func_json_search(thd, *item_list);
}
return func;
}
Create_func_last_insert_id Create_func_last_insert_id::s_singleton; Create_func_last_insert_id Create_func_last_insert_id::s_singleton;
Item* Item*
@ -6313,17 +6604,25 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("IS_USED_LOCK") }, BUILDER(Create_func_is_used_lock)}, { { C_STRING_WITH_LEN("IS_USED_LOCK") }, BUILDER(Create_func_is_used_lock)},
{ { C_STRING_WITH_LEN("JSON_ARRAY") }, BUILDER(Create_func_json_array)}, { { C_STRING_WITH_LEN("JSON_ARRAY") }, BUILDER(Create_func_json_array)},
{ { C_STRING_WITH_LEN("JSON_ARRAY_APPEND") }, BUILDER(Create_func_json_array_append)}, { { C_STRING_WITH_LEN("JSON_ARRAY_APPEND") }, BUILDER(Create_func_json_array_append)},
{ { C_STRING_WITH_LEN("JSON_ARRAY_INSERT") }, BUILDER(Create_func_json_array_insert)},
{ { C_STRING_WITH_LEN("JSON_CONTAINS") }, BUILDER(Create_func_json_contains)}, { { C_STRING_WITH_LEN("JSON_CONTAINS") }, BUILDER(Create_func_json_contains)},
{ { C_STRING_WITH_LEN("JSON_CONTAINS_PATH") }, BUILDER(Create_func_json_contains_path)}, { { C_STRING_WITH_LEN("JSON_CONTAINS_PATH") }, BUILDER(Create_func_json_contains_path)},
{ { C_STRING_WITH_LEN("JSON_DEPTH") }, BUILDER(Create_func_json_depth)}, { { C_STRING_WITH_LEN("JSON_DEPTH") }, BUILDER(Create_func_json_depth)},
{ { C_STRING_WITH_LEN("JSON_EXISTS") }, BUILDER(Create_func_json_exists)}, { { C_STRING_WITH_LEN("JSON_EXISTS") }, BUILDER(Create_func_json_exists)},
{ { C_STRING_WITH_LEN("JSON_EXTRACT") }, BUILDER(Create_func_json_extract)}, { { C_STRING_WITH_LEN("JSON_EXTRACT") }, BUILDER(Create_func_json_extract)},
{ { C_STRING_WITH_LEN("JSON_INSERT") }, BUILDER(Create_func_json_insert)},
{ { C_STRING_WITH_LEN("JSON_KEYS") }, BUILDER(Create_func_json_keys)},
{ { C_STRING_WITH_LEN("JSON_LENGTH") }, BUILDER(Create_func_json_length)}, { { C_STRING_WITH_LEN("JSON_LENGTH") }, BUILDER(Create_func_json_length)},
{ { C_STRING_WITH_LEN("JSON_MERGE") }, BUILDER(Create_func_json_merge)}, { { C_STRING_WITH_LEN("JSON_MERGE") }, BUILDER(Create_func_json_merge)},
{ { C_STRING_WITH_LEN("JSON_QUERY") }, BUILDER(Create_func_json_query)}, { { C_STRING_WITH_LEN("JSON_QUERY") }, BUILDER(Create_func_json_query)},
{ { C_STRING_WITH_LEN("JSON_QUOTE") }, BUILDER(Create_func_json_quote)}, { { C_STRING_WITH_LEN("JSON_QUOTE") }, BUILDER(Create_func_json_quote)},
{ { C_STRING_WITH_LEN("JSON_OBJECT") }, BUILDER(Create_func_json_object)}, { { C_STRING_WITH_LEN("JSON_OBJECT") }, BUILDER(Create_func_json_object)},
{ { C_STRING_WITH_LEN("JSON_REMOVE") }, BUILDER(Create_func_json_remove)},
{ { C_STRING_WITH_LEN("JSON_REPLACE") }, BUILDER(Create_func_json_replace)},
{ { C_STRING_WITH_LEN("JSON_SET") }, BUILDER(Create_func_json_set)},
{ { C_STRING_WITH_LEN("JSON_SEARCH") }, BUILDER(Create_func_json_search)},
{ { C_STRING_WITH_LEN("JSON_TYPE") }, BUILDER(Create_func_json_type)}, { { C_STRING_WITH_LEN("JSON_TYPE") }, BUILDER(Create_func_json_type)},
{ { C_STRING_WITH_LEN("JSON_UNQUOTE") }, BUILDER(Create_func_json_unquote)},
{ { C_STRING_WITH_LEN("JSON_VALID") }, BUILDER(Create_func_json_valid)}, { { C_STRING_WITH_LEN("JSON_VALID") }, BUILDER(Create_func_json_valid)},
{ { C_STRING_WITH_LEN("JSON_VALUE") }, BUILDER(Create_func_json_value)}, { { C_STRING_WITH_LEN("JSON_VALUE") }, BUILDER(Create_func_json_value)},
{ { C_STRING_WITH_LEN("LAST_DAY") }, BUILDER(Create_func_last_day)}, { { C_STRING_WITH_LEN("LAST_DAY") }, BUILDER(Create_func_last_day)},
@ -6716,6 +7015,9 @@ create_func_cast(THD *thd, Item *a, Cast_target cast_type,
res= new (thd->mem_root) Item_char_typecast(thd, a, len, real_cs); res= new (thd->mem_root) Item_char_typecast(thd, a, len, real_cs);
break; break;
} }
case ITEM_CAST_JSON:
res= new (thd->mem_root) Item_json_typecast(thd, a);
break;
default: default:
{ {
DBUG_ASSERT(0); DBUG_ASSERT(0);

View File

@ -2197,7 +2197,7 @@ enum Cast_target
{ {
ITEM_CAST_BINARY, ITEM_CAST_SIGNED_INT, ITEM_CAST_UNSIGNED_INT, ITEM_CAST_BINARY, ITEM_CAST_SIGNED_INT, ITEM_CAST_UNSIGNED_INT,
ITEM_CAST_DATE, ITEM_CAST_TIME, ITEM_CAST_DATETIME, ITEM_CAST_CHAR, ITEM_CAST_DATE, ITEM_CAST_TIME, ITEM_CAST_DATETIME, ITEM_CAST_CHAR,
ITEM_CAST_DECIMAL, ITEM_CAST_DOUBLE ITEM_CAST_DECIMAL, ITEM_CAST_DOUBLE, ITEM_CAST_JSON
}; };

File diff suppressed because it is too large Load Diff

View File

@ -123,6 +123,21 @@ public:
}; };
class Item_func_json_unquote: public Item_str_func
{
protected:
String tmp_s;
public:
Item_func_json_unquote(THD *thd, Item *s): Item_str_func(thd, s) {}
const char *func_name() const { return "json_unquote"; }
void fix_length_and_dec();
String *val_str(String *);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_json_unquote>(thd, mem_root, this); }
};
class Item_json_str_multipath: public Item_str_func class Item_json_str_multipath: public Item_str_func
{ {
protected: protected:
@ -134,6 +149,7 @@ public:
bool fix_fields(THD *thd, Item **ref); bool fix_fields(THD *thd, Item **ref);
void cleanup(); void cleanup();
virtual uint get_n_paths() const = 0; virtual uint get_n_paths() const = 0;
bool is_json_type() { return true; }
}; };
@ -207,6 +223,7 @@ public:
Item_func_json_array(THD *thd, List<Item> &list): Item_func_json_array(THD *thd, List<Item> &list):
Item_str_func(thd, list) {} Item_str_func(thd, list) {}
String *val_str(String *); String *val_str(String *);
bool is_json_type() { return true; }
void fix_length_and_dec(); void fix_length_and_dec();
const char *func_name() const { return "json_array"; } const char *func_name() const { return "json_array"; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root) Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@ -231,6 +248,18 @@ public:
}; };
class Item_func_json_array_insert: public Item_func_json_array_append
{
public:
Item_func_json_array_insert(THD *thd, List<Item> &list):
Item_func_json_array_append(thd, list) {}
String *val_str(String *);
const char *func_name() const { return "json_array_insert"; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_json_array_insert>(thd, mem_root, this); }
};
class Item_func_json_object: public Item_func_json_array class Item_func_json_object: public Item_func_json_array
{ {
public: public:
@ -239,6 +268,7 @@ public:
Item_func_json_object(THD *thd, List<Item> &list): Item_func_json_object(THD *thd, List<Item> &list):
Item_func_json_array(thd, list) {} Item_func_json_array(thd, list) {}
String *val_str(String *); String *val_str(String *);
bool is_json_type() { return true; }
const char *func_name() const { return "json_object"; } const char *func_name() const { return "json_object"; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root) Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_json_object>(thd, mem_root, this); } { return get_item_copy<Item_func_json_object>(thd, mem_root, this); }
@ -253,6 +283,7 @@ public:
Item_func_json_merge(THD *thd, List<Item> &list): Item_func_json_merge(THD *thd, List<Item> &list):
Item_func_json_array(thd, list) {} Item_func_json_array(thd, list) {}
String *val_str(String *); String *val_str(String *);
bool is_json_type() { return true; }
const char *func_name() const { return "json_merge"; } const char *func_name() const { return "json_merge"; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root) Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_json_merge>(thd, mem_root, this); } { return get_item_copy<Item_func_json_merge>(thd, mem_root, this); }
@ -301,4 +332,102 @@ public:
}; };
class Item_func_json_insert: public Item_json_str_multipath
{
protected:
String tmp_js;
String tmp_val;
bool mode_insert, mode_replace;
public:
Item_func_json_insert(bool i_mode, bool r_mode, THD *thd, List<Item> &list):
Item_json_str_multipath(thd, list),
mode_insert(i_mode), mode_replace(r_mode) {}
void fix_length_and_dec();
String *val_str(String *);
uint get_n_paths() const { return arg_count/2; }
const char *func_name() const
{
return mode_insert ?
(mode_replace ? "json_set" : "json_insert") : "json_update";
}
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_json_insert>(thd, mem_root, this); }
};
class Item_func_json_remove: public Item_json_str_multipath
{
protected:
String tmp_js;
public:
Item_func_json_remove(THD *thd, List<Item> &list):
Item_json_str_multipath(thd, list) {}
void fix_length_and_dec();
String *val_str(String *);
uint get_n_paths() const { return arg_count - 1; }
const char *func_name() const { return "json_remove"; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_json_remove>(thd, mem_root, this); }
};
class Item_func_json_keys: public Item_str_func
{
protected:
json_path_with_flags path;
String tmp_js, tmp_path;
public:
Item_func_json_keys(THD *thd, List<Item> &list):
Item_str_func(thd, list) {}
const char *func_name() const { return "json_keys"; }
void fix_length_and_dec();
String *val_str(String *);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_json_keys>(thd, mem_root, this); }
};
class Item_func_json_search: public Item_json_str_multipath
{
protected:
String tmp_js;
bool mode_one;
bool ooa_constant, ooa_parsed;
int escape;
int n_path_found;
json_path_t sav_path;
int compare_json_value_wild(json_engine_t *je, const String *cmp_str);
public:
Item_func_json_search(THD *thd, List<Item> &list):
Item_json_str_multipath(thd, list) {}
const char *func_name() const { return "json_search"; }
bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
String *val_str(String *);
uint get_n_paths() const { return arg_count > 4 ? arg_count - 4 : 0; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_json_search>(thd, mem_root, this); }
};
class Item_json_typecast: public Item_str_func
{
public:
Item_json_typecast(THD *thd, Item *a): Item_str_func(thd, a) {}
const char *func_name() const { return "cast_as_json"; }
bool is_json_type() { return true; }
void fix_length_and_dec();
String *val_str(String *str)
{
return args[0]->val_str(str);
}
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_json_typecast>(thd, mem_root, this); }
};
#endif /* ITEM_JSONFUNC_INCLUDED */ #endif /* ITEM_JSONFUNC_INCLUDED */

View File

@ -309,6 +309,7 @@ static SYMBOL symbols[] = {
{ "ITERATE", SYM(ITERATE_SYM)}, { "ITERATE", SYM(ITERATE_SYM)},
{ "INVOKER", SYM(INVOKER_SYM)}, { "INVOKER", SYM(INVOKER_SYM)},
{ "JOIN", SYM(JOIN_SYM)}, { "JOIN", SYM(JOIN_SYM)},
{ "JSON", SYM(JSON_SYM)},
{ "KEY", SYM(KEY_SYM)}, { "KEY", SYM(KEY_SYM)},
{ "KEYS", SYM(KEYS)}, { "KEYS", SYM(KEYS)},
{ "KEY_BLOCK_SIZE", SYM(KEY_BLOCK_SIZE)}, { "KEY_BLOCK_SIZE", SYM(KEY_BLOCK_SIZE)},

View File

@ -1324,6 +1324,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token ISSUER_SYM %token ISSUER_SYM
%token ITERATE_SYM %token ITERATE_SYM
%token JOIN_SYM /* SQL-2003-R */ %token JOIN_SYM /* SQL-2003-R */
%token JSON_SYM
%token KEYS %token KEYS
%token KEY_BLOCK_SIZE %token KEY_BLOCK_SIZE
%token KEY_SYM /* SQL-2003-N */ %token KEY_SYM /* SQL-2003-N */
@ -10709,6 +10710,7 @@ cast_type:
} }
| cast_type_numeric { $$= $1; Lex->charset= NULL; } | cast_type_numeric { $$= $1; Lex->charset= NULL; }
| cast_type_temporal { $$= $1; Lex->charset= NULL; } | cast_type_temporal { $$= $1; Lex->charset= NULL; }
| JSON_SYM { $$.set(ITEM_CAST_JSON); }
; ;
cast_type_numeric: cast_type_numeric:
@ -13226,11 +13228,10 @@ opt_extended_describe:
opt_format_json: opt_format_json:
/* empty */ {} /* empty */ {}
| FORMAT_SYM '=' JSON_SYM { Lex->explain_json= true; }
| FORMAT_SYM '=' ident_or_text | FORMAT_SYM '=' ident_or_text
{ {
if (!my_strcasecmp(system_charset_info, $3.str, "JSON")) if (!my_strcasecmp(system_charset_info, $3.str, "TRADITIONAL"))
Lex->explain_json= true;
else if (!my_strcasecmp(system_charset_info, $3.str, "TRADITIONAL"))
DBUG_ASSERT(Lex->explain_json==false); DBUG_ASSERT(Lex->explain_json==false);
else else
my_yyabort_error((ER_UNKNOWN_EXPLAIN_FORMAT, MYF(0), $3.str)); my_yyabort_error((ER_UNKNOWN_EXPLAIN_FORMAT, MYF(0), $3.str));

View File

@ -13,5 +13,6 @@ jdbc : Variable settings depend on machine configuration
jdbc_new : Variable settings depend on machine configuration jdbc_new : Variable settings depend on machine configuration
jdbc_oracle : Variable settings depend on machine configuration jdbc_oracle : Variable settings depend on machine configuration
jdbc_postgresql : Variable settings depend on machine configuration jdbc_postgresql : Variable settings depend on machine configuration
json : TABLE_TYPE = JSON conflicts with the SQL syntax
json_udf : conflicts with the server JSON functions json_udf : conflicts with the server JSON functions
json_udf_bin : conflicts with the server JSON functions json_udf_bin : conflicts with the server JSON functions

View File

@ -1174,7 +1174,7 @@ static int handle_match(json_engine_t *je, json_path_t *p,
Check if the name of the current JSON key matches Check if the name of the current JSON key matches
the step of the path. the step of the path.
*/ */
static int json_key_matches(json_engine_t *je, json_string_t *k) int json_key_matches(json_engine_t *je, json_string_t *k)
{ {
while (json_read_keyname_chr(je) == 0) while (json_read_keyname_chr(je) == 0)
{ {
@ -1409,6 +1409,8 @@ int json_unescape(CHARSET_INFO *json_cs,
CHARSET_INFO *res_cs, uchar *res, uchar *res_end) CHARSET_INFO *res_cs, uchar *res, uchar *res_end)
{ {
json_string_t s; json_string_t s;
const uchar *res_b= res;
json_string_setup(&s, json_cs, json_str, json_end); json_string_setup(&s, json_cs, json_str, json_end);
while (json_read_string_const_chr(&s) == 0) while (json_read_string_const_chr(&s) == 0)
{ {
@ -1434,7 +1436,7 @@ int json_unescape(CHARSET_INFO *json_cs,
return -1; return -1;
} }
return s.error ? 1 : 0; return s.error==JE_EOS ? res - res_b : -1;
} }