mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
fixed mechanism of detection selection from table wich we update
(BUG##9398, BUG#8703) fixed wrong join view detection in multi-delete which lead to server crash
This commit is contained in:
@ -680,33 +680,12 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
|
||||
const char *db_name,
|
||||
const char *table_name)
|
||||
{
|
||||
if (lower_case_table_names)
|
||||
for (; table; table= *(TABLE_LIST **) ((char*) table + offset))
|
||||
{
|
||||
for (; table; table= *(TABLE_LIST **) ((char*) table + offset))
|
||||
{
|
||||
if ((table->table == 0 || table->table->s->tmp_table == NO_TMP_TABLE) &&
|
||||
((!strcmp(table->db, db_name) &&
|
||||
!strcmp(table->table_name, table_name)) ||
|
||||
(table->view &&
|
||||
!my_strcasecmp(table_alias_charset,
|
||||
table->db, db_name) &&
|
||||
!my_strcasecmp(table_alias_charset,
|
||||
table->table->alias, table_name))))
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; table; table= *(TABLE_LIST **) ((char*) table + offset))
|
||||
{
|
||||
if ((table->table == 0 || table->table->s->tmp_table == NO_TMP_TABLE) &&
|
||||
((!strcmp(table->db, db_name) &&
|
||||
!strcmp(table->table_name, table_name)) ||
|
||||
(table->view &&
|
||||
!strcmp(table->table->s->db, db_name) &&
|
||||
!strcmp(table->table->alias, table_name))))
|
||||
break;
|
||||
}
|
||||
if ((table->table == 0 || table->table->s->tmp_table == NO_TMP_TABLE) &&
|
||||
strcmp(table->db, db_name) == 0 &&
|
||||
strcmp(table->table_name, table_name) == 0)
|
||||
break;
|
||||
}
|
||||
return table;
|
||||
}
|
||||
@ -717,8 +696,25 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
|
||||
|
||||
SYNOPSIS
|
||||
unique_table()
|
||||
table table which should be chaked
|
||||
table_list list of tables
|
||||
table table which should be chaked
|
||||
table_list list of tables
|
||||
|
||||
NOTE: to exclude derived tables from check we use following mechanism:
|
||||
a) during derived table processing set THD::derived_tables_processing
|
||||
b) JOIN::prepare set SELECT::exclude_from_table_unique_test if
|
||||
THD::derived_tables_processing set. (we can't use JOIN::execute
|
||||
because for PS we perform only JOIN::prepare, but we can't set this
|
||||
flag in JOIN::prepare if we are not sure that we are in derived table
|
||||
processing loop, because multi-update call fix_fields() for some its
|
||||
items (which mean JOIN::prepare for subqueries) before unique_table
|
||||
call to detect which tables should be locked for write).
|
||||
c) unique_table skip all tables which belong to SELECT with
|
||||
SELECT::exclude_from_table_unique_test set.
|
||||
Also SELECT::exclude_from_table_unique_test used to exclude from check
|
||||
tables of main SELECT of multi-delete and multi-update
|
||||
|
||||
TODO: when we will have table/view change detection we can do this check
|
||||
only once for PS/SP
|
||||
|
||||
RETURN
|
||||
found duplicate
|
||||
@ -758,11 +754,17 @@ TABLE_LIST* unique_table(TABLE_LIST *table, TABLE_LIST *table_list)
|
||||
for(;;)
|
||||
{
|
||||
if (!(res= find_table_in_global_list(table_list, d_name, t_name)) ||
|
||||
!res->table || res->table != table->table)
|
||||
(!res->table || res->table != table->table) &&
|
||||
(res->select_lex && !res->select_lex->exclude_from_table_unique_test))
|
||||
break;
|
||||
/* if we found entry of this table try again. */
|
||||
/*
|
||||
If we found entry of this table or or table of SELECT which already
|
||||
processed in derived table or top select of multi-update/multi-delete
|
||||
(exclude_from_table_unique_test).
|
||||
*/
|
||||
table_list= res->next_global;
|
||||
DBUG_PRINT("info", ("found same copy of table"));
|
||||
DBUG_PRINT("info",
|
||||
("found same copy of table or table which we should skip"));
|
||||
}
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
Reference in New Issue
Block a user