mirror of
https://github.com/MariaDB/server.git
synced 2025-06-26 17:42:13 +03:00
PS and SP made compatible in mechanism used for preparing query for rexecutions (Bug #2266)
mysql-test/r/sp.result: test suite for Bug #2266 mysql-test/t/sp.test: test suite for Bug #2266 sql/item_subselect.cc: made ancestor for Statement (Item_arena) sql/item_subselect.h: made ancestor for Statement (Item_arena) sql/item_sum.cc: made ancestor for Statement (Item_arena) sql/item_sum.h: made ancestor for Statement (Item_arena) sql/mysql_priv.h: reset_stmt_for_execute use PS and SP sql/sp_head.cc: sp_head use Item_arena as ancestor to be PS cleunup compatible SP use PS storing/restoring/cleanup mechanisms cleanup() of SP Items added Items created in temporary memory pool during SP execution saved for normal freeing after SP execution sql/sp_head.h: sp_head use Item_arena sql/sql_base.cc: made ancestor for Statement (Item_arena) results of wild_setup made permanent setup_conds make natural joins expanding only once and store results in PS/SP memory sql/sql_class.cc: made ancestor for Statement (Item_arena) sql/sql_class.h: made ancestor for Statement (Item_arena) method to detect PS preparation added sql/sql_delete.cc: storing where for DELETE and mark first execution sql/sql_derived.cc: use method sql/sql_insert.cc: mark first execution for INSERT sql/sql_lex.cc: flags to correctly make transformations of query and storing them in memory of PS/SP made ancestor for Statement (Item_arena) sql/sql_lex.h: reved variable od SP ol saving data flags to correctly make transformations of query and storing them in memory of PS/SP sql/sql_parse.cc: cleunup unit for any query sql/sql_prepare.cc: made ancestor for Statement (Item_arena) storing where moved to preparation changed interface of reset_stmt_for_execute to use it is SP do not restore where/order by/group by before first execution (but tables and unit can be chenged without execution and should be prepared (subqueries executes on demand)) sql/sql_select.cc: storing where for SELECT/multi-DELETE/... and mark first execution sql/sql_union.cc: made ancestor for Statement (Item_arena) sql/sql_update.cc: storing where for UPDATE and mark first execution
This commit is contained in:
@ -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;
|
||||||
|
@ -1444,3 +1444,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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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;
|
|||||||
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
|
|||||||
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):
|
|||||||
*/
|
*/
|
||||||
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 @@
|
|||||||
|
|
||||||
#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 @@ public:
|
|||||||
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);
|
|||||||
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,
|
||||||
|
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));
|
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)
|
|||||||
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()
|
|||||||
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()
|
|||||||
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)
|
|||||||
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;
|
||||||
@ -430,6 +434,9 @@ 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 +694,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 +784,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 +804,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -919,7 +918,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 +925,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 *
|
|||||||
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 &);
|
||||||
@ -206,9 +206,7 @@ public:
|
|||||||
|
|
||||||
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
|
||||||
|
|
||||||
|
@ -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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
!(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)
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
*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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
** 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,24 +1210,48 @@ int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
Item_arena::Item_arena(THD* thd)
|
||||||
Statement functions
|
:free_list(0)
|
||||||
*/
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
init_sql_alloc(&mem_root,
|
init_sql_alloc(&mem_root,
|
||||||
thd->variables.query_alloc_block_size,
|
thd->variables.query_alloc_block_size,
|
||||||
thd->variables.query_prealloc_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:
|
This constructor is called when statement is a subobject of THD:
|
||||||
Some variables are initialized in THD::init due to locking problems
|
Some variables are initialized in THD::init due to locking problems
|
||||||
@ -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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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)
|
|||||||
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
|
|||||||
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);
|
|||||||
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 @@ public:
|
|||||||
*/
|
*/
|
||||||
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 @@ public:
|
|||||||
/* 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 @@ public:
|
|||||||
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 @@ public:
|
|||||||
|
|
||||||
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 @@ public:
|
|||||||
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 @@ public:
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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()
|
|||||||
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)
|
|||||||
|
|
||||||
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,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
|
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 @@ public:
|
|||||||
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 @@ public:
|
|||||||
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 @@ public:
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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,43 +1389,33 @@ 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
|
{
|
||||||
*/
|
/*
|
||||||
if (sl->prep_where)
|
Copy WHERE clause pointers to avoid damaging they by optimisation
|
||||||
sl->where= sl->prep_where->copy_andor_structure(thd);
|
*/
|
||||||
DBUG_ASSERT(sl->join == 0);
|
if (sl->prep_where)
|
||||||
ORDER *order;
|
sl->where= sl->prep_where->copy_andor_structure(thd);
|
||||||
/* Fix GROUP list */
|
DBUG_ASSERT(sl->join == 0);
|
||||||
for (order= (ORDER *)sl->group_list.first; order; order= order->next)
|
ORDER *order;
|
||||||
order->item= &order->item_ptr;
|
/* Fix GROUP list */
|
||||||
/* Fix ORDER list */
|
for (order= (ORDER *)sl->group_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;
|
/* 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
|
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= 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)
|
|||||||
|
|
||||||
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,7 +367,14 @@ 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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user