summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2019-12-13 17:30:37 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2019-12-13 17:30:37 +0200
commit8fa759a5762733d9f8a4050437fadcd255ecd1a2 (patch)
tree093c167478abbbf6f51cd47f8df8651ee17f97f1 /sql
parent014e1258309da2475b8ae36d445261f87422adaf (diff)
parent3466b47b0d2f0aca0a2191574c593c7eaea0b0b8 (diff)
downloadmariadb-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.cc75
-rw-r--r--sql/item.cc2
-rw-r--r--sql/item_cmpfunc.h1
-rw-r--r--sql/opt_subselect.cc7
-rw-r--r--sql/sp_head.cc6
-rw-r--r--sql/sql_table.cc54
-rw-r--r--sql/sql_tvc.cc56
-rw-r--r--sql/temporary_tables.cc7
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.