Commit ba8e5e68 authored by Alexey Botchkov's avatar Alexey Botchkov

MDEV-16620 JSON_ARRAYAGG and JSON_OBJECTAGG.

Ison_objectagg implemented.
parent b1c2c4ee
......@@ -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 @@ class Item_func_json_format: public Item_json_func
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 @@ class Item_func_json_arrayagg : public Item_func_group_concat
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 @@ class Item_func_json_arrayagg : public Item_func_group_concat
{
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:
......
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