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('{}')
select json_length('[1, 2, {"a": 3}]');
json_length('[1, 2, {"a": 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);
show create table json;
Table Create Table
......
......@@ -170,6 +170,8 @@ select json_depth('[10, {"a": 20}]');
select json_length('');
select json_length('{}');
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);
show create table json;
......
......@@ -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()
{
String *js= args[0]->val_str(&tmp_js);
json_engine_t je;
uint length= 0;
uint array_counters[JSON_DEPTH_LIMIT];
if ((null_value= args[0]->null_value))
return 0;
json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
(const uchar *) js->ptr() + js->length());
do
if (arg_count > 1)
{
if (je.state == JST_VALUE)
/* 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)
{
case JST_VALUE:
case JST_KEY:
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)
return length - 1;
return length;
err_return:
report_json_error(js, &je, 0);
null_return:
null_value= 1;
return 0;
}
......
......@@ -67,8 +67,8 @@ class Item_func_json_exists: public Item_int_func
String tmp_js, tmp_path;
public:
Item_func_json_exists(THD *thd, Item *js, Item *path):
Item_int_func(thd, js, path) {}
Item_func_json_exists(THD *thd, Item *js, Item *i_path):
Item_int_func(thd, js, i_path) {}
const char *func_name() const { return "json_exists"; }
bool is_bool_type() { return true; }
void fix_length_and_dec();
......@@ -85,8 +85,8 @@ class Item_func_json_value: public Item_str_func
String tmp_js, tmp_path;
public:
Item_func_json_value(THD *thd, Item *js, Item *path):
Item_str_func(thd, js, path) {}
Item_func_json_value(THD *thd, Item *js, Item *i_path):
Item_str_func(thd, js, i_path) {}
const char *func_name() const { return "json_value"; }
void fix_length_and_dec();
String *val_str(String *);
......@@ -99,8 +99,8 @@ class Item_func_json_value: public Item_str_func
class Item_func_json_query: public Item_func_json_value
{
public:
Item_func_json_query(THD *thd, Item *js, Item *path):
Item_func_json_value(thd, js, path) {}
Item_func_json_query(THD *thd, Item *js, Item *i_path):
Item_func_json_value(thd, js, i_path) {}
const char *func_name() const { return "json_query"; }
bool check_and_get_value(json_engine_t *je, String *res, int *error);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
......@@ -291,12 +291,14 @@ class Item_func_json_merge: public Item_func_json_array
class Item_func_json_length: public Item_int_func
{
protected:
json_path_with_flags path;
String tmp_js;
String tmp_path;
public:
Item_func_json_length(THD *thd, List<Item> &list):
Item_int_func(thd, list) {}
const char *func_name() const { return "json_length"; }
void fix_length_and_dec();
longlong val_int();
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ 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