Commit 62cc4df4 authored by Sergey Petrunya's avatar Sergey Petrunya

Alternate version of MySQL's fix for BUG#49453.

The cause of the crash is sj_nest->sj_subq_pred->unit->first_select()->item_list
contains "stale" items for the second execution. By "stale" I mean that they have
item->fixed==FALSE, and they are Item_field object instead of Item_direct_view_ref.

The solution is to use sj_nest->sj_subq_pred->unit->first_select()->ref_pointer_array.
Surprisingly, that array contains items that are ok.

Oracle team has introduced and is using NESTED_JOIN::sj_inner_exprs, but we go without that
and always copy the ref_pointer_array.
parent 9e7495df
...@@ -183,7 +183,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred); ...@@ -183,7 +183,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred);
static bool convert_subq_to_jtbm(JOIN *parent_join, static bool convert_subq_to_jtbm(JOIN *parent_join,
Item_in_subselect *subq_pred, bool *remove); Item_in_subselect *subq_pred, bool *remove);
static TABLE_LIST *alloc_join_nest(THD *thd); static TABLE_LIST *alloc_join_nest(THD *thd);
static uint get_tmp_table_rec_length(List<Item> &items); static uint get_tmp_table_rec_length(Item **p_list, uint elements);
static double get_tmp_table_lookup_cost(THD *thd, double row_count, static double get_tmp_table_lookup_cost(THD *thd, double row_count,
uint row_size); uint row_size);
static double get_tmp_table_write_cost(THD *thd, double row_count, static double get_tmp_table_write_cost(THD *thd, double row_count,
...@@ -1806,8 +1806,11 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map) ...@@ -1806,8 +1806,11 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map)
sjm->materialization_cost.convert_from_cost(subjoin_read_time); sjm->materialization_cost.convert_from_cost(subjoin_read_time);
sjm->rows= subjoin_out_rows; sjm->rows= subjoin_out_rows;
List<Item> &right_expr_list= // Don't use the following list because it has "stale" items. use
sj_nest->sj_subq_pred->unit->first_select()->item_list; // ref_pointer_array instead:
//
//List<Item> &right_expr_list=
// sj_nest->sj_subq_pred->unit->first_select()->item_list;
/* /*
Adjust output cardinality estimates. If the subquery has form Adjust output cardinality estimates. If the subquery has form
...@@ -1825,17 +1828,20 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map) ...@@ -1825,17 +1828,20 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map)
See also get_post_group_estimate(). See also get_post_group_estimate().
*/ */
SELECT_LEX *subq_select= sj_nest->sj_subq_pred->unit->first_select();
{ {
for (uint i=0 ; i < join->const_tables + sjm->tables ; i++) for (uint i=0 ; i < join->const_tables + sjm->tables ; i++)
{ {
JOIN_TAB *tab= join->best_positions[i].table; JOIN_TAB *tab= join->best_positions[i].table;
join->map2table[tab->table->tablenr]= tab; join->map2table[tab->table->tablenr]= tab;
} }
List_iterator<Item> it(right_expr_list); //List_iterator<Item> it(right_expr_list);
Item *item; Item **ref_array= subq_select->ref_pointer_array;
Item **ref_array_end= ref_array + subq_select->item_list.elements;
table_map map= 0; table_map map= 0;
while ((item= it++)) //while ((item= it++))
map |= item->used_tables(); for (;ref_array < ref_array_end; ref_array++)
map |= (*ref_array)->used_tables();
map= map & ~PSEUDO_TABLE_BITS; map= map & ~PSEUDO_TABLE_BITS;
Table_map_iterator tm_it(map); Table_map_iterator tm_it(map);
int tableno; int tableno;
...@@ -1850,7 +1856,8 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map) ...@@ -1850,7 +1856,8 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map)
/* /*
Calculate temporary table parameters and usage costs Calculate temporary table parameters and usage costs
*/ */
uint rowlen= get_tmp_table_rec_length(right_expr_list); uint rowlen= get_tmp_table_rec_length(subq_select->ref_pointer_array,
subq_select->item_list.elements);
double lookup_cost= get_tmp_table_lookup_cost(join->thd, double lookup_cost= get_tmp_table_lookup_cost(join->thd,
subjoin_out_rows, rowlen); subjoin_out_rows, rowlen);
double write_cost= get_tmp_table_write_cost(join->thd, double write_cost= get_tmp_table_write_cost(join->thd,
...@@ -1897,13 +1904,15 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map) ...@@ -1897,13 +1904,15 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map)
Length of the temptable record, in bytes Length of the temptable record, in bytes
*/ */
static uint get_tmp_table_rec_length(List<Item> &items) static uint get_tmp_table_rec_length(Item **p_items, uint elements)
{ {
uint len= 0; uint len= 0;
Item *item; Item *item;
List_iterator<Item> it(items); //List_iterator<Item> it(items);
while ((item= it++)) Item **p_item;
for (p_item= p_items; p_item < p_items + elements ; p_item++)
{ {
item = *p_item;
switch (item->result_type()) { switch (item->result_type()) {
case REAL_RESULT: case REAL_RESULT:
len += sizeof(double); len += sizeof(double);
...@@ -2908,19 +2917,23 @@ bool setup_sj_materialization_part1(JOIN_TAB *sjm_tab) ...@@ -2908,19 +2917,23 @@ bool setup_sj_materialization_part1(JOIN_TAB *sjm_tab)
SJ_MATERIALIZATION_INFO *sjm= emb_sj_nest->sj_mat_info; SJ_MATERIALIZATION_INFO *sjm= emb_sj_nest->sj_mat_info;
THD *thd= tab->join->thd; THD *thd= tab->join->thd;
/* First the calls come to the materialization function */ /* First the calls come to the materialization function */
List<Item> &item_list= emb_sj_nest->sj_subq_pred->unit->first_select()->item_list; //List<Item> &item_list= emb_sj_nest->sj_subq_pred->unit->first_select()->item_list;
DBUG_ASSERT(sjm->is_used); DBUG_ASSERT(sjm->is_used);
/* /*
Set up the table to write to, do as select_union::create_result_table does Set up the table to write to, do as select_union::create_result_table does
*/ */
sjm->sjm_table_param.init(); sjm->sjm_table_param.init();
sjm->sjm_table_param.field_count= item_list.elements;
sjm->sjm_table_param.bit_fields_as_long= TRUE; sjm->sjm_table_param.bit_fields_as_long= TRUE;
List_iterator<Item> it(item_list); //List_iterator<Item> it(item_list);
Item *right_expr; SELECT_LEX *subq_select= emb_sj_nest->sj_subq_pred->unit->first_select();
while((right_expr= it++)) Item **p_item= subq_select->ref_pointer_array;
sjm->sjm_table_cols.push_back(right_expr); Item **p_end= p_item + subq_select->item_list.elements;
//while((right_expr= it++))
for(;p_item != p_end; p_item++)
sjm->sjm_table_cols.push_back(*p_item);
sjm->sjm_table_param.field_count= subq_select->item_list.elements;
if (!(sjm->table= create_tmp_table(thd, &sjm->sjm_table_param, if (!(sjm->table= create_tmp_table(thd, &sjm->sjm_table_param,
sjm->sjm_table_cols, (ORDER*) 0, sjm->sjm_table_cols, (ORDER*) 0,
...@@ -2952,8 +2965,8 @@ bool setup_sj_materialization_part2(JOIN_TAB *sjm_tab) ...@@ -2952,8 +2965,8 @@ bool setup_sj_materialization_part2(JOIN_TAB *sjm_tab)
SJ_MATERIALIZATION_INFO *sjm= emb_sj_nest->sj_mat_info; SJ_MATERIALIZATION_INFO *sjm= emb_sj_nest->sj_mat_info;
THD *thd= tab->join->thd; THD *thd= tab->join->thd;
uint i; uint i;
List<Item> &item_list= emb_sj_nest->sj_subq_pred->unit->first_select()->item_list; //List<Item> &item_list= emb_sj_nest->sj_subq_pred->unit->first_select()->item_list;
List_iterator<Item> it(item_list); //List_iterator<Item> it(item_list);
if (!sjm->is_sj_scan) if (!sjm->is_sj_scan)
{ {
...@@ -3069,11 +3082,13 @@ bool setup_sj_materialization_part2(JOIN_TAB *sjm_tab) ...@@ -3069,11 +3082,13 @@ bool setup_sj_materialization_part2(JOIN_TAB *sjm_tab)
*/ */
sjm->copy_field= new Copy_field[sjm->sjm_table_cols.elements]; sjm->copy_field= new Copy_field[sjm->sjm_table_cols.elements];
//it.rewind(); //it.rewind();
Item **p_item= emb_sj_nest->sj_subq_pred->unit->first_select()->ref_pointer_array;
for (uint i=0; i < sjm->sjm_table_cols.elements; i++) for (uint i=0; i < sjm->sjm_table_cols.elements; i++)
{ {
bool dummy; bool dummy;
Item_equal *item_eq; Item_equal *item_eq;
Item *item= (it++)->real_item(); //Item *item= (it++)->real_item();
Item *item= (*(p_item++))->real_item();
DBUG_ASSERT(item->type() == Item::FIELD_ITEM); DBUG_ASSERT(item->type() == Item::FIELD_ITEM);
Field *copy_to= ((Item_field*)item)->field; Field *copy_to= ((Item_field*)item)->field;
/* /*
...@@ -4513,7 +4528,9 @@ bool JOIN::choose_subquery_plan(table_map join_tables) ...@@ -4513,7 +4528,9 @@ bool JOIN::choose_subquery_plan(table_map join_tables)
C. Compute execution costs. C. Compute execution costs.
*/ */
/* C.1 Compute the cost of the materialization strategy. */ /* C.1 Compute the cost of the materialization strategy. */
uint rowlen= get_tmp_table_rec_length(unit->first_select()->item_list); //uint rowlen= get_tmp_table_rec_length(unit->first_select()->item_list);
uint rowlen= get_tmp_table_rec_length(ref_pointer_array,
select_lex->item_list.elements);
/* The cost of writing one row into the temporary table. */ /* The cost of writing one row into the temporary table. */
double write_cost= get_tmp_table_write_cost(thd, inner_record_count_1, double write_cost= get_tmp_table_write_cost(thd, inner_record_count_1,
rowlen); rowlen);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment