summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/item_subselect.cc10
-rw-r--r--sql/item_subselect.h113
-rw-r--r--sql/opt_subselect.cc11
-rw-r--r--sql/sql_join_cache.cc12
-rw-r--r--sql/sql_select.cc84
5 files changed, 98 insertions, 132 deletions
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 324a331c32b..283a96d6149 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -33,11 +33,11 @@
Item_subselect::Item_subselect():
- Item_result_field(), value_assigned(0), thd(0), substitution(0),
- expr_cache(0), engine(0), old_engine(0), used_tables_cache(0),
- have_to_be_excluded(0), const_item_cache(1), inside_first_fix_fields(0),
- done_first_fix_fields(FALSE), eliminated(FALSE), engine_changed(0),
- changed(0), is_correlated(FALSE)
+ Item_result_field(), value_assigned(0), thd(0), old_engine(0),
+ used_tables_cache(0), have_to_be_excluded(0), const_item_cache(1),
+ inside_first_fix_fields(0), done_first_fix_fields(FALSE),
+ substitution(0), expr_cache(0), engine(0), eliminated(FALSE),
+ engine_changed(0), changed(0), is_correlated(FALSE)
{
with_subselect= 1;
reset();
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 39780708e60..b3b4c717f38 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -36,6 +36,22 @@ class Item_subselect :public Item_result_field
protected:
/* thread handler, will be assigned in fix_fields only */
THD *thd;
+ /* old engine if engine was changed */
+ subselect_engine *old_engine;
+ /* cache of used external tables */
+ table_map used_tables_cache;
+ /* allowed number of columns (1 for single value subqueries) */
+ uint max_columns;
+ /* where subquery is placed */
+ enum_parsing_place parsing_place;
+ /* work with 'substitution' */
+ bool have_to_be_excluded;
+ /* cache of constant state */
+ bool const_item_cache;
+
+ bool inside_first_fix_fields;
+ bool done_first_fix_fields;
+public:
/*
Used inside Item_subselect::fix_fields() according to this scenario:
> Item_subselect::fix_fields
@@ -49,30 +65,12 @@ protected:
substitution= NULL;
< Item_subselect::fix_fields
*/
-public:
Item *substitution;
/* unit of subquery */
st_select_lex_unit *unit;
Item *expr_cache;
/* engine that perform execution of subselect (single select or union) */
subselect_engine *engine;
-protected:
- /* old engine if engine was changed */
- subselect_engine *old_engine;
- /* cache of used external tables */
- table_map used_tables_cache;
- /* allowed number of columns (1 for single value subqueries) */
- uint max_columns;
- /* where subquery is placed */
- enum_parsing_place parsing_place;
- /* work with 'substitution' */
- bool have_to_be_excluded;
- /* cache of constant state */
- bool const_item_cache;
-
- bool inside_first_fix_fields;
- bool done_first_fix_fields;
-public:
/* A reference from inside subquery predicate to somewhere outside of it */
class Ref_to_outside : public Sql_alloc
{
@@ -774,61 +772,26 @@ public:
of subselect_single_select_engine::[prepare | cols].
*/
subselect_single_select_engine *materialize_engine;
-protected:
- /* The engine used to compute the IN predicate. */
- subselect_engine *lookup_engine;
/*
QEP to execute the subquery and materialize its result into a
temporary table. Created during the first call to exec().
*/
-public:
JOIN *materialize_join;
-protected:
- /* Keyparts of the only non-NULL composite index in a rowid merge. */
- MY_BITMAP non_null_key_parts;
- /* Keyparts of the single column indexes with NULL, one keypart per index. */
- MY_BITMAP partial_match_key_parts;
- uint count_partial_match_columns;
- uint count_null_only_columns;
/*
A conjunction of all the equality condtions between all pairs of expressions
that are arguments of an IN predicate. We need these to post-filter some
IN results because index lookups sometimes match values that are actually
not equal to the search key in SQL terms.
- */
-public:
+ */
Item_cond_and *semi_join_conds;
-protected:
- /* Possible execution strategies that can be used to compute hash semi-join.*/
- enum exec_strategy {
- UNDEFINED,
- COMPLETE_MATCH, /* Use regular index lookups. */
- PARTIAL_MATCH, /* Use some partial matching strategy. */
- PARTIAL_MATCH_MERGE, /* Use partial matching through index merging. */
- PARTIAL_MATCH_SCAN, /* Use partial matching through table scan. */
- IMPOSSIBLE /* Subquery materialization is not applicable. */
- };
- /* The chosen execution strategy. Computed after materialization. */
- exec_strategy strategy;
-protected:
- exec_strategy get_strategy_using_schema();
- exec_strategy get_strategy_using_data();
- ulonglong rowid_merge_buff_size(bool has_non_null_key,
- bool has_covering_null_row,
- MY_BITMAP *partial_match_key_parts);
- void choose_partial_match_strategy(bool has_non_null_key,
- bool has_covering_null_row,
- MY_BITMAP *partial_match_key_parts);
- bool make_semi_join_conds();
- subselect_uniquesubquery_engine* make_unique_engine();
-public:
subselect_hash_sj_engine(THD *thd, Item_subselect *in_predicate,
subselect_single_select_engine *old_engine)
- :subselect_engine(thd, in_predicate, NULL), tmp_table(NULL),
- is_materialized(FALSE), materialize_engine(old_engine), lookup_engine(NULL),
- materialize_join(NULL), count_partial_match_columns(0),
- count_null_only_columns(0), semi_join_conds(NULL), strategy(UNDEFINED)
+ : subselect_engine(thd, in_predicate, NULL),
+ tmp_table(NULL), is_materialized(FALSE), materialize_engine(old_engine),
+ materialize_join(NULL), semi_join_conds(NULL), lookup_engine(NULL),
+ count_partial_match_columns(0), count_null_only_columns(0),
+ strategy(UNDEFINED)
{}
~subselect_hash_sj_engine();
@@ -856,6 +819,38 @@ public:
//=>base class
bool change_result(Item_subselect *si, select_result_interceptor *result);
bool no_tables();//=>base class
+
+protected:
+ /* The engine used to compute the IN predicate. */
+ subselect_engine *lookup_engine;
+ /* Keyparts of the only non-NULL composite index in a rowid merge. */
+ MY_BITMAP non_null_key_parts;
+ /* Keyparts of the single column indexes with NULL, one keypart per index. */
+ MY_BITMAP partial_match_key_parts;
+ uint count_partial_match_columns;
+ uint count_null_only_columns;
+ /* Possible execution strategies that can be used to compute hash semi-join.*/
+ enum exec_strategy {
+ UNDEFINED,
+ COMPLETE_MATCH, /* Use regular index lookups. */
+ PARTIAL_MATCH, /* Use some partial matching strategy. */
+ PARTIAL_MATCH_MERGE, /* Use partial matching through index merging. */
+ PARTIAL_MATCH_SCAN, /* Use partial matching through table scan. */
+ IMPOSSIBLE /* Subquery materialization is not applicable. */
+ };
+ /* The chosen execution strategy. Computed after materialization. */
+ exec_strategy strategy;
+ exec_strategy get_strategy_using_schema();
+ exec_strategy get_strategy_using_data();
+ ulonglong rowid_merge_buff_size(bool has_non_null_key,
+ bool has_covering_null_row,
+ MY_BITMAP *partial_match_key_parts);
+ void choose_partial_match_strategy(bool has_non_null_key,
+ bool has_covering_null_row,
+ MY_BITMAP *partial_match_key_parts);
+ bool make_semi_join_conds();
+ subselect_uniquesubquery_engine* make_unique_engine();
+
};
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index a4d5578f3cf..2601e54b865 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -826,15 +826,12 @@ void get_delayed_table_estimates(TABLE *table,
((subselect_hash_sj_engine*)item->engine);
JOIN *join= hash_sj_engine->materialize_join;
- double rows= 1;
- double read_time= 0.0;
+ double rows;
+ double read_time;
/* Calculate #rows and cost of join execution */
- for (uint i= join->const_tables; i < join->tables; i++)
- {
- rows *= join->best_positions[i].records_read;
- read_time += join->best_positions[i].read_time;
- }
+ get_partial_join_cost(join, join->tables, &read_time, &rows);
+
*out_rows= (ha_rows)rows;
*startup_cost= read_time;
/* Calculate cost of scanning the temptable */
diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc
index face1f9196e..af0c3c6709e 100644
--- a/sql/sql_join_cache.cc
+++ b/sql/sql_join_cache.cc
@@ -185,6 +185,7 @@ void JOIN_CACHE::calc_record_fields()
start_tab= tab;
if (start_tab->bush_children)
start_tab= start_tab->bush_children->start;
+ DBUG_ASSERT(!start_tab->bush_children);
tab= start_tab;
@@ -508,7 +509,6 @@ void JOIN_CACHE::create_key_arg_fields()
/* Now create local fields that are used to build ref for this key access */
copy= field_descr+flag_fields;
for (tab= start_tab; tab != join_tab; tab= next_linear_tab(join, tab, FALSE))
- //for (tab= join_tab-tables; tab; tab= get_next_table(tab))
{
length+= add_table_data_fields_to_join_cache(tab, &tab->table->tmp_set,
&data_field_count, &copy,
@@ -721,8 +721,11 @@ ulong JOIN_CACHE::get_min_join_buffer_size()
if (!min_buff_size)
{
size_t len= 0;
- for (JOIN_TAB *tab= start_tab; tab != join_tab; tab= next_linear_tab(join, tab, FALSE))
+ for (JOIN_TAB *tab= start_tab; tab != join_tab;
+ tab= next_linear_tab(join, tab, FALSE))
+ {
len+= tab->get_max_used_fieldlength();
+ }
len+= get_record_max_affix_length() + get_max_key_addon_space_per_record();
size_t min_sz= len*min_records;
size_t add_sz= 0;
@@ -774,8 +777,11 @@ ulong JOIN_CACHE::get_max_join_buffer_size(bool optimize_buff_size)
size_t max_sz;
size_t min_sz= get_min_join_buffer_size();
size_t len= 0;
- for (JOIN_TAB *tab= start_tab; tab != join_tab; tab= next_linear_tab(join, tab, FALSE))
+ for (JOIN_TAB *tab= start_tab; tab != join_tab;
+ tab= next_linear_tab(join, tab, FALSE))
+ {
len+= tab->get_used_fieldlength();
+ }
len+= get_record_max_affix_length();
avg_record_length= len;
len+= get_max_key_addon_space_per_record() + avg_aux_buffer_incr;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index d443fbc802d..b5d6cc1acb6 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1035,31 +1035,15 @@ JOIN::optimize()
Perform the optimization on fields evaluation mentioned above
for all on expressions.
*/
-
+ for (JOIN_TAB *tab= first_linear_tab(this, TRUE); tab;
+ tab= next_linear_tab(this, tab, TRUE))
{
- List_iterator<JOIN_TAB_RANGE> it(join_tab_ranges);
- JOIN_TAB_RANGE *jt_range;
- /* For upper level JOIN_TABs, we need to skip the const tables: */
- uint first_tab_offs= const_tables;
- while ((jt_range= it++))
+ if (*tab->on_expr_ref)
{
- for (JOIN_TAB *tab= jt_range->start + first_tab_offs;
- tab < jt_range->end; tab++)
- {
- if (*tab->on_expr_ref)
- {
- *tab->on_expr_ref= substitute_for_best_equal_field(*tab->on_expr_ref,
- tab->cond_equal,
- map2table);
- (*tab->on_expr_ref)->update_used_tables();
- }
- }
- /*
- Next jt_range will refer to SJM nest (and not the top-level range).
- Inside SJM nests, we dont have const tables, so should start from the
- first table:
- */
- first_tab_offs= 0;
+ *tab->on_expr_ref= substitute_for_best_equal_field(*tab->on_expr_ref,
+ tab->cond_equal,
+ map2table);
+ (*tab->on_expr_ref)->update_used_tables();
}
}
@@ -1067,47 +1051,34 @@ JOIN::optimize()
Perform the optimization on fields evaliation mentioned above
for all used ref items.
*/
- //for (JOIN_TAB *tab= join_tab + const_tables; tab < join_tab + tables; tab++)
- //{
+ for (JOIN_TAB *tab= first_linear_tab(this, TRUE); tab;
+ tab= next_linear_tab(this, tab, TRUE))
{
- List_iterator<JOIN_TAB_RANGE> it(join_tab_ranges);
- JOIN_TAB_RANGE *jt_range;
- uint first_tab_offs= const_tables;
- while ((jt_range= it++))
- {
- for (JOIN_TAB *tab= jt_range->start + first_tab_offs;
- tab < jt_range->end; tab++)
- {
uint key_copy_index=0;
- for (uint i=0; i < tab->ref.key_parts; i++)
- {
-
- Item **ref_item_ptr= tab->ref.items+i;
- Item *ref_item= *ref_item_ptr;
+ for (uint i=0; i < tab->ref.key_parts; i++)
+ {
+ Item **ref_item_ptr= tab->ref.items+i;
+ Item *ref_item= *ref_item_ptr;
if (!ref_item->used_tables() && !(select_options & SELECT_DESCRIBE))
continue;
- COND_EQUAL *equals= tab->first_inner ? tab->first_inner->cond_equal :
- cond_equal;
- ref_item= substitute_for_best_equal_field(ref_item, equals, map2table);
- ref_item->update_used_tables();
- if (*ref_item_ptr != ref_item)
- {
- *ref_item_ptr= ref_item;
- Item *item= ref_item->real_item();
+ COND_EQUAL *equals= tab->first_inner ? tab->first_inner->cond_equal :
+ cond_equal;
+ ref_item= substitute_for_best_equal_field(ref_item, equals, map2table);
+ ref_item->update_used_tables();
+ if (*ref_item_ptr != ref_item)
+ {
+ *ref_item_ptr= ref_item;
+ Item *item= ref_item->real_item();
store_key *key_copy= tab->ref.key_copy[key_copy_index];
- if (key_copy->type() == store_key::FIELD_STORE_KEY)
- {
- store_key_field *field_copy= ((store_key_field *)key_copy);
- field_copy->change_source_field((Item_field *) item);
- }
- }
- key_copy_index++;
+ if (key_copy->type() == store_key::FIELD_STORE_KEY)
+ {
+ store_key_field *field_copy= ((store_key_field *)key_copy);
+ field_copy->change_source_field((Item_field *) item);
}
}
- first_tab_offs= 0;
+ key_copy_index++;
}
}
- //}
if (conds && const_table_map != found_const_table_map &&
(select_options & SELECT_DESCRIBE))
@@ -1638,9 +1609,6 @@ bool JOIN::setup_subquery_caches()
for (JOIN_TAB *tab= first_linear_tab(this, TRUE);
tab;
tab= next_linear_tab(this, tab, TRUE))
- //for (JOIN_TAB *tab= join_tab + const_tables;
- // tab < join_tab + tables ;
- // tab++)
{
if (tab->select_cond)
tab->select_cond=