mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
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. sql/mysql_priv.h: Add UNCACHEABLE_PREPARE to mark subqueries as non-constant in mysql_stmt_prepare sql/sql_lex.cc: Add a missing assert: noone can call unit::set_limit from mysql_stmt_prepare. sql/sql_lex.h: Comment fixed. sql/sql_parse.cc: Mark new SELECT_LEXes as uncacheable if they created during statement prepare. sql/sql_prepare.cc: Switch off the uncacheable flag when prepare is done.
This commit is contained in:
parent
0bc3c6221c
commit
936688feb5
5 changed files with 15 additions and 6 deletions
|
@ -336,6 +336,8 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
|
|||
#define UNCACHEABLE_SIDEEFFECT 4
|
||||
// forcing to save JOIN for explain
|
||||
#define UNCACHEABLE_EXPLAIN 8
|
||||
/* Don't evaluate subqueries in prepare even if they're not correlated */
|
||||
#define UNCACHEABLE_PREPARE 16
|
||||
|
||||
#ifdef EXTRA_DEBUG
|
||||
/*
|
||||
|
|
|
@ -1757,6 +1757,7 @@ void st_select_lex_unit::set_limit(SELECT_LEX *sl)
|
|||
{
|
||||
ulonglong select_limit_val;
|
||||
|
||||
DBUG_ASSERT(! thd->current_arena->is_stmt_prepare());
|
||||
select_limit_val= sl->select_limit ? sl->select_limit->val_uint() :
|
||||
HA_POS_ERROR;
|
||||
offset_limit_cnt= sl->offset_limit ? sl->offset_limit->val_uint() : ULL(0);
|
||||
|
|
|
@ -303,6 +303,7 @@ public:
|
|||
UNCACHEABLE_RAND
|
||||
UNCACHEABLE_SIDEEFFECT
|
||||
UNCACHEABLE_EXPLAIN
|
||||
UNCACHEABLE_PREPARE
|
||||
*/
|
||||
uint8 uncacheable;
|
||||
enum sub_select_type linkage;
|
||||
|
|
|
@ -5169,26 +5169,28 @@ bool
|
|||
mysql_new_select(LEX *lex, bool move_down)
|
||||
{
|
||||
SELECT_LEX *select_lex;
|
||||
THD *thd;
|
||||
THD *thd= lex->thd;
|
||||
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);
|
||||
select_lex->select_number= ++lex->thd->select_number;
|
||||
select_lex->select_number= ++thd->select_number;
|
||||
select_lex->init_query();
|
||||
select_lex->init_select();
|
||||
select_lex->parent_lex= lex;
|
||||
if (thd->current_arena->is_stmt_prepare())
|
||||
select_lex->uncacheable|= UNCACHEABLE_PREPARE;
|
||||
if (move_down)
|
||||
{
|
||||
SELECT_LEX_UNIT *unit;
|
||||
lex->subqueries= TRUE;
|
||||
/* 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);
|
||||
|
||||
unit->init_query();
|
||||
unit->init_select();
|
||||
unit->thd= lex->thd;
|
||||
unit->thd= thd;
|
||||
unit->include_down(lex->current_select);
|
||||
unit->link_next= 0;
|
||||
unit->link_prev= 0;
|
||||
|
@ -5212,7 +5214,7 @@ mysql_new_select(LEX *lex, bool move_down)
|
|||
as far as we included SELECT_LEX for UNION unit should have
|
||||
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);
|
||||
fake->include_standalone(unit,
|
||||
(SELECT_LEX_NODE**)&unit->fake_select_lex);
|
||||
|
|
|
@ -1838,7 +1838,10 @@ void init_stmt_after_parse(THD *thd, LEX *lex)
|
|||
optimisation.
|
||||
*/
|
||||
for (; sl; sl= sl->next_select_in_list())
|
||||
{
|
||||
sl->prep_where= sl->where;
|
||||
sl->uncacheable&= ~UNCACHEABLE_PREPARE;
|
||||
}
|
||||
|
||||
for (TABLE_LIST *table= lex->query_tables; table; table= table->next_global)
|
||||
table->prep_on_expr= table->on_expr;
|
||||
|
|
Loading…
Reference in a new issue