Commit 350d8a21 authored by bell@sanja.is.com.ua's avatar bell@sanja.is.com.ua

Merge sanja.is.com.ua:/home/bell/mysql/bk/mysql-5.0

into sanja.is.com.ua:/home/bell/mysql/bk/work-sp2_bak-5.0
parents c0643063 e822f61d
...@@ -1305,3 +1305,13 @@ test bar PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINE ...@@ -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 procedure bar|
drop table t1; drop table t1;
drop table t2; 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;
...@@ -1450,3 +1450,15 @@ drop procedure bar| ...@@ -1450,3 +1450,15 @@ drop procedure bar|
delimiter ;| delimiter ;|
drop table t1; drop table t1;
drop table t2; 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;
...@@ -104,7 +104,7 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref) ...@@ -104,7 +104,7 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
{ {
DBUG_ASSERT(fixed == 0); DBUG_ASSERT(fixed == 0);
engine->set_thd((thd= thd_param)); engine->set_thd((thd= thd_param));
stmt= thd->current_statement; arena= thd->current_arena;
char const *save_where= thd->where; char const *save_where= thd->where;
int res= engine->prepare(); int res= engine->prepare();
...@@ -316,8 +316,8 @@ Item_singlerow_subselect::select_transformer(JOIN *join) ...@@ -316,8 +316,8 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
if (join->conds || join->having) if (join->conds || join->having)
{ {
Item *cond; Item *cond;
if (stmt) if (arena)
thd->set_n_backup_item_arena(stmt, &backup); thd->set_n_backup_item_arena(arena, &backup);
if (!join->having) if (!join->having)
cond= join->conds; cond= join->conds;
...@@ -330,15 +330,15 @@ Item_singlerow_subselect::select_transformer(JOIN *join) ...@@ -330,15 +330,15 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
new Item_null()))) new Item_null())))
goto err; goto err;
} }
if (stmt) if (arena)
thd->restore_backup_item_arena(stmt, &backup); thd->restore_backup_item_arena(arena, &backup);
return RES_REDUCE; return RES_REDUCE;
} }
return RES_OK; return RES_OK;
err: err:
if (stmt) if (arena)
thd->restore_backup_item_arena(stmt, &backup); thd->restore_backup_item_arena(arena, &backup);
return RES_ERROR; return RES_ERROR;
} }
...@@ -618,8 +618,8 @@ Item_in_subselect::single_value_transformer(JOIN *join, ...@@ -618,8 +618,8 @@ Item_in_subselect::single_value_transformer(JOIN *join,
Statement backup; Statement backup;
thd->where= "scalar IN/ALL/ANY subquery"; thd->where= "scalar IN/ALL/ANY subquery";
if (stmt) if (arena)
thd->set_n_backup_item_arena(stmt, &backup); thd->set_n_backup_item_arena(arena, &backup);
if (select_lex->item_list.elements > 1) if (select_lex->item_list.elements > 1)
{ {
...@@ -823,21 +823,21 @@ Item_in_subselect::single_value_transformer(JOIN *join, ...@@ -823,21 +823,21 @@ Item_in_subselect::single_value_transformer(JOIN *join,
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_SELECT_REDUCED, warn_buff); ER_SELECT_REDUCED, warn_buff);
} }
if (stmt) if (arena)
thd->restore_backup_item_arena(stmt, &backup); thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(RES_REDUCE); DBUG_RETURN(RES_REDUCE);
} }
} }
} }
ok: ok:
if (stmt) if (arena)
thd->restore_backup_item_arena(stmt, &backup); thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(RES_OK); DBUG_RETURN(RES_OK);
err: err:
if (stmt) if (arena)
thd->restore_backup_item_arena(stmt, &backup); thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(RES_ERROR); DBUG_RETURN(RES_ERROR);
} }
...@@ -855,8 +855,8 @@ Item_in_subselect::row_value_transformer(JOIN *join) ...@@ -855,8 +855,8 @@ Item_in_subselect::row_value_transformer(JOIN *join)
Item *item= 0; Item *item= 0;
thd->where= "row IN/ALL/ANY subquery"; thd->where= "row IN/ALL/ANY subquery";
if (stmt) if (arena)
thd->set_n_backup_item_arena(stmt, &backup); thd->set_n_backup_item_arena(arena, &backup);
SELECT_LEX *select_lex= join->select_lex; SELECT_LEX *select_lex= join->select_lex;
...@@ -940,13 +940,13 @@ Item_in_subselect::row_value_transformer(JOIN *join) ...@@ -940,13 +940,13 @@ Item_in_subselect::row_value_transformer(JOIN *join)
if (join->conds->fix_fields(thd, join->tables_list, 0)) if (join->conds->fix_fields(thd, join->tables_list, 0))
goto err; goto err;
} }
if (stmt) if (arena)
thd->restore_backup_item_arena(stmt, &backup); thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(RES_OK); DBUG_RETURN(RES_OK);
err: err:
if (stmt) if (arena)
thd->restore_backup_item_arena(stmt, &backup); thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(RES_ERROR); DBUG_RETURN(RES_ERROR);
} }
......
...@@ -26,7 +26,7 @@ class JOIN; ...@@ -26,7 +26,7 @@ class JOIN;
class select_subselect; class select_subselect;
class subselect_engine; class subselect_engine;
class Item_bool_func2; class Item_bool_func2;
class Statement; class Item_arena;
/* base class for subselects */ /* base class for subselects */
...@@ -36,8 +36,8 @@ class Item_subselect :public Item_result_field ...@@ -36,8 +36,8 @@ class Item_subselect :public Item_result_field
protected: protected:
/* thread handler, will be assigned in fix_fields only */ /* thread handler, will be assigned in fix_fields only */
THD *thd; THD *thd;
/* prepared statement, or 0 */ /* Item_arena used or 0 */
Statement *stmt; Item_arena *arena;
/* substitution instead of subselect in case of optimization */ /* substitution instead of subselect in case of optimization */
Item *substitution; Item *substitution;
/* unit of subquery */ /* unit of subquery */
......
...@@ -77,15 +77,15 @@ Item_sum::Item_sum(THD *thd, Item_sum *item): ...@@ -77,15 +77,15 @@ Item_sum::Item_sum(THD *thd, Item_sum *item):
*/ */
bool Item_sum::save_args_for_prepared_statements(THD *thd) bool Item_sum::save_args_for_prepared_statements(THD *thd)
{ {
if (thd->current_statement) if (thd->current_arena && args_copy == 0)
return save_args(thd->current_statement); return save_args(thd->current_arena);
return 0; 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; return 1;
memcpy(args_copy, args, sizeof(Item*)*arg_count); memcpy(args_copy, args, sizeof(Item*)*arg_count);
return 0; return 0;
......
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#include <my_tree.h> #include <my_tree.h>
class Item_arena;
class Item_sum :public Item_result_field class Item_sum :public Item_result_field
{ {
public: public:
...@@ -93,7 +95,7 @@ class Item_sum :public Item_result_field ...@@ -93,7 +95,7 @@ class Item_sum :public Item_result_field
virtual void make_unique() {} virtual void make_unique() {}
Item *get_tmp_table_item(THD *thd); Item *get_tmp_table_item(THD *thd);
bool save_args_for_prepared_statements(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); bool walk (Item_processor processor, byte *argument);
}; };
......
...@@ -681,6 +681,7 @@ void mysql_stmt_reset(THD *thd, char *packet); ...@@ -681,6 +681,7 @@ void mysql_stmt_reset(THD *thd, char *packet);
void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length); void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length);
int check_insert_fields(THD *thd,TABLE *table,List<Item> &fields, int check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
List<Item> &values, ulong counter); List<Item> &values, ulong counter);
void reset_stmt_for_execute(THD *thd, LEX *lex);
/* sql_error.cc */ /* sql_error.cc */
MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code, MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code,
......
...@@ -186,8 +186,8 @@ sp_head::operator new(size_t size) ...@@ -186,8 +186,8 @@ sp_head::operator new(size_t size)
bzero((char *)&own_root, sizeof(own_root)); bzero((char *)&own_root, sizeof(own_root));
init_alloc_root(&own_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC); init_alloc_root(&own_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
sp= (sp_head *)alloc_root(&own_root, size); 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); DBUG_RETURN(sp);
} }
...@@ -198,16 +198,18 @@ sp_head::operator delete(void *ptr, size_t size) ...@@ -198,16 +198,18 @@ sp_head::operator delete(void *ptr, size_t size)
MEM_ROOT own_root; MEM_ROOT own_root;
sp_head *sp= (sp_head *)ptr; sp_head *sp= (sp_head *)ptr;
DBUG_PRINT("info", ("root: %lx", &sp->m_mem_root)); memcpy(&own_root, (const void *)&sp->mem_root, sizeof(MEM_ROOT));
memcpy(&own_root, (const void *)&sp->m_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)); free_root(&own_root, MYF(0));
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
sp_head::sp_head() sp_head::sp_head()
: Sql_alloc(), m_returns_cs(NULL), m_has_return(FALSE), m_simple_case(FALSE), :Item_arena((bool)FALSE), m_returns_cs(NULL), m_has_return(FALSE),
m_multi_results(FALSE), m_free_list(NULL) m_simple_case(FALSE), m_multi_results(FALSE)
{ {
DBUG_ENTER("sp_head::sp_head"); DBUG_ENTER("sp_head::sp_head");
...@@ -216,6 +218,7 @@ sp_head::sp_head() ...@@ -216,6 +218,7 @@ sp_head::sp_head()
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
void void
sp_head::init(LEX *lex) sp_head::init(LEX *lex)
{ {
...@@ -359,7 +362,7 @@ sp_head::destroy() ...@@ -359,7 +362,7 @@ sp_head::destroy()
delete i; delete i;
delete_dynamic(&m_instr); delete_dynamic(&m_instr);
m_pcont->destroy(); m_pcont->destroy();
free_items(m_free_list); free_items(free_list);
while ((lex= (LEX *)m_lex.pop())) while ((lex= (LEX *)m_lex.pop()))
{ {
if (lex != &m_thd->main_lex) // We got interrupted and have lex'es left if (lex != &m_thd->main_lex) // We got interrupted and have lex'es left
...@@ -392,6 +395,7 @@ sp_head::execute(THD *thd) ...@@ -392,6 +395,7 @@ sp_head::execute(THD *thd)
if (ctx) if (ctx)
ctx->clear_handler(); ctx->clear_handler();
thd->query_error= 0; thd->query_error= 0;
thd->current_arena= this;
do do
{ {
sp_instr *i; sp_instr *i;
...@@ -402,6 +406,8 @@ sp_head::execute(THD *thd) ...@@ -402,6 +406,8 @@ sp_head::execute(THD *thd)
break; break;
DBUG_PRINT("execute", ("Instruction %u", ip)); DBUG_PRINT("execute", ("Instruction %u", ip));
ret= i->execute(thd, &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 // 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 // Note: We havo to check even if ret==0, since warnings (and some
// errors don't return a non-zero value. // errors don't return a non-zero value.
...@@ -430,6 +436,11 @@ sp_head::execute(THD *thd) ...@@ -430,6 +436,11 @@ sp_head::execute(THD *thd)
done: done:
DBUG_PRINT("info", ("ret=%d killed=%d query_error=%d", DBUG_PRINT("info", ("ret=%d killed=%d query_error=%d",
ret, thd->killed, thd->query_error)); 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) if (thd->killed || thd->query_error || thd->net.report_error)
ret= -1; ret= -1;
/* If the DB has changed, the pointer has changed too, but the /* If the DB has changed, the pointer has changed too, but the
...@@ -687,21 +698,6 @@ sp_head::restore_lex(THD *thd) ...@@ -687,21 +698,6 @@ sp_head::restore_lex(THD *thd)
// Update some state in the old one first // Update some state in the old one first
oldlex->ptr= sublex->ptr; oldlex->ptr= sublex->ptr;
oldlex->next_state= sublex->next_state; 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. // Collect some data from the sub statement lex.
sp_merge_funs(oldlex, sublex); sp_merge_funs(oldlex, sublex);
...@@ -792,19 +788,19 @@ sp_head::set_info(char *definer, uint definerlen, ...@@ -792,19 +788,19 @@ sp_head::set_info(char *definer, uint definerlen,
if (! p) if (! p)
p= definer; // Weird... p= definer; // Weird...
len= p-definer; 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; m_definer_user.length= len;
len= definerlen-len-1; 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_definer_host.length= len;
m_created= created; m_created= created;
m_modified= modified; 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)); memcpy(m_chistics, chistics, sizeof(st_sp_chistics));
if (m_chistics->comment.length == 0) if (m_chistics->comment.length == 0)
m_chistics->comment.str= 0; m_chistics->comment.str= 0;
else 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.str,
m_chistics->comment.length); m_chistics->comment.length);
} }
...@@ -812,26 +808,33 @@ sp_head::set_info(char *definer, uint definerlen, ...@@ -812,26 +808,33 @@ sp_head::set_info(char *definer, uint definerlen,
void void
sp_head::reset_thd_mem_root(THD *thd) sp_head::reset_thd_mem_root(THD *thd)
{ {
DBUG_ENTER("sp_head::reset_thd_mem_root");
m_thd_root= thd->mem_root; m_thd_root= thd->mem_root;
thd->mem_root= m_mem_root; thd->mem_root= mem_root;
m_free_list= thd->free_list; // Keep the old list 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 thd->free_list= NULL; // Start a new one
/* Copy the db, since substatements will point to it */ /* Copy the db, since substatements will point to it */
m_thd_db= thd->db; m_thd_db= thd->db;
thd->db= strmake_root(&thd->mem_root, thd->db, thd->db_length); thd->db= strmake_root(&thd->mem_root, thd->db, thd->db_length);
m_thd= thd; m_thd= thd;
DBUG_VOID_RETURN;
} }
void void
sp_head::restore_thd_mem_root(THD *thd) sp_head::restore_thd_mem_root(THD *thd)
{ {
Item *flist= m_free_list; // The old list DBUG_ENTER("sp_head::restore_thd_mem_root");
m_free_list= thd->free_list; // Get the new one 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->free_list= flist; // Restore the old one
thd->db= m_thd_db; // Restore the original db pointer thd->db= m_thd_db; // Restore the original db pointer
m_mem_root= thd->mem_root;
thd->mem_root= m_thd_root; thd->mem_root= m_thd_root;
m_thd= NULL; m_thd= NULL;
DBUG_VOID_RETURN;
} }
...@@ -861,6 +864,23 @@ sp_head::show_create_procedure(THD *thd) ...@@ -861,6 +864,23 @@ sp_head::show_create_procedure(THD *thd)
DBUG_RETURN(res); 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 int
sp_head::show_create_function(THD *thd) sp_head::show_create_function(THD *thd)
{ {
...@@ -919,7 +939,6 @@ int ...@@ -919,7 +939,6 @@ int
sp_instr_stmt::exec_stmt(THD *thd, LEX *lex) sp_instr_stmt::exec_stmt(THD *thd, LEX *lex)
{ {
LEX *olex; // The other lex LEX *olex; // The other lex
Item *freelist;
SELECT_LEX *sl; SELECT_LEX *sl;
int res; int res;
...@@ -927,94 +946,24 @@ sp_instr_stmt::exec_stmt(THD *thd, LEX *lex) ...@@ -927,94 +946,24 @@ sp_instr_stmt::exec_stmt(THD *thd, LEX *lex)
thd->lex= lex; // Use my own lex thd->lex= lex; // Use my own lex
thd->lex->thd = thd; // QQ Not reentrant! thd->lex->thd = thd; // QQ Not reentrant!
thd->lex->unit.thd= thd; // QQ Not reentrant thd->lex->unit.thd= thd; // QQ Not reentrant
freelist= thd->free_list;
thd->free_list= NULL; thd->free_list= NULL;
VOID(pthread_mutex_lock(&LOCK_thread_count)); VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query_id= query_id++; thd->query_id= query_id++;
VOID(pthread_mutex_unlock(&LOCK_thread_count)); VOID(pthread_mutex_unlock(&LOCK_thread_count));
// Copy WHERE clause pointers to avoid damaging by optimisation reset_stmt_for_execute(thd, lex);
// 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;
}
}
res= mysql_execute_command(thd); res= mysql_execute_command(thd);
lex->unit.cleanup();
if (thd->lock || thd->open_tables || thd->derived_tables) if (thd->lock || thd->open_tables || thd->derived_tables)
{ {
thd->proc_info="closing tables"; thd->proc_info="closing tables";
close_thread_tables(thd); /* Free 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->lex= olex; // Restore the other lex
thd->free_list= freelist;
return res; return res;
} }
......
...@@ -70,7 +70,7 @@ sp_name * ...@@ -70,7 +70,7 @@ sp_name *
sp_name_current_db_new(THD *thd, LEX_STRING 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 */ sp_head(const sp_head &); /* Prevent use of these */
void operator=(sp_head &); void operator=(sp_head &);
...@@ -142,11 +142,8 @@ class sp_head : public Sql_alloc ...@@ -142,11 +142,8 @@ class sp_head : public Sql_alloc
int int
show_create_function(THD *thd); show_create_function(THD *thd);
inline void void
add_instr(sp_instr *i) add_instr(sp_instr *instr);
{
insert_dynamic(&m_instr, (gptr)&i);
}
inline uint inline uint
instructions() instructions()
...@@ -206,9 +203,7 @@ class sp_head : public Sql_alloc ...@@ -206,9 +203,7 @@ class sp_head : public Sql_alloc
private: private:
MEM_ROOT m_mem_root; // My own mem_root
MEM_ROOT m_thd_root; // Temp. store for thd's 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 THD *m_thd; // Set if we have reset mem_root
char *m_thd_db; // Original thd->db pointer char *m_thd_db; // Original thd->db pointer
...@@ -251,13 +246,15 @@ class sp_instr : public Sql_alloc ...@@ -251,13 +246,15 @@ class sp_instr : public Sql_alloc
public: public:
Item *free_list; // My Items
// Should give each a name or type code for debugging purposes? // Should give each a name or type code for debugging purposes?
sp_instr(uint ip) sp_instr(uint ip)
: Sql_alloc(), m_ip(ip) :Sql_alloc(), free_list(0), m_ip(ip)
{} {}
virtual ~sp_instr() virtual ~sp_instr()
{} { free_items(free_list); }
// Execute this instrution. '*nextp' will be set to the index of the next // Execute this instrution. '*nextp' will be set to the index of the next
// instruction to execute. (For most instruction this will be the // instruction to execute. (For most instruction this will be the
......
...@@ -2158,14 +2158,14 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, ...@@ -2158,14 +2158,14 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
{ {
if (!wild_num) if (!wild_num)
return 0; 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 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 temporary mem_root to statement mem root to save changes of SELECT list
*/ */
if (stmt) if (arena)
thd->set_n_backup_item_arena(stmt, &backup); thd->set_n_backup_item_arena(arena, &backup);
reg2 Item *item; reg2 Item *item;
List_iterator<Item> it(fields); List_iterator<Item> it(fields);
while ( wild_num && (item= it++)) while ( wild_num && (item= it++))
...@@ -2178,8 +2178,8 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, ...@@ -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, if (insert_fields(thd,tables,((Item_field*) item)->db_name,
((Item_field*) item)->table_name, &it)) ((Item_field*) item)->table_name, &it))
{ {
if (stmt) if (arena)
thd->restore_backup_item_arena(stmt, &backup); thd->restore_backup_item_arena(arena, &backup);
return (-1); return (-1);
} }
if (sum_func_list) if (sum_func_list)
...@@ -2194,8 +2194,15 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, ...@@ -2194,8 +2194,15 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
wild_num--; wild_num--;
} }
} }
if (stmt) if (arena)
thd->restore_backup_item_arena(stmt, &backup); {
/* 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; return 0;
} }
...@@ -2408,12 +2415,17 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, ...@@ -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) int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
{ {
table_map not_null_tables= 0; 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"); DBUG_ENTER("setup_conds");
thd->set_query_id=1; thd->set_query_id=1;
thd->lex->current_select->cond_count= 0; select_lex->cond_count= 0;
if (*conds) if (*conds)
{ {
thd->where="where clause"; thd->where="where clause";
...@@ -2436,7 +2448,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) ...@@ -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->fix_fields(thd, tables, &table->on_expr) ||
table->on_expr->check_cols(1)) table->on_expr->check_cols(1))
DBUG_RETURN(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 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) ...@@ -2447,12 +2459,12 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
!(specialflag & SPECIAL_NO_NEW_FUNC))) !(specialflag & SPECIAL_NO_NEW_FUNC)))
{ {
table->outer_join= 0; table->outer_join= 0;
if (stmt) if (arena)
thd->set_n_backup_item_arena(stmt, &backup); thd->set_n_backup_item_arena(arena, &backup);
*conds= and_conds(*conds, table->on_expr); *conds= and_conds(*conds, table->on_expr);
table->on_expr=0; table->on_expr=0;
if (stmt) if (arena)
thd->restore_backup_item_arena(stmt, &backup); thd->restore_backup_item_arena(arena, &backup);
if ((*conds) && !(*conds)->fixed && if ((*conds) && !(*conds)->fixed &&
(*conds)->fix_fields(thd, tables, conds)) (*conds)->fix_fields(thd, tables, conds))
DBUG_RETURN(1); DBUG_RETURN(1);
...@@ -2460,8 +2472,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) ...@@ -2460,8 +2472,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
} }
if (table->natural_join) if (table->natural_join)
{ {
if (stmt) if (arena)
thd->set_n_backup_item_arena(stmt, &backup); thd->set_n_backup_item_arena(arena, &backup);
/* Make a join of all fields with have the same name */ /* Make a join of all fields with have the same name */
TABLE *t1= table->table; TABLE *t1= table->table;
TABLE *t2= table->natural_join->table; TABLE *t2= table->natural_join->table;
...@@ -2491,7 +2503,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) ...@@ -2491,7 +2503,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
t2->used_keys.intersect(t2_field->part_of_key); 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 // to prevent natural join processing during PS re-execution
table->natural_join= 0; table->natural_join= 0;
...@@ -2500,8 +2512,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) ...@@ -2500,8 +2512,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
{ {
*conds= and_conds(*conds, cond_and); *conds= and_conds(*conds, cond_and);
// fix_fields() should be made with temporary memory pool // fix_fields() should be made with temporary memory pool
if (stmt) if (arena)
thd->restore_backup_item_arena(stmt, &backup); thd->restore_backup_item_arena(arena, &backup);
if (*conds && !(*conds)->fixed) if (*conds && !(*conds)->fixed)
{ {
if ((*conds)->fix_fields(thd, tables, conds)) if ((*conds)->fix_fields(thd, tables, conds))
...@@ -2512,8 +2524,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **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); table->on_expr= and_conds(table->on_expr, cond_and);
// fix_fields() should be made with temporary memory pool // fix_fields() should be made with temporary memory pool
if (stmt) if (arena)
thd->restore_backup_item_arena(stmt, &backup); thd->restore_backup_item_arena(arena, &backup);
if (table->on_expr && !table->on_expr->fixed) if (table->on_expr && !table->on_expr->fixed)
{ {
if (table->on_expr->fix_fields(thd, tables, &table->on_expr)) 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) ...@@ -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 We are in prepared statement preparation code => we should store
WHERE clause changing for next executions. 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)); DBUG_RETURN(test(thd->net.report_error));
err: err:
if (stmt) if (arena)
thd->restore_backup_item_arena(stmt, &backup); thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
......
...@@ -86,7 +86,7 @@ extern "C" void free_user_var(user_var_entry *entry) ...@@ -86,7 +86,7 @@ extern "C" void free_user_var(user_var_entry *entry)
** Thread specific functions ** 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), last_insert_id_used(0),
insert_id_used(0), rand_used(0), in_lock_tables(0), insert_id_used(0), rand_used(0), in_lock_tables(0),
global_read_lock(0), bootstrap(0), spcont(NULL) global_read_lock(0), bootstrap(0), spcont(NULL)
...@@ -1210,23 +1210,47 @@ int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u) ...@@ -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 functions
*/ */
Statement::Statement(THD *thd) Statement::Statement(THD *thd)
:id(++thd->statement_id_counter), :Item_arena(thd),
id(++thd->statement_id_counter),
set_query_id(1), set_query_id(1),
allow_sum_func(0), allow_sum_func(0),
lex(&main_lex), lex(&main_lex),
query(0), query(0),
query_length(0), query_length(0)
free_list(0) {}
{
init_sql_alloc(&mem_root,
thd->variables.query_alloc_block_size,
thd->variables.query_prealloc_size);
}
/* /*
This constructor is called when statement is a subobject of THD: This constructor is called when statement is a subobject of THD:
...@@ -1235,15 +1259,14 @@ Statement::Statement(THD *thd) ...@@ -1235,15 +1259,14 @@ Statement::Statement(THD *thd)
*/ */
Statement::Statement() Statement::Statement()
:id(0), :Item_arena(),
id(0),
set_query_id(1), set_query_id(1),
allow_sum_func(0), /* initialized later */ allow_sum_func(0), /* initialized later */
lex(&main_lex), lex(&main_lex),
query(0), /* these two are set */ query(0), /* these two are set */
query_length(0), /* in alloc_query() */ query_length(0) /* in alloc_query() */
free_list(0)
{ {
bzero((char *) &mem_root, sizeof(mem_root));
} }
...@@ -1264,14 +1287,14 @@ void Statement::set_statement(Statement *stmt) ...@@ -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); backup->set_item_arena(this);
set_item_arena(set); 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->set_item_arena(this);
set_item_arena(backup); set_item_arena(backup);
...@@ -1279,7 +1302,7 @@ void Statement::restore_backup_item_arena(Statement *set, Statement *backup) ...@@ -1279,7 +1302,7 @@ void Statement::restore_backup_item_arena(Statement *set, Statement *backup)
init_alloc_root(&backup->mem_root, 0, 0); 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; mem_root= set->mem_root;
free_list= set->free_list; free_list= set->free_list;
......
...@@ -434,6 +434,48 @@ struct system_variables ...@@ -434,6 +434,48 @@ struct system_variables
void free_tmp_table(THD *thd, TABLE *entry); 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. State of a single command executed against this connection.
One connection can contain a lot of simultaneously running statements, One connection can contain a lot of simultaneously running statements,
...@@ -448,7 +490,7 @@ void free_tmp_table(THD *thd, TABLE *entry); ...@@ -448,7 +490,7 @@ void free_tmp_table(THD *thd, TABLE *entry);
be used explicitly. be used explicitly.
*/ */
class Statement class Statement: public Item_arena
{ {
Statement(const Statement &rhs); /* not implemented: */ Statement(const Statement &rhs); /* not implemented: */
Statement &operator=(const Statement &rhs); /* non-copyable */ Statement &operator=(const Statement &rhs); /* non-copyable */
...@@ -489,12 +531,6 @@ class Statement ...@@ -489,12 +531,6 @@ class Statement
*/ */
char *query; char *query;
uint32 query_length; // current query length 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: public:
/* We build without RTTI, so dynamic_cast can't be used. */ /* We build without RTTI, so dynamic_cast can't be used. */
...@@ -518,31 +554,6 @@ class Statement ...@@ -518,31 +554,6 @@ class Statement
/* return class type */ /* return class type */
virtual Type type() const; 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 @@ class THD :public ilink, ...@@ -746,9 +757,9 @@ class THD :public ilink,
Vio* active_vio; Vio* active_vio;
#endif #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 next_insert_id is set on SET INSERT_ID= #. This is used as the next
generated auto_increment value in handler.cc generated auto_increment value in handler.cc
...@@ -969,7 +980,7 @@ class THD :public ilink, ...@@ -969,7 +980,7 @@ class THD :public ilink,
inline void allocate_temporary_memory_pool_for_ps_preparing() 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, We do not want to have in PS memory all that junk,
which will be created by preparation => substitute memory which will be created by preparation => substitute memory
...@@ -978,7 +989,7 @@ class THD :public ilink, ...@@ -978,7 +989,7 @@ class THD :public ilink,
We know that PS memory pool is now copied to THD, we move it back We know that PS memory pool is now copied to THD, we move it back
to allow some code use it. to allow some code use it.
*/ */
current_statement->set_item_arena(this); current_arena->set_item_arena(this);
init_sql_alloc(&mem_root, init_sql_alloc(&mem_root,
variables.query_alloc_block_size, variables.query_alloc_block_size,
variables.query_prealloc_size); variables.query_prealloc_size);
...@@ -986,12 +997,16 @@ class THD :public ilink, ...@@ -986,12 +997,16 @@ class THD :public ilink,
} }
inline void free_temporary_memory_pool_for_ps_preparing() inline void free_temporary_memory_pool_for_ps_preparing()
{ {
DBUG_ASSERT(current_statement!=0); DBUG_ASSERT(current_arena!=0);
cleanup_items(current_statement->free_list); cleanup_items(current_arena->free_list);
free_items(free_list); free_items(free_list);
close_thread_tables(this); // to close derived tables close_thread_tables(this); // to close derived tables
free_root(&mem_root, MYF(0)); free_root(&mem_root, MYF(0));
set_item_arena(current_statement); set_item_arena(current_arena);
}
inline bool only_prepare()
{
return command == COM_PREPARE;
} }
}; };
......
...@@ -264,10 +264,11 @@ int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) ...@@ -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-> TABLE_LIST *delete_table_list= ((TABLE_LIST*) thd->lex->
select_lex.table_list.first); select_lex.table_list.first);
SELECT_LEX *select_lex= &thd->lex->select_lex;
DBUG_ENTER("mysql_prepare_delete"); DBUG_ENTER("mysql_prepare_delete");
if (setup_conds(thd, delete_table_list, conds) || if (setup_conds(thd, delete_table_list, conds) ||
setup_ftfuncs(&thd->lex->select_lex)) setup_ftfuncs(select_lex))
DBUG_RETURN(-1); DBUG_RETURN(-1);
if (find_real_table_in_list(table_list->next, if (find_real_table_in_list(table_list->next,
table_list->db, table_list->real_name)) table_list->db, table_list->real_name))
...@@ -275,6 +276,11 @@ int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) ...@@ -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); my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
DBUG_RETURN(-1); 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); DBUG_RETURN(0);
} }
......
...@@ -152,7 +152,7 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, ...@@ -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 if it is preparation PS only then we do not need real data and we
can skip execution (and parameters is not defined, too) can skip execution (and parameters is not defined, too)
*/ */
if (!thd->current_statement) if (!thd->only_prepare())
{ {
if (is_union) if (is_union)
{ {
......
...@@ -460,6 +460,7 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, ...@@ -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); my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
thd->lex->select_lex.first_execution= 0;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
......
...@@ -1011,10 +1011,12 @@ void st_select_lex::init_query() ...@@ -1011,10 +1011,12 @@ void st_select_lex::init_query()
having_fix_field= 0; having_fix_field= 0;
resolve_mode= NOMATTER_MODE; resolve_mode= NOMATTER_MODE;
cond_count= with_wild= 0; cond_count= with_wild= 0;
conds_processed_with_permanent_arena= 0;
ref_pointer_array= 0; ref_pointer_array= 0;
select_n_having_items= 0; select_n_having_items= 0;
prep_where= 0; prep_where= 0;
explicit_limit= 0; explicit_limit= 0;
first_execution= 1;
} }
void st_select_lex::init_select() void st_select_lex::init_select()
...@@ -1414,7 +1416,9 @@ bool st_select_lex::add_order_to_list(THD *thd, Item *item, bool asc) ...@@ -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) 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,9 +1504,9 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) ...@@ -1500,9 +1504,9 @@ 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 We have to create array in prepared statement memory if it is
prepared statement 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= return (ref_pointer_array=
(Item **)stmt->alloc(sizeof(Item*) * (Item **)arena->alloc(sizeof(Item*) *
(item_list.elements + (item_list.elements +
select_n_having_items + select_n_having_items +
order_group_num)* 5)) == 0; order_group_num)* 5)) == 0;
......
...@@ -405,8 +405,6 @@ class st_select_lex: public st_select_lex_node ...@@ -405,8 +405,6 @@ class st_select_lex: public st_select_lex_node
enum olap_type olap; enum olap_type olap;
SQL_LIST table_list, group_list; /* FROM & GROUP BY clauses */ SQL_LIST table_list, group_list; /* FROM & GROUP BY clauses */
List<Item> item_list; /* list of fields & expressions */ 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, List<String> interval_list, use_index, *use_index_ptr,
ignore_index, *ignore_index_ptr; ignore_index, *ignore_index_ptr;
/* /*
...@@ -435,6 +433,11 @@ class st_select_lex: public st_select_lex_node ...@@ -435,6 +433,11 @@ class st_select_lex: public st_select_lex_node
uint cond_count; /* number of arguments of and/or/xor in where/having */ uint cond_count; /* number of arguments of and/or/xor in where/having */
enum_parsing_place parsing_place; /* where we are parsing expression */ enum_parsing_place parsing_place; /* where we are parsing expression */
bool with_sum_func; /* sum function indicator */ 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; ulong table_join_options;
uint in_sum_expr; uint in_sum_expr;
...@@ -445,6 +448,7 @@ class st_select_lex: public st_select_lex_node ...@@ -445,6 +448,7 @@ class st_select_lex: public st_select_lex_node
bool having_fix_field; bool having_fix_field;
/* explicit LIMIT clause was used */ /* explicit LIMIT clause was used */
bool explicit_limit; bool explicit_limit;
bool first_execution; /* first execution in SP or PS */
/* /*
SELECT for SELECT command st_select_lex. Used to privent scaning SELECT for SELECT command st_select_lex. Used to privent scaning
......
...@@ -4182,12 +4182,14 @@ void mysql_parse(THD *thd, char *inBuf, uint length) ...@@ -4182,12 +4182,14 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
query_cache_end_of_result(thd); query_cache_end_of_result(thd);
} }
} }
lex->unit.cleanup();
} }
else else
{ {
DBUG_PRINT("info",("Command aborted. Fatal_error: %d", DBUG_PRINT("info",("Command aborted. Fatal_error: %d",
thd->is_fatal_error)); thd->is_fatal_error));
query_cache_abort(&thd->net); query_cache_abort(&thd->net);
lex->unit.cleanup();
if (thd->lex->sphead) if (thd->lex->sphead)
{ {
/* Clean up after failed stored procedure/function */ /* Clean up after failed stored procedure/function */
......
...@@ -1357,7 +1357,7 @@ void mysql_stmt_prepare(THD *thd, char *packet, uint packet_length) ...@@ -1357,7 +1357,7 @@ void mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
mysql_log.write(thd, COM_PREPARE, "%s", packet); 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); lex= lex_start(thd, (uchar *) thd->query, thd->query_length);
mysql_init_query(thd); mysql_init_query(thd);
lex->safe_to_cache_query= 0; lex->safe_to_cache_query= 0;
...@@ -1381,7 +1381,7 @@ void mysql_stmt_prepare(THD *thd, char *packet, uint packet_length) ...@@ -1381,7 +1381,7 @@ void mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
stmt->set_item_arena(thd); stmt->set_item_arena(thd);
thd->set_statement(&thd->stmt_backup); thd->set_statement(&thd->stmt_backup);
thd->set_item_arena(&thd->stmt_backup); thd->set_item_arena(&thd->stmt_backup);
thd->current_statement= 0; thd->current_arena= 0;
if (error) if (error)
{ {
...@@ -1389,29 +1389,18 @@ void mysql_stmt_prepare(THD *thd, char *packet, uint packet_length) ...@@ -1389,29 +1389,18 @@ void mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
thd->stmt_map.erase(stmt); thd->stmt_map.erase(stmt);
/* error is sent inside yyparse/send_prepare_results */ /* 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; DBUG_VOID_RETURN;
} }
/* Reinit statement before execution */ /* 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= lex->all_selects_list;
SELECT_LEX *sl= stmt->lex->all_selects_list;
for (; sl; sl= sl->next_select_in_list()) for (; sl; sl= sl->next_select_in_list())
{
if (!sl->first_execution)
{ {
/* /*
Copy WHERE clause pointers to avoid damaging they by optimisation Copy WHERE clause pointers to avoid damaging they by optimisation
...@@ -1426,6 +1415,7 @@ static void reset_stmt_for_execute(Prepared_statement *stmt) ...@@ -1426,6 +1415,7 @@ static void reset_stmt_for_execute(Prepared_statement *stmt)
/* Fix ORDER list */ /* Fix ORDER list */
for (order= (ORDER *)sl->order_list.first; order; order= order->next) for (order= (ORDER *)sl->order_list.first; order; order= order->next)
order->item= &order->item_ptr; order->item= &order->item_ptr;
}
/* /*
TODO: When the new table structure is ready, then have a status bit 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) ...@@ -1443,7 +1433,6 @@ static void reset_stmt_for_execute(Prepared_statement *stmt)
tables->table= 0; tables->table= 0;
tables->table_list= 0; tables->table_list= 0;
} }
{ {
SELECT_LEX_UNIT *unit= sl->master_unit(); SELECT_LEX_UNIT *unit= sl->master_unit();
unit->unclean(); unit->unclean();
...@@ -1506,7 +1495,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) ...@@ -1506,7 +1495,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
thd->stmt_backup.set_statement(thd); thd->stmt_backup.set_statement(thd);
thd->set_statement(stmt); thd->set_statement(stmt);
reset_stmt_for_execute(stmt); reset_stmt_for_execute(thd, stmt->lex);
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
if (stmt->param_count) if (stmt->param_count)
{ {
......
...@@ -367,9 +367,16 @@ JOIN::prepare(Item ***rref_pointer_array, ...@@ -367,9 +367,16 @@ JOIN::prepare(Item ***rref_pointer_array,
Item_subselect::trans_res res; Item_subselect::trans_res res;
if ((res= subselect->select_transformer(this)) != if ((res= subselect->select_transformer(this)) !=
Item_subselect::RES_OK) 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)); DBUG_RETURN((res == Item_subselect::RES_ERROR));
} }
} }
}
if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */ if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */
DBUG_RETURN(-1); DBUG_RETURN(-1);
...@@ -470,6 +477,11 @@ JOIN::prepare(Item ***rref_pointer_array, ...@@ -470,6 +477,11 @@ JOIN::prepare(Item ***rref_pointer_array,
if (alloc_func_list()) if (alloc_func_list())
goto err; 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 DBUG_RETURN(0); // All OK
err: err:
......
...@@ -262,27 +262,32 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, ...@@ -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; thd_arg->lex->current_select= lex_select_save;
if (!item_list.elements) if (!item_list.elements)
{ {
Statement *stmt= thd->current_statement; Item_arena *arena= thd->current_arena;
Statement backup; Item_arena backup;
if (stmt) if (arena)
thd->set_n_backup_item_arena(stmt, &backup); thd->set_n_backup_item_arena(arena, &backup);
Field **field; Field **field;
for (field= table->field; *field; field++) for (field= table->field; *field; field++)
{ {
Item_field *item= new Item_field(*field); Item_field *item= new Item_field(*field);
if (!item || item_list.push_back(item)) if (!item || item_list.push_back(item))
{ {
if (stmt) if (arena)
thd->restore_backup_item_arena(stmt, &backup); thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(-1); 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 */ /* prepare fake select to initialize it correctly */
ulong options_tmp= init_prepare_fake_select_lex(thd); 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, if (!(fake_select_lex->join= new JOIN(thd, item_list, thd->options,
result))) result)))
{ {
......
...@@ -425,6 +425,7 @@ int mysql_prepare_update(THD *thd, TABLE_LIST *table_list, ...@@ -425,6 +425,7 @@ int mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
TABLE *table= table_list->table; TABLE *table= table_list->table;
TABLE_LIST tables; TABLE_LIST tables;
List<Item> all_fields; List<Item> all_fields;
SELECT_LEX *select_lex= &thd->lex->select_lex;
DBUG_ENTER("mysql_prepare_update"); DBUG_ENTER("mysql_prepare_update");
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
...@@ -437,10 +438,10 @@ int mysql_prepare_update(THD *thd, TABLE_LIST *table_list, ...@@ -437,10 +438,10 @@ int mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
if (setup_tables(update_table_list) || if (setup_tables(update_table_list) ||
setup_conds(thd, update_table_list, conds) || setup_conds(thd, update_table_list, conds) ||
thd->lex->select_lex.setup_ref_array(thd, order_num) || select_lex->setup_ref_array(thd, order_num) ||
setup_order(thd, thd->lex->select_lex.ref_pointer_array, setup_order(thd, select_lex->ref_pointer_array,
update_table_list, all_fields, all_fields, order) || update_table_list, all_fields, all_fields, order) ||
setup_ftfuncs(&thd->lex->select_lex)) setup_ftfuncs(select_lex))
DBUG_RETURN(-1); DBUG_RETURN(-1);
/* Check that we are not using table that we are updating in a sub select */ /* 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, ...@@ -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); my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
DBUG_RETURN(-1); 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); DBUG_RETURN(0);
} }
......
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