summaryrefslogtreecommitdiff
path: root/sql/sql_derived.cc
diff options
context:
space:
mode:
authorAlexey Botchkov <holyfoot@askmonty.org>2011-11-12 19:56:29 +0400
committerAlexey Botchkov <holyfoot@askmonty.org>2011-11-12 19:56:29 +0400
commit7c7269d3723a4044816b1f80424af0ff2bc56f3f (patch)
tree877f14dd7dcbe276aa07dc26cbe63541bc893aff /sql/sql_derived.cc
parent45bb808c7ec0a77bb51038ff370753f8ed5c7ddf (diff)
parentdb0aed93482759844af7b39c9bf6e7fe141f28f6 (diff)
downloadmariadb-git-7c7269d3723a4044816b1f80424af0ff2bc56f3f.tar.gz
merging.
Diffstat (limited to 'sql/sql_derived.cc')
-rw-r--r--sql/sql_derived.cc140
1 files changed, 65 insertions, 75 deletions
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 9bfa49c5f2d..e012c161945 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -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);
}
@@ -343,43 +346,52 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived)
if (derived->merged)
return FALSE;
+ if (thd->lex->sql_command == SQLCOM_UPDATE_MULTI ||
+ thd->lex->sql_command == SQLCOM_DELETE_MULTI)
+ thd->save_prep_leaf_list= TRUE;
+
arena= thd->activate_stmt_arena_if_needed(&backup); // For easier test
derived->merged= TRUE;
- /*
- 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
- and small subqueries, and the bigger one can't be merged it wouldn't
- block the smaller one.
- */
- if (parent_lex->get_free_table_map(&map, &tablenr))
- {
- /* There is no enough table bits, fall back to materialization. */
- derived->change_refs_to_fields();
- derived->set_materialized_derived();
- goto exit_merge;
- }
- if (dt_select->leaf_tables.elements + tablenr > MAX_TABLES)
+ if (!derived->merged_for_insert ||
+ (derived->is_multitable() &&
+ (thd->lex->sql_command == SQLCOM_UPDATE_MULTI ||
+ thd->lex->sql_command == SQLCOM_DELETE_MULTI)))
{
- /* There is no enough table bits, fall back to materialization. */
- derived->change_refs_to_fields();
- derived->set_materialized_derived();
- goto exit_merge;
- }
+ /*
+ 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
+ and small subqueries, and the bigger one can't be merged it wouldn't
+ block the smaller one.
+ */
+ if (parent_lex->get_free_table_map(&map, &tablenr))
+ {
+ /* There is no enough table bits, fall back to materialization. */
+ derived->change_refs_to_fields();
+ derived->set_materialized_derived();
+ goto exit_merge;
+ }
+
+ if (dt_select->leaf_tables.elements + tablenr > MAX_TABLES)
+ {
+ /* There is no enough table bits, fall back to materialization. */
+ derived->change_refs_to_fields();
+ derived->set_materialized_derived();
+ goto exit_merge;
+ }
- if (dt_select->options & OPTION_SCHEMA_TABLE)
- parent_lex->options |= OPTION_SCHEMA_TABLE;
+ if (dt_select->options & OPTION_SCHEMA_TABLE)
+ parent_lex->options |= OPTION_SCHEMA_TABLE;
- parent_lex->cond_count+= dt_select->cond_count;
+ parent_lex->cond_count+= dt_select->cond_count;
- if (!derived->get_unit()->prepared)
- {
- dt_select->leaf_tables.empty();
- make_leaves_list(dt_select->leaf_tables, derived, TRUE, 0);
- }
+ if (!derived->get_unit()->prepared)
+ {
+ dt_select->leaf_tables.empty();
+ 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;
@@ -387,7 +399,7 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived)
}
/* Merge derived table's subquery in the parent select. */
- if (parent_lex->merge_subquery(derived, dt_select, tablenr, map))
+ if (parent_lex->merge_subquery(thd, derived, dt_select, tablenr, map))
{
res= TRUE;
goto exit_merge;
@@ -463,52 +475,21 @@ exit_merge:
bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived)
{
- SELECT_LEX *dt_select= derived->get_single_select();
-
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())
- {
- bool res= derived->create_field_translation(thd);
- return res;
- }
+ if (derived->is_materialized_derived())
+ return mysql_derived_prepare(thd, lex, derived);
if (!derived->is_multitable())
{
- TABLE_LIST *tl=((TABLE_LIST*)dt_select->table_list.first);
- TABLE *table= tl->table;
- /* preserve old map & tablenr. */
- if (!derived->merged_for_insert && derived->table)
- table->set_table_map(derived->table->map, derived->table->tablenr);
-
- derived->table= table;
- derived->schema_table=
- ((TABLE_LIST*)dt_select->table_list.first)->schema_table;
- if (!derived->merged)
+ if (!derived->updatable)
+ return derived->create_field_translation(thd);
+ if (derived->merge_underlying_list)
{
- Query_arena *arena, backup;
- arena= thd->activate_stmt_arena_if_needed(&backup); // For easier test
- derived->select_lex->leaf_tables.push_back(tl);
- derived->nested_join= (NESTED_JOIN*) thd->calloc(sizeof(NESTED_JOIN));
- if (derived->nested_join)
- {
- derived->wrap_into_nested_join(tl->select_lex->top_join_list);
- derived->get_unit()->exclude_level();
- }
- if (arena)
- thd->restore_active_arena(arena, &backup);
- derived->merged= TRUE;
- if (!derived->nested_join)
- return TRUE;
- }
- }
- else
- {
- if (!derived->merged_for_insert && mysql_derived_merge(thd, lex, derived))
- return TRUE;
- }
- derived->merged_for_insert= TRUE;
-
+ derived->table= derived->merge_underlying_list->table;
+ derived->schema_table= derived->merge_underlying_list->schema_table;
+ derived->merged_for_insert= TRUE;
+ }
+ }
return FALSE;
}
@@ -609,7 +590,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;
@@ -659,13 +644,18 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
!unit->union_distinct->next_select() (i.e. it is union and last distinct
SELECT is last SELECT of UNION).
*/
+ thd->create_tmp_table_for_derived= TRUE;
if (derived->derived_result->create_result_table(thd, &unit->types, FALSE,
(first_select->options |
thd->options |
TMP_TABLE_ALL_COLUMNS),
derived->alias,
FALSE, FALSE))
+ {
+ thd->create_tmp_table_for_derived= FALSE;
goto exit;
+ }
+ thd->create_tmp_table_for_derived= FALSE;
derived->table= derived->derived_result->table;
if (derived->is_derived() && derived->is_merged_derived())
@@ -747,7 +737,7 @@ bool mysql_derived_optimize(THD *thd, LEX *lex, TABLE_LIST *derived)
bool res= FALSE;
- if (unit->optimized && !unit->uncacheable && !unit->describe)
+ if (unit->optimized)
return FALSE;
lex->current_select= first_select;