mirror of
https://github.com/MariaDB/server.git
synced 2025-01-18 13:02:28 +01:00
Merge sanja.is.com.ua:/home/bell/mysql/bk/mysql-5.0
into sanja.is.com.ua:/home/bell/mysql/bk/work-sp2-5.0
This commit is contained in:
commit
5e83cf32a6
22 changed files with 306 additions and 275 deletions
|
@ -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;
|
||||
|
|
|
@ -1444,3 +1444,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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
136
sql/sp_head.cc
136
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;
|
||||
|
@ -430,6 +434,9 @@ 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 +694,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 +784,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 +804,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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -919,7 +918,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 +925,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;
|
||||
}
|
||||
|
|
|
@ -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 &);
|
||||
|
@ -206,9 +206,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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,24 +1210,48 @@ int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Statement functions
|
||||
*/
|
||||
|
||||
Statement::Statement(THD *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)
|
||||
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)
|
||||
:Item_arena(thd),
|
||||
id(++thd->statement_id_counter),
|
||||
set_query_id(1),
|
||||
allow_sum_func(0),
|
||||
lex(&main_lex),
|
||||
query(0),
|
||||
query_length(0)
|
||||
{}
|
||||
|
||||
/*
|
||||
This constructor is called when statement is a subobject of THD:
|
||||
Some variables are initialized in THD::init due to locking problems
|
||||
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)))
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue