summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/sp.result10
-rw-r--r--mysql-test/t/sp.test12
-rw-r--r--sql/item_subselect.cc42
-rw-r--r--sql/item_subselect.h6
-rw-r--r--sql/item_sum.cc8
-rw-r--r--sql/item_sum.h4
-rw-r--r--sql/mysql_priv.h1
-rw-r--r--sql/sp_head.cc157
-rw-r--r--sql/sp_head.h21
-rw-r--r--sql/sql_base.cc67
-rw-r--r--sql/sql_class.cc55
-rw-r--r--sql/sql_class.h93
-rw-r--r--sql/sql_delete.cc8
-rw-r--r--sql/sql_derived.cc2
-rw-r--r--sql/sql_insert.cc1
-rw-r--r--sql/sql_lex.cc16
-rw-r--r--sql/sql_lex.h8
-rw-r--r--sql/sql_parse.cc2
-rw-r--r--sql/sql_prepare.cc53
-rw-r--r--sql/sql_select.cc12
-rw-r--r--sql/sql_union.cc21
-rw-r--r--sql/sql_update.cc12
22 files changed, 331 insertions, 280 deletions
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index cd5c2aa67c1..f8dcc114990 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -1305,3 +1305,13 @@ test bar PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINE
drop procedure bar|
drop table t1;
drop table t2;
+create procedure p1 () select (select s1 from t1) from t1;
+create table t1 (s1 int);
+call p1();
+(select s1 from t1)
+insert into t1 values (1);
+call p1();
+(select s1 from t1)
+1
+drop procedure p1;
+drop table t1;
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 867aa96256f..6a8dcca409a 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -1450,3 +1450,15 @@ drop procedure bar|
delimiter ;|
drop table t1;
drop table t2;
+
+#
+# rexecution
+#
+create procedure p1 () select (select s1 from t1) from t1;
+create table t1 (s1 int);
+call p1();
+insert into t1 values (1);
+call p1();
+drop procedure p1;
+drop table t1;
+
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index a84d75a5895..dc773de158b 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -104,7 +104,7 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
{
DBUG_ASSERT(fixed == 0);
engine->set_thd((thd= thd_param));
- stmt= thd->current_statement;
+ arena= thd->current_arena;
char const *save_where= thd->where;
int res= engine->prepare();
@@ -316,8 +316,8 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
if (join->conds || join->having)
{
Item *cond;
- if (stmt)
- thd->set_n_backup_item_arena(stmt, &backup);
+ if (arena)
+ thd->set_n_backup_item_arena(arena, &backup);
if (!join->having)
cond= join->conds;
@@ -330,15 +330,15 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
new Item_null())))
goto err;
}
- if (stmt)
- thd->restore_backup_item_arena(stmt, &backup);
+ if (arena)
+ thd->restore_backup_item_arena(arena, &backup);
return RES_REDUCE;
}
return RES_OK;
err:
- if (stmt)
- thd->restore_backup_item_arena(stmt, &backup);
+ if (arena)
+ thd->restore_backup_item_arena(arena, &backup);
return RES_ERROR;
}
@@ -618,8 +618,8 @@ Item_in_subselect::single_value_transformer(JOIN *join,
Statement backup;
thd->where= "scalar IN/ALL/ANY subquery";
- if (stmt)
- thd->set_n_backup_item_arena(stmt, &backup);
+ if (arena)
+ thd->set_n_backup_item_arena(arena, &backup);
if (select_lex->item_list.elements > 1)
{
@@ -823,21 +823,21 @@ Item_in_subselect::single_value_transformer(JOIN *join,
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_SELECT_REDUCED, warn_buff);
}
- if (stmt)
- thd->restore_backup_item_arena(stmt, &backup);
+ if (arena)
+ thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(RES_REDUCE);
}
}
}
ok:
- if (stmt)
- thd->restore_backup_item_arena(stmt, &backup);
+ if (arena)
+ thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(RES_OK);
err:
- if (stmt)
- thd->restore_backup_item_arena(stmt, &backup);
+ if (arena)
+ thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(RES_ERROR);
}
@@ -855,8 +855,8 @@ Item_in_subselect::row_value_transformer(JOIN *join)
Item *item= 0;
thd->where= "row IN/ALL/ANY subquery";
- if (stmt)
- thd->set_n_backup_item_arena(stmt, &backup);
+ if (arena)
+ thd->set_n_backup_item_arena(arena, &backup);
SELECT_LEX *select_lex= join->select_lex;
@@ -940,13 +940,13 @@ Item_in_subselect::row_value_transformer(JOIN *join)
if (join->conds->fix_fields(thd, join->tables_list, 0))
goto err;
}
- if (stmt)
- thd->restore_backup_item_arena(stmt, &backup);
+ if (arena)
+ thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(RES_OK);
err:
- if (stmt)
- thd->restore_backup_item_arena(stmt, &backup);
+ if (arena)
+ thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(RES_ERROR);
}
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 6d8f5353695..f9c570d5e25 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -26,7 +26,7 @@ class JOIN;
class select_subselect;
class subselect_engine;
class Item_bool_func2;
-class Statement;
+class Item_arena;
/* base class for subselects */
@@ -36,8 +36,8 @@ class Item_subselect :public Item_result_field
protected:
/* thread handler, will be assigned in fix_fields only */
THD *thd;
- /* prepared statement, or 0 */
- Statement *stmt;
+ /* Item_arena used or 0 */
+ Item_arena *arena;
/* substitution instead of subselect in case of optimization */
Item *substitution;
/* unit of subquery */
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index c68754f6cae..94f791a06cc 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -77,15 +77,15 @@ Item_sum::Item_sum(THD *thd, Item_sum *item):
*/
bool Item_sum::save_args_for_prepared_statements(THD *thd)
{
- if (thd->current_statement)
- return save_args(thd->current_statement);
+ if (thd->current_arena && args_copy == 0)
+ return save_args(thd->current_arena);
return 0;
}
-bool Item_sum::save_args(Statement* stmt)
+bool Item_sum::save_args(Item_arena* arena)
{
- if (!(args_copy= (Item**) stmt->alloc(sizeof(Item*)*arg_count)))
+ if (!(args_copy= (Item**) arena->alloc(sizeof(Item*)*arg_count)))
return 1;
memcpy(args_copy, args, sizeof(Item*)*arg_count);
return 0;
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 953ff76b65d..4da8db11cb0 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -23,6 +23,8 @@
#include <my_tree.h>
+class Item_arena;
+
class Item_sum :public Item_result_field
{
public:
@@ -93,7 +95,7 @@ public:
virtual void make_unique() {}
Item *get_tmp_table_item(THD *thd);
bool save_args_for_prepared_statements(THD *);
- bool save_args(Statement* stmt);
+ bool save_args(Item_arena* stmt);
bool walk (Item_processor processor, byte *argument);
};
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 444c335d7a6..9cd4c65118d 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -681,6 +681,7 @@ void mysql_stmt_reset(THD *thd, char *packet);
void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length);
int check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
List<Item> &values, ulong counter);
+void reset_stmt_for_execute(THD *thd, LEX *lex);
/* sql_error.cc */
MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code,
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 96e340fa745..c22e57830f8 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -186,8 +186,8 @@ sp_head::operator new(size_t size)
bzero((char *)&own_root, sizeof(own_root));
init_alloc_root(&own_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
sp= (sp_head *)alloc_root(&own_root, size);
- sp->m_mem_root= own_root;
-
+ sp->mem_root= own_root;
+ DBUG_PRINT("info", ("mem_root 0x%lx", (ulong) &sp->mem_root));
DBUG_RETURN(sp);
}
@@ -198,16 +198,18 @@ sp_head::operator delete(void *ptr, size_t size)
MEM_ROOT own_root;
sp_head *sp= (sp_head *)ptr;
- DBUG_PRINT("info", ("root: %lx", &sp->m_mem_root));
- memcpy(&own_root, (const void *)&sp->m_mem_root, sizeof(MEM_ROOT));
+ memcpy(&own_root, (const void *)&sp->mem_root, sizeof(MEM_ROOT));
+ DBUG_PRINT("info", ("mem_root 0x%lx moved to 0x%lx",
+ (ulong) &sp->mem_root, (ulong) &own_root));
free_root(&own_root, MYF(0));
DBUG_VOID_RETURN;
}
+
sp_head::sp_head()
- : Sql_alloc(), m_returns_cs(NULL), m_has_return(FALSE), m_simple_case(FALSE),
- m_multi_results(FALSE), m_free_list(NULL)
+ :Item_arena((bool)FALSE), m_returns_cs(NULL), m_has_return(FALSE),
+ m_simple_case(FALSE), m_multi_results(FALSE)
{
DBUG_ENTER("sp_head::sp_head");
@@ -216,6 +218,7 @@ sp_head::sp_head()
DBUG_VOID_RETURN;
}
+
void
sp_head::init(LEX *lex)
{
@@ -359,7 +362,7 @@ sp_head::destroy()
delete i;
delete_dynamic(&m_instr);
m_pcont->destroy();
- free_items(m_free_list);
+ free_items(free_list);
while ((lex= (LEX *)m_lex.pop()))
{
if (lex != &m_thd->main_lex) // We got interrupted and have lex'es left
@@ -392,6 +395,7 @@ sp_head::execute(THD *thd)
if (ctx)
ctx->clear_handler();
thd->query_error= 0;
+ thd->current_arena= this;
do
{
sp_instr *i;
@@ -402,6 +406,8 @@ sp_head::execute(THD *thd)
break;
DBUG_PRINT("execute", ("Instruction %u", ip));
ret= i->execute(thd, &ip);
+ if (i->free_list)
+ cleanup_items(i->free_list);
// Check if an exception has occurred and a handler has been found
// Note: We havo to check even if ret==0, since warnings (and some
// errors don't return a non-zero value.
@@ -430,6 +436,11 @@ sp_head::execute(THD *thd)
done:
DBUG_PRINT("info", ("ret=%d killed=%d query_error=%d",
ret, thd->killed, thd->query_error));
+
+ if (thd->current_arena)
+ cleanup_items(thd->current_arena->free_list);
+ thd->current_arena= 0;
+
if (thd->killed || thd->query_error || thd->net.report_error)
ret= -1;
/* If the DB has changed, the pointer has changed too, but the
@@ -687,21 +698,6 @@ sp_head::restore_lex(THD *thd)
// Update some state in the old one first
oldlex->ptr= sublex->ptr;
oldlex->next_state= sublex->next_state;
- for (sl= sublex->all_selects_list ;
- sl ;
- sl= sl->next_select_in_list())
- {
- // Save WHERE clause pointers to avoid damaging by optimisation
- sl->prep_where= sl->where;
- if (sl->with_wild)
- {
- // Copy item_list. We will restore it before calling the
- // sub-statement, so it's ok to pop them.
- sl->item_list_copy.empty();
- while (Item *it= sl->item_list.pop())
- sl->item_list_copy.push_back(it);
- }
- }
// Collect some data from the sub statement lex.
sp_merge_funs(oldlex, sublex);
@@ -792,19 +788,19 @@ sp_head::set_info(char *definer, uint definerlen,
if (! p)
p= definer; // Weird...
len= p-definer;
- m_definer_user.str= strmake_root(&m_mem_root, definer, len);
+ m_definer_user.str= strmake_root(&mem_root, definer, len);
m_definer_user.length= len;
len= definerlen-len-1;
- m_definer_host.str= strmake_root(&m_mem_root, p+1, len);
+ m_definer_host.str= strmake_root(&mem_root, p+1, len);
m_definer_host.length= len;
m_created= created;
m_modified= modified;
- m_chistics= (st_sp_chistics *)alloc_root(&m_mem_root, sizeof(st_sp_chistics));
+ m_chistics= (st_sp_chistics *)alloc_root(&mem_root, sizeof(st_sp_chistics));
memcpy(m_chistics, chistics, sizeof(st_sp_chistics));
if (m_chistics->comment.length == 0)
m_chistics->comment.str= 0;
else
- m_chistics->comment.str= strmake_root(&m_mem_root,
+ m_chistics->comment.str= strmake_root(&mem_root,
m_chistics->comment.str,
m_chistics->comment.length);
}
@@ -812,26 +808,33 @@ sp_head::set_info(char *definer, uint definerlen,
void
sp_head::reset_thd_mem_root(THD *thd)
{
+ DBUG_ENTER("sp_head::reset_thd_mem_root");
m_thd_root= thd->mem_root;
- thd->mem_root= m_mem_root;
- m_free_list= thd->free_list; // Keep the old list
+ thd->mem_root= mem_root;
+ DBUG_PRINT("info", ("mem_root 0x%lx moved to thd mem root 0x%lx",
+ (ulong) &mem_root, (ulong) &thd->mem_root));
+ free_list= thd->free_list; // Keep the old list
thd->free_list= NULL; // Start a new one
/* Copy the db, since substatements will point to it */
m_thd_db= thd->db;
thd->db= strmake_root(&thd->mem_root, thd->db, thd->db_length);
m_thd= thd;
+ DBUG_VOID_RETURN;
}
void
sp_head::restore_thd_mem_root(THD *thd)
{
- Item *flist= m_free_list; // The old list
- m_free_list= thd->free_list; // Get the new one
+ DBUG_ENTER("sp_head::restore_thd_mem_root");
+ Item *flist= free_list; // The old list
+ set_item_arena(thd); // Get new fre_list and mem_root
+ DBUG_PRINT("info", ("mem_root 0x%lx returned from thd mem root 0x%lx",
+ (ulong) &mem_root, (ulong) &thd->mem_root));
thd->free_list= flist; // Restore the old one
thd->db= m_thd_db; // Restore the original db pointer
- m_mem_root= thd->mem_root;
thd->mem_root= m_thd_root;
m_thd= NULL;
+ DBUG_VOID_RETURN;
}
@@ -861,6 +864,23 @@ sp_head::show_create_procedure(THD *thd)
DBUG_RETURN(res);
}
+
+/*
+ Add instruction to SP
+
+ SYNOPSIS
+ sp_head::add_instr()
+ instr Instruction
+*/
+
+void sp_head::add_instr(sp_instr *instr)
+{
+ instr->free_list= m_thd->free_list;
+ m_thd->free_list= 0;
+ insert_dynamic(&m_instr, (gptr)&instr);
+}
+
+
int
sp_head::show_create_function(THD *thd)
{
@@ -919,7 +939,6 @@ int
sp_instr_stmt::exec_stmt(THD *thd, LEX *lex)
{
LEX *olex; // The other lex
- Item *freelist;
SELECT_LEX *sl;
int res;
@@ -927,94 +946,24 @@ sp_instr_stmt::exec_stmt(THD *thd, LEX *lex)
thd->lex= lex; // Use my own lex
thd->lex->thd = thd; // QQ Not reentrant!
thd->lex->unit.thd= thd; // QQ Not reentrant
- freelist= thd->free_list;
thd->free_list= NULL;
VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query_id= query_id++;
VOID(pthread_mutex_unlock(&LOCK_thread_count));
- // Copy WHERE clause pointers to avoid damaging by optimisation
- // Also clear ref_pointer_arrays.
- for (sl= lex->all_selects_list ;
- sl ;
- sl= sl->next_select_in_list())
- {
- if (lex->sql_command == SQLCOM_CREATE_TABLE ||
- lex->sql_command == SQLCOM_INSERT_SELECT)
- { // Destroys sl->table_list.first
- sl->table_list_first_copy= sl->table_list.first;
- }
- if (sl->with_wild)
- {
- // Restore item_list
- // Note: We have to do this before executing the sub-statement,
- // to make sure that the list nodes are in the right
- // memroot.
- List_iterator_fast<Item> li(sl->item_list_copy);
-
- sl->item_list.empty();
- while (Item *it= li++)
- sl->item_list.push_back(it);
- }
- sl->ref_pointer_array= 0;
- if (sl->prep_where)
- sl->where= sl->prep_where->copy_andor_structure(thd);
- for (ORDER *order= (ORDER *)sl->order_list.first ;
- order ;
- order= order->next)
- {
- order->item_copy= order->item;
- }
- for (ORDER *group= (ORDER *)sl->group_list.first ;
- group ;
- group= group->next)
- {
- group->item_copy= group->item;
- }
- }
+ reset_stmt_for_execute(thd, lex);
res= mysql_execute_command(thd);
+ lex->unit.cleanup();
if (thd->lock || thd->open_tables || thd->derived_tables)
{
thd->proc_info="closing tables";
close_thread_tables(thd); /* Free tables */
}
- for (sl= lex->all_selects_list ;
- sl ;
- sl= sl->next_select_in_list())
- {
- TABLE_LIST *tabs;
-
- if (lex->sql_command == SQLCOM_CREATE_TABLE ||
- lex->sql_command == SQLCOM_INSERT_SELECT)
- { // Restore sl->table_list.first
- sl->table_list.first= sl->table_list_first_copy;
- }
- // We have closed all tables, get rid of pointers to them
- for (tabs=(TABLE_LIST *)sl->table_list.first ;
- tabs ;
- tabs= tabs->next)
- {
- tabs->table= NULL;
- }
- for (ORDER *order= (ORDER *)sl->order_list.first ;
- order ;
- order= order->next)
- {
- order->item= order->item_copy;
- }
- for (ORDER *group= (ORDER *)sl->group_list.first ;
- group ;
- group= group->next)
- {
- group->item= group->item_copy;
- }
- }
thd->lex= olex; // Restore the other lex
- thd->free_list= freelist;
return res;
}
diff --git a/sql/sp_head.h b/sql/sp_head.h
index cb2e56adabe..e9ec7068783 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -70,7 +70,7 @@ sp_name *
sp_name_current_db_new(THD *thd, LEX_STRING name);
-class sp_head : public Sql_alloc
+class sp_head :private Item_arena
{
sp_head(const sp_head &); /* Prevent use of these */
void operator=(sp_head &);
@@ -108,7 +108,7 @@ public:
static void *
operator new(size_t size);
- static void
+ static void
operator delete(void *ptr, size_t size);
sp_head();
@@ -123,7 +123,7 @@ public:
int
create(THD *thd);
-
+
virtual ~sp_head();
// Free memory
@@ -142,11 +142,8 @@ public:
int
show_create_function(THD *thd);
- inline void
- add_instr(sp_instr *i)
- {
- insert_dynamic(&m_instr, (gptr)&i);
- }
+ void
+ add_instr(sp_instr *instr);
inline uint
instructions()
@@ -206,9 +203,7 @@ public:
private:
- MEM_ROOT m_mem_root; // My own mem_root
MEM_ROOT m_thd_root; // Temp. store for thd's mem_root
- Item *m_free_list; // Where the items go
THD *m_thd; // Set if we have reset mem_root
char *m_thd_db; // Original thd->db pointer
@@ -251,13 +246,15 @@ class sp_instr : public Sql_alloc
public:
+ Item *free_list; // My Items
+
// Should give each a name or type code for debugging purposes?
sp_instr(uint ip)
- : Sql_alloc(), m_ip(ip)
+ :Sql_alloc(), free_list(0), m_ip(ip)
{}
virtual ~sp_instr()
- {}
+ { free_items(free_list); }
// Execute this instrution. '*nextp' will be set to the index of the next
// instruction to execute. (For most instruction this will be the
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 190e930deed..1c8c310e36a 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2158,14 +2158,14 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
{
if (!wild_num)
return 0;
- Statement *stmt= thd->current_statement, backup;
+ Item_arena *arena= thd->current_arena, backup;
/*
If we are in preparing prepared statement phase then we have change
temporary mem_root to statement mem root to save changes of SELECT list
*/
- if (stmt)
- thd->set_n_backup_item_arena(stmt, &backup);
+ if (arena)
+ thd->set_n_backup_item_arena(arena, &backup);
reg2 Item *item;
List_iterator<Item> it(fields);
while ( wild_num && (item= it++))
@@ -2178,8 +2178,8 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
if (insert_fields(thd,tables,((Item_field*) item)->db_name,
((Item_field*) item)->table_name, &it))
{
- if (stmt)
- thd->restore_backup_item_arena(stmt, &backup);
+ if (arena)
+ thd->restore_backup_item_arena(arena, &backup);
return (-1);
}
if (sum_func_list)
@@ -2194,8 +2194,15 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
wild_num--;
}
}
- if (stmt)
- thd->restore_backup_item_arena(stmt, &backup);
+ if (arena)
+ {
+ /* make * substituting permanent */
+ SELECT_LEX *select_lex= thd->lex->current_select;
+ select_lex->with_wild= 0;
+ select_lex->item_list= fields;
+
+ thd->restore_backup_item_arena(arena, &backup);
+ }
return 0;
}
@@ -2408,12 +2415,17 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
{
table_map not_null_tables= 0;
- Statement *stmt= thd->current_statement, backup;
-
+ SELECT_LEX *select_lex= thd->lex->current_select;
+ Item_arena *arena= ((thd->current_arena &&
+ !select_lex->conds_processed_with_permanent_arena) ?
+ thd->current_arena :
+ 0);
+ Item_arena backup;
DBUG_ENTER("setup_conds");
+
thd->set_query_id=1;
- thd->lex->current_select->cond_count= 0;
+ select_lex->cond_count= 0;
if (*conds)
{
thd->where="where clause";
@@ -2436,7 +2448,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
table->on_expr->fix_fields(thd, tables, &table->on_expr) ||
table->on_expr->check_cols(1))
DBUG_RETURN(1);
- thd->lex->current_select->cond_count++;
+ select_lex->cond_count++;
/*
If it's a normal join or a LEFT JOIN which can be optimized away
@@ -2447,12 +2459,12 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
!(specialflag & SPECIAL_NO_NEW_FUNC)))
{
table->outer_join= 0;
- if (stmt)
- thd->set_n_backup_item_arena(stmt, &backup);
+ if (arena)
+ thd->set_n_backup_item_arena(arena, &backup);
*conds= and_conds(*conds, table->on_expr);
table->on_expr=0;
- if (stmt)
- thd->restore_backup_item_arena(stmt, &backup);
+ if (arena)
+ thd->restore_backup_item_arena(arena, &backup);
if ((*conds) && !(*conds)->fixed &&
(*conds)->fix_fields(thd, tables, conds))
DBUG_RETURN(1);
@@ -2460,8 +2472,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
}
if (table->natural_join)
{
- if (stmt)
- thd->set_n_backup_item_arena(stmt, &backup);
+ if (arena)
+ thd->set_n_backup_item_arena(arena, &backup);
/* Make a join of all fields with have the same name */
TABLE *t1= table->table;
TABLE *t2= table->natural_join->table;
@@ -2491,7 +2503,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
t2->used_keys.intersect(t2_field->part_of_key);
}
}
- thd->lex->current_select->cond_count+= cond_and->list.elements;
+ select_lex->cond_count+= cond_and->list.elements;
// to prevent natural join processing during PS re-execution
table->natural_join= 0;
@@ -2500,8 +2512,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
{
*conds= and_conds(*conds, cond_and);
// fix_fields() should be made with temporary memory pool
- if (stmt)
- thd->restore_backup_item_arena(stmt, &backup);
+ if (arena)
+ thd->restore_backup_item_arena(arena, &backup);
if (*conds && !(*conds)->fixed)
{
if ((*conds)->fix_fields(thd, tables, conds))
@@ -2512,8 +2524,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
{
table->on_expr= and_conds(table->on_expr, cond_and);
// fix_fields() should be made with temporary memory pool
- if (stmt)
- thd->restore_backup_item_arena(stmt, &backup);
+ if (arena)
+ thd->restore_backup_item_arena(arena, &backup);
if (table->on_expr && !table->on_expr->fixed)
{
if (table->on_expr->fix_fields(thd, tables, &table->on_expr))
@@ -2523,21 +2535,22 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
}
}
- if (stmt)
+ if (arena)
{
/*
We are in prepared statement preparation code => we should store
WHERE clause changing for next executions.
- We do this ON -> WHERE transformation only once per PS statement.
+ We do this ON -> WHERE transformation only once per PS/SP statement.
*/
- thd->lex->current_select->where= *conds;
+ select_lex->where= *conds;
+ select_lex->conds_processed_with_permanent_arena= 1;
}
DBUG_RETURN(test(thd->net.report_error));
err:
- if (stmt)
- thd->restore_backup_item_arena(stmt, &backup);
+ if (arena)
+ thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(1);
}
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index f8b2efe911c..00a9c44d8d9 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -86,7 +86,7 @@ extern "C" void free_user_var(user_var_entry *entry)
** Thread specific functions
****************************************************************************/
-THD::THD():user_time(0), current_statement(0), is_fatal_error(0),
+THD::THD():user_time(0), current_arena(0), is_fatal_error(0),
last_insert_id_used(0),
insert_id_used(0), rand_used(0), in_lock_tables(0),
global_read_lock(0), bootstrap(0), spcont(NULL)
@@ -1210,23 +1210,47 @@ int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
}
+Item_arena::Item_arena(THD* thd)
+ :free_list(0)
+{
+ init_sql_alloc(&mem_root,
+ thd->variables.query_alloc_block_size,
+ thd->variables.query_prealloc_size);
+}
+
+
+Item_arena::Item_arena()
+ :free_list(0)
+{
+ bzero((char *) &mem_root, sizeof(mem_root));
+}
+
+
+Item_arena::Item_arena(bool init_mem_root)
+ :free_list(0)
+{
+ if (init_mem_root)
+ bzero((char *) &mem_root, sizeof(mem_root));
+}
+
+
+Item_arena::~Item_arena()
+{}
+
+
/*
Statement functions
*/
Statement::Statement(THD *thd)
- :id(++thd->statement_id_counter),
+ :Item_arena(thd),
+ id(++thd->statement_id_counter),
set_query_id(1),
allow_sum_func(0),
lex(&main_lex),
query(0),
- query_length(0),
- free_list(0)
-{
- init_sql_alloc(&mem_root,
- thd->variables.query_alloc_block_size,
- thd->variables.query_prealloc_size);
-}
+ query_length(0)
+{}
/*
This constructor is called when statement is a subobject of THD:
@@ -1235,15 +1259,14 @@ Statement::Statement(THD *thd)
*/
Statement::Statement()
- :id(0),
+ :Item_arena(),
+ id(0),
set_query_id(1),
allow_sum_func(0), /* initialized later */
lex(&main_lex),
query(0), /* these two are set */
- query_length(0), /* in alloc_query() */
- free_list(0)
+ query_length(0) /* in alloc_query() */
{
- bzero((char *) &mem_root, sizeof(mem_root));
}
@@ -1264,14 +1287,14 @@ void Statement::set_statement(Statement *stmt)
}
-void Statement::set_n_backup_item_arena(Statement *set, Statement *backup)
+void Item_arena::set_n_backup_item_arena(Item_arena *set, Item_arena *backup)
{
backup->set_item_arena(this);
set_item_arena(set);
}
-void Statement::restore_backup_item_arena(Statement *set, Statement *backup)
+void Item_arena::restore_backup_item_arena(Item_arena *set, Item_arena *backup)
{
set->set_item_arena(this);
set_item_arena(backup);
@@ -1279,7 +1302,7 @@ void Statement::restore_backup_item_arena(Statement *set, Statement *backup)
init_alloc_root(&backup->mem_root, 0, 0);
}
-void Statement::set_item_arena(Statement *set)
+void Item_arena::set_item_arena(Item_arena *set)
{
mem_root= set->mem_root;
free_list= set->free_list;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 0cca76568b4..d5140f83752 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -434,6 +434,48 @@ struct system_variables
void free_tmp_table(THD *thd, TABLE *entry);
+class Item_arena
+{
+public:
+ /*
+ List of items created in the parser for this query. Every item puts
+ itself to the list on creation (see Item::Item() for details))
+ */
+ Item *free_list;
+ MEM_ROOT mem_root;
+
+ Item_arena(THD *thd);
+ Item_arena();
+ Item_arena(bool init_mem_root);
+ ~Item_arena();
+
+ inline gptr alloc(unsigned int size) { return alloc_root(&mem_root,size); }
+ inline gptr calloc(unsigned int size)
+ {
+ gptr ptr;
+ if ((ptr=alloc_root(&mem_root,size)))
+ bzero((char*) ptr,size);
+ return ptr;
+ }
+ inline char *strdup(const char *str)
+ { return strdup_root(&mem_root,str); }
+ inline char *strmake(const char *str, uint size)
+ { return strmake_root(&mem_root,str,size); }
+ inline char *memdup(const char *str, uint size)
+ { return memdup_root(&mem_root,str,size); }
+ inline char *memdup_w_gap(const char *str, uint size, uint gap)
+ {
+ gptr ptr;
+ if ((ptr=alloc_root(&mem_root,size+gap)))
+ memcpy(ptr,str,size);
+ return ptr;
+ }
+
+ void set_n_backup_item_arena(Item_arena *set, Item_arena *backup);
+ void restore_backup_item_arena(Item_arena *set, Item_arena *backup);
+ void set_item_arena(Item_arena *set);
+};
+
/*
State of a single command executed against this connection.
One connection can contain a lot of simultaneously running statements,
@@ -448,7 +490,7 @@ void free_tmp_table(THD *thd, TABLE *entry);
be used explicitly.
*/
-class Statement
+class Statement: public Item_arena
{
Statement(const Statement &rhs); /* not implemented: */
Statement &operator=(const Statement &rhs); /* non-copyable */
@@ -489,12 +531,6 @@ public:
*/
char *query;
uint32 query_length; // current query length
- /*
- List of items created in the parser for this query. Every item puts
- itself to the list on creation (see Item::Item() for details))
- */
- Item *free_list;
- MEM_ROOT mem_root;
public:
/* We build without RTTI, so dynamic_cast can't be used. */
@@ -518,31 +554,6 @@ public:
/* return class type */
virtual Type type() const;
- inline gptr alloc(unsigned int size) { return alloc_root(&mem_root,size); }
- inline gptr calloc(unsigned int size)
- {
- gptr ptr;
- if ((ptr=alloc_root(&mem_root,size)))
- bzero((char*) ptr,size);
- return ptr;
- }
- inline char *strdup(const char *str)
- { return strdup_root(&mem_root,str); }
- inline char *strmake(const char *str, uint size)
- { return strmake_root(&mem_root,str,size); }
- inline char *memdup(const char *str, uint size)
- { return memdup_root(&mem_root,str,size); }
- inline char *memdup_w_gap(const char *str, uint size, uint gap)
- {
- gptr ptr;
- if ((ptr=alloc_root(&mem_root,size+gap)))
- memcpy(ptr,str,size);
- return ptr;
- }
-
- void set_n_backup_item_arena(Statement *set, Statement *backup);
- void restore_backup_item_arena(Statement *set, Statement *backup);
- void set_item_arena(Statement *set);
};
@@ -746,9 +757,9 @@ public:
Vio* active_vio;
#endif
/*
- Current prepared Statement if there one, or 0
+ Current prepared Item_arena if there one, or 0
*/
- Statement *current_statement;
+ Item_arena *current_arena;
/*
next_insert_id is set on SET INSERT_ID= #. This is used as the next
generated auto_increment value in handler.cc
@@ -969,7 +980,7 @@ public:
inline void allocate_temporary_memory_pool_for_ps_preparing()
{
- DBUG_ASSERT(current_statement!=0);
+ DBUG_ASSERT(current_arena!=0);
/*
We do not want to have in PS memory all that junk,
which will be created by preparation => substitute memory
@@ -978,7 +989,7 @@ public:
We know that PS memory pool is now copied to THD, we move it back
to allow some code use it.
*/
- current_statement->set_item_arena(this);
+ current_arena->set_item_arena(this);
init_sql_alloc(&mem_root,
variables.query_alloc_block_size,
variables.query_prealloc_size);
@@ -986,12 +997,16 @@ public:
}
inline void free_temporary_memory_pool_for_ps_preparing()
{
- DBUG_ASSERT(current_statement!=0);
- cleanup_items(current_statement->free_list);
+ DBUG_ASSERT(current_arena!=0);
+ cleanup_items(current_arena->free_list);
free_items(free_list);
close_thread_tables(this); // to close derived tables
free_root(&mem_root, MYF(0));
- set_item_arena(current_statement);
+ set_item_arena(current_arena);
+ }
+ inline bool only_prepare()
+ {
+ return command == COM_PREPARE;
}
};
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 9f725c7e17f..b9769e3a940 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -264,10 +264,11 @@ int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
{
TABLE_LIST *delete_table_list= ((TABLE_LIST*) thd->lex->
select_lex.table_list.first);
+ SELECT_LEX *select_lex= &thd->lex->select_lex;
DBUG_ENTER("mysql_prepare_delete");
if (setup_conds(thd, delete_table_list, conds) ||
- setup_ftfuncs(&thd->lex->select_lex))
+ setup_ftfuncs(select_lex))
DBUG_RETURN(-1);
if (find_real_table_in_list(table_list->next,
table_list->db, table_list->real_name))
@@ -275,6 +276,11 @@ int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
DBUG_RETURN(-1);
}
+ if (thd->current_arena && select_lex->first_execution)
+ {
+ select_lex->prep_where= select_lex->where;
+ select_lex->first_execution= 0;
+ }
DBUG_RETURN(0);
}
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 2e2ad6786fc..46794f45f3c 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -152,7 +152,7 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
if it is preparation PS only then we do not need real data and we
can skip execution (and parameters is not defined, too)
*/
- if (!thd->current_statement)
+ if (!thd->only_prepare())
{
if (is_union)
{
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 5fb525aa9a9..b9a1f0cebd9 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -460,6 +460,7 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
DBUG_RETURN(-1);
}
+ thd->lex->select_lex.first_execution= 0;
DBUG_RETURN(0);
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 7e38941f344..1a3558b5eeb 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1011,10 +1011,12 @@ void st_select_lex::init_query()
having_fix_field= 0;
resolve_mode= NOMATTER_MODE;
cond_count= with_wild= 0;
+ conds_processed_with_permanent_arena= 0;
ref_pointer_array= 0;
select_n_having_items= 0;
prep_where= 0;
explicit_limit= 0;
+ first_execution= 1;
}
void st_select_lex::init_select()
@@ -1414,7 +1416,9 @@ bool st_select_lex::add_order_to_list(THD *thd, Item *item, bool asc)
bool st_select_lex::add_item_to_list(THD *thd, Item *item)
{
- return item_list.push_back(item);
+ DBUG_ENTER("st_select_lex::add_item_to_list");
+ DBUG_PRINT("info", ("Item: %p", item));
+ DBUG_RETURN(item_list.push_back(item));
}
@@ -1500,12 +1504,12 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
We have to create array in prepared statement memory if it is
prepared statement
*/
- Statement *stmt= thd->current_statement ? thd->current_statement : thd;
+ Item_arena *arena= thd->current_arena ? thd->current_arena : thd;
return (ref_pointer_array=
- (Item **)stmt->alloc(sizeof(Item*) *
- (item_list.elements +
- select_n_having_items +
- order_group_num)* 5)) == 0;
+ (Item **)arena->alloc(sizeof(Item*) *
+ (item_list.elements +
+ select_n_having_items +
+ order_group_num)* 5)) == 0;
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 60965209cc9..0f0c39ab493 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -405,8 +405,6 @@ public:
enum olap_type olap;
SQL_LIST table_list, group_list; /* FROM & GROUP BY clauses */
List<Item> item_list; /* list of fields & expressions */
- List<Item> item_list_copy; /* For SPs */
- byte *table_list_first_copy; /* For SPs */
List<String> interval_list, use_index, *use_index_ptr,
ignore_index, *ignore_index_ptr;
/*
@@ -435,6 +433,11 @@ public:
uint cond_count; /* number of arguments of and/or/xor in where/having */
enum_parsing_place parsing_place; /* where we are parsing expression */
bool with_sum_func; /* sum function indicator */
+ /*
+ PS or SP cond natural joins was alredy processed with permanent
+ arena and all additional items which we need alredy stored in it
+ */
+ bool conds_processed_with_permanent_arena;
ulong table_join_options;
uint in_sum_expr;
@@ -445,6 +448,7 @@ public:
bool having_fix_field;
/* explicit LIMIT clause was used */
bool explicit_limit;
+ bool first_execution; /* first execution in SP or PS */
/*
SELECT for SELECT command st_select_lex. Used to privent scaning
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 598f131985c..bd36880433f 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -4182,12 +4182,14 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
query_cache_end_of_result(thd);
}
}
+ lex->unit.cleanup();
}
else
{
DBUG_PRINT("info",("Command aborted. Fatal_error: %d",
thd->is_fatal_error));
query_cache_abort(&thd->net);
+ lex->unit.cleanup();
if (thd->lex->sphead)
{
/* Clean up after failed stored procedure/function */
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index f3ae4052bb4..a6e6e1deae2 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1357,7 +1357,7 @@ void mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
mysql_log.write(thd, COM_PREPARE, "%s", packet);
- thd->current_statement= stmt;
+ thd->current_arena= stmt;
lex= lex_start(thd, (uchar *) thd->query, thd->query_length);
mysql_init_query(thd);
lex->safe_to_cache_query= 0;
@@ -1381,7 +1381,7 @@ void mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
stmt->set_item_arena(thd);
thd->set_statement(&thd->stmt_backup);
thd->set_item_arena(&thd->stmt_backup);
- thd->current_statement= 0;
+ thd->current_arena= 0;
if (error)
{
@@ -1389,43 +1389,33 @@ void mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
thd->stmt_map.erase(stmt);
/* error is sent inside yyparse/send_prepare_results */
}
- else
- {
- SELECT_LEX *sl= stmt->lex->all_selects_list;
- /*
- Save WHERE clause pointers, because they may be changed during query
- optimisation.
- */
- for (; sl; sl= sl->next_select_in_list())
- {
- sl->prep_where= sl->where;
- }
- }
DBUG_VOID_RETURN;
}
/* Reinit statement before execution */
-static void reset_stmt_for_execute(Prepared_statement *stmt)
+void reset_stmt_for_execute(THD *thd, LEX *lex)
{
- THD *thd= stmt->thd;
- SELECT_LEX *sl= stmt->lex->all_selects_list;
+ SELECT_LEX *sl= lex->all_selects_list;
for (; sl; sl= sl->next_select_in_list())
{
- /*
- Copy WHERE clause pointers to avoid damaging they by optimisation
- */
- if (sl->prep_where)
- sl->where= sl->prep_where->copy_andor_structure(thd);
- DBUG_ASSERT(sl->join == 0);
- ORDER *order;
- /* Fix GROUP list */
- for (order= (ORDER *)sl->group_list.first; order; order= order->next)
- order->item= &order->item_ptr;
- /* Fix ORDER list */
- for (order= (ORDER *)sl->order_list.first; order; order= order->next)
- order->item= &order->item_ptr;
+ if (!sl->first_execution)
+ {
+ /*
+ Copy WHERE clause pointers to avoid damaging they by optimisation
+ */
+ if (sl->prep_where)
+ sl->where= sl->prep_where->copy_andor_structure(thd);
+ DBUG_ASSERT(sl->join == 0);
+ ORDER *order;
+ /* Fix GROUP list */
+ for (order= (ORDER *)sl->group_list.first; order; order= order->next)
+ order->item= &order->item_ptr;
+ /* Fix ORDER list */
+ for (order= (ORDER *)sl->order_list.first; order; order= order->next)
+ order->item= &order->item_ptr;
+ }
/*
TODO: When the new table structure is ready, then have a status bit
@@ -1443,7 +1433,6 @@ static void reset_stmt_for_execute(Prepared_statement *stmt)
tables->table= 0;
tables->table_list= 0;
}
-
{
SELECT_LEX_UNIT *unit= sl->master_unit();
unit->unclean();
@@ -1506,7 +1495,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
thd->stmt_backup.set_statement(thd);
thd->set_statement(stmt);
- reset_stmt_for_execute(stmt);
+ reset_stmt_for_execute(thd, stmt->lex);
#ifndef EMBEDDED_LIBRARY
if (stmt->param_count)
{
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 3cbf292cb2f..9d6a6999591 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -367,7 +367,14 @@ JOIN::prepare(Item ***rref_pointer_array,
Item_subselect::trans_res res;
if ((res= subselect->select_transformer(this)) !=
Item_subselect::RES_OK)
+ {
+ if (thd->current_arena && select_lex->first_execution)
+ {
+ select_lex->prep_where= select_lex->where;
+ select_lex->first_execution= 0;
+ }
DBUG_RETURN((res == Item_subselect::RES_ERROR));
+ }
}
}
@@ -470,6 +477,11 @@ JOIN::prepare(Item ***rref_pointer_array,
if (alloc_func_list())
goto err;
+ if (thd->current_arena && select_lex->first_execution)
+ {
+ select_lex->prep_where= select_lex->where;
+ select_lex->first_execution= 0;
+ }
DBUG_RETURN(0); // All OK
err:
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 8136ce44d1d..794fbc74c73 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -262,27 +262,32 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
thd_arg->lex->current_select= lex_select_save;
if (!item_list.elements)
{
- Statement *stmt= thd->current_statement;
- Statement backup;
- if (stmt)
- thd->set_n_backup_item_arena(stmt, &backup);
+ Item_arena *arena= thd->current_arena;
+ Item_arena backup;
+ if (arena)
+ thd->set_n_backup_item_arena(arena, &backup);
Field **field;
for (field= table->field; *field; field++)
{
Item_field *item= new Item_field(*field);
if (!item || item_list.push_back(item))
{
- if (stmt)
- thd->restore_backup_item_arena(stmt, &backup);
+ if (arena)
+ thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(-1);
}
}
- if (stmt)
+ if (arena)
{
- thd->restore_backup_item_arena(stmt, &backup);
+ thd->restore_backup_item_arena(arena, &backup);
/* prepare fake select to initialize it correctly */
ulong options_tmp= init_prepare_fake_select_lex(thd);
+ /*
+ it should be done only once (because item_list builds only onece
+ per statement)
+ */
+ DBUG_ASSERT(fake_select_lex->join == 0);
if (!(fake_select_lex->join= new JOIN(thd, item_list, thd->options,
result)))
{
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 918a4c769b4..5c6ed023485 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -425,6 +425,7 @@ int mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
TABLE *table= table_list->table;
TABLE_LIST tables;
List<Item> all_fields;
+ SELECT_LEX *select_lex= &thd->lex->select_lex;
DBUG_ENTER("mysql_prepare_update");
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -437,10 +438,10 @@ int mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
if (setup_tables(update_table_list) ||
setup_conds(thd, update_table_list, conds) ||
- thd->lex->select_lex.setup_ref_array(thd, order_num) ||
- setup_order(thd, thd->lex->select_lex.ref_pointer_array,
+ select_lex->setup_ref_array(thd, order_num) ||
+ setup_order(thd, select_lex->ref_pointer_array,
update_table_list, all_fields, all_fields, order) ||
- setup_ftfuncs(&thd->lex->select_lex))
+ setup_ftfuncs(select_lex))
DBUG_RETURN(-1);
/* Check that we are not using table that we are updating in a sub select */
@@ -450,6 +451,11 @@ int mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
DBUG_RETURN(-1);
}
+ if (thd->current_arena && select_lex->first_execution)
+ {
+ select_lex->prep_where= select_lex->where;
+ select_lex->first_execution= 0;
+ }
DBUG_RETURN(0);
}