mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 20:42:30 +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 VIEW v1;
|
||||||
DROP TABLE t1,t2;
|
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
|
# LP bug #802023: MIN/MAX optimization
|
||||||
# for mergeable derived tables and views
|
# for mergeable derived tables and views
|
||||||
#
|
#
|
||||||
|
|
|
@ -236,6 +236,30 @@ SELECT * FROM v1 JOIN t2 ON v1.f1 = t2.f1;
|
||||||
DROP VIEW v1;
|
DROP VIEW v1;
|
||||||
DROP TABLE t1,t2;
|
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 #
|
||||||
--echo # LP bug #802023: MIN/MAX optimization
|
--echo # LP bug #802023: MIN/MAX optimization
|
||||||
--echo # for mergeable derived tables and views
|
--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)
|
if (select_lex->first_cond_optimization)
|
||||||
{
|
{
|
||||||
leaves.empty();
|
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);
|
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++))
|
while ((table_list= ti++))
|
||||||
{
|
{
|
||||||
|
|
|
@ -817,6 +817,7 @@ THD::THD()
|
||||||
memset(&invoker_host, 0, sizeof(invoker_host));
|
memset(&invoker_host, 0, sizeof(invoker_host));
|
||||||
prepare_derived_at_open= FALSE;
|
prepare_derived_at_open= FALSE;
|
||||||
create_tmp_table_for_derived= FALSE;
|
create_tmp_table_for_derived= FALSE;
|
||||||
|
save_prep_leaf_list= FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1601,6 +1601,8 @@ public:
|
||||||
*/
|
*/
|
||||||
bool create_tmp_table_for_derived;
|
bool create_tmp_table_for_derived;
|
||||||
|
|
||||||
|
bool save_prep_leaf_list;
|
||||||
|
|
||||||
#ifndef MYSQL_CLIENT
|
#ifndef MYSQL_CLIENT
|
||||||
int binlog_setup_trx_data();
|
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))
|
if (open_and_lock_tables(thd, table_list))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
if (mysql_handle_list_of_derived(thd->lex, table_list, DT_MERGE_FOR_INSERT) ||
|
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))
|
DBUG_RETURN(TRUE);
|
||||||
|
if (mysql_handle_list_of_derived(thd->lex, table_list, DT_PREPARE))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
if (!table_list->updatable)
|
if (!table_list->updatable)
|
||||||
|
@ -586,10 +587,11 @@ int mysql_multi_delete_prepare(THD *thd)
|
||||||
TABLE_LIST *target_tbl;
|
TABLE_LIST *target_tbl;
|
||||||
DBUG_ENTER("mysql_multi_delete_prepare");
|
DBUG_ENTER("mysql_multi_delete_prepare");
|
||||||
|
|
||||||
TABLE_LIST *tables= lex->query_tables;
|
if (mysql_handle_derived(lex, DT_INIT))
|
||||||
if (mysql_handle_derived(lex, DT_INIT) ||
|
DBUG_RETURN(TRUE);
|
||||||
mysql_handle_list_of_derived(lex, tables, DT_MERGE_FOR_INSERT) ||
|
if (mysql_handle_derived(lex, DT_MERGE_FOR_INSERT))
|
||||||
mysql_handle_list_of_derived(lex, tables, DT_PREPARE))
|
DBUG_RETURN(TRUE);
|
||||||
|
if (mysql_handle_derived(lex, DT_PREPARE))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
/*
|
/*
|
||||||
setup_tables() need for VIEWs. JOIN::prepare() will not do it second
|
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)
|
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),
|
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
|
||||||
target_tbl->correspondent_table->view_db.str,
|
target_tbl->correspondent_table->view_db.str,
|
||||||
|
@ -651,6 +654,10 @@ int mysql_multi_delete_prepare(THD *thd)
|
||||||
with further calls to unique_table
|
with further calls to unique_table
|
||||||
*/
|
*/
|
||||||
lex->select_lex.exclude_from_table_unique_test= FALSE;
|
lex->select_lex.exclude_from_table_unique_test= FALSE;
|
||||||
|
|
||||||
|
if (lex->select_lex.save_prep_leaf_tables(thd))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,15 +85,18 @@ mysql_handle_derived(LEX *lex, uint phases)
|
||||||
cursor && !res;
|
cursor && !res;
|
||||||
cursor= cursor->next_local)
|
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 :
|
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.
|
Skip derived tables to which the phase isn't applicable.
|
||||||
TODO: mark derived at the parse time, later set it's type
|
TODO: mark derived at the parse time, later set it's type
|
||||||
(merged or materialized)
|
(merged or materialized)
|
||||||
*/
|
*/
|
||||||
if ((phase_flag != DT_PREPARE && !(allowed_phases & phase_flag)) ||
|
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;
|
continue;
|
||||||
res= (*processors[phase])(lex->thd, lex, cursor);
|
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
|
arena= thd->activate_stmt_arena_if_needed(&backup); // For easier test
|
||||||
derived->merged= TRUE;
|
derived->merged= TRUE;
|
||||||
|
|
||||||
|
if (!derived->merged_for_insert)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
Check whether there is enough free bits in table map to merge subquery.
|
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
|
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);
|
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)
|
if (!derived->nested_join)
|
||||||
{
|
{
|
||||||
res= TRUE;
|
res= TRUE;
|
||||||
|
@ -467,14 +472,16 @@ bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived)
|
||||||
|
|
||||||
if (derived->merged_for_insert)
|
if (derived->merged_for_insert)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
/* It's a target view for an INSERT, create field translation only. */
|
if (derived->is_materialized_derived())
|
||||||
if (!derived->updatable || 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;
|
return res;
|
||||||
}
|
}
|
||||||
if (!derived->is_multitable())
|
if (!derived->is_multitable())
|
||||||
{
|
{
|
||||||
|
if (!derived->updatable)
|
||||||
|
return derived->create_field_translation(thd);
|
||||||
TABLE_LIST *tl=((TABLE_LIST*)dt_select->table_list.first);
|
TABLE_LIST *tl=((TABLE_LIST*)dt_select->table_list.first);
|
||||||
TABLE *table= tl->table;
|
TABLE *table= tl->table;
|
||||||
/* preserve old map & tablenr. */
|
/* preserve old map & tablenr. */
|
||||||
|
@ -504,6 +511,9 @@ bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived)
|
||||||
}
|
}
|
||||||
else
|
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))
|
if (!derived->merged_for_insert && mysql_derived_merge(thd, lex, derived))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -609,7 +619,11 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
|
||||||
bool res= FALSE;
|
bool res= FALSE;
|
||||||
|
|
||||||
// Skip already prepared views/DT
|
// 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);
|
DBUG_RETURN(FALSE);
|
||||||
|
|
||||||
Query_arena *arena= thd->stmt_arena, backup;
|
Query_arena *arena= thd->stmt_arena, backup;
|
||||||
|
|
|
@ -1604,6 +1604,7 @@ void st_select_lex::init_query()
|
||||||
top_join_list.empty();
|
top_join_list.empty();
|
||||||
join_list= &top_join_list;
|
join_list= &top_join_list;
|
||||||
embedding= 0;
|
embedding= 0;
|
||||||
|
leaf_tables_prep.empty();
|
||||||
leaf_tables.empty();
|
leaf_tables.empty();
|
||||||
item_list.empty();
|
item_list.empty();
|
||||||
join= 0;
|
join= 0;
|
||||||
|
@ -1672,6 +1673,7 @@ void st_select_lex::init_select()
|
||||||
cond_value= having_value= Item::COND_UNDEF;
|
cond_value= having_value= Item::COND_UNDEF;
|
||||||
inner_refs_list.empty();
|
inner_refs_list.empty();
|
||||||
full_group_by_flag= 0;
|
full_group_by_flag= 0;
|
||||||
|
is_prep_leaf_list_saved= FALSE;
|
||||||
insert_tables= 0;
|
insert_tables= 0;
|
||||||
merged_into= 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)
|
bool st_select_lex::save_leaf_tables(THD *thd)
|
||||||
{
|
{
|
||||||
Query_arena *arena= thd->stmt_arena, backup;
|
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
|
A routine used by the parser to decide whether we are specifying a full
|
||||||
partitioning or if only partitions to add or to split.
|
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;
|
||||||
List<TABLE_LIST> leaf_tables_exec;
|
List<TABLE_LIST> leaf_tables_exec;
|
||||||
|
List<TABLE_LIST> leaf_tables_prep;
|
||||||
|
bool is_prep_leaf_list_saved;
|
||||||
uint insert_tables;
|
uint insert_tables;
|
||||||
st_select_lex *merged_into; /* select which this select is merged into */
|
st_select_lex *merged_into; /* select which this select is merged into */
|
||||||
/* (not 0 only for views/derived tables) */
|
/* (not 0 only for views/derived tables) */
|
||||||
|
@ -899,6 +901,7 @@ public:
|
||||||
void mark_const_derived(bool empty);
|
void mark_const_derived(bool empty);
|
||||||
|
|
||||||
bool save_leaf_tables(THD *thd);
|
bool save_leaf_tables(THD *thd);
|
||||||
|
bool save_prep_leaf_tables(THD *thd);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/* current index hint kind. used in filling up index_hints */
|
/* 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
|
thd->fill_derived_tables() is false here for sure (because it is
|
||||||
preparation of PS, so we even do not check it).
|
preparation of PS, so we even do not check it).
|
||||||
*/
|
*/
|
||||||
if (table_list->handle_derived(thd->lex, DT_MERGE_FOR_INSERT) ||
|
if (table_list->handle_derived(thd->lex, DT_MERGE_FOR_INSERT))
|
||||||
table_list->handle_derived(thd->lex, DT_PREPARE))
|
goto error;
|
||||||
|
if (table_list->handle_derived(thd->lex, DT_PREPARE))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (!table_list->updatable)
|
if (!table_list->updatable)
|
||||||
|
@ -1340,9 +1341,11 @@ static bool mysql_test_delete(Prepared_statement *stmt,
|
||||||
open_tables(thd, &table_list, &table_count, 0))
|
open_tables(thd, &table_list, &table_count, 0))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (mysql_handle_derived(thd->lex, DT_INIT) ||
|
if (mysql_handle_derived(thd->lex, DT_INIT))
|
||||||
mysql_handle_list_of_derived(thd->lex, table_list, DT_MERGE_FOR_INSERT) ||
|
goto error;
|
||||||
mysql_handle_list_of_derived(thd->lex, table_list, DT_PREPARE))
|
if (mysql_handle_derived(thd->lex, DT_MERGE_FOR_INSERT))
|
||||||
|
goto error;
|
||||||
|
if (mysql_handle_derived(thd->lex, DT_PREPARE))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (!table_list->updatable)
|
if (!table_list->updatable)
|
||||||
|
|
|
@ -1038,8 +1038,9 @@ reopen_tables:
|
||||||
call in setup_tables()).
|
call in setup_tables()).
|
||||||
*/
|
*/
|
||||||
//We need to merge for insert prior to prepare.
|
//We need to merge for insert prior to prepare.
|
||||||
if (mysql_handle_list_of_derived(lex, table_list, DT_MERGE_FOR_INSERT))
|
if (mysql_handle_derived(lex, DT_MERGE_FOR_INSERT))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
if (mysql_handle_derived(lex, DT_PREPARE))
|
if (mysql_handle_derived(lex, DT_PREPARE))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
|
@ -1238,6 +1239,9 @@ reopen_tables:
|
||||||
*/
|
*/
|
||||||
lex->select_lex.exclude_from_table_unique_test= FALSE;
|
lex->select_lex.exclude_from_table_unique_test= FALSE;
|
||||||
|
|
||||||
|
if (lex->select_lex.save_prep_leaf_tables(thd))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
DBUG_RETURN (FALSE);
|
DBUG_RETURN (FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue