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:
@ -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
|
||||||
#
|
#
|
||||||
|
@ -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 #
|
||||||
|
@ -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)))
|
||||||
|
@ -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)
|
||||||
|
@ -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.
|
||||||
|
@ -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; }
|
||||||
|
Reference in New Issue
Block a user