summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <konstantin@mysql.com>2005-06-08 00:34:53 +0400
committerunknown <konstantin@mysql.com>2005-06-08 00:34:53 +0400
commit936688feb5638a8e11d0de363a05eaced99abdd5 (patch)
tree45fafa0273fdf02d6120d49c8ab078c18fe54107
parent0bc3c6221cbaae56ba444e06603c4afbf11f685e (diff)
downloadmariadb-git-936688feb5638a8e11d0de363a05eaced99abdd5.tar.gz
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.
-rw-r--r--sql/mysql_priv.h2
-rw-r--r--sql/sql_lex.cc1
-rw-r--r--sql/sql_lex.h1
-rw-r--r--sql/sql_parse.cc14
-rw-r--r--sql/sql_prepare.cc3
5 files changed, 15 insertions, 6 deletions
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index e8ec1b69959..338e45fa058 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -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
/*
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 6b9330182d6..1270aab18ae 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -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);
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 5022392565c..a6f729d7677 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -303,6 +303,7 @@ public:
UNCACHEABLE_RAND
UNCACHEABLE_SIDEEFFECT
UNCACHEABLE_EXPLAIN
+ UNCACHEABLE_PREPARE
*/
uint8 uncacheable;
enum sub_select_type linkage;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 7d00cfa4c98..f48bc3713e6 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -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);
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 1521b206e0d..4440e542434 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -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;