diff options
author | Alexey Botchkov <holyfoot@askmonty.org> | 2011-11-12 19:56:29 +0400 |
---|---|---|
committer | Alexey Botchkov <holyfoot@askmonty.org> | 2011-11-12 19:56:29 +0400 |
commit | 7c7269d3723a4044816b1f80424af0ff2bc56f3f (patch) | |
tree | 877f14dd7dcbe276aa07dc26cbe63541bc893aff /sql/sql_derived.cc | |
parent | 45bb808c7ec0a77bb51038ff370753f8ed5c7ddf (diff) | |
parent | db0aed93482759844af7b39c9bf6e7fe141f28f6 (diff) | |
download | mariadb-git-7c7269d3723a4044816b1f80424af0ff2bc56f3f.tar.gz |
merging.
Diffstat (limited to 'sql/sql_derived.cc')
-rw-r--r-- | sql/sql_derived.cc | 140 |
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; |