diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2019-12-13 17:30:37 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2019-12-13 17:30:37 +0200 |
commit | 8fa759a5762733d9f8a4050437fadcd255ecd1a2 (patch) | |
tree | 093c167478abbbf6f51cd47f8df8651ee17f97f1 /sql | |
parent | 014e1258309da2475b8ae36d445261f87422adaf (diff) | |
parent | 3466b47b0d2f0aca0a2191574c593c7eaea0b0b8 (diff) | |
download | mariadb-git-8fa759a5762733d9f8a4050437fadcd255ecd1a2.tar.gz |
Merge 10.3 into 10.4
We disable the MDEV-21189 test galera.galera_partition
because it times out.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/derror.cc | 75 | ||||
-rw-r--r-- | sql/item.cc | 2 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 1 | ||||
-rw-r--r-- | sql/opt_subselect.cc | 7 | ||||
-rw-r--r-- | sql/sp_head.cc | 6 | ||||
-rw-r--r-- | sql/sql_table.cc | 54 | ||||
-rw-r--r-- | sql/sql_tvc.cc | 56 | ||||
-rw-r--r-- | sql/temporary_tables.cc | 7 |
8 files changed, 180 insertions, 28 deletions
diff --git a/sql/derror.cc b/sql/derror.cc index a1150596ee3..14b60ee4db4 100644 --- a/sql/derror.cc +++ b/sql/derror.cc @@ -69,6 +69,9 @@ bool init_errmessage(void) { const char **errmsgs; bool error= FALSE; + const char *lang= my_default_lc_messages->errmsgs->language; + my_bool use_english; + DBUG_ENTER("init_errmessage"); free_error_messages(); @@ -77,35 +80,63 @@ bool init_errmessage(void) error_message_charset_info= system_charset_info; - /* Read messages from file. */ - if (read_texts(ERRMSG_FILE, my_default_lc_messages->errmsgs->language, - &original_error_messages)) + use_english= !strcmp(lang, "english"); + if (!use_english) { - /* - No error messages. Create a temporary empty error message so - that we don't get a crash if some code wrongly tries to access - a non existing error message. - */ + /* Read messages from file. */ + use_english= !read_texts(ERRMSG_FILE,lang, &original_error_messages); + error= TRUE; + } + + if (use_english) + { + static const struct + { + const char* name; + uint id; + const char* fmt; + } + english_msgs[]= + { + #include <mysqld_ername.h> + }; + + memset(errors_per_range, 0, sizeof(errors_per_range)); + /* Calculate nr of messages per range. */ + for (size_t i= 0; i < array_elements(english_msgs); i++) + { + uint id= english_msgs[i].id; + + // We rely on the fact the array is sorted by id. + DBUG_ASSERT(i == 0 || english_msgs[i-1].id < id); + + errors_per_range[id/ERRORS_PER_RANGE-1]= id%ERRORS_PER_RANGE + 1; + } + + size_t all_errors= 0; + for (size_t i= 0; i < MAX_ERROR_RANGES; i++) + all_errors+= errors_per_range[i]; + if (!(original_error_messages= (const char***) - my_malloc(MAX_ERROR_RANGES * sizeof(char**) + - (ERRORS_PER_RANGE * sizeof(char*)), - MYF(0)))) + my_malloc((all_errors + MAX_ERROR_RANGES)* sizeof(void*), + MYF(MY_ZEROFILL)))) DBUG_RETURN(TRUE); - errmsgs= (const char**) (original_error_messages + MAX_ERROR_RANGES); - for (uint i=0 ; i < MAX_ERROR_RANGES ; i++) + errmsgs= (const char**)(original_error_messages + MAX_ERROR_RANGES); + + original_error_messages[0]= errmsgs; + for (uint i= 1; i < MAX_ERROR_RANGES; i++) { - original_error_messages[i]= errmsgs; - errors_per_range[i]= ERRORS_PER_RANGE; + original_error_messages[i]= + original_error_messages[i-1] + errors_per_range[i-1]; } - errors_per_range[2]= 0; // MYSYS error messages - - for (const char **ptr= errmsgs; - ptr < errmsgs + ERRORS_PER_RANGE ; - ptr++) - *ptr= ""; - error= TRUE; + for (uint i= 0; i < array_elements(english_msgs); i++) + { + uint id= english_msgs[i].id; + original_error_messages[id/ERRORS_PER_RANGE-1][id%ERRORS_PER_RANGE]= + english_msgs[i].fmt; + } } /* Register messages for use with my_error(). */ diff --git a/sql/item.cc b/sql/item.cc index 925d44a481f..dc39755f63d 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -10108,6 +10108,8 @@ bool Item_cache_str::cache_value() value_buff.copy(*value); value= &value_buff; } + else + value_buff.copy(); return TRUE; } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 0a91d45c2a2..8eaa0ab7c36 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -2468,6 +2468,7 @@ public: bool to_be_transformed_into_in_subq(THD *thd); bool create_value_list_for_tvc(THD *thd, List< List<Item> > *values); Item *in_predicate_to_in_subs_transformer(THD *thd, uchar *arg); + uint32 max_length_of_left_expr(); }; class cmp_item_row :public cmp_item diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 961bbdaabc8..23767bfbc16 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -861,7 +861,12 @@ bool subquery_types_allow_materialization(THD* thd, Item_in_subselect *in_subs) OPT_TRACE_TRANSFORM(thd, trace_wrapper, trace_transform, in_subs->get_select_lex()->select_number, "IN (SELECT)", "materialization"); - + + /* + The checks here must be kept in sync with the one in + Item_func_in::in_predicate_to_in_subs_transformer(). + */ + bool all_are_fields= TRUE; uint32 total_key_length = 0; for (uint i= 0; i < elements; i++) diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 8631d800001..eb3c35a4492 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -2627,7 +2627,7 @@ sp_head::backpatch_goto(THD *thd, sp_label *lab,sp_label *lab_begin_block) } if (bp->instr_type == CPOP) { - uint n= lab->ctx->diff_cursors(lab_begin_block->ctx, true); + uint n= bp->instr->m_ctx->diff_cursors(lab_begin_block->ctx, true); if (n == 0) { // Remove cpop instr @@ -2644,7 +2644,7 @@ sp_head::backpatch_goto(THD *thd, sp_label *lab,sp_label *lab_begin_block) } if (bp->instr_type == HPOP) { - uint n= lab->ctx->diff_handlers(lab_begin_block->ctx, true); + uint n= bp->instr->m_ctx->diff_handlers(lab_begin_block->ctx, true); if (n == 0) { // Remove hpop instr @@ -3149,6 +3149,8 @@ void sp_head::optimize() sp_instr *i; uint src, dst; + DBUG_EXECUTE_IF("sp_head_optimize_disable", return; ); + opt_mark(); bp.empty(); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 3430762fa49..8c695988853 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4305,10 +4305,10 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, continue; { - /* Check that there's no repeating constraint names. */ + /* Check that there's no repeating table CHECK constraint names. */ List_iterator_fast<Virtual_column_info> dup_it(alter_info->check_constraint_list); - Virtual_column_info *dup_check; + const Virtual_column_info *dup_check; while ((dup_check= dup_it++) && dup_check != check) { if (!lex_string_cmp(system_charset_info, @@ -4320,6 +4320,27 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, } } + /* Check that there's no repeating key constraint names. */ + List_iterator_fast<Key> key_it(alter_info->key_list); + while (const Key *key= key_it++) + { + /* + Not all keys considered to be the CONSTRAINT + Noly Primary Key UNIQUE and Foreign keys. + */ + if (key->type != Key::PRIMARY && key->type != Key::UNIQUE && + key->type != Key::FOREIGN_KEY) + continue; + + if (check->name.length == key->name.length && + my_strcasecmp(system_charset_info, + check->name.str, key->name.str) == 0) + { + my_error(ER_DUP_CONSTRAINT_NAME, MYF(0), "CHECK", check->name.str); + DBUG_RETURN(TRUE); + } + } + if (check_string_char_length(&check->name, 0, NAME_CHAR_LEN, system_charset_info, 1)) { @@ -8657,6 +8678,35 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, } } } + + if (!alter_info->check_constraint_list.is_empty()) + { + /* Check the table FOREIGN KEYs for name duplications. */ + List <FOREIGN_KEY_INFO> fk_child_key_list; + FOREIGN_KEY_INFO *f_key; + table->file->get_foreign_key_list(thd, &fk_child_key_list); + List_iterator<FOREIGN_KEY_INFO> fk_key_it(fk_child_key_list); + while ((f_key= fk_key_it++)) + { + List_iterator_fast<Virtual_column_info> + c_it(alter_info->check_constraint_list); + Virtual_column_info *check; + while ((check= c_it++)) + { + if (!check->name.length || check->automatic_name) + continue; + + if (check->name.length == f_key->foreign_id->length && + my_strcasecmp(system_charset_info, f_key->foreign_id->str, + check->name.str) == 0) + { + my_error(ER_DUP_CONSTRAINT_NAME, MYF(0), "CHECK", check->name.str); + goto err; + } + } + } + } + /* Add new constraints */ new_constraint_list.append(&alter_info->check_constraint_list); diff --git a/sql/sql_tvc.cc b/sql/sql_tvc.cc index e7379a77049..5265d254a05 100644 --- a/sql/sql_tvc.cc +++ b/sql/sql_tvc.cc @@ -795,6 +795,38 @@ bool Item_subselect::wrap_tvc_into_select(THD *thd, st_select_lex *tvc_sl) } +/* + @brief + Check whether the items are of comparable type or not + + @details + This check are done because materialization is not performed + if the left expr and right expr are of the same types. + @see subquery_types_allow_materialization() + + @retval + 0 comparable + 1 not comparable +*/ + +static bool cmp_row_types(Item* item1, Item* item2) +{ + uint n= item1->cols(); + if (item2->check_cols(n)) + return true; + + for (uint i=0; i < n; i++) + { + Item *inner= item1->element_index(i); + Item *outer= item2->element_index(i); + if (!inner->type_handler()->subquery_type_allows_materialization(inner, + outer)) + return true; + } + return false; +} + + /** @brief Transform IN predicate into IN subquery @@ -839,10 +871,22 @@ Item *Item_func_in::in_predicate_to_in_subs_transformer(THD *thd, /* SELECT_LEX object where the transformation is performed */ SELECT_LEX *parent_select= lex->current_select; uint8 save_derived_tables= lex->derived_tables; + + /* + Make sure that create_tmp_table will not fail due to too long keys. + Here the strategy would mainly use materialization, so we need to make + sure that the materialized table can be created. + + The checks here are the same as in subquery_type_allows_materialization() + */ + uint32 length= max_length_of_left_expr(); + if (!length || length > tmp_table_max_key_length() || + args[0]->cols() > tmp_table_max_key_parts()) + return this; for (uint i=1; i < arg_count; i++) { - if (!args[i]->const_item()) + if (!args[i]->const_item() || cmp_row_types(args[0], args[i])) return this; } @@ -947,6 +991,16 @@ err: } +uint32 Item_func_in::max_length_of_left_expr() +{ + uint n= args[0]->cols(); + uint32 length= 0; + for (uint i=0; i < n; i++) + length+= args[0]->element_index(i)->max_length; + return length; +} + + /** @brief Check if this IN-predicate can be transformed in IN-subquery diff --git a/sql/temporary_tables.cc b/sql/temporary_tables.cc index b39423e9131..2e0f0a4918e 100644 --- a/sql/temporary_tables.cc +++ b/sql/temporary_tables.cc @@ -346,6 +346,13 @@ bool THD::open_temporary_table(TABLE_LIST *tl) DBUG_RETURN(false); } + if (!tl->db.str) + { + DBUG_PRINT("info", + ("Table reference to a temporary table must have database set")); + DBUG_RETURN(false); + } + /* Temporary tables are not safe for parallel replication. They were designed to be visible to one thread only, so have no table locking. |