mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-16620 JSON_ARRAYAGG and JSON_OBJECTAGG.
Ison_objectagg implemented.
This commit is contained in:
@ -1198,7 +1198,17 @@ JSON_ARRAYAGG(JSON_OBJECT('a', a, 'b', b))
|
||||
SELECT JSON_ARRAYAGG(a, b) FROM t1;
|
||||
ERROR 42000: Incorrect parameter count in the call to native function 'JSON_ARRAYAGG'
|
||||
SELECT JSON_ARRAYAGG(JSON_ARRAYAGG(a, b)) FROM t1;
|
||||
ERROR 42000: Incorrect parameter count in the call to native function 'JSON_ARRAYAGG'
|
||||
SELECT JSON_ARRAYAGG(JSON_ARRAYAGG(a)) FROM t1;
|
||||
ERROR HY000: Invalid use of group function
|
||||
#
|
||||
# MDEV-16620 JSON_OBJECTAGG
|
||||
#
|
||||
SELECT JSON_OBJECTAGG(a, b) FROM t1;
|
||||
JSON_OBJECTAGG(a, b)
|
||||
{"1":"Hello", "1":"World", "2":"This", "2":"Will", "2":"Work", "2":"!", "3":null, "1":"Hello", "1":"World", "2":"This", "2":"Will", "2":"Work", "2":"!", "3":null}
|
||||
SELECT JSON_OBJECTAGG(a) FROM t1;
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') FROM t1' at line 1
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# End of 10.4 tests
|
||||
|
@ -713,9 +713,20 @@ SELECT JSON_ARRAYAGG(JSON_OBJECT('a', a, 'b', b)) FROM t1 GROUP BY a;
|
||||
--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
|
||||
SELECT JSON_ARRAYAGG(a, b) FROM t1;
|
||||
|
||||
--error ER_INVALID_GROUP_FUNC_USE
|
||||
--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
|
||||
SELECT JSON_ARRAYAGG(JSON_ARRAYAGG(a, b)) FROM t1;
|
||||
|
||||
--error ER_INVALID_GROUP_FUNC_USE
|
||||
SELECT JSON_ARRAYAGG(JSON_ARRAYAGG(a)) FROM t1;
|
||||
|
||||
-- echo #
|
||||
-- echo # MDEV-16620 JSON_OBJECTAGG
|
||||
-- echo #
|
||||
|
||||
SELECT JSON_OBJECTAGG(a, b) FROM t1;
|
||||
--error ER_PARSE_ERROR
|
||||
SELECT JSON_OBJECTAGG(a) FROM t1;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
|
@ -3643,3 +3643,119 @@ String* Item_func_json_arrayagg::val_str(String *str)
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
Item_func_json_objectagg::
|
||||
Item_func_json_objectagg(THD *thd, Item_func_json_objectagg *item)
|
||||
:Item_sum(thd, item)
|
||||
{
|
||||
result.set_charset(collation.collation);
|
||||
result.append("{");
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Item_func_json_objectagg::fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
uint i; /* for loop variable */
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
|
||||
if (init_sum_func_check(thd))
|
||||
return TRUE;
|
||||
|
||||
maybe_null= 1;
|
||||
|
||||
/*
|
||||
Fix fields for select list and ORDER clause
|
||||
*/
|
||||
|
||||
for (i=0 ; i < arg_count ; i++)
|
||||
{
|
||||
if (args[i]->fix_fields_if_needed_for_scalar(thd, &args[i]))
|
||||
return TRUE;
|
||||
m_with_subquery|= args[i]->with_subquery();
|
||||
with_param|= args[i]->with_param;
|
||||
with_window_func|= args[i]->with_window_func;
|
||||
}
|
||||
|
||||
/* skip charset aggregation for order columns */
|
||||
if (agg_arg_charsets_for_string_result(collation, args, arg_count))
|
||||
return 1;
|
||||
|
||||
result.set_charset(collation.collation);
|
||||
result_field= 0;
|
||||
null_value= 1;
|
||||
max_length= (uint32)(thd->variables.group_concat_max_len
|
||||
/ collation.collation->mbminlen
|
||||
* collation.collation->mbmaxlen);
|
||||
|
||||
if (check_sum_func(thd, ref))
|
||||
return TRUE;
|
||||
|
||||
fixed= 1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
void Item_func_json_objectagg::cleanup()
|
||||
{
|
||||
DBUG_ENTER("Item_func_json_objectagg::cleanup");
|
||||
Item_sum::cleanup();
|
||||
|
||||
result.length(1);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
Item *Item_func_json_objectagg::copy_or_same(THD* thd)
|
||||
{
|
||||
return new (thd->mem_root) Item_func_json_objectagg(thd, this);
|
||||
}
|
||||
|
||||
|
||||
void Item_func_json_objectagg::clear()
|
||||
{
|
||||
result.length(1);
|
||||
null_value= 1;
|
||||
}
|
||||
|
||||
|
||||
bool Item_func_json_objectagg::add()
|
||||
{
|
||||
StringBuffer<MAX_FIELD_WIDTH> buf;
|
||||
String *key;
|
||||
|
||||
key= args[0]->val_str(&buf);
|
||||
if (args[0]->is_null())
|
||||
return 0;
|
||||
|
||||
null_value= 0;
|
||||
if (result.length() > 1)
|
||||
result.append(", ");
|
||||
|
||||
result.append("\"");
|
||||
result.append(*key);
|
||||
result.append("\":");
|
||||
|
||||
buf.length(0);
|
||||
append_json_value(&result, args[1], &buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
String* Item_func_json_objectagg::val_str(String* str)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
if (null_value)
|
||||
return 0;
|
||||
|
||||
result.append("}");
|
||||
return &result;
|
||||
}
|
||||
|
||||
|
||||
void Item_func_json_objectagg::print(String *str, enum_query_type query_type)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -527,7 +527,6 @@ public:
|
||||
class Item_func_json_arrayagg : public Item_func_group_concat
|
||||
{
|
||||
public:
|
||||
|
||||
Item_func_json_arrayagg(THD *thd, Name_resolution_context *context_arg,
|
||||
bool is_distinct, List<Item> *is_select,
|
||||
const SQL_I_List<ORDER> &is_order, String *is_separator,
|
||||
@ -536,6 +535,8 @@ public:
|
||||
is_separator, limit_clause, row_limit, offset_limit)
|
||||
{
|
||||
}
|
||||
Item_func_json_arrayagg(THD *thd, Item_func_json_arrayagg *item);
|
||||
bool is_json_type() { return true; }
|
||||
|
||||
const char *func_name() const { return "json_arrayagg("; }
|
||||
enum Sumfunctype sum_func() const {return JSON_ARRAYAGG_FUNC;}
|
||||
@ -548,6 +549,58 @@ public:
|
||||
{
|
||||
return Item_func_group_concat::add(false);
|
||||
}
|
||||
Item *get_copy(THD *thd)
|
||||
{ return get_item_copy<Item_func_json_arrayagg>(thd, this); }
|
||||
};
|
||||
|
||||
|
||||
class Item_func_json_objectagg : public Item_sum
|
||||
{
|
||||
String result;
|
||||
public:
|
||||
Item_func_json_objectagg(THD *thd, Item *key, Item *value) :
|
||||
Item_sum(thd, key, value)
|
||||
{
|
||||
result.append("{");
|
||||
}
|
||||
|
||||
Item_func_json_objectagg(THD *thd, Item_func_json_objectagg *item);
|
||||
bool is_json_type() { return true; }
|
||||
void cleanup();
|
||||
|
||||
enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;}
|
||||
const char *func_name() const { return "json_objectagg("; }
|
||||
const Type_handler *type_handler() const
|
||||
{
|
||||
if (too_big_for_varchar())
|
||||
return &type_handler_blob;
|
||||
return &type_handler_varchar;
|
||||
}
|
||||
void clear();
|
||||
bool add();
|
||||
void reset_field() { DBUG_ASSERT(0); } // not used
|
||||
void update_field() { DBUG_ASSERT(0); } // not used
|
||||
bool fix_fields(THD *,Item **);
|
||||
|
||||
double val_real()
|
||||
{ return 0.0; }
|
||||
longlong val_int()
|
||||
{ return 0; }
|
||||
my_decimal *val_decimal(my_decimal *decimal_value)
|
||||
{
|
||||
my_decimal_set_zero(decimal_value);
|
||||
return decimal_value;
|
||||
}
|
||||
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
|
||||
{
|
||||
return get_date_from_string(thd, ltime, fuzzydate);
|
||||
}
|
||||
String* val_str(String* str);
|
||||
Item *copy_or_same(THD* thd);
|
||||
void no_rows_in_result() {}
|
||||
void print(String *str, enum_query_type query_type);
|
||||
Item *get_copy(THD *thd)
|
||||
{ return get_item_copy<Item_func_json_objectagg>(thd, this); }
|
||||
};
|
||||
|
||||
|
||||
|
@ -3652,14 +3652,6 @@ int dump_leaf_key(void* key_arg, element_count count __attribute__((unused)),
|
||||
if (item->limit_clause && !(*row_limit))
|
||||
return 1;
|
||||
|
||||
if (item->sum_func() == Item_sum::JSON_ARRAYAGG_FUNC &&
|
||||
item->arg_count_field > 1)
|
||||
{
|
||||
/* JSON_ARRAYAGG supports only one parameter */
|
||||
my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), "JSON_ARRAYAGG");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (item->no_appended)
|
||||
item->no_appended= FALSE;
|
||||
else
|
||||
|
@ -742,6 +742,7 @@ static SYMBOL sql_functions[] = {
|
||||
{ "FIRST_VALUE", SYM(FIRST_VALUE_SYM)},
|
||||
{ "GROUP_CONCAT", SYM(GROUP_CONCAT_SYM)},
|
||||
{ "JSON_ARRAYAGG", SYM(JSON_ARRAYAGG_SYM)},
|
||||
{ "JSON_OBJECTAGG", SYM(JSON_OBJECTAGG_SYM)},
|
||||
{ "LAG", SYM(LAG_SYM)},
|
||||
{ "LEAD", SYM(LEAD_SYM)},
|
||||
{ "MAX", SYM(MAX_SYM)},
|
||||
|
@ -1007,6 +1007,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
|
||||
%token <kwd> GRANT /* SQL-2003-R */
|
||||
%token <kwd> GROUP_CONCAT_SYM
|
||||
%token <rwd> JSON_ARRAYAGG_SYM
|
||||
%token <rwd> JSON_OBJECTAGG_SYM
|
||||
%token <kwd> GROUP_SYM /* SQL-2003-R */
|
||||
%token <kwd> HAVING /* SQL-2003-R */
|
||||
%token <kwd> HOUR_MICROSECOND_SYM
|
||||
@ -11508,19 +11509,26 @@ sum_expr:
|
||||
}
|
||||
| JSON_ARRAYAGG_SYM '(' opt_distinct
|
||||
{ Select->in_sum_expr++; }
|
||||
expr_list opt_glimit_clause
|
||||
expr_list opt_gorder_clause opt_glimit_clause
|
||||
')'
|
||||
{
|
||||
SELECT_LEX *sel= Select;
|
||||
List<Item> *args= $5;
|
||||
sel->in_sum_expr--;
|
||||
if (args && args->elements > 1)
|
||||
{
|
||||
/* JSON_ARRAYAGG supports only one parameter */
|
||||
my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), "JSON_ARRAYAGG");
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
String* s= new (thd->mem_root) String(",", 1, &my_charset_latin1);
|
||||
if (unlikely(s == NULL))
|
||||
MYSQL_YYABORT;
|
||||
|
||||
$$= new (thd->mem_root)
|
||||
Item_func_json_arrayagg(thd, Lex->current_context(),
|
||||
$3, $5,
|
||||
sel->gorder_list, s, $6,
|
||||
$3, args,
|
||||
sel->gorder_list, s, $7,
|
||||
sel->select_limit,
|
||||
sel->offset_limit);
|
||||
if (unlikely($$ == NULL))
|
||||
@ -11531,6 +11539,17 @@ sum_expr:
|
||||
$5->empty();
|
||||
sel->gorder_list.empty();
|
||||
}
|
||||
| JSON_OBJECTAGG_SYM '('
|
||||
{ Select->in_sum_expr++; }
|
||||
expr ',' expr ')'
|
||||
{
|
||||
SELECT_LEX *sel= Select;
|
||||
sel->in_sum_expr--;
|
||||
|
||||
$$= new (thd->mem_root) Item_func_json_objectagg(thd, $4, $6);
|
||||
if (unlikely($$ == NULL))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
window_func_expr:
|
||||
|
@ -472,6 +472,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
|
||||
%token <kwd> GRANT /* SQL-2003-R */
|
||||
%token <kwd> GROUP_CONCAT_SYM
|
||||
%token <rwd> JSON_ARRAYAGG_SYM
|
||||
%token <rwd> JSON_OBJECTAGG_SYM
|
||||
%token <kwd> GROUP_SYM /* SQL-2003-R */
|
||||
%token <kwd> HAVING /* SQL-2003-R */
|
||||
%token <kwd> HOUR_MICROSECOND_SYM
|
||||
@ -11608,19 +11609,26 @@ sum_expr:
|
||||
}
|
||||
| JSON_ARRAYAGG_SYM '(' opt_distinct
|
||||
{ Select->in_sum_expr++; }
|
||||
expr_list opt_glimit_clause
|
||||
expr_list opt_gorder_clause opt_glimit_clause
|
||||
')'
|
||||
{
|
||||
SELECT_LEX *sel= Select;
|
||||
List<Item> *args= $5;
|
||||
sel->in_sum_expr--;
|
||||
if (args && args->elements > 1)
|
||||
{
|
||||
/* JSON_ARRAYAGG supports only one parameter */
|
||||
my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), "JSON_ARRAYAGG");
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
String* s= new (thd->mem_root) String(",", 1, &my_charset_latin1);
|
||||
if (unlikely(s == NULL))
|
||||
MYSQL_YYABORT;
|
||||
|
||||
$$= new (thd->mem_root)
|
||||
Item_func_json_arrayagg(thd, Lex->current_context(),
|
||||
$3, $5,
|
||||
sel->gorder_list, s, $6,
|
||||
$3, args,
|
||||
sel->gorder_list, s, $7,
|
||||
sel->select_limit,
|
||||
sel->offset_limit);
|
||||
if (unlikely($$ == NULL))
|
||||
@ -11631,6 +11639,17 @@ sum_expr:
|
||||
$5->empty();
|
||||
sel->gorder_list.empty();
|
||||
}
|
||||
| JSON_OBJECTAGG_SYM '('
|
||||
{ Select->in_sum_expr++; }
|
||||
expr ',' expr ')'
|
||||
{
|
||||
SELECT_LEX *sel= Select;
|
||||
sel->in_sum_expr--;
|
||||
|
||||
$$= new (thd->mem_root) Item_func_json_objectagg(thd, $4, $6);
|
||||
if (unlikely($$ == NULL))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
window_func_expr:
|
||||
|
Reference in New Issue
Block a user