mirror of
https://github.com/MariaDB/server.git
synced 2025-01-30 10:31:54 +01:00
Merge
This commit is contained in:
commit
efb57a8ebf
7 changed files with 346 additions and 124 deletions
|
@ -1765,6 +1765,7 @@ MIN(a)
|
||||||
1
|
1
|
||||||
DROP TABLE t1,t2,t3;
|
DROP TABLE t1,t2,t3;
|
||||||
#
|
#
|
||||||
|
#
|
||||||
# BUG#902632: Crash or invalid read at st_join_table::cleanup, st_table::disable_keyread
|
# BUG#902632: Crash or invalid read at st_join_table::cleanup, st_table::disable_keyread
|
||||||
#
|
#
|
||||||
CREATE TABLE t1 ( a INT );
|
CREATE TABLE t1 ( a INT );
|
||||||
|
@ -1780,6 +1781,20 @@ AND b IN ( SELECT c FROM t3 GROUP BY c )
|
||||||
);
|
);
|
||||||
a
|
a
|
||||||
DROP TABLE t1,t2,t3;
|
DROP TABLE t1,t2,t3;
|
||||||
|
#
|
||||||
|
# BUG#901506: Crash in TABLE_LIST::print on EXPLAIN EXTENDED
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 ( a INT, KEY(a) );
|
||||||
|
INSERT INTO t1 VALUES (8);
|
||||||
|
EXPLAIN EXTENDED
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE a IN ( SELECT MIN(a) FROM t1 );
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY t1 system NULL NULL NULL NULL 1 100.00
|
||||||
|
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select 8 AS `a` from `test`.`t1` where <expr_cache><8>(<in_optimizer>(8,<exists>(select min(`test`.`t1`.`a`) from `test`.`t1` having (<cache>(8) = <ref_null_helper>(min(`test`.`t1`.`a`))))))
|
||||||
|
DROP TABLE t1;
|
||||||
# This must be at the end:
|
# This must be at the end:
|
||||||
set optimizer_switch=@subselect_sj_mat_tmp;
|
set optimizer_switch=@subselect_sj_mat_tmp;
|
||||||
set @subselect_mat_test_optimizer_switch_value=null;
|
set @subselect_mat_test_optimizer_switch_value=null;
|
||||||
|
|
|
@ -1801,6 +1801,7 @@ MIN(a)
|
||||||
1
|
1
|
||||||
DROP TABLE t1,t2,t3;
|
DROP TABLE t1,t2,t3;
|
||||||
#
|
#
|
||||||
|
#
|
||||||
# BUG#902632: Crash or invalid read at st_join_table::cleanup, st_table::disable_keyread
|
# BUG#902632: Crash or invalid read at st_join_table::cleanup, st_table::disable_keyread
|
||||||
#
|
#
|
||||||
CREATE TABLE t1 ( a INT );
|
CREATE TABLE t1 ( a INT );
|
||||||
|
@ -1816,5 +1817,20 @@ AND b IN ( SELECT c FROM t3 GROUP BY c )
|
||||||
);
|
);
|
||||||
a
|
a
|
||||||
DROP TABLE t1,t2,t3;
|
DROP TABLE t1,t2,t3;
|
||||||
|
#
|
||||||
|
# BUG#901506: Crash in TABLE_LIST::print on EXPLAIN EXTENDED
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 ( a INT, KEY(a) );
|
||||||
|
INSERT INTO t1 VALUES (8);
|
||||||
|
EXPLAIN EXTENDED
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE a IN ( SELECT MIN(a) FROM t1 );
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY t1 system a NULL NULL NULL 1 100.00
|
||||||
|
1 PRIMARY <subquery2> system NULL NULL NULL NULL 1 100.00
|
||||||
|
2 MATERIALIZED NULL NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select 8 AS `a` from <materialize> (select min(`test`.`t1`.`a`) from `test`.`t1`) join `test`.`t1` where 1
|
||||||
|
DROP TABLE t1;
|
||||||
# This must be at the end:
|
# This must be at the end:
|
||||||
set optimizer_switch=@subselect_sj_mat_tmp;
|
set optimizer_switch=@subselect_sj_mat_tmp;
|
||||||
|
|
|
@ -1465,6 +1465,7 @@ SELECT MIN(a) FROM t1, t2 WHERE b IN (SELECT c FROM t3 GROUP BY c);
|
||||||
|
|
||||||
DROP TABLE t1,t2,t3;
|
DROP TABLE t1,t2,t3;
|
||||||
|
|
||||||
|
--echo #
|
||||||
--echo #
|
--echo #
|
||||||
--echo # BUG#902632: Crash or invalid read at st_join_table::cleanup, st_table::disable_keyread
|
--echo # BUG#902632: Crash or invalid read at st_join_table::cleanup, st_table::disable_keyread
|
||||||
--echo #
|
--echo #
|
||||||
|
@ -1482,6 +1483,18 @@ SELECT * FROM t1 WHERE EXISTS (
|
||||||
);
|
);
|
||||||
DROP TABLE t1,t2,t3;
|
DROP TABLE t1,t2,t3;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # BUG#901506: Crash in TABLE_LIST::print on EXPLAIN EXTENDED
|
||||||
|
--echo #
|
||||||
|
CREATE TABLE t1 ( a INT, KEY(a) );
|
||||||
|
INSERT INTO t1 VALUES (8);
|
||||||
|
|
||||||
|
EXPLAIN EXTENDED
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE a IN ( SELECT MIN(a) FROM t1 );
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
--echo # This must be at the end:
|
--echo # This must be at the end:
|
||||||
set optimizer_switch=@subselect_sj_mat_tmp;
|
set optimizer_switch=@subselect_sj_mat_tmp;
|
||||||
|
|
||||||
|
|
|
@ -448,11 +448,44 @@ public:
|
||||||
Same as above, but they also allow to scan the materialized table.
|
Same as above, but they also allow to scan the materialized table.
|
||||||
*/
|
*/
|
||||||
bool sjm_scan_allowed;
|
bool sjm_scan_allowed;
|
||||||
double jtbm_read_time;
|
|
||||||
double jtbm_record_count;
|
|
||||||
bool is_jtbm_merged;
|
|
||||||
bool is_jtbm_const_tab;
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
JoinTaB Materialization (JTBM) members
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
TRUE <=> This subselect has been converted into non-mergeable semi-join
|
||||||
|
table.
|
||||||
|
*/
|
||||||
|
bool is_jtbm_merged;
|
||||||
|
|
||||||
|
/* (Applicable if is_jtbm_merged==TRUE) Time required to run the materialized join */
|
||||||
|
double jtbm_read_time;
|
||||||
|
|
||||||
|
/* (Applicable if is_jtbm_merged==TRUE) Number of output rows in materialized join */
|
||||||
|
double jtbm_record_count;
|
||||||
|
|
||||||
|
/*
|
||||||
|
(Applicable if is_jtbm_merged==TRUE) TRUE <=> The materialized subselect is
|
||||||
|
a degenerate subselect which produces 0 or 1 rows, which we know at
|
||||||
|
optimization phase.
|
||||||
|
Examples:
|
||||||
|
1. subquery has "Impossible WHERE":
|
||||||
|
|
||||||
|
SELECT * FROM ot WHERE ot.column IN (SELECT it.col FROM it WHERE 2 > 3)
|
||||||
|
|
||||||
|
2. Subquery produces one row which opt_sum.cc is able to get with one lookup:
|
||||||
|
|
||||||
|
SELECT * FROM ot WHERE ot.column IN (SELECT MAX(it.key_col) FROM it)
|
||||||
|
*/
|
||||||
|
bool is_jtbm_const_tab;
|
||||||
|
|
||||||
|
/*
|
||||||
|
(Applicable if is_jtbm_const_tab==TRUE) Whether the subquery has produced
|
||||||
|
the row (or not)
|
||||||
|
*/
|
||||||
|
bool jtbm_const_row_found;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TRUE<=>this is a flattenable semi-join, false overwise.
|
TRUE<=>this is a flattenable semi-join, false overwise.
|
||||||
*/
|
*/
|
||||||
|
@ -744,6 +777,9 @@ public:
|
||||||
|
|
||||||
friend class subselect_hash_sj_engine;
|
friend class subselect_hash_sj_engine;
|
||||||
friend class Item_in_subselect;
|
friend class Item_in_subselect;
|
||||||
|
friend bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
|
||||||
|
Item **join_where);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4623,6 +4623,234 @@ enum_nested_loop_state join_tab_execution_startup(JOIN_TAB *tab)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create a dummy temporary table, useful only for the sake of having a
|
||||||
|
TABLE* object with map,tablenr and maybe_null properties.
|
||||||
|
|
||||||
|
This is used by non-mergeable semi-join materilization code to handle
|
||||||
|
degenerate cases where materialized subquery produced "Impossible WHERE"
|
||||||
|
and thus wasn't materialized.
|
||||||
|
*/
|
||||||
|
|
||||||
|
TABLE *create_dummy_tmp_table(THD *thd)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("create_dummy_tmp_table");
|
||||||
|
TABLE *table;
|
||||||
|
TMP_TABLE_PARAM sjm_table_param;
|
||||||
|
sjm_table_param.init();
|
||||||
|
sjm_table_param.field_count= 1;
|
||||||
|
List<Item> sjm_table_cols;
|
||||||
|
Item *column_item= new Item_int(1);
|
||||||
|
sjm_table_cols.push_back(column_item);
|
||||||
|
if (!(table= create_tmp_table(thd, &sjm_table_param,
|
||||||
|
sjm_table_cols, (ORDER*) 0,
|
||||||
|
TRUE /* distinct */,
|
||||||
|
1, /*save_sum_fields*/
|
||||||
|
thd->options | TMP_TABLE_ALL_COLUMNS,
|
||||||
|
HA_POS_ERROR /*rows_limit */,
|
||||||
|
(char*)"dummy", TRUE /* Do not open */)))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(NULL);
|
||||||
|
}
|
||||||
|
DBUG_RETURN(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
A class that is used to catch one single tuple that is sent to the join
|
||||||
|
output, and save it in Item_cache element(s).
|
||||||
|
|
||||||
|
It is very similar to select_singlerow_subselect but doesn't require a
|
||||||
|
Item_singlerow_subselect item.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class select_value_catcher :public select_subselect
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
select_value_catcher(Item_subselect *item_arg)
|
||||||
|
:select_subselect(item_arg)
|
||||||
|
{}
|
||||||
|
int send_data(List<Item> &items);
|
||||||
|
int setup(List<Item> *items);
|
||||||
|
bool assigned; /* TRUE <=> we've caught a value */
|
||||||
|
uint n_elements; /* How many elements we get */
|
||||||
|
Item_cache **row; /* Array of cache elements */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int select_value_catcher::setup(List<Item> *items)
|
||||||
|
{
|
||||||
|
assigned= FALSE;
|
||||||
|
n_elements= items->elements;
|
||||||
|
|
||||||
|
if (!(row= (Item_cache**) sql_alloc(sizeof(Item_cache*)*n_elements)))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
Item *sel_item;
|
||||||
|
List_iterator<Item> li(*items);
|
||||||
|
for (uint i= 0; (sel_item= li++); i++)
|
||||||
|
{
|
||||||
|
if (!(row[i]= Item_cache::get_cache(sel_item)))
|
||||||
|
return TRUE;
|
||||||
|
row[i]->setup(sel_item);
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int select_value_catcher::send_data(List<Item> &items)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("select_value_catcher::send_data");
|
||||||
|
DBUG_ASSERT(!assigned);
|
||||||
|
DBUG_ASSERT(items.elements == n_elements);
|
||||||
|
|
||||||
|
if (unit->offset_limit_cnt)
|
||||||
|
{ // Using limit offset,count
|
||||||
|
unit->offset_limit_cnt--;
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Item *val_item;
|
||||||
|
List_iterator_fast<Item> li(items);
|
||||||
|
for (uint i= 0; (val_item= li++); i++)
|
||||||
|
{
|
||||||
|
row[i]->store(val_item);
|
||||||
|
row[i]->cache_value();
|
||||||
|
}
|
||||||
|
assigned= TRUE;
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Setup JTBM join tabs for execution
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
|
||||||
|
Item **join_where)
|
||||||
|
{
|
||||||
|
TABLE_LIST *table;
|
||||||
|
NESTED_JOIN *nested_join;
|
||||||
|
List_iterator<TABLE_LIST> li(*join_list);
|
||||||
|
DBUG_ENTER("setup_jtbm_semi_joins");
|
||||||
|
|
||||||
|
while ((table= li++))
|
||||||
|
{
|
||||||
|
Item_in_subselect *item;
|
||||||
|
|
||||||
|
if ((item= table->jtbm_subselect))
|
||||||
|
{
|
||||||
|
Item_in_subselect *subq_pred= item;
|
||||||
|
double rows;
|
||||||
|
double read_time;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Perform optimization of the subquery, so that we know estmated
|
||||||
|
- cost of materialization process
|
||||||
|
- how many records will be in the materialized temp.table
|
||||||
|
*/
|
||||||
|
if (subq_pred->optimize(&rows, &read_time))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
|
subq_pred->jtbm_read_time= read_time;
|
||||||
|
subq_pred->jtbm_record_count=rows;
|
||||||
|
JOIN *subq_join= subq_pred->unit->first_select()->join;
|
||||||
|
|
||||||
|
if (!subq_join->tables_list || !subq_join->table_count)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
A special case; subquery's join is degenerate, and it either produces
|
||||||
|
0 or 1 record. Examples of both cases:
|
||||||
|
|
||||||
|
select * from ot where col in (select ... from it where 2>3)
|
||||||
|
select * from ot where col in (select min(it.key) from it)
|
||||||
|
|
||||||
|
in this case, the subquery predicate has not been setup for
|
||||||
|
materialization. In particular, there is no materialized temp.table.
|
||||||
|
We'll now need to
|
||||||
|
1. Check whether 1 or 0 records are produced, setup this as a
|
||||||
|
constant join tab.
|
||||||
|
2. Create a dummy temporary table, because all of the join
|
||||||
|
optimization code relies on TABLE object being present (here we
|
||||||
|
follow a bad tradition started by derived tables)
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(subq_pred->engine->engine_type() ==
|
||||||
|
subselect_engine::SINGLE_SELECT_ENGINE);
|
||||||
|
subselect_single_select_engine *engine=
|
||||||
|
(subselect_single_select_engine*)subq_pred->engine;
|
||||||
|
select_value_catcher *new_sink;
|
||||||
|
if (!(new_sink= new select_value_catcher(subq_pred)))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
if (new_sink->setup(&engine->select_lex->join->fields_list) ||
|
||||||
|
engine->select_lex->join->change_result(new_sink) ||
|
||||||
|
engine->exec())
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
subq_pred->is_jtbm_const_tab= TRUE;
|
||||||
|
|
||||||
|
if (new_sink->assigned)
|
||||||
|
{
|
||||||
|
subq_pred->jtbm_const_row_found= TRUE;
|
||||||
|
/*
|
||||||
|
Subselect produced one row, which is saved in new_sink->row.
|
||||||
|
Inject "left_expr[i] == row[i] equalities into parent's WHERE.
|
||||||
|
*/
|
||||||
|
Item *eq_cond;
|
||||||
|
for (uint i= 0; i < subq_pred->left_expr->cols(); i++)
|
||||||
|
{
|
||||||
|
eq_cond= new Item_func_eq(subq_pred->left_expr->element_index(i),
|
||||||
|
new_sink->row[i]);
|
||||||
|
if (!eq_cond || eq_cond->fix_fields(join->thd, &eq_cond))
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
|
(*join_where)= and_items(*join_where, eq_cond);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Subselect produced no rows. Just set the flag, */
|
||||||
|
subq_pred->jtbm_const_row_found= FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up a dummy TABLE*, optimizer code needs JOIN_TABs to have TABLE */
|
||||||
|
TABLE *dummy_table;
|
||||||
|
if (!(dummy_table= create_dummy_tmp_table(join->thd)))
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
table->table= dummy_table;
|
||||||
|
table->table->pos_in_table_list= table;
|
||||||
|
setup_table_map(table->table, table, table->jtbm_table_no);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(subq_pred->test_set_strategy(SUBS_MATERIALIZATION));
|
||||||
|
subq_pred->is_jtbm_const_tab= FALSE;
|
||||||
|
subselect_hash_sj_engine *hash_sj_engine=
|
||||||
|
((subselect_hash_sj_engine*)item->engine);
|
||||||
|
|
||||||
|
table->table= hash_sj_engine->tmp_table;
|
||||||
|
table->table->pos_in_table_list= table;
|
||||||
|
|
||||||
|
setup_table_map(table->table, table, table->jtbm_table_no);
|
||||||
|
|
||||||
|
Item *sj_conds= hash_sj_engine->semi_join_conds;
|
||||||
|
|
||||||
|
(*join_where)= and_items(*join_where, sj_conds);
|
||||||
|
if (!(*join_where)->fixed)
|
||||||
|
(*join_where)->fix_fields(join->thd, join_where);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((nested_join= table->nested_join))
|
||||||
|
{
|
||||||
|
if (setup_jtbm_semi_joins(join, &nested_join->join_list, join_where))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Choose an optimal strategy to execute an IN/ALL/ANY subquery predicate
|
Choose an optimal strategy to execute an IN/ALL/ANY subquery predicate
|
||||||
based on cost.
|
based on cost.
|
||||||
|
@ -4931,8 +5159,16 @@ bool JOIN::choose_tableless_subquery_plan()
|
||||||
NULL.
|
NULL.
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subs_predicate->is_in_predicate())
|
/*
|
||||||
|
For IN subqueries, use IN->EXISTS transfomation, unless the subquery
|
||||||
|
has been converted to a JTBM semi-join. In that case, just leave
|
||||||
|
everything as-is, setup_jtbm_semi_joins() has special handling for cases
|
||||||
|
like this.
|
||||||
|
*/
|
||||||
|
if (subs_predicate->is_in_predicate() &&
|
||||||
|
!(subs_predicate->substype() == Item_subselect::IN_SUBS &&
|
||||||
|
((Item_in_subselect*)subs_predicate)->is_jtbm_merged))
|
||||||
{
|
{
|
||||||
Item_in_subselect *in_subs;
|
Item_in_subselect *in_subs;
|
||||||
in_subs= (Item_in_subselect*) subs_predicate;
|
in_subs= (Item_in_subselect*) subs_predicate;
|
||||||
|
|
|
@ -10,6 +10,8 @@ int check_and_do_in_subquery_rewrites(JOIN *join);
|
||||||
bool convert_join_subqueries_to_semijoins(JOIN *join);
|
bool convert_join_subqueries_to_semijoins(JOIN *join);
|
||||||
int pull_out_semijoin_tables(JOIN *join);
|
int pull_out_semijoin_tables(JOIN *join);
|
||||||
bool optimize_semijoin_nests(JOIN *join, table_map all_table_map);
|
bool optimize_semijoin_nests(JOIN *join, table_map all_table_map);
|
||||||
|
bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
|
||||||
|
Item **join_where);
|
||||||
|
|
||||||
// used by Loose_scan_opt
|
// used by Loose_scan_opt
|
||||||
ulonglong get_bound_sj_equalities(TABLE_LIST *sj_nest,
|
ulonglong get_bound_sj_equalities(TABLE_LIST *sj_nest,
|
||||||
|
|
|
@ -798,117 +798,6 @@ err:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Create a dummy temporary table, useful only for the sake of having a
|
|
||||||
TABLE* object with map,tablenr and maybe_null properties.
|
|
||||||
|
|
||||||
This is used by non-mergeable semi-join materilization code to handle
|
|
||||||
degenerate cases where materialized subquery produced "Impossible WHERE"
|
|
||||||
and thus wasn't materialized.
|
|
||||||
*/
|
|
||||||
|
|
||||||
TABLE *create_dummy_tmp_table(THD *thd)
|
|
||||||
{
|
|
||||||
DBUG_ENTER("create_dummy_tmp_table");
|
|
||||||
TABLE *table;
|
|
||||||
TMP_TABLE_PARAM sjm_table_param;
|
|
||||||
sjm_table_param.init();
|
|
||||||
sjm_table_param.field_count= 1;
|
|
||||||
List<Item> sjm_table_cols;
|
|
||||||
Item *column_item= new Item_int(1);
|
|
||||||
sjm_table_cols.push_back(column_item);
|
|
||||||
if (!(table= create_tmp_table(thd, &sjm_table_param,
|
|
||||||
sjm_table_cols, (ORDER*) 0,
|
|
||||||
TRUE /* distinct */,
|
|
||||||
1, /*save_sum_fields*/
|
|
||||||
thd->options | TMP_TABLE_ALL_COLUMNS,
|
|
||||||
HA_POS_ERROR /*rows_limit */,
|
|
||||||
(char*)"dummy", TRUE /* Do not open */)))
|
|
||||||
{
|
|
||||||
DBUG_RETURN(NULL);
|
|
||||||
}
|
|
||||||
DBUG_RETURN(table);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list, Item **join_where)
|
|
||||||
{
|
|
||||||
TABLE_LIST *table;
|
|
||||||
NESTED_JOIN *nested_join;
|
|
||||||
List_iterator<TABLE_LIST> li(*join_list);
|
|
||||||
DBUG_ENTER("setup_jtbm_semi_joins");
|
|
||||||
|
|
||||||
|
|
||||||
while ((table= li++))
|
|
||||||
{
|
|
||||||
Item_in_subselect *item;
|
|
||||||
|
|
||||||
if ((item= table->jtbm_subselect))
|
|
||||||
{
|
|
||||||
Item_in_subselect *subq_pred= item;
|
|
||||||
double rows;
|
|
||||||
double read_time;
|
|
||||||
|
|
||||||
subq_pred->optimize(&rows, &read_time);
|
|
||||||
subq_pred->jtbm_read_time= read_time;
|
|
||||||
subq_pred->jtbm_record_count=rows;
|
|
||||||
subq_pred->is_jtbm_merged= TRUE;
|
|
||||||
JOIN *subq_join= subq_pred->unit->first_select()->join;
|
|
||||||
if (!subq_join->tables_list || !subq_join->table_count)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
This is an empty and constant table.
|
|
||||||
|
|
||||||
TODO: what if this is not empty but still constant?
|
|
||||||
|
|
||||||
We'll need to check the equality but there's no materializatnion
|
|
||||||
table?
|
|
||||||
|
|
||||||
A: create an IN-equality from
|
|
||||||
- left_expr
|
|
||||||
- right_expr. Q: how can right-expr exist in the context of
|
|
||||||
parent select? We don't have refs from outside to inside!
|
|
||||||
A: create/check in the context of the child select?
|
|
||||||
|
|
||||||
for injection, check how in->exists is performed.
|
|
||||||
*/
|
|
||||||
subq_pred->is_jtbm_const_tab= TRUE;
|
|
||||||
|
|
||||||
TABLE *dummy_table= create_dummy_tmp_table(join->thd);
|
|
||||||
table->table= dummy_table;
|
|
||||||
table->table->pos_in_table_list= table;
|
|
||||||
|
|
||||||
setup_table_map(table->table, table, table->jtbm_table_no);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DBUG_ASSERT(subq_pred->test_set_strategy(SUBS_MATERIALIZATION));
|
|
||||||
subq_pred->is_jtbm_const_tab= FALSE;
|
|
||||||
subselect_hash_sj_engine *hash_sj_engine=
|
|
||||||
((subselect_hash_sj_engine*)item->engine);
|
|
||||||
|
|
||||||
table->table= hash_sj_engine->tmp_table;
|
|
||||||
table->table->pos_in_table_list= table;
|
|
||||||
|
|
||||||
setup_table_map(table->table, table, table->jtbm_table_no);
|
|
||||||
|
|
||||||
Item *sj_conds= hash_sj_engine->semi_join_conds;
|
|
||||||
|
|
||||||
(*join_where)= and_items(*join_where, sj_conds);
|
|
||||||
if (!(*join_where)->fixed)
|
|
||||||
(*join_where)->fix_fields(join->thd, join_where);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((nested_join= table->nested_join))
|
|
||||||
{
|
|
||||||
setup_jtbm_semi_joins(join, &nested_join->join_list, join_where);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DBUG_VOID_RETURN;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
global select optimisation.
|
global select optimisation.
|
||||||
|
|
||||||
|
@ -1030,7 +919,8 @@ JOIN::optimize()
|
||||||
thd->restore_active_arena(arena, &backup);
|
thd->restore_active_arena(arena, &backup);
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_jtbm_semi_joins(this, join_list, &conds);
|
if (setup_jtbm_semi_joins(this, join_list, &conds))
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
conds= optimize_cond(this, conds, join_list, &cond_value, &cond_equal);
|
conds= optimize_cond(this, conds, join_list, &cond_value, &cond_equal);
|
||||||
|
|
||||||
|
@ -15658,7 +15548,12 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos)
|
||||||
tab->table->pos_in_table_list->jtbm_subselect->is_jtbm_const_tab)
|
tab->table->pos_in_table_list->jtbm_subselect->is_jtbm_const_tab)
|
||||||
{
|
{
|
||||||
/* Row will not be found */
|
/* Row will not be found */
|
||||||
DBUG_RETURN(-1);
|
int res;
|
||||||
|
if (tab->table->pos_in_table_list->jtbm_subselect->jtbm_const_row_found)
|
||||||
|
res= 0;
|
||||||
|
else
|
||||||
|
res= -1;
|
||||||
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
else if (tab->type == JT_SYSTEM)
|
else if (tab->type == JT_SYSTEM)
|
||||||
{
|
{
|
||||||
|
@ -21455,11 +21350,20 @@ void TABLE_LIST::print(THD *thd, table_map eliminated_tables, String *str,
|
||||||
}
|
}
|
||||||
else if (jtbm_subselect)
|
else if (jtbm_subselect)
|
||||||
{
|
{
|
||||||
str->append(STRING_WITH_LEN(" <materialize> ("));
|
if (jtbm_subselect->is_jtbm_const_tab)
|
||||||
subselect_hash_sj_engine *hash_engine;
|
{
|
||||||
hash_engine= (subselect_hash_sj_engine*)jtbm_subselect->engine;
|
str->append(STRING_WITH_LEN(" <materialize> ("));
|
||||||
hash_engine->materialize_engine->print(str, query_type);
|
jtbm_subselect->engine->print(str, query_type);
|
||||||
str->append(')');
|
str->append(')');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
str->append(STRING_WITH_LEN(" <materialize> ("));
|
||||||
|
subselect_hash_sj_engine *hash_engine;
|
||||||
|
hash_engine= (subselect_hash_sj_engine*)jtbm_subselect->engine;
|
||||||
|
hash_engine->materialize_engine->print(str, query_type);
|
||||||
|
str->append(')');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue