1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

MDEV-21914 JSON_ARRAYAGG doesn't reject ORDER BY clause, but doesn't work either.

ORDER BY fixed for JSON_ARRAYAGG.
This commit is contained in:
Alexey Botchkov
2020-06-04 13:53:14 +04:00
parent 07daf73542
commit 74198384e1
6 changed files with 81 additions and 18 deletions

View File

@ -1240,6 +1240,9 @@ select * from v;
JSON_DATA JSON_DATA
[{"type": "permPeriod", "id": "asd"}] [{"type": "permPeriod", "id": "asd"}]
drop view v; drop view v;
select json_arrayagg(a order by a asc) from (select 1 a union select 2 a) t;
json_arrayagg(a order by a asc)
[1,2]
# #
# End of 10.5 tests # End of 10.5 tests
# #

View File

@ -759,6 +759,8 @@ create view v as (select json_arrayagg(json_object("type", "permPeriod", "id", "
select * from v; select * from v;
drop view v; drop view v;
select json_arrayagg(a order by a asc) from (select 1 a union select 2 a) t;
--echo # --echo #
--echo # End of 10.5 tests --echo # End of 10.5 tests
--echo # --echo #

View File

@ -1452,6 +1452,52 @@ append_null:
} }
static int append_json_value_from_field(String *str,
Item *i, Field *f, const uchar *key, size_t offset, String *tmp_val)
{
if (i->type_handler()->is_bool_type())
{
longlong v_int= f->val_int(key + offset);
const char *t_f;
int t_f_len;
if (f->is_null(offset))
goto append_null;
if (v_int)
{
t_f= "true";
t_f_len= 4;
}
else
{
t_f= "false";
t_f_len= 5;
}
return str->append(t_f, t_f_len);
}
{
String *sv= f->val_str(tmp_val, key + offset);
if (f->is_null(offset))
goto append_null;
if (i->is_json_type())
return str->append(sv->ptr(), sv->length());
if (i->result_type() == STRING_RESULT)
{
return str->append("\"", 1) ||
st_append_escaped(str, sv) ||
str->append("\"", 1);
}
return st_append_escaped(str, sv);
}
append_null:
return str->append("null", 4);
}
static int append_json_keyname(String *str, Item *item, String *tmp_val) static int append_json_keyname(String *str, Item *item, String *tmp_val)
{ {
String *sv= item->val_str(tmp_val); String *sv= item->val_str(tmp_val);
@ -3621,15 +3667,28 @@ int Arg_comparator::compare_e_json_str_basic(Item *j, Item *s)
} }
String* Item_func_json_arrayagg::convert_to_json(Item *item) String *Item_func_json_arrayagg::get_str_from_item(Item *i, String *tmp)
{ {
String tmp;
m_tmp_json.length(0); m_tmp_json.length(0);
append_json_value(&m_tmp_json, item, &tmp); if (append_json_value(&m_tmp_json, i, tmp))
return NULL;
return &m_tmp_json; return &m_tmp_json;
} }
String *Item_func_json_arrayagg::get_str_from_field(Item *i,Field *f,
String *tmp, const uchar *key, size_t offset)
{
m_tmp_json.length(0);
if (append_json_value_from_field(&m_tmp_json, i, f, key, offset, tmp))
return NULL;
return &m_tmp_json;
}
String* Item_func_json_arrayagg::val_str(String *str) String* Item_func_json_arrayagg::val_str(String *str)
{ {
if ((str= Item_func_group_concat::val_str(str))) if ((str= Item_func_group_concat::val_str(str)))

View File

@ -542,10 +542,13 @@ protected:
Overrides Item_func_group_concat::skip_nulls() Overrides Item_func_group_concat::skip_nulls()
NULL-s should be added to the result as JSON null value. NULL-s should be added to the result as JSON null value.
*/ */
virtual bool skip_nulls() const { return false; } bool skip_nulls() const { return false; }
String *get_str_from_item(Item *i, String *tmp);
String *get_str_from_field(Item *i, Field *f, String *tmp,
const uchar *key, size_t offset);
public: public:
String m_tmp_json; /* Used in convert_to_json. */ String m_tmp_json; /* Used in get_str_from_*.. */
Item_func_json_arrayagg(THD *thd, Name_resolution_context *context_arg, Item_func_json_arrayagg(THD *thd, Name_resolution_context *context_arg,
bool is_distinct, List<Item> *is_select, bool is_distinct, List<Item> *is_select,
const SQL_I_List<ORDER> &is_order, String *is_separator, const SQL_I_List<ORDER> &is_order, String *is_separator,
@ -560,7 +563,6 @@ public:
const char *func_name() const { return "json_arrayagg("; } const char *func_name() const { return "json_arrayagg("; }
enum Sumfunctype sum_func() const {return JSON_ARRAYAGG_FUNC;} enum Sumfunctype sum_func() const {return JSON_ARRAYAGG_FUNC;}
String* convert_to_json(Item *item);
String* val_str(String *str); String* val_str(String *str);
Item *get_copy(THD *thd) Item *get_copy(THD *thd)

View File

@ -3660,7 +3660,7 @@ int dump_leaf_key(void* key_arg, element_count count __attribute__((unused)),
because it contains both order and arg list fields. because it contains both order and arg list fields.
*/ */
if ((*arg)->const_item()) if ((*arg)->const_item())
res= (*arg)->val_str(&tmp); res= item->get_str_from_item(*arg, &tmp);
else else
{ {
Field *field= (*arg)->get_tmp_table_field(); Field *field= (*arg)->get_tmp_table_field();
@ -3669,19 +3669,10 @@ int dump_leaf_key(void* key_arg, element_count count __attribute__((unused)),
uint offset= (field->offset(field->table->record[0]) - uint offset= (field->offset(field->table->record[0]) -
table->s->null_bytes); table->s->null_bytes);
DBUG_ASSERT(offset < table->s->reclength); DBUG_ASSERT(offset < table->s->reclength);
res= field->val_str(&tmp, key + offset); res= item->get_str_from_field(*arg, field, &tmp, key, offset);
} }
else else
res= (*arg)->val_str(&tmp); res= item->get_str_from_item(*arg, &tmp);
}
if (item->sum_func() == Item_sum::JSON_ARRAYAGG_FUNC)
{
/*
JSON_ARRAYAGG needs to convert the type into valid JSON before
appending it to the result
*/
Item_func_json_arrayagg *arrayagg= (Item_func_json_arrayagg *) item_arg;
res= arrayagg->convert_to_json(*arg);
} }
if (res) if (res)
@ -3981,6 +3972,7 @@ bool Item_func_group_concat::repack_tree(THD *thd)
return 0; return 0;
} }
/* /*
Repacking the tree is expensive. But it keeps the tree small, and Repacking the tree is expensive. But it keeps the tree small, and
inserting into an unnecessary large tree is also waste of time. inserting into an unnecessary large tree is also waste of time.

View File

@ -1924,6 +1924,11 @@ protected:
Redefined in JSON_ARRAYAGG. Redefined in JSON_ARRAYAGG.
*/ */
virtual bool skip_nulls() const { return true; } virtual bool skip_nulls() const { return true; }
virtual String *get_str_from_item(Item *i, String *tmp)
{ return i->val_str(tmp); }
virtual String *get_str_from_field(Item *i, Field *f, String *tmp,
const uchar *key, size_t offset)
{ return f->val_str(tmp, key + offset); }
public: public:
// Methods used by ColumnStore // Methods used by ColumnStore
bool get_distinct() const { return distinct; } bool get_distinct() const { return distinct; }