1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

BUG#868908: Crash in check_simple_equality() with semijoin + materialization + prepared statement

- Part 1 of the fix: for semi-join merged subqueries, calling child_join->optimize() until we're done with all
  PS-lifetime optimizations in the parent.
This commit is contained in:
Sergey Petrunya
2011-12-07 01:03:00 +04:00
parent 264aaf111d
commit 8e25dcfcd7
11 changed files with 225 additions and 34 deletions

View File

@ -798,6 +798,39 @@ 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
inject_jtbm_conds(JOIN *join, List<TABLE_LIST> *join_list, Item **join_where)
{
@ -817,29 +850,58 @@ inject_jtbm_conds(JOIN *join, List<TABLE_LIST> *join_list, Item **join_where)
double rows;
double read_time;
//DBUG_ASSERT(subq_pred->test_set_strategy(SUBS_MATERIALIZATION));
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.
subselect_hash_sj_engine *hash_sj_engine=
((subselect_hash_sj_engine*)item->engine);
//repeat of convert_subq_to_jtbm:
table->table= hash_sj_engine->tmp_table;
table->table->pos_in_table_list= table;
TODO: what if this is not empty but still constant?
We'll need to check the equality but there's no materializatnion
table?
setup_table_map(table->table, table, table->jtbm_table_no);
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;
Item *sj_conds= hash_sj_engine->semi_join_conds;
TABLE *dummy_table= create_dummy_tmp_table(join->thd);
table->table= dummy_table;
table->table->pos_in_table_list= table;
(*join_where)= and_items(*join_where, sj_conds);
if (!(*join_where)->fixed)
(*join_where)->fix_fields(join->thd, join_where);
//parent_join->select_lex->where= parent_join->conds;
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);
//repeat of convert_subq_to_jtbm:
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);
//parent_join->select_lex->where= parent_join->conds;
}
}
if ((nested_join= table->nested_join))
@ -3120,6 +3182,14 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
set_position(join,const_count++,s,(KEYUSE*) 0);
no_rows_const_tables |= table->map;
}
/* SJ-Materialization handling: */
if (table->pos_in_table_list->jtbm_subselect &&
table->pos_in_table_list->jtbm_subselect->is_jtbm_const_tab)
{
set_position(join,const_count++,s,(KEYUSE*) 0);
no_rows_const_tables |= table->map;
}
}
stat_vector[i]=0;
@ -9629,8 +9699,16 @@ void JOIN_TAB::cleanup()
if (table->pos_in_table_list &&
table->pos_in_table_list->jtbm_subselect)
{
end_read_record(&read_record);
table->pos_in_table_list->jtbm_subselect->cleanup();
if (table->pos_in_table_list->jtbm_subselect->is_jtbm_const_tab)
{
free_tmp_table(join->thd, table);
table= NULL;
}
else
{
end_read_record(&read_record);
table->pos_in_table_list->jtbm_subselect->cleanup();
}
DBUG_VOID_RETURN;
}
/*
@ -11904,7 +11982,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top,
{
if (!table->prep_on_expr)
table->prep_on_expr= table->on_expr;
used_tables= table->table->map;
used_tables= table->get_map();
if (conds)
not_null_tables= conds->not_null_tables();
}
@ -11961,7 +12039,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top,
table->embedding->on_expr_dep_tables|= table->on_expr->used_tables();
}
else
table->dep_tables&= ~table->table->map;
table->dep_tables&= ~table->get_map();
}
if (prev_table)
@ -11974,7 +12052,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top,
prev_table->dep_tables|= table->on_expr_dep_tables;
table_map prev_used_tables= prev_table->nested_join ?
prev_table->nested_join->used_tables :
prev_table->table->map;
prev_table->get_map();
/*
If on expression contains only references to inner tables
we still make the inner tables dependent on the outer tables.
@ -15525,6 +15603,12 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos)
/* Skip materialized derived tables/views. */
DBUG_RETURN(0);
}
else if (tab->table->pos_in_table_list->jtbm_subselect &&
tab->table->pos_in_table_list->jtbm_subselect->is_jtbm_const_tab)
{
/* Row will not be found */
DBUG_RETURN(-1);
}
else if (tab->type == JT_SYSTEM)
{
if ((error=join_read_system(tab)))