mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 12:32:27 +01:00
Merge with the latest 5.3 code.
This commit is contained in:
commit
6e5413853e
11 changed files with 179 additions and 57 deletions
|
@ -590,6 +590,31 @@ f1 f1
|
|||
DROP VIEW v1;
|
||||
DROP TABLE t1,t2;
|
||||
#
|
||||
# LP bug #794890: abort failure on multi-update with view
|
||||
#
|
||||
CREATE TABLE t1 (a int);
|
||||
INSERT INTO t1 VALUES (20), (7);
|
||||
CREATE TABLE t2 (a int);
|
||||
INSERT INTO t2 VALUES (7), (9), (7);
|
||||
CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT a FROM t1;
|
||||
CREATE VIEW v2 AS SELECT t2.a FROM t2, v1 WHERE t2.a=t2.a;
|
||||
UPDATE v2 SET a = 2;
|
||||
SELECT * FROM t2;
|
||||
a
|
||||
2
|
||||
2
|
||||
2
|
||||
UPDATE t1,v2 SET t1.a = 3;
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
3
|
||||
3
|
||||
DELETE t1 FROM t1,v2;
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
DROP VIEW v1,v2;
|
||||
DROP TABLE t1,t2;
|
||||
#
|
||||
# LP bug #802023: MIN/MAX optimization
|
||||
# for mergeable derived tables and views
|
||||
#
|
||||
|
|
|
@ -236,6 +236,30 @@ SELECT * FROM v1 JOIN t2 ON v1.f1 = t2.f1;
|
|||
DROP VIEW v1;
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
--echo #
|
||||
--echo # LP bug #794890: abort failure on multi-update with view
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a int);
|
||||
INSERT INTO t1 VALUES (20), (7);
|
||||
CREATE TABLE t2 (a int);
|
||||
INSERT INTO t2 VALUES (7), (9), (7);
|
||||
|
||||
CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT a FROM t1;
|
||||
|
||||
CREATE VIEW v2 AS SELECT t2.a FROM t2, v1 WHERE t2.a=t2.a;
|
||||
UPDATE v2 SET a = 2;
|
||||
SELECT * FROM t2;
|
||||
|
||||
UPDATE t1,v2 SET t1.a = 3;
|
||||
SELECT * FROM t1;
|
||||
|
||||
DELETE t1 FROM t1,v2;
|
||||
SELECT * FROM t1;
|
||||
|
||||
DROP VIEW v1,v2;
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
--echo #
|
||||
--echo # LP bug #802023: MIN/MAX optimization
|
||||
--echo # for mergeable derived tables and views
|
||||
|
|
|
@ -7794,8 +7794,17 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
|
|||
if (select_lex->first_cond_optimization)
|
||||
{
|
||||
leaves.empty();
|
||||
select_lex->leaf_tables_exec.empty();
|
||||
if (!select_lex->is_prep_leaf_list_saved)
|
||||
{
|
||||
make_leaves_list(leaves, tables, full_table_list, first_select_table);
|
||||
select_lex->leaf_tables_exec.empty();
|
||||
}
|
||||
else
|
||||
{
|
||||
List_iterator_fast <TABLE_LIST> ti(select_lex->leaf_tables_prep);
|
||||
while ((table_list= ti++))
|
||||
leaves.push_back(table_list);
|
||||
}
|
||||
|
||||
while ((table_list= ti++))
|
||||
{
|
||||
|
|
|
@ -817,6 +817,7 @@ THD::THD()
|
|||
memset(&invoker_host, 0, sizeof(invoker_host));
|
||||
prepare_derived_at_open= FALSE;
|
||||
create_tmp_table_for_derived= FALSE;
|
||||
save_prep_leaf_list= FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1601,6 +1601,8 @@ public:
|
|||
*/
|
||||
bool create_tmp_table_for_derived;
|
||||
|
||||
bool save_prep_leaf_list;
|
||||
|
||||
#ifndef MYSQL_CLIENT
|
||||
int binlog_setup_trx_data();
|
||||
|
||||
|
|
|
@ -61,8 +61,9 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
|||
if (open_and_lock_tables(thd, table_list))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
if (mysql_handle_list_of_derived(thd->lex, table_list, DT_MERGE_FOR_INSERT) ||
|
||||
mysql_handle_list_of_derived(thd->lex, table_list, DT_PREPARE))
|
||||
if (mysql_handle_list_of_derived(thd->lex, table_list, DT_MERGE_FOR_INSERT))
|
||||
DBUG_RETURN(TRUE);
|
||||
if (mysql_handle_list_of_derived(thd->lex, table_list, DT_PREPARE))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
if (!table_list->updatable)
|
||||
|
@ -586,10 +587,11 @@ int mysql_multi_delete_prepare(THD *thd)
|
|||
TABLE_LIST *target_tbl;
|
||||
DBUG_ENTER("mysql_multi_delete_prepare");
|
||||
|
||||
TABLE_LIST *tables= lex->query_tables;
|
||||
if (mysql_handle_derived(lex, DT_INIT) ||
|
||||
mysql_handle_list_of_derived(lex, tables, DT_MERGE_FOR_INSERT) ||
|
||||
mysql_handle_list_of_derived(lex, tables, DT_PREPARE))
|
||||
if (mysql_handle_derived(lex, DT_INIT))
|
||||
DBUG_RETURN(TRUE);
|
||||
if (mysql_handle_derived(lex, DT_MERGE_FOR_INSERT))
|
||||
DBUG_RETURN(TRUE);
|
||||
if (mysql_handle_derived(lex, DT_PREPARE))
|
||||
DBUG_RETURN(TRUE);
|
||||
/*
|
||||
setup_tables() need for VIEWs. JOIN::prepare() will not do it second
|
||||
|
@ -616,7 +618,8 @@ int mysql_multi_delete_prepare(THD *thd)
|
|||
target_tbl= target_tbl->next_local)
|
||||
{
|
||||
|
||||
if (!(target_tbl->table= target_tbl->correspondent_table->table))
|
||||
target_tbl->table= target_tbl->correspondent_table->table;
|
||||
if (target_tbl->correspondent_table->is_multitable())
|
||||
{
|
||||
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
|
||||
target_tbl->correspondent_table->view_db.str,
|
||||
|
@ -651,6 +654,10 @@ int mysql_multi_delete_prepare(THD *thd)
|
|||
with further calls to unique_table
|
||||
*/
|
||||
lex->select_lex.exclude_from_table_unique_test= FALSE;
|
||||
|
||||
if (lex->select_lex.save_prep_leaf_tables(thd))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
|
|
|
@ -85,15 +85,18 @@ mysql_handle_derived(LEX *lex, uint phases)
|
|||
cursor && !res;
|
||||
cursor= cursor->next_local)
|
||||
{
|
||||
if (!cursor->is_view_or_derived() && phases == DT_MERGE_FOR_INSERT)
|
||||
continue;
|
||||
uint8 allowed_phases= (cursor->is_merged_derived() ? DT_PHASES_MERGE :
|
||||
DT_PHASES_MATERIALIZE);
|
||||
DT_PHASES_MATERIALIZE | DT_MERGE_FOR_INSERT);
|
||||
/*
|
||||
Skip derived tables to which the phase isn't applicable.
|
||||
TODO: mark derived at the parse time, later set it's type
|
||||
(merged or materialized)
|
||||
*/
|
||||
if ((phase_flag != DT_PREPARE && !(allowed_phases & phase_flag)) ||
|
||||
(cursor->merged_for_insert && phase_flag != DT_REINIT))
|
||||
(cursor->merged_for_insert && phase_flag != DT_REINIT &&
|
||||
phase_flag != DT_PREPARE))
|
||||
continue;
|
||||
res= (*processors[phase])(lex->thd, lex, cursor);
|
||||
}
|
||||
|
@ -345,6 +348,9 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived)
|
|||
|
||||
arena= thd->activate_stmt_arena_if_needed(&backup); // For easier test
|
||||
derived->merged= TRUE;
|
||||
|
||||
if (!derived->merged_for_insert)
|
||||
{
|
||||
/*
|
||||
Check whether there is enough free bits in table map to merge subquery.
|
||||
If not - materialize it. This check isn't cached so when there is a big
|
||||
|
@ -378,8 +384,7 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived)
|
|||
make_leaves_list(dt_select->leaf_tables, derived, TRUE, 0);
|
||||
}
|
||||
|
||||
if (!derived->merged_for_insert)
|
||||
{ derived->nested_join= (NESTED_JOIN*) thd->calloc(sizeof(NESTED_JOIN));
|
||||
derived->nested_join= (NESTED_JOIN*) thd->calloc(sizeof(NESTED_JOIN));
|
||||
if (!derived->nested_join)
|
||||
{
|
||||
res= TRUE;
|
||||
|
@ -467,14 +472,16 @@ bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived)
|
|||
|
||||
if (derived->merged_for_insert)
|
||||
return FALSE;
|
||||
/* It's a target view for an INSERT, create field translation only. */
|
||||
if (!derived->updatable || derived->is_materialized_derived())
|
||||
if (derived->is_materialized_derived())
|
||||
{
|
||||
bool res= derived->create_field_translation(thd);
|
||||
bool res= mysql_derived_prepare(thd, lex, derived);
|
||||
derived->select_lex->leaf_tables.push_back(derived);
|
||||
return res;
|
||||
}
|
||||
if (!derived->is_multitable())
|
||||
{
|
||||
if (!derived->updatable)
|
||||
return derived->create_field_translation(thd);
|
||||
TABLE_LIST *tl=((TABLE_LIST*)dt_select->table_list.first);
|
||||
TABLE *table= tl->table;
|
||||
/* preserve old map & tablenr. */
|
||||
|
@ -504,6 +511,9 @@ bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (thd->lex->sql_command == SQLCOM_UPDATE_MULTI ||
|
||||
thd->lex->sql_command == SQLCOM_DELETE_MULTI)
|
||||
thd->save_prep_leaf_list= TRUE;
|
||||
if (!derived->merged_for_insert && mysql_derived_merge(thd, lex, derived))
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -609,7 +619,11 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
|
|||
bool res= FALSE;
|
||||
|
||||
// Skip already prepared views/DT
|
||||
if (!unit || unit->prepared || derived->merged_for_insert)
|
||||
if (!unit || unit->prepared ||
|
||||
(derived->merged_for_insert &&
|
||||
!(derived->is_multitable() &&
|
||||
(thd->lex->sql_command == SQLCOM_UPDATE_MULTI ||
|
||||
thd->lex->sql_command == SQLCOM_DELETE_MULTI))))
|
||||
DBUG_RETURN(FALSE);
|
||||
|
||||
Query_arena *arena= thd->stmt_arena, backup;
|
||||
|
|
|
@ -1604,6 +1604,7 @@ void st_select_lex::init_query()
|
|||
top_join_list.empty();
|
||||
join_list= &top_join_list;
|
||||
embedding= 0;
|
||||
leaf_tables_prep.empty();
|
||||
leaf_tables.empty();
|
||||
item_list.empty();
|
||||
join= 0;
|
||||
|
@ -1672,6 +1673,7 @@ void st_select_lex::init_select()
|
|||
cond_value= having_value= Item::COND_UNDEF;
|
||||
inner_refs_list.empty();
|
||||
full_group_by_flag= 0;
|
||||
is_prep_leaf_list_saved= FALSE;
|
||||
insert_tables= 0;
|
||||
merged_into= 0;
|
||||
}
|
||||
|
@ -3624,6 +3626,7 @@ void SELECT_LEX::mark_const_derived(bool empty)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
bool st_select_lex::save_leaf_tables(THD *thd)
|
||||
{
|
||||
Query_arena *arena= thd->stmt_arena, backup;
|
||||
|
@ -3648,6 +3651,33 @@ bool st_select_lex::save_leaf_tables(THD *thd)
|
|||
}
|
||||
|
||||
|
||||
bool st_select_lex::save_prep_leaf_tables(THD *thd)
|
||||
{
|
||||
if (!thd->save_prep_leaf_list)
|
||||
return 0;
|
||||
|
||||
Query_arena *arena= thd->stmt_arena, backup;
|
||||
if (arena->is_conventional())
|
||||
arena= 0;
|
||||
else
|
||||
thd->set_n_backup_active_arena(arena, &backup);
|
||||
|
||||
List_iterator_fast<TABLE_LIST> li(leaf_tables);
|
||||
TABLE_LIST *table;
|
||||
while ((table= li++))
|
||||
{
|
||||
if (leaf_tables_prep.push_back(table))
|
||||
return 1;
|
||||
}
|
||||
thd->lex->select_lex.is_prep_leaf_list_saved= TRUE;
|
||||
thd->save_prep_leaf_list= FALSE;
|
||||
if (arena)
|
||||
thd->restore_active_arena(arena, &backup);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
A routine used by the parser to decide whether we are specifying a full
|
||||
partitioning or if only partitions to add or to split.
|
||||
|
|
|
@ -639,6 +639,8 @@ public:
|
|||
*/
|
||||
List<TABLE_LIST> leaf_tables;
|
||||
List<TABLE_LIST> leaf_tables_exec;
|
||||
List<TABLE_LIST> leaf_tables_prep;
|
||||
bool is_prep_leaf_list_saved;
|
||||
uint insert_tables;
|
||||
st_select_lex *merged_into; /* select which this select is merged into */
|
||||
/* (not 0 only for views/derived tables) */
|
||||
|
@ -899,6 +901,7 @@ public:
|
|||
void mark_const_derived(bool empty);
|
||||
|
||||
bool save_leaf_tables(THD *thd);
|
||||
bool save_prep_leaf_tables(THD *thd);
|
||||
|
||||
private:
|
||||
/* current index hint kind. used in filling up index_hints */
|
||||
|
|
|
@ -1269,8 +1269,9 @@ static int mysql_test_update(Prepared_statement *stmt,
|
|||
thd->fill_derived_tables() is false here for sure (because it is
|
||||
preparation of PS, so we even do not check it).
|
||||
*/
|
||||
if (table_list->handle_derived(thd->lex, DT_MERGE_FOR_INSERT) ||
|
||||
table_list->handle_derived(thd->lex, DT_PREPARE))
|
||||
if (table_list->handle_derived(thd->lex, DT_MERGE_FOR_INSERT))
|
||||
goto error;
|
||||
if (table_list->handle_derived(thd->lex, DT_PREPARE))
|
||||
goto error;
|
||||
|
||||
if (!table_list->updatable)
|
||||
|
@ -1340,9 +1341,11 @@ static bool mysql_test_delete(Prepared_statement *stmt,
|
|||
open_tables(thd, &table_list, &table_count, 0))
|
||||
goto error;
|
||||
|
||||
if (mysql_handle_derived(thd->lex, DT_INIT) ||
|
||||
mysql_handle_list_of_derived(thd->lex, table_list, DT_MERGE_FOR_INSERT) ||
|
||||
mysql_handle_list_of_derived(thd->lex, table_list, DT_PREPARE))
|
||||
if (mysql_handle_derived(thd->lex, DT_INIT))
|
||||
goto error;
|
||||
if (mysql_handle_derived(thd->lex, DT_MERGE_FOR_INSERT))
|
||||
goto error;
|
||||
if (mysql_handle_derived(thd->lex, DT_PREPARE))
|
||||
goto error;
|
||||
|
||||
if (!table_list->updatable)
|
||||
|
|
|
@ -1038,8 +1038,9 @@ reopen_tables:
|
|||
call in setup_tables()).
|
||||
*/
|
||||
//We need to merge for insert prior to prepare.
|
||||
if (mysql_handle_list_of_derived(lex, table_list, DT_MERGE_FOR_INSERT))
|
||||
DBUG_RETURN(1);
|
||||
if (mysql_handle_derived(lex, DT_MERGE_FOR_INSERT))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
if (mysql_handle_derived(lex, DT_PREPARE))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
|
@ -1238,6 +1239,9 @@ reopen_tables:
|
|||
*/
|
||||
lex->select_lex.exclude_from_table_unique_test= FALSE;
|
||||
|
||||
if (lex->select_lex.save_prep_leaf_tables(thd))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
DBUG_RETURN (FALSE);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue