summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorpsergey <psergey@epc>2010-07-10 20:51:12 +0300
committerpsergey <psergey@epc>2010-07-10 20:51:12 +0300
commit946aef4a58337c6e5adf5a08d04dd397630f0c46 (patch)
treeb7798906d606a067b055d46cd20e1fc4cfc09f19 /sql
parente9bac8db82f54d715997cceff082452c5406d36e (diff)
downloadmariadb-git-946aef4a58337c6e5adf5a08d04dd397630f0c46.tar.gz
MWL#90: code cleanup
- Remove deadcode - Improve comments - Do small several small TODOs
Diffstat (limited to 'sql')
-rw-r--r--sql/item_cmpfunc.cc6
-rw-r--r--sql/opt_subselect.cc56
-rw-r--r--sql/opt_subselect.h2
-rw-r--r--sql/sql_join_cache.cc5
-rw-r--r--sql/sql_select.cc133
-rw-r--r--sql/sql_select.h3
6 files changed, 49 insertions, 156 deletions
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index ad8529ed0bb..3de7c9d468b 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -5731,10 +5731,8 @@ Item_field* Item_equal::get_first(Item_field *field)
{
/*
It's a field from an materialized semi-join. We can substitute it only
- for a field from the same semi-join.
+ for a field from the same semi-join. Find the first of such items.
*/
-
- /* Find an item to substitute for. */
while ((item= it++))
{
if (item->field->table->pos_in_table_list->embedding == emb_nest)
@@ -5762,7 +5760,7 @@ Item_field* Item_equal::get_first(Item_field *field)
First let's note that either it1.col or it2.col participates in
subquery's IN-equality. It can't be otherwise, because materialization is
only applicable to uncorrelated subqueries, so the only way we could
- infer "it1.col=ot1.col" is from IN-equality. Ok, so IN-eqality has
+ infer "it1.col=ot1.col" is from the IN-equality. Ok, so IN-eqality has
it1.col or it2.col on its inner side. it1.col is first such item in the
join order, so it's not possible for SJ-Mat to be
SJ-Materialization-lookup, it is SJ-Materialization-Scan. The scan part
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 8493a8e4082..0add6db447a 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -30,6 +30,8 @@
3.1.1 Merged semi-join TABLE_LIST object
3.1.2 Non-merged semi-join data structure
3.2 Semi-joins and query optimization
+ 3.2.1 Non-merged semi-joins and join optimization
+ 3.2.2 Merged semi-joins and join optimization
3.3 Semi-joins and query execution
1. What is a semi-join subquery
@@ -99,8 +101,8 @@
3. Code-level view of semi-join processing
------------------------------------------
- 3.1 Conversion
- --------------
+ 3.1 Conversion and pre-optimization data structures
+ ---------------------------------------------------
* When doing JOIN::prepare for the subquery, we detect that it can be
converted into a semi-join and register it in parent_join->sj_subselects
@@ -117,7 +119,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Merged semi-join object is a TABLE_LIST that contains a sub-join of
subquery tables and the semi-join ON expression (in this respect it is
- ery similar to nested outer join representation)
+ very similar to nested outer join representation)
Merged semi-join represents this SQL:
... SEMI JOIN (inner_tbl1 JOIN ... JOIN inner_tbl_n) ON sj_on_expr
@@ -135,14 +137,38 @@
clause. (They do remain in PS-saved WHERE clause, and they replace themselves
with Item_int(1) on subsequent re-executions).
- 3.2 Semi-joins and query optimization
- -------------------------------------
- Query optimizer operates on semi-join nests.
+ 3.2 Semi-joins and join optimization
+ ------------------------------------
+
+ 3.2.1 Non-merged semi-joins and join optimization
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ For join optimization purposes, non-merged semi-join nests are similar to
+ base tables - they've got one JOIN_TAB, which can be accessed with one of
+ two methods:
+ - full table scan (representing SJ-Materialization-Scan strategy)
+ - eq_ref-like table lookup (representing SJ-Materialization-Lookup)
+
+ Unlike regular base tables, non-merged semi-joins have:
+ - non-zero JOIN_TAB::startup_cost, and
+ - join_tab->table->is_filled_at_execution()==TRUE, which means one
+ cannot do const table detection or range analysis or other table data-
+ dependent inferences
+ // instead, get_delayed_table_estimates() runs optimization on the nest so that
+ // we get an idea about temptable size
+
+ 3.2.2 Merged semi-joins and join optimization
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ - optimize_semijoin_nests() does pre-optimization
+ - during join optimization, the join has one JOIN_TAB (or is it POSITION?)
+ array, and suffix-based detection is used, see advance_sj_state()
+ - after join optimization is done, get_best_combination() switches
+ the data-structure to prefix-based, multiple JOIN_TAB ranges format.
3.3 Semi-joins and query execution
----------------------------------
* Join executor has hooks for all semi-join strategies.
- TODO elaborate
+ TODO elaborate.
+
*/
@@ -2682,8 +2708,6 @@ bool setup_sj_materialization(JOIN_TAB *sjm_tab)
temptable.
*/
TABLE_REF *tab_ref;
- //if (!(tab_ref= (TABLE_REF*) thd->alloc(sizeof(TABLE_REF))))
- // DBUG_RETURN(TRUE); /* purecov: inspected */
tab_ref= &sjm_tab->ref;
tab_ref->key= 0; /* The only temp table index. */
tab_ref->key_length= tmp_key->key_length;
@@ -3966,17 +3990,19 @@ static void remove_subq_pushed_predicates(JOIN *join, Item **where)
pointers.
RETURN
- FALSE Ok
- TRUE Error, join execution is not possible.
+ NESTED_LOOP_OK - OK
+ NESTED_LOOP_ERROR| NESTED_LOOP_KILLED - Error, abort the join execution
*/
-bool join_tab_execution_startup(JOIN_TAB *tab)
+enum_nested_loop_state join_tab_execution_startup(JOIN_TAB *tab)
{
Item_in_subselect *in_subs;
DBUG_ENTER("join_tab_execution_startup");
+
if (tab->table->pos_in_table_list &&
(in_subs= tab->table->pos_in_table_list->jtbm_subselect))
{
+ /* It's a non-merged SJM nest */
DBUG_ASSERT(in_subs->engine->engine_type() ==
subselect_engine::HASH_SJ_ENGINE);
@@ -3988,13 +4014,13 @@ bool join_tab_execution_startup(JOIN_TAB *tab)
hash_sj_engine->is_materialized= TRUE;
if (hash_sj_engine->materialize_join->error || tab->join->thd->is_fatal_error)
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(NESTED_LOOP_ERROR);
}
}
else if (tab->bush_children)
{
/* It's a merged SJM nest */
- int rc; // psergey3: todo: error codes!
+ enum_nested_loop_state rc;
JOIN *join= tab->join;
SJ_MATERIALIZATION_INFO *sjm= tab->bush_children->start->emb_sj_nest->sj_mat_info;
JOIN_TAB *join_tab= tab->bush_children->start;
@@ -4018,6 +4044,6 @@ bool join_tab_execution_startup(JOIN_TAB *tab)
}
}
- DBUG_RETURN(0);
+ DBUG_RETURN(NESTED_LOOP_OK);
}
diff --git a/sql/opt_subselect.h b/sql/opt_subselect.h
index b0dc4059858..5ed995f74bf 100644
--- a/sql/opt_subselect.h
+++ b/sql/opt_subselect.h
@@ -372,5 +372,5 @@ void get_delayed_table_estimates(TABLE *table,
double *scan_time,
double *startup_cost);
-bool join_tab_execution_startup(JOIN_TAB *tab);
+enum_nested_loop_state join_tab_execution_startup(JOIN_TAB *tab);
diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc
index 5db5928fba1..1d5c04711e1 100644
--- a/sql/sql_join_cache.cc
+++ b/sql/sql_join_cache.cc
@@ -1809,11 +1809,8 @@ enum_nested_loop_state JOIN_CACHE_BNL::join_matching_records(bool skip_last)
/* Start retrieving all records of the joined table */
- if (join_tab_execution_startup(join_tab))
- {
- rc= NESTED_LOOP_ERROR;
+ if ((rc= join_tab_execution_startup(join_tab)) < 0)
goto finish;
- }
if ((error= join_init_read_record(join_tab)))
{
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index ebaaf268505..31e087533d7 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -8100,6 +8100,8 @@ void JOIN::cleanup(bool full)
{
for (tab= top_jtrange_tables?join_tab:NULL; tab; tab= next_linear_tab(this, tab, TRUE))
tab->cleanup();
+ //psergey4: how is the above supposed to work when
+ //top_jtrange_tables==FALSE? It will crash right away!
table= 0;
}
else
@@ -12746,133 +12748,6 @@ int rr_sequential_and_unpack(READ_RECORD *info)
/*
- Semi-join materialization join function
-
- SYNOPSIS
- sub_select_sjm()
- join The join
- join_tab The first table in the materialization nest
- end_of_records FALSE <=> This call is made to pass another record
- combination
- TRUE <=> EOF
-
- DESCRIPTION
- This is a join execution function that does materialization of a join
- suborder before joining it to the rest of the join.
-
- The table pointed by join_tab is the first of the materialized tables.
- This function first creates the materialized table and then switches to
- joining the materialized table with the rest of the join.
-
- The materialized table can be accessed in two ways:
- - index lookups
- - full table scan
-
- RETURN
- One of enum_nested_loop_state values
-*/
-#if 0
-enum_nested_loop_state
-sub_select_sjm(JOIN *join, JOIN_TAB *join_tab, bool end_of_records)
-{
- int res;
- enum_nested_loop_state rc;
-
- DBUG_ENTER("sub_select_sjm");
-
- if (!join_tab->emb_sj_nest)
- {
- /*
- We're handling GROUP BY/ORDER BY, this is the first table, and we've
- actually executed the join already and now we're just reading the
- result of the join from the temporary table.
- Bypass to regular join handling.
- Yes, it would be nicer if sub_select_sjm wasn't called at all in this
- case but there's no easy way to arrange this.
- */
- rc= sub_select(join, join_tab, end_of_records);
- DBUG_RETURN(rc);
- }
-
- SJ_MATERIALIZATION_INFO *sjm= join_tab->emb_sj_nest->sj_mat_info;
- if (end_of_records)
- {
- rc= (*join_tab[sjm->tables - 1].next_select)(join,
- join_tab + sjm->tables,
- end_of_records);
- DBUG_RETURN(rc);
- }
- if (!sjm->materialized)
- {
- /*
- Do the materialization. First, put end_sj_materialize after the last
- inner table so we can catch record combinations of sj-inner tables.
- */
- Next_select_func next_func= join_tab[sjm->tables - 1].next_select;
- join_tab[sjm->tables - 1].next_select= end_sj_materialize;
-
- /*
- Now run the join for the inner tables. The first call is to run the
- join, the second one is to signal EOF (this is essential for some
- join strategies, e.g. it will make join buffering flush the records)
- */
- if ((rc= sub_select(join, join_tab, FALSE)) < 0 ||
- (rc= sub_select(join, join_tab, TRUE/*EOF*/)) < 0)
- {
- join_tab[sjm->tables - 1].next_select= next_func;
- DBUG_RETURN(rc); /* it's NESTED_LOOP_(ERROR|KILLED)*/
- }
- join_tab[sjm->tables - 1].next_select= next_func;
-
- /*
- Ok, materialization finished. Initialize the access to the temptable
- */
- sjm->materialized= TRUE;
- join_tab->read_record.read_record= join_no_more_records;
- if (sjm->is_sj_scan)
- {
- /* Initialize full scan */
- JOIN_TAB *last_tab= join_tab + (sjm->tables - 1);
- init_read_record(&last_tab->read_record, join->thd,
- sjm->table, NULL, TRUE, TRUE, FALSE);
-
- DBUG_ASSERT(last_tab->read_record.read_record == rr_sequential);
- last_tab->read_first_record= join_read_record_no_init;
- last_tab->read_record.copy_field= sjm->copy_field;
- last_tab->read_record.copy_field_end= sjm->copy_field +
- sjm->sjm_table_cols.elements;
- last_tab->read_record.read_record= rr_sequential_and_unpack;
- }
- }
-
- if (sjm->is_sj_scan)
- {
- /* Do full scan of the materialized table */
- JOIN_TAB *last_tab= join_tab + (sjm->tables - 1);
-
- Item *save_cond= last_tab->select_cond;
- last_tab->set_select_cond(sjm->join_cond, __LINE__);
-
- rc= sub_select(join, last_tab, end_of_records);
- last_tab->set_select_cond(save_cond, __LINE__);
- DBUG_RETURN(rc);
- }
- else
- {
- /* Do index lookup in the materialized table */
- if ((res= join_read_key2(join_tab, sjm->table, sjm->tab_ref)) == 1)
- DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
- if (res || !sjm->in_equality->val_int())
- DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS);
- }
- rc= (*join_tab[sjm->tables - 1].next_select)(join,
- join_tab + sjm->tables,
- end_of_records);
- DBUG_RETURN(rc);
-}
-#endif
-
-/*
Fill the join buffer with partial records, retrieve all full matches for them
SYNOPSIS
@@ -13122,8 +12997,8 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
}
join->thd->row_count= 0;
- if (join_tab_execution_startup(join_tab))
- DBUG_RETURN(NESTED_LOOP_ERROR);
+ if ((rc= join_tab_execution_startup(join_tab)) < 0)
+ DBUG_RETURN(rc);
error= (*join_tab->read_first_record)(join_tab);
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 2344a7a59c1..32c1eff97f7 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -1247,9 +1247,6 @@ enum_nested_loop_state sub_select_cache(JOIN *join, JOIN_TAB *join_tab, bool
end_of_records);
enum_nested_loop_state sub_select(JOIN *join,JOIN_TAB *join_tab, bool
end_of_records);
-enum_nested_loop_state sub_select_sjm(JOIN *join, JOIN_TAB *join_tab,
- bool end_of_records);
-
enum_nested_loop_state
end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
bool end_of_records);