Commit ebe5ebba authored by Alexey Botchkov's avatar Alexey Botchkov

MDEV-9143 JSON_xxx functions.

        The rest of mysql/json functions implemented.
        CAST AS JSON implemented.
parent 1122c1f0
...@@ -226,6 +226,13 @@ int json_scan_next(json_engine_t *j); ...@@ -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.
......
...@@ -1731,36 +1731,36 @@ column_json(column_create(1, "val", 2, column_create(3, "val2"))) ...@@ -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
......
...@@ -46,6 +46,18 @@ json_array_append('["a", "b"]', '$', FALSE) ...@@ -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") ...@@ -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 ...@@ -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"}}
...@@ -805,24 +805,24 @@ select column_json(column_create(1, "val", 2, column_create(3, "val2"))); ...@@ -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
......
...@@ -19,6 +19,11 @@ select json_array(1, "text", false, null); ...@@ -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"); ...@@ -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]'); ...@@ -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));
...@@ -1457,6 +1457,7 @@ class Item: public Value_source, ...@@ -1457,6 +1457,7 @@ class Item: public Value_source,
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 @@ class Item_iterator_row: public Item_iterator ...@@ -5763,4 +5764,15 @@ class Item_iterator_row: public Item_iterator
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 */
...@@ -5124,13 +5124,10 @@ bool Item_func_like::with_sargable_pattern() const ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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.
......
This diff is collapsed.
...@@ -2197,7 +2197,7 @@ enum Cast_target ...@@ -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
}; };
......
This diff is collapsed.
...@@ -123,6 +123,21 @@ class Item_func_json_quote: public Item_str_func ...@@ -123,6 +123,21 @@ class Item_func_json_quote: public Item_str_func
}; };
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 @@ class Item_json_str_multipath: public Item_str_func ...@@ -134,6 +149,7 @@ class Item_json_str_multipath: public Item_str_func
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 @@ class Item_func_json_array: public Item_str_func ...@@ -207,6 +223,7 @@ class Item_func_json_array: public Item_str_func
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 @@ class Item_func_json_array_append: public Item_json_str_multipath ...@@ -231,6 +248,18 @@ class Item_func_json_array_append: public Item_json_str_multipath
}; };
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 @@ class Item_func_json_object: public Item_func_json_array ...@@ -239,6 +268,7 @@ class Item_func_json_object: public Item_func_json_array
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 @@ class Item_func_json_merge: public Item_func_json_array ...@@ -253,6 +283,7 @@ class Item_func_json_merge: public Item_func_json_array
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 @@ class Item_func_json_type: public Item_str_func ...@@ -301,4 +332,102 @@ class Item_func_json_type: public Item_str_func
}; };
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 */
...@@ -309,6 +309,7 @@ static SYMBOL symbols[] = { ...@@ -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)},
......
...@@ -1324,6 +1324,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -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: ...@@ -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: ...@@ -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));
......
...@@ -13,5 +13,6 @@ jdbc : Variable settings depend on machine configuration ...@@ -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
...@@ -1174,7 +1174,7 @@ static int handle_match(json_engine_t *je, json_path_t *p, ...@@ -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, ...@@ -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, ...@@ -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;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment