Skip to content

Commit c6e3fe2

Browse files
committed
MDEV-30646 View created via JSON_ARRAYAGG returns incorrect json object
Backporting add782a from 10.6, this fixes the problem.
1 parent dc25d60 commit c6e3fe2

File tree

8 files changed

+59
-12
lines changed

8 files changed

+59
-12
lines changed

mysql-test/main/func_json.result

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,9 +1640,9 @@ SELECT t1.id, JSON_ARRAYAGG(JSON_OBJECT('id',t2.id) ORDER BY t2.id) as materials
16401640
from t1 LEFT JOIN t2 on t1.id = t2.owner_id
16411641
GROUP BY t1.id ORDER BY id;
16421642
id materials
1643-
1 ["{\"id\": 1}","{\"id\": 2}"]
1644-
2 ["{\"id\": 3}"]
1645-
3 ["{\"id\": 4}"]
1643+
1 [{"id": 1},{"id": 2}]
1644+
2 [{"id": 3}]
1645+
3 [{"id": 4}]
16461646
DROP TABLE t1;
16471647
DROP TABLE t2;
16481648
#

mysql-test/suite/json/r/type_json.result

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2880,5 +2880,13 @@ DROP PROCEDURE p1;
28802880
DROP PROCEDURE p2;
28812881
DROP TABLE t1, t1c, t2;
28822882
#
2883+
# MDEV-30646 View created via JSON_ARRAYAGG returns incorrect json object
2884+
#
2885+
CREATE VIEW v1 AS SELECT JSON_OBJECT('plugin','unix_socket') as v1_json;
2886+
SELECT JSON_ARRAYAGG(v1_json) FROM v1;
2887+
JSON_ARRAYAGG(v1_json)
2888+
[{"plugin": "unix_socket"}]
2889+
DROP VIEW v1;
2890+
#
28832891
# End of 10.5 tests
28842892
#

mysql-test/suite/json/t/type_json.test

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,15 @@ DROP PROCEDURE p2;
138138

139139
DROP TABLE t1, t1c, t2;
140140

141+
--echo #
142+
--echo # MDEV-30646 View created via JSON_ARRAYAGG returns incorrect json object
143+
--echo #
144+
145+
CREATE VIEW v1 AS SELECT JSON_OBJECT('plugin','unix_socket') as v1_json;
146+
SELECT JSON_ARRAYAGG(v1_json) FROM v1;
147+
DROP VIEW v1;
148+
149+
141150
--echo #
142151
--echo # End of 10.5 tests
143152
--echo #

sql/item_jsonfunc.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1633,7 +1633,7 @@ longlong Item_func_json_contains_path::val_int()
16331633
`CONVERT(arg USING charset)` is actually a general purpose string
16341634
expression, not a JSON expression.
16351635
*/
1636-
static bool is_json_type(const Item *item)
1636+
bool is_json_type(const Item *item)
16371637
{
16381638
for ( ; ; )
16391639
{

sql/item_jsonfunc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,5 +640,6 @@ class Item_func_json_objectagg : public Item_sum
640640
{ return get_item_copy<Item_func_json_objectagg>(thd, this); }
641641
};
642642

643+
extern bool is_json_type(const Item *item);
643644

644645
#endif /* ITEM_JSONFUNC_INCLUDED */

sql/sql_select.cc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18569,6 +18569,25 @@ Field *Item_func_sp::create_tmp_field_ex(MEM_ROOT *root, TABLE *table,
1856918569
return result;
1857018570
}
1857118571

18572+
18573+
static bool make_json_valid_expr(TABLE *table, Field *field)
18574+
{
18575+
THD *thd= table->in_use;
18576+
Query_arena backup_arena;
18577+
Item *expr, *item_field;
18578+
18579+
if (!table->expr_arena && table->init_expr_arena(thd->mem_root))
18580+
return 1;
18581+
18582+
thd->set_n_backup_active_arena(table->expr_arena, &backup_arena);
18583+
if ((item_field= new (thd->mem_root) Item_field(thd, field)) &&
18584+
(expr= new (thd->mem_root) Item_func_json_valid(thd, item_field)))
18585+
field->check_constraint= add_virtual_expression(thd, expr);
18586+
thd->restore_active_arena(table->expr_arena, &backup_arena);
18587+
return field->check_constraint == NULL;
18588+
}
18589+
18590+
1857218591
/**
1857318592
Create field for temporary table.
1857418593

@@ -18614,6 +18633,9 @@ Field *create_tmp_field(TABLE *table, Item *item,
1861418633
make_copy_field);
1861518634
Field *result= item->create_tmp_field_ex(table->in_use->mem_root,
1861618635
table, &src, &prm);
18636+
if (is_json_type(item) && make_json_valid_expr(table, result))
18637+
result= NULL;
18638+
1861718639
*from_field= src.field();
1861818640
*default_field= src.default_field();
1861918641
if (src.item_result_field())

sql/table.cc

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,17 @@
5353
#define MYSQL57_GENERATED_FIELD 128
5454
#define MYSQL57_GCOL_HEADER_SIZE 4
5555

56+
bool TABLE::init_expr_arena(MEM_ROOT *mem_root)
57+
{
58+
/*
59+
We need to use CONVENTIONAL_EXECUTION here to ensure that
60+
any new items created by fix_fields() are not reverted.
61+
*/
62+
expr_arena= new (alloc_root(mem_root, sizeof(Query_arena)))
63+
Query_arena(mem_root, Query_arena::STMT_CONVENTIONAL_EXECUTION);
64+
return expr_arena == NULL;
65+
}
66+
5667
struct extra2_fields
5768
{
5869
LEX_CUSTRING version;
@@ -1145,14 +1156,8 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table,
11451156
table->s->table_check_constraints * sizeof(Virtual_column_info*));
11461157

11471158
DBUG_ASSERT(table->expr_arena == NULL);
1148-
/*
1149-
We need to use CONVENTIONAL_EXECUTION here to ensure that
1150-
any new items created by fix_fields() are not reverted.
1151-
*/
1152-
table->expr_arena= new (alloc_root(mem_root, sizeof(Query_arena)))
1153-
Query_arena(mem_root,
1154-
Query_arena::STMT_CONVENTIONAL_EXECUTION);
1155-
if (!table->expr_arena)
1159+
1160+
if (table->init_expr_arena(mem_root))
11561161
DBUG_RETURN(1);
11571162

11581163
thd->set_n_backup_active_arena(table->expr_arena, &backup_arena);

sql/table.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1645,6 +1645,8 @@ struct TABLE
16451645
m_needs_reopen= value;
16461646
}
16471647

1648+
bool init_expr_arena(MEM_ROOT *mem_root);
1649+
16481650
bool alloc_keys(uint key_count);
16491651
bool check_tmp_key(uint key, uint key_parts,
16501652
uint (*next_field_no) (uchar *), uchar *arg);

0 commit comments

Comments
 (0)