Commit 3c9594b0 authored by sergefp@pylon.mylan's avatar sergefp@pylon.mylan

Merge spetrunia@bk-internal.mysql.com:/home/bk/mysql-5.0-opt

into  mysql.com:/home/psergey/mysql-5.0-bug29582
parents de8f84ad c37f9b9e
...@@ -2417,7 +2417,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, ...@@ -2417,7 +2417,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
if ((table->s->system || table->file->records <= 1) && ! s->dependent && if ((table->s->system || table->file->records <= 1) && ! s->dependent &&
!(table->file->table_flags() & HA_NOT_EXACT_COUNT) && !(table->file->table_flags() & HA_NOT_EXACT_COUNT) &&
!table->fulltext_searched) !table->fulltext_searched && !join->no_const_tables)
{ {
set_position(join,const_count++,s,(KEYUSE*) 0); set_position(join,const_count++,s,(KEYUSE*) 0);
} }
......
...@@ -277,6 +277,14 @@ public: ...@@ -277,6 +277,14 @@ public:
SELECT_LEX_UNIT *unit; SELECT_LEX_UNIT *unit;
// select that processed // select that processed
SELECT_LEX *select_lex; SELECT_LEX *select_lex;
/*
TRUE <=> optimizer must not mark any table as a constant table.
This is needed for subqueries in form "a IN (SELECT .. UNION SELECT ..):
when we optimize the select that reads the results of the union from a
temporary table, we must not mark the temp. table as constant because
the number of rows in it may vary from one subquery execution to another.
*/
bool no_const_tables;
JOIN *tmp_join; // copy of this JOIN to be used with temporary tables JOIN *tmp_join; // copy of this JOIN to be used with temporary tables
ROLLUP rollup; // Used with rollup ROLLUP rollup; // Used with rollup
...@@ -406,6 +414,8 @@ public: ...@@ -406,6 +414,8 @@ public:
tmp_table_param.init(); tmp_table_param.init();
tmp_table_param.end_write_records= HA_POS_ERROR; tmp_table_param.end_write_records= HA_POS_ERROR;
rollup.state= ROLLUP::STATE_NONE; rollup.state= ROLLUP::STATE_NONE;
no_const_tables= FALSE;
} }
int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num, int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num,
......
...@@ -545,6 +545,10 @@ bool st_select_lex_unit::exec() ...@@ -545,6 +545,10 @@ bool st_select_lex_unit::exec()
/* /*
allocate JOIN for fake select only once (prevent allocate JOIN for fake select only once (prevent
mysql_select automatic allocation) mysql_select automatic allocation)
TODO: The above is nonsense. mysql_select() will not allocate the
join if one already exists. There must be some other reason why we
don't let it allocate the join. Perhaps this is because we need
some special parameter values passed to join constructor?
*/ */
if (!(fake_select_lex->join= new JOIN(thd, item_list, if (!(fake_select_lex->join= new JOIN(thd, item_list,
fake_select_lex->options, result))) fake_select_lex->options, result)))
...@@ -552,33 +556,52 @@ bool st_select_lex_unit::exec() ...@@ -552,33 +556,52 @@ bool st_select_lex_unit::exec()
fake_select_lex->table_list.empty(); fake_select_lex->table_list.empty();
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
fake_select_lex->join->no_const_tables= TRUE;
/* /*
Fake st_select_lex should have item list for correctref_array Fake st_select_lex should have item list for correctref_array
allocation. allocation.
*/ */
fake_select_lex->item_list= item_list; fake_select_lex->item_list= item_list;
saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array,
&result_table_list,
0, item_list, NULL,
global_parameters->order_list.elements,
(ORDER*)global_parameters->order_list.first,
(ORDER*) NULL, NULL, (ORDER*) NULL,
fake_select_lex->options | SELECT_NO_UNLOCK,
result, this, fake_select_lex);
} }
else else
{ {
JOIN_TAB *tab,*end; if (describe)
for (tab=join->join_tab, end=tab+join->tables ; {
tab && tab != end ; /*
tab++) In EXPLAIN command, constant subqueries that do not use any
{ tables are executed two times:
delete tab->select; - 1st time is a real evaluation to get the subquery value
delete tab->quick; - 2nd time is to produce EXPLAIN output rows.
} 1st execution sets certain members (e.g. select_result) to perform
join->init(thd, item_list, fake_select_lex->options, result); subquery execution rather than EXPLAIN line production. In order
to reset them back, we re-do all of the actions (yes it is ugly):
*/
join->init(thd, item_list, fake_select_lex->options, result);
saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array,
&result_table_list,
0, item_list, NULL,
global_parameters->order_list.elements,
(ORDER*)global_parameters->order_list.first,
(ORDER*) NULL, NULL, (ORDER*) NULL,
fake_select_lex->options | SELECT_NO_UNLOCK,
result, this, fake_select_lex);
}
else
{
join->examined_rows= 0;
join->reinit();
saved_error= join->exec();
}
} }
saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array,
&result_table_list,
0, item_list, NULL,
global_parameters->order_list.elements,
(ORDER*)global_parameters->order_list.first,
(ORDER*) NULL, NULL, (ORDER*) NULL,
fake_select_lex->options | SELECT_NO_UNLOCK,
result, this, fake_select_lex);
fake_select_lex->table_list.empty(); fake_select_lex->table_list.empty();
if (!saved_error) if (!saved_error)
......
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