summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergey Petrunya <psergey@askmonty.org>2009-06-29 17:51:15 +0400
committerSergey Petrunya <psergey@askmonty.org>2009-06-29 17:51:15 +0400
commit9fa1bce4366ee6c8266395b66debc6110c090087 (patch)
tree383decc7e4c9b73faf541ce594a1bca90f861ba8 /sql
parentd764108a2c259e1e38487eda1dfa7ac894b9e5a5 (diff)
downloadmariadb-git-9fa1bce4366ee6c8266395b66debc6110c090087.tar.gz
MWL#17: Table elimination
mysql-test/r/table_elim.result: MWL#17: Table elimination - More tests mysql-test/t/table_elim.test: MWL#17: Table elimination - More tests sql/opt_table_elimination.cc: MWL#17: Table elimination - Code cleanup sql/sql_select.cc: MWL#17: Table elimination - Code cleanup sql/sql_select.h: MWL#17: Table elimination - Code cleanup sql/table.h: MWL#17: Table elimination - Code cleanup
Diffstat (limited to 'sql')
-rw-r--r--sql/opt_table_elimination.cc345
-rw-r--r--sql/sql_select.cc56
-rw-r--r--sql/sql_select.h20
-rw-r--r--sql/table.h7
4 files changed, 212 insertions, 216 deletions
diff --git a/sql/opt_table_elimination.cc b/sql/opt_table_elimination.cc
index 26ebb2232c4..4da061d0e60 100644
--- a/sql/opt_table_elimination.cc
+++ b/sql/opt_table_elimination.cc
@@ -42,14 +42,16 @@
Table elimination is redone on every PS re-execution.
*/
-static int
-eliminate_tables_for_join_list(JOIN *join, List<TABLE_LIST> *join_list,
- table_map tables_used_elsewhere,
- uint *const_tbl_count, table_map *const_tables);
-static bool table_has_one_match(TABLE *table, table_map bound_tables);
-static void
-mark_table_as_eliminated(JOIN *join, TABLE *table, uint *const_tbl_count,
- table_map *const_tables);
+static void mark_as_eliminated(JOIN *join, TABLE_LIST *tbl);
+static bool table_has_one_match(TABLE *table, table_map bound_tables,
+ bool *multiple_matches);
+static uint
+eliminate_tables_for_list(JOIN *join, TABLE **leaves_arr,
+ List<TABLE_LIST> *join_list,
+ bool its_outer_join,
+ table_map tables_in_list,
+ table_map tables_used_elsewhere,
+ bool *multiple_matches);
static bool
extra_keyuses_bind_all_keyparts(table_map bound_tables, TABLE *table,
KEYUSE *key_start, KEYUSE *key_end,
@@ -95,8 +97,7 @@ extra_keyuses_bind_all_keyparts(table_map bound_tables, TABLE *table,
*/
-void eliminate_tables(JOIN *join, uint *const_tbl_count,
- table_map *const_tables)
+void eliminate_tables(JOIN *join)
{
Item *item;
table_map used_tables;
@@ -139,221 +140,141 @@ void eliminate_tables(JOIN *join, uint *const_tbl_count,
used_tables |= item->used_tables();
}
}
-
- if (((1 << join->tables) - 1) & ~used_tables)
+
+ table_map all_tables= join->all_tables_map();
+ if (all_tables & ~used_tables)
{
/* There are some tables that we probably could eliminate. Try it. */
- eliminate_tables_for_join_list(join, join->join_list, used_tables,
- const_tbl_count, const_tables);
+ TABLE *leaves_array[MAX_TABLES];
+ bool multiple_matches= FALSE;
+ eliminate_tables_for_list(join, leaves_array, join->join_list, FALSE,
+ all_tables, used_tables, &multiple_matches);
}
DBUG_VOID_RETURN;
}
-
-
-
/*
Perform table elimination in a given join list
SYNOPSIS
- eliminate_tables_for_join_list()
+ eliminate_tables_for_list()
join The join
join_list Join list to work on
tables_used_elsewhere Bitmap of tables that are referred to from
somewhere outside of the join list (e.g.
select list, HAVING, etc).
- const_tbl_count INOUT Number of constant tables (eliminated tables
- are considered constant)
- const_tables INOUT Bitmap of constant tables.
-
DESCRIPTION
- Try eliminating members of the given join list (and its children,
- recursively).
-
- Search for tables to be eliminated is performed on recursive descent,
- while the elimination is done on ascent.
-
- DESCENT AND NO-REFERENCES CHECK
- The descent part is needed because of the following: consider a join list
-
- t0 LEFT JOIN
- (t1
- LEFT JOIN t2 ON cond1(t1,t2)
- LEFT JOIN t3 ON cond2(..., possibly-t2) (*)
- LEFT JOIN t4 ON cond3(..., possibly-t2, possibly-t3)
- ) ON cond4
-
- Suppose we're looking at whether we can eliminate outer join marked with
- (*), in other words, table t3. Before we can do that, we need to
- 1. Check that there are no references to table t3 in cond4 (in general:
- all ON expressions of embedding outer joins, this explains the need for
- descent)
- 2. Check that there are no references to table t3 in its following-siblings,
- in this example, in cond3.
- 3. Although SQL language doesn't allow referring to table t3 from cond1,
- simplify_joins() may create such back-references, so we'll also need to
- check if t3's preceding-siblings have ON expressions with references
- from t3.
-
- ASCENT AND THE ELIMINATION
- The removal is done in a bottom-up way because we can consider an outer
- join nest for elimination only after we have successfully eliminated all
- of its children outer joins.
RETURN
- Number of tables that have been eliminated
+ Number of base tables left after elimination. 0 means everything was
+ eliminated. Tables that belong to the
+ children of this join nest are also counted.
+
+// TRUE The entire join list can be eliminated (caller should remove)
+// FALSE Otherwise
+ number of tables that were eliminated (compare this with total number of
+ tables in the join_list to tell if the entire join was eliminated)
*/
-
-static int
-eliminate_tables_for_join_list(JOIN *join, List<TABLE_LIST> *join_list,
- table_map tables_used_elsewhere,
- uint *const_tbl_count, table_map *const_tables)
+static uint
+eliminate_tables_for_list(JOIN *join, TABLE **leaves_arr,
+ List<TABLE_LIST> *join_list,
+ bool its_outer_join,
+ table_map tables_in_list,
+ table_map tables_used_elsewhere,
+ bool *multiple_matches)
{
- List_iterator<TABLE_LIST> it(*join_list);
- table_map used_tables_on_right[MAX_TABLES];
- table_map tables_used_on_left;
TABLE_LIST *tbl;
- int i, n_tables;
- int eliminated=0;
+ List_iterator<TABLE_LIST> it(*join_list);
+ table_map tables_used_on_left= 0;
+ TABLE **cur_table= leaves_arr;
+ bool children_have_multiple_matches= FALSE;
+ uint base_tables= 0;
- /* Collect used_tables_on_right array */
- for (i=0; (tbl= it++); i++)
- {
- used_tables_on_right[i]= 0;
- if (tbl->on_expr)
- used_tables_on_right[i]= tbl->on_expr->used_tables();
- if (tbl->nested_join)
- used_tables_on_right[i]= tbl->nested_join->used_tables;
- }
- n_tables= i;
- for (i= n_tables - 2; i > 0; i--)
- used_tables_on_right[i] |= used_tables_on_right[i+1];
-
- i= 1;
- it.rewind();
- tables_used_on_left= 0;
- /* For each member of the join list, check if we can eliminate it */
while ((tbl= it++))
{
- table_map tables_used_outside= tables_used_on_left |
- used_tables_on_right[i] |
- tables_used_elsewhere;
- table_map cur_tables= 0;
-
- if (tbl->nested_join)
+ if (tbl->on_expr)
{
- DBUG_ASSERT(tbl->on_expr);
- /*
- There can be cases where table removal is applicable for tables
- within the outer join but not for the outer join itself. Ask to
- remove the children first.
-
- TODO: NoHopelessEliminationAttempts: the below call can return
- information about whether it would make any sense to try removing
- this entire outer join nest.
- */
- int eliminated_in_children=
- eliminate_tables_for_join_list(join, &tbl->nested_join->join_list,
- tables_used_outside,
- const_tbl_count, const_tables);
- tbl->nested_join->n_tables -=eliminated_in_children;
- cur_tables= tbl->nested_join->used_tables;
- if (!(cur_tables & tables_used_outside))
+ table_map outside_used_tables= tables_used_elsewhere |
+ tables_used_on_left;
+ bool multiple_matches= FALSE;
+ if (tbl->nested_join)
{
- /*
- Check if all embedded tables together can produce at most one
- record combination. This is true when
- - each of them has one_match(outer-tables) property
- (this is a stronger condition than all of them together having
- this property but that's irrelevant here)
- - there are no outer joins among them
- (except for the case of outer join which has all inner tables
- to be constant and is guaranteed to produce only one record.
- that record will be null-complemented)
- */
- bool one_match= TRUE;
- List_iterator<TABLE_LIST> it2(tbl->nested_join->join_list);
- TABLE_LIST *inner;
- while ((inner= it2++))
- {
- /*
- Bail out if we see an outer join (TODO: handle the above
- null-complemntated-rows-only case)
- */
- if (inner->on_expr)
- {
- one_match= FALSE;
- break;
- }
-
- if (inner->table && // <-- to be removed after NoHopelessEliminationAttempts
- !table_has_one_match(inner->table,
- ~tbl->nested_join->used_tables))
- {
- one_match= FALSE;
- break;
- }
- }
- if (one_match)
+ /* This is "... LEFT JOIN (join_nest) ON cond" */
+ uint n;
+ if (!(n= eliminate_tables_for_list(join, cur_table,
+ &tbl->nested_join->join_list, TRUE,
+ tbl->nested_join->used_tables,
+ outside_used_tables,
+ &multiple_matches)))
{
- it2.rewind();
- while ((inner= it2++))
- {
- mark_table_as_eliminated(join, inner->table, const_tbl_count,
- const_tables);
- }
- eliminated += tbl->nested_join->join_list.elements;
- //psergey-todo: do we need to do anything about removing the join
- //nest?
- tbl->on_expr->walk(&Item::mark_as_eliminated_processor, FALSE, NULL);
+ mark_as_eliminated(join, tbl);
}
- else
+ tbl->nested_join->n_tables= n;
+ base_tables += n;
+ }
+ else
+ {
+ /* This is "... LEFT JOIN tbl ON cond" */
+ if (!(tbl->table->map & outside_used_tables) &&
+ table_has_one_match(tbl->table, join->all_tables_map(),
+ &multiple_matches))
{
- eliminated += eliminated_in_children;
+ mark_as_eliminated(join, tbl);
}
+ else
+ base_tables++;
}
+ tables_used_on_left |= tbl->on_expr->used_tables();
+ children_have_multiple_matches= children_have_multiple_matches ||
+ multiple_matches;
}
- else if (tbl->on_expr)
+ else
{
- cur_tables= tbl->on_expr->used_tables();
- if (!(tbl->table->map & tables_used_outside) &&
- table_has_one_match(tbl->table, (table_map)-1))
- {
- mark_table_as_eliminated(join, tbl->table, const_tbl_count,
- const_tables);
- tbl->on_expr->walk(&Item::mark_as_eliminated_processor, FALSE, NULL);
- eliminated += 1;
- }
+ DBUG_ASSERT(!tbl->nested_join);
+ base_tables++;
}
- i++;
- tables_used_on_left |= cur_tables;
+ if (tbl->table)
+ *(cur_table++)= tbl->table;
}
- return eliminated;
-}
-
-
-/*
- Mark table as eliminated:
- - Mark it as constant table
- - Move it to the front of join order
- - Record it in join->eliminated_tables
-*/
-static
-void mark_table_as_eliminated(JOIN *join, TABLE *table, uint *const_tbl_count,
- table_map *const_tables)
-{
- JOIN_TAB *tab= table->reginfo.join_tab;
- if (!(*const_tables & tab->table->map))
+ *multiple_matches |= children_have_multiple_matches;
+
+ /* Try eliminating the nest we're called for */
+ if (its_outer_join && !children_have_multiple_matches &&
+ !(tables_in_list & tables_used_elsewhere))
{
- DBUG_PRINT("info", ("Eliminated table %s", table->alias));
- tab->type= JT_CONST;
- join->eliminated_tables |= table->map;
- *const_tables |= table->map;
- join->const_table_map|= table->map;
- set_position(join, (*const_tbl_count)++, tab, (KEYUSE*)0);
+ table_map bound_tables= join->const_table_map | (join->all_tables_map() &
+ ~tables_in_list);
+ table_map old_bound_tables;
+ TABLE **leaves_end= cur_table;
+ /*
+ Do the same as const table search table: try to expand the set of bound
+ tables until it covers all tables in the join_list
+ */
+ do
+ {
+ old_bound_tables= bound_tables;
+ for (cur_table= leaves_arr; cur_table != leaves_end; cur_table++)
+ {
+ if (!((*cur_table)->map & join->eliminated_tables) &&
+ table_has_one_match(*cur_table, bound_tables, multiple_matches))
+ {
+ bound_tables |= (*cur_table)->map;
+ }
+ }
+ } while (old_bound_tables != bound_tables);
+
+ if (!(tables_in_list & ~bound_tables))
+ {
+ /*
+ This join_list can be eliminated. Signal about this to the caller by
+ returning number of tables.
+ */
+ base_tables= 0;
+ }
}
+ return base_tables;
}
@@ -362,8 +283,11 @@ void mark_table_as_eliminated(JOIN *join, TABLE *table, uint *const_tbl_count,
SYNOPSIS
table_has_one_match()
- table The [base] table being checked
- bound_tables Tables that should be considered bound.
+ table The [base] table being checked
+ bound_tables Tables that should be considered bound.
+ multiple_matches OUT Set to TRUE when there is no way we could
+ find find a limitation that would give us one-match
+ property.
DESCRIPTION
Check if table will produce at most one matching record for each record
@@ -389,7 +313,8 @@ void mark_table_as_eliminated(JOIN *join, TABLE *table, uint *const_tbl_count,
FALSE No
*/
-static bool table_has_one_match(TABLE *table, table_map bound_tables)
+static bool table_has_one_match(TABLE *table, table_map bound_tables,
+ bool *multiple_matches)
{
KEYUSE *keyuse= table->reginfo.join_tab->keyuse;
if (keyuse)
@@ -405,7 +330,7 @@ static bool table_has_one_match(TABLE *table, table_map bound_tables)
do /* For each keypart and each way to read it */
{
- if (keyuse->usable)
+ if (keyuse->usable == 1)
{
if(!(keyuse->used_tables & ~bound_tables) &&
!(keyuse->optimize & KEY_OPTIMIZE_REF_OR_NULL))
@@ -516,8 +441,10 @@ extra_keyuses_bind_all_keyparts(table_map bound_tables, TABLE *table,
{
if (!(uses[i].dependency_parts & ~bound_parts))
{
+ table_map old= bound_parts;
bound_parts|= key_part_map(1) << uses[i].keyuse->keypart;
- n_bounded++;
+ if (old != bound_parts)
+ n_bounded++;
}
if (bound_parts == PREV_BITS(key_part_map, keyinfo->key_parts))
return TRUE;
@@ -527,6 +454,42 @@ extra_keyuses_bind_all_keyparts(table_map bound_tables, TABLE *table,
return FALSE;
}
+
+/*
+ Mark one table or the whole join nest as eliminated.
+*/
+static void mark_as_eliminated(JOIN *join, TABLE_LIST *tbl)
+{
+ TABLE *table;
+ /*
+ NOTE: there are TABLE_LIST object that have
+ tbl->table!= NULL && tbl->nested_join!=NULL and
+ tbl->table == tbl->nested_join->join_list->element(..)->table
+ */
+ if (tbl->nested_join)
+ {
+ TABLE_LIST *child;
+ List_iterator<TABLE_LIST> it(tbl->nested_join->join_list);
+ while ((child= it++))
+ mark_as_eliminated(join, child);
+ }
+ else if ((table= tbl->table))
+ {
+ JOIN_TAB *tab= tbl->table->reginfo.join_tab;
+ if (!(join->const_table_map & tab->table->map))
+ {
+ DBUG_PRINT("info", ("Eliminated table %s", table->alias));
+ tab->type= JT_CONST;
+ join->eliminated_tables |= table->map;
+ join->const_table_map|= table->map;
+ set_position(join, join->const_tables++, tab, (KEYUSE*)0);
+ }
+ }
+
+ if (tbl->on_expr)
+ tbl->on_expr->walk(&Item::mark_as_eliminated_processor, FALSE, NULL);
+}
+
/**
@} (end of group Table_Elimination)
*/
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 2d9b1766c4f..729ee190a0f 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -2653,12 +2653,13 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
~outer_join, join->select_lex, &sargables))
goto error;
- /* Read tables with 0 or 1 rows (system tables) */
join->const_table_map= 0;
-
- eliminate_tables(join, &const_count, &found_const_table_map);
- join->const_table_map= found_const_table_map;
+ join->const_tables= const_count;
+ eliminate_tables(join);
+ const_count= join->const_tables;
+ found_const_table_map= join->const_table_map;
+ /* Read tables with 0 or 1 rows (system tables) */
for (POSITION *p_pos=join->positions, *p_end=p_pos+const_count;
p_pos < p_end ;
p_pos++)
@@ -2761,7 +2762,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
{
start_keyuse=keyuse;
key=keyuse->key;
- if (keyuse->usable)
+ if (keyuse->usable == 1)
s->keys.set_bit(key); // QQ: remove this ?
refs=0;
@@ -2769,7 +2770,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
eq_part.clear_all();
do
{
- if (keyuse->usable && keyuse->val->type() != Item::NULL_ITEM &&
+ if (keyuse->usable==1 && keyuse->val->type() != Item::NULL_ITEM &&
!keyuse->optimize)
{
if (!((~found_const_table_map) & keyuse->used_tables))
@@ -3601,7 +3602,12 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array,KEY_FIELD *key_field)
keyuse.optimize= key_field->optimize & KEY_OPTIMIZE_REF_OR_NULL;
keyuse.null_rejecting= key_field->null_rejecting;
keyuse.cond_guard= key_field->cond_guard;
- keyuse.usable= key_field->usable;
+ if (!(keyuse.usable= key_field->usable))
+ {
+ /* The following will have special meanings: */
+ keyuse.keypart_map= 0;
+ keyuse.used_tables= 0;
+ }
VOID(insert_dynamic(keyuse_array,(uchar*) &keyuse));
}
}
@@ -3668,7 +3674,7 @@ add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
keyuse.used_tables=cond_func->key_item()->used_tables();
keyuse.optimize= 0;
keyuse.keypart_map= 0;
- keyuse.usable= TRUE;
+ keyuse.usable= 1;
VOID(insert_dynamic(keyuse_array,(uchar*) &keyuse));
}
@@ -3686,7 +3692,7 @@ sort_keyuse(KEYUSE *a,KEYUSE *b)
// Usable ones go before the unusable
if (a->usable != b->usable)
- return (int)a->usable - (int)b->usable;
+ return (int)b->usable - (int)a->usable;
// Place const values before other ones
if ((res= test((a->used_tables & ~OUTER_REF_TABLE_BIT)) -
@@ -3898,7 +3904,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
found_eq_constant=0;
for (i=0 ; i < keyuse->elements-1 ; i++,use++)
{
- if (use->usable && !use->used_tables &&
+ if (use->usable == 1 && !use->used_tables &&
use->optimize != KEY_OPTIMIZE_REF_OR_NULL)
use->table->const_key_parts[use->key]|= use->keypart_map;
if (use->keypart != FT_KEYPART)
@@ -3923,7 +3929,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
/* Save ptr to first use */
if (!use->table->reginfo.join_tab->keyuse)
use->table->reginfo.join_tab->keyuse=save_pos;
- if (use->usable)
+ if (use->usable == 1)
use->table->reginfo.join_tab->checked_keys.set_bit(use->key);
save_pos++;
}
@@ -3954,7 +3960,7 @@ static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array)
To avoid bad matches, we don't make ref_table_rows less than 100.
*/
keyuse->ref_table_rows= ~(ha_rows) 0; // If no ref
- if (keyuse->usable && keyuse->used_tables &
+ if (keyuse->usable == 1 && keyuse->used_tables &
(map= (keyuse->used_tables & ~join->const_table_map &
~OUTER_REF_TABLE_BIT)))
{
@@ -4146,7 +4152,7 @@ best_access_path(JOIN *join,
if 1. expression doesn't refer to forward tables
2. we won't get two ref-or-null's
*/
- if (keyuse->usable &&
+ if (keyuse->usable == 1&&
!(remaining_tables & keyuse->used_tables) &&
!(ref_or_null_part && (keyuse->optimize &
KEY_OPTIMIZE_REF_OR_NULL)))
@@ -5601,7 +5607,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
*/
do
{
- if (!(~used_tables & keyuse->used_tables))
+ if (!(~used_tables & keyuse->used_tables) && keyuse->usable == 1)
{
if (keyparts == keyuse->keypart &&
!(found_part_ref_or_null & keyuse->optimize))
@@ -5652,7 +5658,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
for (i=0 ; i < keyparts ; keyuse++,i++)
{
while (keyuse->keypart != i || ((~used_tables) & keyuse->used_tables) ||
- !keyuse->usable)
+ !(keyuse->usable == 1))
{
keyuse++; /* Skip other parts */
}
@@ -8985,6 +8991,20 @@ static void restore_prev_nj_state(JOIN_TAB *last)
JOIN *join= last->join;
while (last_emb)
{
+ /*
+ psergey-elim: (nevermind)
+ new_prefix= cur_prefix & ~last;
+ if (!(new_prefix & cur_table_map)) // removed last inner table
+ {
+ join->cur_embedding_map&= ~last_emb->nested_join->nj_map;
+ }
+ else (current)
+ {
+ // Won't hurt doing it all the time:
+ join->cur_embedding_map |= ...;
+ }
+ else
+ */
if (!(--last_emb->nested_join->counter))
join->cur_embedding_map&= ~last_emb->nested_join->nj_map;
else if (last_emb->nested_join->n_tables-1 ==
@@ -16685,13 +16705,13 @@ static void print_join(THD *thd,
DBUG_ASSERT(tables->elements >= 1);
/*
- Assert that the first table in the list isn't eliminated (if it was we
- would have skipped the entire join nest)
+ Assert that the first table in the list isn't eliminated. This comes from
+ the fact that the first table can't be inner table of an outer join.
*/
DBUG_ASSERT(!eliminated_tables ||
!((*table)->table && ((*table)->table->map & eliminated_tables) ||
(*table)->nested_join && !((*table)->nested_join->used_tables &
- ~eliminated_tables)));
+ ~eliminated_tables)));
(*table)->print(thd, eliminated_tables, str, query_type);
TABLE_LIST **end= table + tables->elements;
diff --git a/sql/sql_select.h b/sql/sql_select.h
index b2f61337ab4..ae334a2f012 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -57,14 +57,14 @@ typedef struct keyuse_t {
*/
bool *cond_guard;
/*
- TRUE <=> This keyuse can be used to construct key access.
- FALSE <=> Otherwise. Currently unusable KEYUSEs represent equalities
+ 1 <=> This keyuse can be used to construct key access.
+ 0 <=> Otherwise. Currently unusable KEYUSEs represent equalities
where one table column refers to another one, like this:
t.keyXpartA=func(t.keyXpartB)
This equality cannot be used for index access but is useful
for table elimination.
*/
- bool usable;
+ int usable;
} KEYUSE;
class store_key;
@@ -299,7 +299,12 @@ public:
fetching data from a cursor
*/
bool resume_nested_loop;
- table_map const_table_map,found_const_table_map;
+ table_map const_table_map;
+ /*
+ Constant tables for which we have found a row (as opposed to those for
+ which we didn't).
+ */
+ table_map found_const_table_map;
/* Tables removed by table elimination. Set to 0 before the elimination. */
table_map eliminated_tables;
@@ -548,6 +553,10 @@ public:
return (unit == &thd->lex->unit && (unit->fake_select_lex == 0 ||
select_lex == unit->fake_select_lex));
}
+ inline table_map all_tables_map()
+ {
+ return (table_map(1) << tables) - 1;
+ }
private:
bool make_simple_join(JOIN *join, TABLE *tmp_table);
};
@@ -755,6 +764,5 @@ inline bool optimizer_flag(THD *thd, uint flag)
return (thd->variables.optimizer_switch & flag);
}
-void eliminate_tables(JOIN *join, uint *const_tbl_count,
- table_map *const_tables);
+void eliminate_tables(JOIN *join);
diff --git a/sql/table.h b/sql/table.h
index f443d591dec..e342fb7194c 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1616,7 +1616,10 @@ public:
typedef struct st_nested_join
{
List<TABLE_LIST> join_list; /* list of elements in the nested join */
- table_map used_tables; /* bitmap of tables in the nested join */
+ /*
+ Bitmap of tables within this nested join (including those embedded within
+ its children). Eliminated tables are still in the bitmap */
+ table_map used_tables;
table_map not_null_tables; /* tables that rejects nulls */
struct st_join_table *first_nested;/* the first nested table in the plan */
/*
@@ -1625,6 +1628,8 @@ typedef struct st_nested_join
2. check_interleaving_with_nj/restore_prev_nj_state (these are called
by the join optimizer.
Before each use the counters are zeroed by reset_nj_counters.
+ Meaning, in both cases: number of base tables within this nested join and
+ its children. Eliminated tables are not counted.
*/
uint counter;
/* Tables left after elimination */