From add782a13e58c027c14d548fa705f48fc25cc3e1 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 30 Jun 2021 21:28:07 +0200 Subject: [PATCH] fix JSON_ARRAYAGG not to over-quote json in joins This replaces 8711adb7863 if a temptable field is created for some json expression (is_json_type() returns true), make this temptable field a proper json field. A field is a json field (see Item_field::is_json_type()) if it has a CHECK constraint of JSON_VALID(field). Note that it will never be actually checked for temptable fields, so it won't cause a run-time slowdown. --- sql/sql_select.cc | 22 ++++++++++++++++++++++ sql/table.cc | 21 +++++++++++++-------- sql/table.h | 2 ++ 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 50a42ff8410..5a02218bb4a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -18412,6 +18412,25 @@ Field *Item_func_sp::create_tmp_field_ex(MEM_ROOT *root, TABLE *table, return result; } + +static bool make_json_valid_expr(TABLE *table, Field *field) +{ + THD *thd= table->in_use; + Query_arena backup_arena; + Item *expr, *item_field; + + if (!table->expr_arena && table->init_expr_arena(thd->mem_root)) + return NULL; + + thd->set_n_backup_active_arena(table->expr_arena, &backup_arena); + if ((item_field= new (thd->mem_root) Item_field(thd, field)) && + (expr= new (thd->mem_root) Item_func_json_valid(thd, item_field))) + field->check_constraint= add_virtual_expression(thd, expr); + thd->restore_active_arena(table->expr_arena, &backup_arena); + return field->check_constraint == NULL; +} + + /** Create field for temporary table. @@ -18457,6 +18476,9 @@ Field *create_tmp_field(TABLE *table, Item *item, make_copy_field); Field *result= item->create_tmp_field_ex(table->in_use->mem_root, table, &src, &prm); + if (item->is_json_type() && make_json_valid_expr(table, result)) + result= NULL; + *from_field= src.field(); *default_field= src.default_field(); if (src.item_result_field()) diff --git a/sql/table.cc b/sql/table.cc index c9420892160..73d701e0b2b 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -61,6 +61,17 @@ public: } }; +bool TABLE::init_expr_arena(MEM_ROOT *mem_root) +{ + /* + We need to use CONVENTIONAL_EXECUTION here to ensure that + any new items created by fix_fields() are not reverted. + */ + expr_arena= new (alloc_root(mem_root, sizeof(Table_arena))) + Table_arena(mem_root, Query_arena::STMT_CONVENTIONAL_EXECUTION); + return expr_arena == NULL; +} + struct extra2_fields { LEX_CUSTRING version; @@ -1155,14 +1166,8 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table, table->s->table_check_constraints * sizeof(Virtual_column_info*)); DBUG_ASSERT(table->expr_arena == NULL); - /* - We need to use CONVENTIONAL_EXECUTION here to ensure that - any new items created by fix_fields() are not reverted. - */ - table->expr_arena= new (alloc_root(mem_root, sizeof(Table_arena))) - Table_arena(mem_root, - Query_arena::STMT_CONVENTIONAL_EXECUTION); - if (!table->expr_arena) + + if (table->init_expr_arena(mem_root)) DBUG_RETURN(1); thd->set_n_backup_active_arena(table->expr_arena, &backup_arena); diff --git a/sql/table.h b/sql/table.h index 183ade8f1d9..2e074abcea0 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1612,6 +1612,8 @@ public: m_needs_reopen= value; } + bool init_expr_arena(MEM_ROOT *mem_root); + bool alloc_keys(uint key_count); bool check_tmp_key(uint key, uint key_parts, uint (*next_field_no) (uchar *), uchar *arg);