Commit 3a177279 authored by Alexey Botchkov's avatar Alexey Botchkov

MDEV-11573 JSON_LENGTH returns incorrect results.

        Item_func_json_length fixed.
parent 4d10273b
...@@ -425,6 +425,12 @@ json_length('{}') ...@@ -425,6 +425,12 @@ json_length('{}')
select json_length('[1, 2, {"a": 3}]'); select json_length('[1, 2, {"a": 3}]');
json_length('[1, 2, {"a": 3}]') json_length('[1, 2, {"a": 3}]')
3 3
select json_length('{"a": 1, "b": {"c": 30}}', '$.b');
json_length('{"a": 1, "b": {"c": 30}}', '$.b')
1
select json_length('{"a": 1, "b": {"c": 30}}');
json_length('{"a": 1, "b": {"c": 30}}')
2
create table json (j INT); create table json (j INT);
show create table json; show create table json;
Table Create Table Table Create Table
......
...@@ -170,6 +170,8 @@ select json_depth('[10, {"a": 20}]'); ...@@ -170,6 +170,8 @@ select json_depth('[10, {"a": 20}]');
select json_length(''); select json_length('');
select json_length('{}'); select json_length('{}');
select json_length('[1, 2, {"a": 3}]'); select json_length('[1, 2, {"a": 3}]');
select json_length('{"a": 1, "b": {"c": 30}}', '$.b');
select json_length('{"a": 1, "b": {"c": 30}}');
create table json (j INT); create table json (j INT);
show create table json; show create table json;
......
...@@ -1599,29 +1599,85 @@ String *Item_func_json_merge::val_str(String *str) ...@@ -1599,29 +1599,85 @@ String *Item_func_json_merge::val_str(String *str)
} }
void Item_func_json_length::fix_length_and_dec()
{
if (arg_count > 1)
path.set_constant_flag(args[1]->const_item());
}
longlong Item_func_json_length::val_int() longlong Item_func_json_length::val_int()
{ {
String *js= args[0]->val_str(&tmp_js); String *js= args[0]->val_str(&tmp_js);
json_engine_t je; json_engine_t je;
uint length= 0; uint length= 0;
uint array_counters[JSON_DEPTH_LIMIT];
if ((null_value= args[0]->null_value)) if ((null_value= args[0]->null_value))
return 0; return 0;
json_scan_start(&je, js->charset(),(const uchar *) js->ptr(), json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
(const uchar *) js->ptr() + js->length()); (const uchar *) js->ptr() + js->length());
do if (arg_count > 1)
{
/* Path specified - let's apply it. */
if (!path.parsed)
{
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()))
{
report_path_error(s_p, &path.p, 2);
goto null_return;
}
path.parsed= path.constant;
}
if (args[1]->null_value)
goto null_return;
path.cur_step= path.p.steps;
if (json_find_path(&je, &path.p, &path.cur_step, array_counters))
{
if (je.s.error)
goto err_return;
goto null_return;
}
}
if (json_read_value(&je))
goto err_return;
if (json_value_scalar(&je))
return 1;
while (json_scan_next(&je) == 0 &&
je.state != JST_OBJ_END && je.state != JST_ARRAY_END)
{
switch (je.state)
{ {
if (je.state == JST_VALUE) case JST_VALUE:
case JST_KEY:
length++; length++;
} while (json_scan_next(&je) == 0); break;
case JST_OBJ_START:
case JST_ARRAY_START:
if (json_skip_level(&je))
goto err_return;
break;
default:
break;
};
}
if (!je.s.error) if (!je.s.error)
return length - 1; return length;
err_return:
report_json_error(js, &je, 0); report_json_error(js, &je, 0);
null_return:
null_value= 1; null_value= 1;
return 0; return 0;
} }
......
...@@ -67,8 +67,8 @@ class Item_func_json_exists: public Item_int_func ...@@ -67,8 +67,8 @@ class Item_func_json_exists: public Item_int_func
String tmp_js, tmp_path; String tmp_js, tmp_path;
public: public:
Item_func_json_exists(THD *thd, Item *js, Item *path): Item_func_json_exists(THD *thd, Item *js, Item *i_path):
Item_int_func(thd, js, path) {} Item_int_func(thd, js, i_path) {}
const char *func_name() const { return "json_exists"; } const char *func_name() const { return "json_exists"; }
bool is_bool_type() { return true; } bool is_bool_type() { return true; }
void fix_length_and_dec(); void fix_length_and_dec();
...@@ -85,8 +85,8 @@ class Item_func_json_value: public Item_str_func ...@@ -85,8 +85,8 @@ class Item_func_json_value: public Item_str_func
String tmp_js, tmp_path; String tmp_js, tmp_path;
public: public:
Item_func_json_value(THD *thd, Item *js, Item *path): Item_func_json_value(THD *thd, Item *js, Item *i_path):
Item_str_func(thd, js, path) {} Item_str_func(thd, js, i_path) {}
const char *func_name() const { return "json_value"; } const char *func_name() const { return "json_value"; }
void fix_length_and_dec(); void fix_length_and_dec();
String *val_str(String *); String *val_str(String *);
...@@ -99,8 +99,8 @@ class Item_func_json_value: public Item_str_func ...@@ -99,8 +99,8 @@ class Item_func_json_value: public Item_str_func
class Item_func_json_query: public Item_func_json_value class Item_func_json_query: public Item_func_json_value
{ {
public: public:
Item_func_json_query(THD *thd, Item *js, Item *path): Item_func_json_query(THD *thd, Item *js, Item *i_path):
Item_func_json_value(thd, js, path) {} Item_func_json_value(thd, js, i_path) {}
const char *func_name() const { return "json_query"; } const char *func_name() const { return "json_query"; }
bool check_and_get_value(json_engine_t *je, String *res, int *error); bool check_and_get_value(json_engine_t *je, String *res, int *error);
Item *get_copy(THD *thd, MEM_ROOT *mem_root) Item *get_copy(THD *thd, MEM_ROOT *mem_root)
...@@ -291,12 +291,14 @@ class Item_func_json_merge: public Item_func_json_array ...@@ -291,12 +291,14 @@ class Item_func_json_merge: public Item_func_json_array
class Item_func_json_length: public Item_int_func class Item_func_json_length: public Item_int_func
{ {
protected: protected:
json_path_with_flags path;
String tmp_js; String tmp_js;
String tmp_path; String tmp_path;
public: public:
Item_func_json_length(THD *thd, List<Item> &list): Item_func_json_length(THD *thd, List<Item> &list):
Item_int_func(thd, list) {} Item_int_func(thd, list) {}
const char *func_name() const { return "json_length"; } const char *func_name() const { return "json_length"; }
void fix_length_and_dec();
longlong val_int(); longlong val_int();
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_length>(thd, mem_root, this); } { return get_item_copy<Item_func_json_length>(thd, mem_root, this); }
......
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