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;
|
SELECT JSON_ARRAYAGG(a, b) FROM t1;
|
||||||
ERROR 42000: Incorrect parameter count in the call to native function 'JSON_ARRAYAGG'
|
ERROR 42000: Incorrect parameter count in the call to native function 'JSON_ARRAYAGG'
|
||||||
SELECT JSON_ARRAYAGG(JSON_ARRAYAGG(a, b)) FROM t1;
|
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
|
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;
|
DROP TABLE t1;
|
||||||
#
|
#
|
||||||
# End of 10.4 tests
|
# 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
|
--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
|
||||||
SELECT JSON_ARRAYAGG(a, b) FROM t1;
|
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;
|
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;
|
DROP TABLE t1;
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
|
@ -3643,3 +3643,119 @@ String* Item_func_json_arrayagg::val_str(String *str)
|
|||||||
|
|
||||||
return 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
|
class Item_func_json_arrayagg : public Item_func_group_concat
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
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,
|
||||||
@ -536,6 +535,8 @@ public:
|
|||||||
is_separator, limit_clause, row_limit, offset_limit)
|
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("; }
|
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;}
|
||||||
@ -548,6 +549,58 @@ public:
|
|||||||
{
|
{
|
||||||
return Item_func_group_concat::add(false);
|
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))
|
if (item->limit_clause && !(*row_limit))
|
||||||
return 1;
|
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)
|
if (item->no_appended)
|
||||||
item->no_appended= FALSE;
|
item->no_appended= FALSE;
|
||||||
else
|
else
|
||||||
|
@ -742,6 +742,7 @@ static SYMBOL sql_functions[] = {
|
|||||||
{ "FIRST_VALUE", SYM(FIRST_VALUE_SYM)},
|
{ "FIRST_VALUE", SYM(FIRST_VALUE_SYM)},
|
||||||
{ "GROUP_CONCAT", SYM(GROUP_CONCAT_SYM)},
|
{ "GROUP_CONCAT", SYM(GROUP_CONCAT_SYM)},
|
||||||
{ "JSON_ARRAYAGG", SYM(JSON_ARRAYAGG_SYM)},
|
{ "JSON_ARRAYAGG", SYM(JSON_ARRAYAGG_SYM)},
|
||||||
|
{ "JSON_OBJECTAGG", SYM(JSON_OBJECTAGG_SYM)},
|
||||||
{ "LAG", SYM(LAG_SYM)},
|
{ "LAG", SYM(LAG_SYM)},
|
||||||
{ "LEAD", SYM(LEAD_SYM)},
|
{ "LEAD", SYM(LEAD_SYM)},
|
||||||
{ "MAX", SYM(MAX_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> GRANT /* SQL-2003-R */
|
||||||
%token <kwd> GROUP_CONCAT_SYM
|
%token <kwd> GROUP_CONCAT_SYM
|
||||||
%token <rwd> JSON_ARRAYAGG_SYM
|
%token <rwd> JSON_ARRAYAGG_SYM
|
||||||
|
%token <rwd> JSON_OBJECTAGG_SYM
|
||||||
%token <kwd> GROUP_SYM /* SQL-2003-R */
|
%token <kwd> GROUP_SYM /* SQL-2003-R */
|
||||||
%token <kwd> HAVING /* SQL-2003-R */
|
%token <kwd> HAVING /* SQL-2003-R */
|
||||||
%token <kwd> HOUR_MICROSECOND_SYM
|
%token <kwd> HOUR_MICROSECOND_SYM
|
||||||
@ -11508,19 +11509,26 @@ sum_expr:
|
|||||||
}
|
}
|
||||||
| JSON_ARRAYAGG_SYM '(' opt_distinct
|
| JSON_ARRAYAGG_SYM '(' opt_distinct
|
||||||
{ Select->in_sum_expr++; }
|
{ Select->in_sum_expr++; }
|
||||||
expr_list opt_glimit_clause
|
expr_list opt_gorder_clause opt_glimit_clause
|
||||||
')'
|
')'
|
||||||
{
|
{
|
||||||
SELECT_LEX *sel= Select;
|
SELECT_LEX *sel= Select;
|
||||||
|
List<Item> *args= $5;
|
||||||
sel->in_sum_expr--;
|
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);
|
String* s= new (thd->mem_root) String(",", 1, &my_charset_latin1);
|
||||||
if (unlikely(s == NULL))
|
if (unlikely(s == NULL))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
|
|
||||||
$$= new (thd->mem_root)
|
$$= new (thd->mem_root)
|
||||||
Item_func_json_arrayagg(thd, Lex->current_context(),
|
Item_func_json_arrayagg(thd, Lex->current_context(),
|
||||||
$3, $5,
|
$3, args,
|
||||||
sel->gorder_list, s, $6,
|
sel->gorder_list, s, $7,
|
||||||
sel->select_limit,
|
sel->select_limit,
|
||||||
sel->offset_limit);
|
sel->offset_limit);
|
||||||
if (unlikely($$ == NULL))
|
if (unlikely($$ == NULL))
|
||||||
@ -11531,6 +11539,17 @@ sum_expr:
|
|||||||
$5->empty();
|
$5->empty();
|
||||||
sel->gorder_list.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:
|
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> GRANT /* SQL-2003-R */
|
||||||
%token <kwd> GROUP_CONCAT_SYM
|
%token <kwd> GROUP_CONCAT_SYM
|
||||||
%token <rwd> JSON_ARRAYAGG_SYM
|
%token <rwd> JSON_ARRAYAGG_SYM
|
||||||
|
%token <rwd> JSON_OBJECTAGG_SYM
|
||||||
%token <kwd> GROUP_SYM /* SQL-2003-R */
|
%token <kwd> GROUP_SYM /* SQL-2003-R */
|
||||||
%token <kwd> HAVING /* SQL-2003-R */
|
%token <kwd> HAVING /* SQL-2003-R */
|
||||||
%token <kwd> HOUR_MICROSECOND_SYM
|
%token <kwd> HOUR_MICROSECOND_SYM
|
||||||
@ -11608,19 +11609,26 @@ sum_expr:
|
|||||||
}
|
}
|
||||||
| JSON_ARRAYAGG_SYM '(' opt_distinct
|
| JSON_ARRAYAGG_SYM '(' opt_distinct
|
||||||
{ Select->in_sum_expr++; }
|
{ Select->in_sum_expr++; }
|
||||||
expr_list opt_glimit_clause
|
expr_list opt_gorder_clause opt_glimit_clause
|
||||||
')'
|
')'
|
||||||
{
|
{
|
||||||
SELECT_LEX *sel= Select;
|
SELECT_LEX *sel= Select;
|
||||||
|
List<Item> *args= $5;
|
||||||
sel->in_sum_expr--;
|
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);
|
String* s= new (thd->mem_root) String(",", 1, &my_charset_latin1);
|
||||||
if (unlikely(s == NULL))
|
if (unlikely(s == NULL))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
|
|
||||||
$$= new (thd->mem_root)
|
$$= new (thd->mem_root)
|
||||||
Item_func_json_arrayagg(thd, Lex->current_context(),
|
Item_func_json_arrayagg(thd, Lex->current_context(),
|
||||||
$3, $5,
|
$3, args,
|
||||||
sel->gorder_list, s, $6,
|
sel->gorder_list, s, $7,
|
||||||
sel->select_limit,
|
sel->select_limit,
|
||||||
sel->offset_limit);
|
sel->offset_limit);
|
||||||
if (unlikely($$ == NULL))
|
if (unlikely($$ == NULL))
|
||||||
@ -11631,6 +11639,17 @@ sum_expr:
|
|||||||
$5->empty();
|
$5->empty();
|
||||||
sel->gorder_list.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:
|
window_func_expr:
|
||||||
|
Reference in New Issue
Block a user