Commit 79b82323 authored by konstantin@mysql.com's avatar konstantin@mysql.com

A followup patch for Bug#7306 (limit in prepared statements):

don't evaluate subqueries during statement prepare, even if they
are not correlated.
With post-review fixes.
parent 620d4231
...@@ -336,6 +336,8 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; ...@@ -336,6 +336,8 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
#define UNCACHEABLE_SIDEEFFECT 4 #define UNCACHEABLE_SIDEEFFECT 4
// forcing to save JOIN for explain // forcing to save JOIN for explain
#define UNCACHEABLE_EXPLAIN 8 #define UNCACHEABLE_EXPLAIN 8
/* Don't evaluate subqueries in prepare even if they're not correlated */
#define UNCACHEABLE_PREPARE 16
#ifdef EXTRA_DEBUG #ifdef EXTRA_DEBUG
/* /*
......
...@@ -1757,6 +1757,7 @@ void st_select_lex_unit::set_limit(SELECT_LEX *sl) ...@@ -1757,6 +1757,7 @@ void st_select_lex_unit::set_limit(SELECT_LEX *sl)
{ {
ulonglong select_limit_val; ulonglong select_limit_val;
DBUG_ASSERT(! thd->current_arena->is_stmt_prepare());
select_limit_val= sl->select_limit ? sl->select_limit->val_uint() : select_limit_val= sl->select_limit ? sl->select_limit->val_uint() :
HA_POS_ERROR; HA_POS_ERROR;
offset_limit_cnt= sl->offset_limit ? sl->offset_limit->val_uint() : ULL(0); offset_limit_cnt= sl->offset_limit ? sl->offset_limit->val_uint() : ULL(0);
......
...@@ -303,6 +303,7 @@ class st_select_lex_node { ...@@ -303,6 +303,7 @@ class st_select_lex_node {
UNCACHEABLE_RAND UNCACHEABLE_RAND
UNCACHEABLE_SIDEEFFECT UNCACHEABLE_SIDEEFFECT
UNCACHEABLE_EXPLAIN UNCACHEABLE_EXPLAIN
UNCACHEABLE_PREPARE
*/ */
uint8 uncacheable; uint8 uncacheable;
enum sub_select_type linkage; enum sub_select_type linkage;
......
...@@ -5169,26 +5169,28 @@ bool ...@@ -5169,26 +5169,28 @@ bool
mysql_new_select(LEX *lex, bool move_down) mysql_new_select(LEX *lex, bool move_down)
{ {
SELECT_LEX *select_lex; SELECT_LEX *select_lex;
THD *thd; THD *thd= lex->thd;
DBUG_ENTER("mysql_new_select"); DBUG_ENTER("mysql_new_select");
if (!(select_lex= new(lex->thd->mem_root) SELECT_LEX())) if (!(select_lex= new (thd->mem_root) SELECT_LEX()))
DBUG_RETURN(1); DBUG_RETURN(1);
select_lex->select_number= ++lex->thd->select_number; select_lex->select_number= ++thd->select_number;
select_lex->init_query(); select_lex->init_query();
select_lex->init_select(); select_lex->init_select();
select_lex->parent_lex= lex; select_lex->parent_lex= lex;
if (thd->current_arena->is_stmt_prepare())
select_lex->uncacheable|= UNCACHEABLE_PREPARE;
if (move_down) if (move_down)
{ {
SELECT_LEX_UNIT *unit; SELECT_LEX_UNIT *unit;
lex->subqueries= TRUE; lex->subqueries= TRUE;
/* first select_lex of subselect or derived table */ /* first select_lex of subselect or derived table */
if (!(unit= new(lex->thd->mem_root) SELECT_LEX_UNIT())) if (!(unit= new (thd->mem_root) SELECT_LEX_UNIT()))
DBUG_RETURN(1); DBUG_RETURN(1);
unit->init_query(); unit->init_query();
unit->init_select(); unit->init_select();
unit->thd= lex->thd; unit->thd= thd;
unit->include_down(lex->current_select); unit->include_down(lex->current_select);
unit->link_next= 0; unit->link_next= 0;
unit->link_prev= 0; unit->link_prev= 0;
...@@ -5212,7 +5214,7 @@ mysql_new_select(LEX *lex, bool move_down) ...@@ -5212,7 +5214,7 @@ mysql_new_select(LEX *lex, bool move_down)
as far as we included SELECT_LEX for UNION unit should have as far as we included SELECT_LEX for UNION unit should have
fake SELECT_LEX for UNION processing fake SELECT_LEX for UNION processing
*/ */
if (!(fake= unit->fake_select_lex= new(lex->thd->mem_root) SELECT_LEX())) if (!(fake= unit->fake_select_lex= new (thd->mem_root) SELECT_LEX()))
DBUG_RETURN(1); DBUG_RETURN(1);
fake->include_standalone(unit, fake->include_standalone(unit,
(SELECT_LEX_NODE**)&unit->fake_select_lex); (SELECT_LEX_NODE**)&unit->fake_select_lex);
......
...@@ -1838,7 +1838,10 @@ void init_stmt_after_parse(THD *thd, LEX *lex) ...@@ -1838,7 +1838,10 @@ void init_stmt_after_parse(THD *thd, LEX *lex)
optimisation. optimisation.
*/ */
for (; sl; sl= sl->next_select_in_list()) for (; sl; sl= sl->next_select_in_list())
{
sl->prep_where= sl->where; sl->prep_where= sl->where;
sl->uncacheable&= ~UNCACHEABLE_PREPARE;
}
for (TABLE_LIST *table= lex->query_tables; table; table= table->next_global) for (TABLE_LIST *table= lex->query_tables; table; table= table->next_global)
table->prep_on_expr= table->on_expr; table->prep_on_expr= table->on_expr;
......
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