mirror of
https://github.com/MariaDB/server.git
synced 2025-01-19 13:32:33 +01:00
Merge paul@bk-internal.mysql.com:/home/bk/mysql-4.1
into ice.snake.net:/Volumes/ice2/MySQL/bk/mysql-4.1
This commit is contained in:
commit
c5677d9a3e
20 changed files with 395 additions and 261 deletions
|
@ -271,3 +271,39 @@ i i COUNT(*)
|
|||
100 NULL 2
|
||||
NULL NULL 2
|
||||
drop table t1,t2;
|
||||
CREATE TABLE user_day(
|
||||
user_id INT NOT NULL,
|
||||
date DATE NOT NULL,
|
||||
UNIQUE INDEX user_date (user_id, date)
|
||||
);
|
||||
INSERT INTO user_day VALUES
|
||||
(1, '2004-06-06' ),
|
||||
(1, '2004-06-07' ),
|
||||
(2, '2004-06-06' );
|
||||
SELECT
|
||||
d.date AS day,
|
||||
COUNT(d.user_id) as sample,
|
||||
COUNT(next_day.user_id) AS not_cancelled
|
||||
FROM user_day d
|
||||
LEFT JOIN user_day next_day
|
||||
ON next_day.user_id=d.user_id AND
|
||||
next_day.date= DATE_ADD( d.date, interval 1 day )
|
||||
GROUP BY day;
|
||||
day sample not_cancelled
|
||||
2004-06-06 2 1
|
||||
2004-06-07 1 0
|
||||
SELECT
|
||||
d.date AS day,
|
||||
COUNT(d.user_id) as sample,
|
||||
COUNT(next_day.user_id) AS not_cancelled
|
||||
FROM user_day d
|
||||
LEFT JOIN user_day next_day
|
||||
ON next_day.user_id=d.user_id AND
|
||||
next_day.date= DATE_ADD( d.date, interval 1 day )
|
||||
GROUP BY day
|
||||
WITH ROLLUP;
|
||||
day sample not_cancelled
|
||||
2004-06-06 2 1
|
||||
2004-06-07 1 0
|
||||
NULL 3 1
|
||||
DROP TABLE user_day;
|
||||
|
|
|
@ -219,3 +219,10 @@ Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length I
|
|||
t1 MyISAM 9 Dynamic 0 0 0 4294967295 1024 0 NULL # # # latin1_swedish_ci NULL
|
||||
deallocate prepare stmt1 ;
|
||||
drop table t1;
|
||||
create table t1(a varchar(2), b varchar(3));
|
||||
prepare stmt1 from "select a, b from t1 where (not (a='aa' and b < 'zzz'))";
|
||||
execute stmt1;
|
||||
a b
|
||||
execute stmt1;
|
||||
a b
|
||||
deallocate prepare stmt1;
|
||||
|
|
|
@ -1 +1 @@
|
|||
--innodb_lock_wait_timeout=5
|
||||
--loose-innodb_lock_wait_timeout=5
|
||||
|
|
|
@ -88,3 +88,40 @@ INSERT INTO t2 VALUES (100),(200);
|
|||
SELECT i, COUNT(*) FROM t1 GROUP BY i WITH ROLLUP;
|
||||
SELECT t1.i, t2.i, COUNT(*) FROM t1,t2 GROUP BY t1.i,t2.i WITH ROLLUP;
|
||||
drop table t1,t2;
|
||||
|
||||
#bug #4767: ROLLUP with LEFT JOIN
|
||||
|
||||
CREATE TABLE user_day(
|
||||
user_id INT NOT NULL,
|
||||
date DATE NOT NULL,
|
||||
UNIQUE INDEX user_date (user_id, date)
|
||||
);
|
||||
|
||||
INSERT INTO user_day VALUES
|
||||
(1, '2004-06-06' ),
|
||||
(1, '2004-06-07' ),
|
||||
(2, '2004-06-06' );
|
||||
|
||||
SELECT
|
||||
d.date AS day,
|
||||
COUNT(d.user_id) as sample,
|
||||
COUNT(next_day.user_id) AS not_cancelled
|
||||
FROM user_day d
|
||||
LEFT JOIN user_day next_day
|
||||
ON next_day.user_id=d.user_id AND
|
||||
next_day.date= DATE_ADD( d.date, interval 1 day )
|
||||
GROUP BY day;
|
||||
|
||||
SELECT
|
||||
d.date AS day,
|
||||
COUNT(d.user_id) as sample,
|
||||
COUNT(next_day.user_id) AS not_cancelled
|
||||
FROM user_day d
|
||||
LEFT JOIN user_day next_day
|
||||
ON next_day.user_id=d.user_id AND
|
||||
next_day.date= DATE_ADD( d.date, interval 1 day )
|
||||
GROUP BY day
|
||||
WITH ROLLUP;
|
||||
|
||||
DROP TABLE user_day;
|
||||
|
||||
|
|
|
@ -206,3 +206,15 @@ execute stmt1;
|
|||
show table status from test like 't1%' ;
|
||||
deallocate prepare stmt1 ;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Bug#4912 "mysqld crashs in case a statement is executed a second time":
|
||||
# negation elimination should and prepared statemens
|
||||
#
|
||||
|
||||
create table t1(a varchar(2), b varchar(3));
|
||||
prepare stmt1 from "select a, b from t1 where (not (a='aa' and b < 'zzz'))";
|
||||
execute stmt1;
|
||||
execute stmt1;
|
||||
deallocate prepare stmt1;
|
||||
|
||||
|
|
|
@ -589,10 +589,8 @@ bool Item_in_optimizer::fix_left(THD *thd,
|
|||
/*
|
||||
If it is preparation PS only then we do not know values of parameters =>
|
||||
cant't get there values and do not need that values.
|
||||
|
||||
TODO: during merge with 5.0 it should be changed on !thd->only_prepare()
|
||||
*/
|
||||
if (!thd->current_statement)
|
||||
if (! thd->current_arena->is_stmt_prepare())
|
||||
cache->store(args[0]);
|
||||
if (cache->cols() == 1)
|
||||
{
|
||||
|
|
|
@ -125,7 +125,6 @@ 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;
|
||||
|
||||
char const *save_where= thd->where;
|
||||
int res;
|
||||
|
@ -306,7 +305,10 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
|
|||
return RES_OK;
|
||||
|
||||
SELECT_LEX *select_lex= join->select_lex;
|
||||
Statement backup;
|
||||
|
||||
/* Juggle with current arena only if we're in prepared statement prepare */
|
||||
Item_arena *arena= join->thd->current_arena;
|
||||
Item_arena backup;
|
||||
|
||||
if (!select_lex->master_unit()->first_select()->next_select() &&
|
||||
!select_lex->table_list.elements &&
|
||||
|
@ -341,8 +343,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->is_stmt_prepare())
|
||||
thd->set_n_backup_item_arena(arena, &backup);
|
||||
|
||||
if (!join->having)
|
||||
cond= join->conds;
|
||||
|
@ -355,15 +357,15 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
|
|||
new Item_null())))
|
||||
goto err;
|
||||
}
|
||||
if (stmt)
|
||||
thd->restore_backup_item_arena(stmt, &backup);
|
||||
if (arena->is_stmt_prepare())
|
||||
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->is_stmt_prepare())
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
|
@ -640,11 +642,11 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
|||
}
|
||||
|
||||
SELECT_LEX *select_lex= join->select_lex;
|
||||
Statement backup;
|
||||
Item_arena *arena= join->thd->current_arena, backup;
|
||||
|
||||
thd->where= "scalar IN/ALL/ANY subquery";
|
||||
if (stmt)
|
||||
thd->set_n_backup_item_arena(stmt, &backup);
|
||||
if (arena->is_stmt_prepare())
|
||||
thd->set_n_backup_item_arena(arena, &backup);
|
||||
|
||||
if (select_lex->item_list.elements > 1)
|
||||
{
|
||||
|
@ -857,21 +859,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->is_stmt_prepare())
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
DBUG_RETURN(RES_REDUCE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ok:
|
||||
if (stmt)
|
||||
thd->restore_backup_item_arena(stmt, &backup);
|
||||
if (arena->is_stmt_prepare())
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
DBUG_RETURN(RES_OK);
|
||||
|
||||
err:
|
||||
if (stmt)
|
||||
thd->restore_backup_item_arena(stmt, &backup);
|
||||
if (arena->is_stmt_prepare())
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
DBUG_RETURN(RES_ERROR);
|
||||
}
|
||||
|
||||
|
@ -885,12 +887,12 @@ Item_in_subselect::row_value_transformer(JOIN *join)
|
|||
{
|
||||
DBUG_RETURN(RES_OK);
|
||||
}
|
||||
Statement backup;
|
||||
Item_arena *arena= join->thd->current_arena, backup;
|
||||
Item *item= 0;
|
||||
|
||||
thd->where= "row IN/ALL/ANY subquery";
|
||||
if (stmt)
|
||||
thd->set_n_backup_item_arena(stmt, &backup);
|
||||
if (arena->is_stmt_prepare())
|
||||
thd->set_n_backup_item_arena(arena, &backup);
|
||||
|
||||
SELECT_LEX *select_lex= join->select_lex;
|
||||
|
||||
|
@ -974,13 +976,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->is_stmt_prepare())
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
DBUG_RETURN(RES_OK);
|
||||
|
||||
err:
|
||||
if (stmt)
|
||||
thd->restore_backup_item_arena(stmt, &backup);
|
||||
if (arena->is_stmt_prepare())
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
DBUG_RETURN(RES_ERROR);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,8 +36,6 @@ 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;
|
||||
/* substitution instead of subselect in case of optimization */
|
||||
Item *substitution;
|
||||
/* unit of subquery */
|
||||
|
|
|
@ -64,28 +64,28 @@ Item_sum::Item_sum(THD *thd, Item_sum *item):
|
|||
|
||||
|
||||
/*
|
||||
Save copy of arguments if we are prepare prepared statement
|
||||
Save copy of arguments if we prepare prepared statement
|
||||
(arguments can be rewritten in get_tmp_table_item())
|
||||
|
||||
SYNOPSIS
|
||||
Item_sum::save_args_for_prepared_statements()
|
||||
Item_sum::save_args_for_prepared_statement()
|
||||
thd - thread handler
|
||||
|
||||
RETURN
|
||||
0 - OK
|
||||
1 - Error
|
||||
*/
|
||||
bool Item_sum::save_args_for_prepared_statements(THD *thd)
|
||||
bool Item_sum::save_args_for_prepared_statement(THD *thd)
|
||||
{
|
||||
if (thd->current_statement)
|
||||
return save_args(thd->current_statement);
|
||||
if (thd->current_arena->is_stmt_prepare())
|
||||
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;
|
||||
|
@ -159,7 +159,10 @@ Item *Item_sum::get_tmp_table_item(THD *thd)
|
|||
if (!arg->const_item())
|
||||
{
|
||||
if (arg->type() == Item::FIELD_ITEM)
|
||||
{
|
||||
arg->maybe_null= result_field_tmp->maybe_null();
|
||||
((Item_field*) arg)->field= result_field_tmp++;
|
||||
}
|
||||
else
|
||||
sum_item->args[i]= new Item_field(result_field_tmp++);
|
||||
}
|
||||
|
@ -214,7 +217,7 @@ Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
|
||||
if (save_args_for_prepared_statements(thd))
|
||||
if (save_args_for_prepared_statement(thd))
|
||||
return 1;
|
||||
|
||||
if (!thd->allow_sum_func)
|
||||
|
@ -248,7 +251,7 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
|
||||
if (save_args_for_prepared_statements(thd))
|
||||
if (save_args_for_prepared_statement(thd))
|
||||
return 1;
|
||||
|
||||
Item *item= args[0];
|
||||
|
@ -1947,7 +1950,7 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
|
||||
if (save_args_for_prepared_statements(thd))
|
||||
if (save_args_for_prepared_statement(thd))
|
||||
return 1;
|
||||
|
||||
uint i; /* for loop variable */
|
||||
|
|
|
@ -92,8 +92,8 @@ public:
|
|||
virtual bool setup(THD *thd) {return 0;}
|
||||
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_for_prepared_statement(THD *);
|
||||
bool save_args(Item_arena *arena);
|
||||
|
||||
bool walk (Item_processor processor, byte *argument);
|
||||
};
|
||||
|
|
|
@ -295,7 +295,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout);
|
|||
|
||||
struct st_table;
|
||||
class THD;
|
||||
class Statement;
|
||||
class Item_arena;
|
||||
|
||||
/* Struct to handle simple linked lists */
|
||||
|
||||
|
|
|
@ -2251,14 +2251,15 @@ 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->is_stmt_prepare())
|
||||
thd->set_n_backup_item_arena(arena, &backup);
|
||||
|
||||
reg2 Item *item;
|
||||
List_iterator<Item> it(fields);
|
||||
while ( wild_num && (item= it++))
|
||||
|
@ -2282,8 +2283,8 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
|
|||
else 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->is_stmt_prepare())
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
return (-1);
|
||||
}
|
||||
if (sum_func_list)
|
||||
|
@ -2298,8 +2299,8 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
|
|||
wild_num--;
|
||||
}
|
||||
}
|
||||
if (stmt)
|
||||
thd->restore_backup_item_arena(stmt, &backup);
|
||||
if (arena->is_stmt_prepare())
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2512,7 +2513,7 @@ 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;
|
||||
Item_arena *arena= thd->current_arena, backup;
|
||||
|
||||
DBUG_ENTER("setup_conds");
|
||||
thd->set_query_id=1;
|
||||
|
@ -2551,12 +2552,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->is_stmt_prepare())
|
||||
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->is_stmt_prepare())
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
if ((*conds) && !(*conds)->fixed &&
|
||||
(*conds)->fix_fields(thd, tables, conds))
|
||||
DBUG_RETURN(1);
|
||||
|
@ -2564,8 +2565,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->is_stmt_prepare())
|
||||
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;
|
||||
|
@ -2606,8 +2607,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->is_stmt_prepare())
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
if (*conds && !(*conds)->fixed)
|
||||
{
|
||||
if ((*conds)->fix_fields(thd, tables, conds))
|
||||
|
@ -2618,8 +2619,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->is_stmt_prepare())
|
||||
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))
|
||||
|
@ -2630,7 +2631,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
|
|||
}
|
||||
}
|
||||
|
||||
if (stmt)
|
||||
if (arena->is_stmt_prepare())
|
||||
{
|
||||
/*
|
||||
We are in prepared statement preparation code => we should store
|
||||
|
@ -2643,8 +2644,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
|
|||
DBUG_RETURN(test(thd->net.report_error));
|
||||
|
||||
err:
|
||||
if (stmt)
|
||||
thd->restore_backup_item_arena(stmt, &backup);
|
||||
if (arena->is_stmt_prepare())
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ bool foreign_key_prefix(Key *a, Key *b)
|
|||
** Thread specific functions
|
||||
****************************************************************************/
|
||||
|
||||
THD::THD():user_time(0), current_statement(0), is_fatal_error(0),
|
||||
THD::THD():user_time(0), current_arena(this), is_fatal_error(0),
|
||||
last_insert_id_used(0),
|
||||
insert_id_used(0), rand_used(0), time_zone_used(0),
|
||||
in_lock_tables(0), global_read_lock(0), bootstrap(0)
|
||||
|
@ -1301,23 +1301,59 @@ int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
|
|||
}
|
||||
|
||||
|
||||
Item_arena::Item_arena(THD* thd)
|
||||
:free_list(0),
|
||||
state(INITIALIZED)
|
||||
{
|
||||
init_sql_alloc(&mem_root,
|
||||
thd->variables.query_alloc_block_size,
|
||||
thd->variables.query_prealloc_size);
|
||||
}
|
||||
|
||||
|
||||
/* This constructor is called when Item_arena is a subobject of THD */
|
||||
|
||||
Item_arena::Item_arena()
|
||||
:free_list(0),
|
||||
state(CONVENTIONAL_EXECUTION)
|
||||
{
|
||||
clear_alloc_root(&mem_root);
|
||||
}
|
||||
|
||||
|
||||
Item_arena::Item_arena(bool init_mem_root)
|
||||
:free_list(0),
|
||||
state(INITIALIZED)
|
||||
{
|
||||
if (init_mem_root)
|
||||
clear_alloc_root(&mem_root);
|
||||
}
|
||||
|
||||
Item_arena::Type Item_arena::type() const
|
||||
{
|
||||
DBUG_ASSERT("Item_arena::type()" == "abstract");
|
||||
return STATEMENT;
|
||||
}
|
||||
|
||||
|
||||
Item_arena::~Item_arena()
|
||||
{}
|
||||
|
||||
|
||||
/*
|
||||
Statement functions
|
||||
*/
|
||||
|
||||
Statement::Statement(THD *thd)
|
||||
:id(++thd->statement_id_counter),
|
||||
:Item_arena(thd),
|
||||
id(++thd->statement_id_counter),
|
||||
set_query_id(1),
|
||||
allow_sum_func(0),
|
||||
lex(&main_lex),
|
||||
query(0),
|
||||
query_length(0),
|
||||
free_list(0)
|
||||
query_length(0)
|
||||
{
|
||||
name.str= NULL;
|
||||
init_sql_alloc(&mem_root,
|
||||
thd->variables.query_alloc_block_size,
|
||||
thd->variables.query_prealloc_size);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1332,14 +1368,12 @@ Statement::Statement()
|
|||
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));
|
||||
}
|
||||
|
||||
|
||||
Statement::Type Statement::type() const
|
||||
Item_arena::Type Statement::type() const
|
||||
{
|
||||
return STATEMENT;
|
||||
}
|
||||
|
@ -1356,14 +1390,29 @@ void Statement::set_statement(Statement *stmt)
|
|||
}
|
||||
|
||||
|
||||
void Statement::set_n_backup_item_arena(Statement *set, Statement *backup)
|
||||
void
|
||||
Statement::set_n_backup_statement(Statement *stmt, Statement *backup)
|
||||
{
|
||||
backup->set_statement(this);
|
||||
set_statement(stmt);
|
||||
}
|
||||
|
||||
|
||||
void Statement::restore_backup_statement(Statement *stmt, Statement *backup)
|
||||
{
|
||||
stmt->set_statement(this);
|
||||
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);
|
||||
|
@ -1371,10 +1420,11 @@ 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;
|
||||
state= set->state;
|
||||
}
|
||||
|
||||
Statement::~Statement()
|
||||
|
|
128
sql/sql_class.h
128
sql/sql_class.h
|
@ -418,6 +418,61 @@ 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;
|
||||
static const int INITIALIZED= 0, PREPARED= 1, EXECUTED= 3,
|
||||
CONVENTIONAL_EXECUTION= 2, ERROR= -1;
|
||||
int state;
|
||||
|
||||
/* We build without RTTI, so dynamic_cast can't be used. */
|
||||
enum Type
|
||||
{
|
||||
STATEMENT, PREPARED_STATEMENT, STORED_PROCEDURE
|
||||
};
|
||||
|
||||
Item_arena(THD *thd);
|
||||
Item_arena();
|
||||
Item_arena(bool init_mem_root);
|
||||
virtual Type type() const;
|
||||
virtual ~Item_arena();
|
||||
|
||||
inline bool is_stmt_prepare() const { return state < PREPARED; }
|
||||
inline bool is_first_stmt_execute() const { return state == PREPARED; }
|
||||
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,
|
||||
|
@ -432,7 +487,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 */
|
||||
|
@ -474,20 +529,8 @@ 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. */
|
||||
enum Type
|
||||
{
|
||||
STATEMENT,
|
||||
PREPARED_STATEMENT
|
||||
};
|
||||
|
||||
/*
|
||||
This constructor is called when statement is a subobject of THD:
|
||||
|
@ -500,34 +543,10 @@ public:
|
|||
|
||||
/* Assign execution context (note: not all members) of given stmt to self */
|
||||
void set_statement(Statement *stmt);
|
||||
void set_n_backup_statement(Statement *stmt, Statement *backup);
|
||||
void restore_backup_statement(Statement *stmt, Statement *backup);
|
||||
/* 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);
|
||||
};
|
||||
|
||||
|
||||
|
@ -760,9 +779,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
|
||||
|
@ -983,33 +1002,6 @@ public:
|
|||
}
|
||||
inline CHARSET_INFO *charset() { return variables.character_set_client; }
|
||||
void update_charset();
|
||||
|
||||
inline void allocate_temporary_memory_pool_for_ps_preparing()
|
||||
{
|
||||
DBUG_ASSERT(current_statement!=0);
|
||||
/*
|
||||
We do not want to have in PS memory all that junk,
|
||||
which will be created by preparation => substitute memory
|
||||
from original thread pool.
|
||||
|
||||
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);
|
||||
init_sql_alloc(&mem_root,
|
||||
variables.query_alloc_block_size,
|
||||
variables.query_prealloc_size);
|
||||
free_list= 0;
|
||||
}
|
||||
inline void free_temporary_memory_pool_for_ps_preparing()
|
||||
{
|
||||
DBUG_ASSERT(current_statement!=0);
|
||||
cleanup_items(current_statement->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);
|
||||
}
|
||||
};
|
||||
|
||||
/* Flags for the THD::system_thread (bitmap) variable */
|
||||
|
|
|
@ -151,7 +151,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->current_arena->is_stmt_prepare())
|
||||
{
|
||||
if (is_union)
|
||||
{
|
||||
|
|
|
@ -1527,9 +1527,9 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
|
|||
We have to create array in prepared statement memory if it is
|
||||
prepared statement
|
||||
*/
|
||||
Statement *stmt= thd->current_statement ? thd->current_statement : thd;
|
||||
Item_arena *arena= thd->current_arena;
|
||||
return (ref_pointer_array=
|
||||
(Item **)stmt->alloc(sizeof(Item*) *
|
||||
(Item **)arena->alloc(sizeof(Item*) *
|
||||
(item_list.elements +
|
||||
select_n_having_items +
|
||||
order_group_num)* 5)) == 0;
|
||||
|
|
|
@ -1543,6 +1543,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||
break;
|
||||
mysqld_list_fields(thd,&table_list,fields);
|
||||
free_items(thd->free_list);
|
||||
thd->free_list= 0;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
@ -4047,6 +4048,7 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
|
|||
}
|
||||
thd->proc_info="freeing items";
|
||||
free_items(thd->free_list); /* Free strings used by items */
|
||||
thd->free_list= 0;
|
||||
lex_end(lex);
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
|
@ -4073,6 +4075,7 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length)
|
|||
all_tables_not_ok(thd,(TABLE_LIST*) lex->select_lex.table_list.first))
|
||||
error= 1; /* Ignore question */
|
||||
free_items(thd->free_list); /* Free strings used by items */
|
||||
thd->free_list= 0;
|
||||
lex_end(lex);
|
||||
|
||||
return error;
|
||||
|
|
|
@ -88,7 +88,6 @@ public:
|
|||
uint param_count;
|
||||
uint last_errno;
|
||||
char last_error[MYSQL_ERRMSG_SIZE];
|
||||
bool get_longdata_error;
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
bool (*set_params)(Prepared_statement *st, uchar *data, uchar *data_end,
|
||||
uchar *read_pos, String *expanded_query);
|
||||
|
@ -102,7 +101,7 @@ public:
|
|||
Prepared_statement(THD *thd_arg);
|
||||
virtual ~Prepared_statement();
|
||||
void setup_set_params();
|
||||
virtual Statement::Type type() const;
|
||||
virtual Item_arena::Type type() const;
|
||||
};
|
||||
|
||||
static void execute_stmt(THD *thd, Prepared_statement *stmt,
|
||||
|
@ -133,7 +132,7 @@ find_prepared_statement(THD *thd, ulong id, const char *where,
|
|||
{
|
||||
Statement *stmt= thd->stmt_map.find(id);
|
||||
|
||||
if (stmt == 0 || stmt->type() != Statement::PREPARED_STATEMENT)
|
||||
if (stmt == 0 || stmt->type() != Item_arena::PREPARED_STATEMENT)
|
||||
{
|
||||
char llbuf[22];
|
||||
my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), 22, llstr(id, llbuf), where);
|
||||
|
@ -896,10 +895,8 @@ static int mysql_test_insert(Prepared_statement *stmt,
|
|||
open temporary memory pool for temporary data allocated by derived
|
||||
tables & preparation procedure
|
||||
*/
|
||||
thd->allocate_temporary_memory_pool_for_ps_preparing();
|
||||
if (open_and_lock_tables(thd, table_list))
|
||||
{
|
||||
thd->free_temporary_memory_pool_for_ps_preparing();
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
|
@ -934,7 +931,6 @@ static int mysql_test_insert(Prepared_statement *stmt,
|
|||
res= 0;
|
||||
error:
|
||||
lex->unit.cleanup();
|
||||
thd->free_temporary_memory_pool_for_ps_preparing();
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
|
@ -963,12 +959,6 @@ static int mysql_test_update(Prepared_statement *stmt,
|
|||
if ((res= update_precheck(thd, table_list)))
|
||||
DBUG_RETURN(res);
|
||||
|
||||
/*
|
||||
open temporary memory pool for temporary data allocated by derived
|
||||
tables & preparation procedure
|
||||
*/
|
||||
thd->allocate_temporary_memory_pool_for_ps_preparing();
|
||||
|
||||
if (open_and_lock_tables(thd, table_list))
|
||||
res= -1;
|
||||
else
|
||||
|
@ -988,7 +978,6 @@ static int mysql_test_update(Prepared_statement *stmt,
|
|||
}
|
||||
stmt->lex->unit.cleanup();
|
||||
}
|
||||
thd->free_temporary_memory_pool_for_ps_preparing();
|
||||
/* TODO: here we should send types of placeholders to the client. */
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
@ -1018,12 +1007,6 @@ static int mysql_test_delete(Prepared_statement *stmt,
|
|||
if ((res= delete_precheck(thd, table_list)))
|
||||
DBUG_RETURN(res);
|
||||
|
||||
/*
|
||||
open temporary memory pool for temporary data allocated by derived
|
||||
tables & preparation procedure
|
||||
*/
|
||||
thd->allocate_temporary_memory_pool_for_ps_preparing();
|
||||
|
||||
if (open_and_lock_tables(thd, table_list))
|
||||
res= -1;
|
||||
else
|
||||
|
@ -1031,7 +1014,6 @@ static int mysql_test_delete(Prepared_statement *stmt,
|
|||
res= mysql_prepare_delete(thd, table_list, &lex->select_lex.where);
|
||||
lex->unit.cleanup();
|
||||
}
|
||||
thd->free_temporary_memory_pool_for_ps_preparing();
|
||||
/* TODO: here we should send types of placeholders to the client. */
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
@ -1073,11 +1055,6 @@ static int mysql_test_select(Prepared_statement *stmt,
|
|||
DBUG_RETURN(1);
|
||||
#endif
|
||||
|
||||
/*
|
||||
open temporary memory pool for temporary data allocated by derived
|
||||
tables & preparation procedure
|
||||
*/
|
||||
thd->allocate_temporary_memory_pool_for_ps_preparing();
|
||||
if (open_and_lock_tables(thd, tables))
|
||||
{
|
||||
send_error(thd);
|
||||
|
@ -1092,33 +1069,30 @@ static int mysql_test_select(Prepared_statement *stmt,
|
|||
send_error(thd);
|
||||
goto err_prep;
|
||||
}
|
||||
if (lex->describe)
|
||||
if (!text_protocol)
|
||||
{
|
||||
if (!text_protocol && send_prep_stmt(stmt, 0))
|
||||
goto err_prep;
|
||||
unit->cleanup();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!text_protocol)
|
||||
if (lex->describe)
|
||||
{
|
||||
if (send_prep_stmt(stmt, 0))
|
||||
goto err_prep;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (send_prep_stmt(stmt, lex->select_lex.item_list.elements) ||
|
||||
thd->protocol_simple.send_fields(&lex->select_lex.item_list, 0)
|
||||
thd->protocol_simple.send_fields(&lex->select_lex.item_list, 0)
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
|| net_flush(&thd->net)
|
||||
#endif
|
||||
)
|
||||
goto err_prep;
|
||||
}
|
||||
unit->cleanup();
|
||||
}
|
||||
thd->free_temporary_memory_pool_for_ps_preparing();
|
||||
unit->cleanup();
|
||||
DBUG_RETURN(0);
|
||||
|
||||
err_prep:
|
||||
unit->cleanup();
|
||||
err:
|
||||
thd->free_temporary_memory_pool_for_ps_preparing();
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
|
@ -1147,19 +1121,13 @@ static int mysql_test_do_fields(Prepared_statement *stmt,
|
|||
int res= 0;
|
||||
if (tables && (res= check_table_access(thd, SELECT_ACL, tables, 0)))
|
||||
DBUG_RETURN(res);
|
||||
/*
|
||||
open temporary memory pool for temporary data allocated by derived
|
||||
tables & preparation procedure
|
||||
*/
|
||||
thd->allocate_temporary_memory_pool_for_ps_preparing();
|
||||
|
||||
if (tables && (res= open_and_lock_tables(thd, tables)))
|
||||
{
|
||||
thd->free_temporary_memory_pool_for_ps_preparing();
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
res= setup_fields(thd, 0, 0, *values, 0, 0, 0);
|
||||
stmt->lex->unit.cleanup();
|
||||
thd->free_temporary_memory_pool_for_ps_preparing();
|
||||
if (res)
|
||||
DBUG_RETURN(-1);
|
||||
DBUG_RETURN(0);
|
||||
|
@ -1192,11 +1160,7 @@ static int mysql_test_set_fields(Prepared_statement *stmt,
|
|||
|
||||
if (tables && (res= check_table_access(thd, SELECT_ACL, tables, 0)))
|
||||
DBUG_RETURN(res);
|
||||
/*
|
||||
open temporary memory pool for temporary data allocated by derived
|
||||
tables & preparation procedure
|
||||
*/
|
||||
thd->allocate_temporary_memory_pool_for_ps_preparing();
|
||||
|
||||
if (tables && (res= open_and_lock_tables(thd, tables)))
|
||||
goto error;
|
||||
while ((var= it++))
|
||||
|
@ -1210,7 +1174,6 @@ static int mysql_test_set_fields(Prepared_statement *stmt,
|
|||
}
|
||||
error:
|
||||
stmt->lex->unit.cleanup();
|
||||
thd->free_temporary_memory_pool_for_ps_preparing();
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
|
@ -1235,11 +1198,7 @@ static int select_like_statement_test(Prepared_statement *stmt,
|
|||
THD *thd= stmt->thd;
|
||||
LEX *lex= stmt->lex;
|
||||
int res= 0;
|
||||
/*
|
||||
open temporary memory pool for temporary data allocated by derived
|
||||
tables & preparation procedure
|
||||
*/
|
||||
thd->allocate_temporary_memory_pool_for_ps_preparing();
|
||||
|
||||
if (tables && (res= open_and_lock_tables(thd, tables)))
|
||||
goto end;
|
||||
|
||||
|
@ -1252,7 +1211,6 @@ static int select_like_statement_test(Prepared_statement *stmt,
|
|||
}
|
||||
end:
|
||||
lex->unit.cleanup();
|
||||
thd->free_temporary_memory_pool_for_ps_preparing();
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
|
@ -1596,17 +1554,13 @@ int mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
|
|||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
thd->stmt_backup.set_statement(thd);
|
||||
thd->stmt_backup.set_item_arena(thd);
|
||||
thd->set_statement(stmt);
|
||||
thd->set_item_arena(stmt);
|
||||
thd->set_n_backup_statement(stmt, &thd->stmt_backup);
|
||||
thd->set_n_backup_item_arena(stmt, &thd->stmt_backup);
|
||||
|
||||
if (alloc_query(thd, packet, packet_length))
|
||||
{
|
||||
stmt->set_statement(thd);
|
||||
stmt->set_item_arena(thd);
|
||||
thd->set_statement(&thd->stmt_backup);
|
||||
thd->set_item_arena(&thd->stmt_backup);
|
||||
thd->restore_backup_statement(stmt, &thd->stmt_backup);
|
||||
thd->restore_backup_item_arena(stmt, &thd->stmt_backup);
|
||||
/* Statement map deletes statement on erase */
|
||||
thd->stmt_map.erase(stmt);
|
||||
send_error(thd, ER_OUT_OF_RESOURCES);
|
||||
|
@ -1615,24 +1569,36 @@ int 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;
|
||||
mysql_init_query(thd, (uchar *) thd->query, thd->query_length);
|
||||
lex= thd->lex;
|
||||
lex->safe_to_cache_query= 0;
|
||||
|
||||
error= yyparse((void *)thd) || thd->is_fatal_error ||
|
||||
init_param_array(stmt) ||
|
||||
send_prepare_results(stmt, test(name));
|
||||
init_param_array(stmt);
|
||||
/*
|
||||
While doing context analysis of the query (in send_prepare_results) we
|
||||
allocate a lot of additional memory: for open tables, JOINs, derived
|
||||
tables, etc. Let's save a snapshot of current parse tree to the
|
||||
statement and restore original THD. In cases when some tree
|
||||
transformation can be reused on execute, we set again thd->mem_root from
|
||||
stmt->mem_root (see setup_wild for one place where we do that).
|
||||
*/
|
||||
thd->restore_backup_item_arena(stmt, &thd->stmt_backup);
|
||||
|
||||
if (!error)
|
||||
error= send_prepare_results(stmt, test(name));
|
||||
|
||||
/* restore to WAIT_PRIOR: QUERY_PRIOR is set inside alloc_query */
|
||||
if (!(specialflag & SPECIAL_NO_PRIOR))
|
||||
my_pthread_setprio(pthread_self(),WAIT_PRIOR);
|
||||
lex_end(lex);
|
||||
stmt->set_statement(thd);
|
||||
stmt->set_item_arena(thd);
|
||||
thd->set_statement(&thd->stmt_backup);
|
||||
thd->set_item_arena(&thd->stmt_backup);
|
||||
thd->current_statement= 0;
|
||||
thd->restore_backup_statement(stmt, &thd->stmt_backup);
|
||||
cleanup_items(stmt->free_list);
|
||||
close_thread_tables(thd);
|
||||
free_items(thd->free_list);
|
||||
thd->free_list= 0;
|
||||
thd->current_arena= thd;
|
||||
|
||||
if (error)
|
||||
{
|
||||
|
@ -1653,7 +1619,7 @@ int mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
|
|||
{
|
||||
sl->prep_where= sl->where;
|
||||
}
|
||||
|
||||
stmt->state= Prepared_statement::PREPARED;
|
||||
}
|
||||
|
||||
DBUG_RETURN(!stmt);
|
||||
|
@ -1767,7 +1733,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
|
|||
DBUG_PRINT("exec_query:", ("%s", stmt->query));
|
||||
|
||||
/* Check if we got an error when sending long data */
|
||||
if (stmt->get_longdata_error)
|
||||
if (stmt->state == Item_arena::ERROR)
|
||||
{
|
||||
send_error(thd, stmt->last_errno, stmt->last_error);
|
||||
DBUG_VOID_RETURN;
|
||||
|
@ -1791,6 +1757,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
|
|||
if (stmt->param_count && stmt->set_params_data(stmt, &expanded_query))
|
||||
goto set_params_data_err;
|
||||
#endif
|
||||
DBUG_ASSERT(thd->free_list == NULL);
|
||||
thd->protocol= &thd->protocol_prep; // Switch to binary protocol
|
||||
execute_stmt(thd, stmt, &expanded_query, true);
|
||||
thd->protocol= &thd->protocol_simple; // Use normal protocol
|
||||
|
@ -1834,9 +1801,9 @@ void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name)
|
|||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
thd->free_list= NULL;
|
||||
thd->stmt_backup.set_statement(thd);
|
||||
thd->set_statement(stmt);
|
||||
DBUG_ASSERT(thd->free_list == NULL);
|
||||
|
||||
thd->set_n_backup_statement(stmt, &thd->stmt_backup);
|
||||
if (stmt->set_params_from_vars(stmt,
|
||||
thd->stmt_backup.lex->prepared_stmt_params,
|
||||
&expanded_query))
|
||||
|
@ -1868,11 +1835,7 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt,
|
|||
{
|
||||
DBUG_ENTER("execute_stmt");
|
||||
if (set_context)
|
||||
{
|
||||
thd->free_list= NULL;
|
||||
thd->stmt_backup.set_statement(thd);
|
||||
thd->set_statement(stmt);
|
||||
}
|
||||
thd->set_n_backup_statement(stmt, &thd->stmt_backup);
|
||||
reset_stmt_for_execute(stmt);
|
||||
|
||||
if (expanded_query->length() &&
|
||||
|
@ -1882,6 +1845,13 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt,
|
|||
my_error(ER_OUTOFMEMORY, 0, expanded_query->length());
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
/*
|
||||
At first execution of prepared statement we will perform logical
|
||||
transformations of the query tree (i.e. negations elimination).
|
||||
This should be done permanently on the parse tree of this statement.
|
||||
*/
|
||||
if (stmt->state == Item_arena::PREPARED)
|
||||
thd->current_arena= stmt;
|
||||
|
||||
if (!(specialflag & SPECIAL_NO_PRIOR))
|
||||
my_pthread_setprio(pthread_self(),QUERY_PRIOR);
|
||||
|
@ -1892,6 +1862,12 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt,
|
|||
|
||||
/* Free Items that were created during this execution of the PS. */
|
||||
free_items(thd->free_list);
|
||||
thd->free_list= 0;
|
||||
if (stmt->state == Item_arena::PREPARED)
|
||||
{
|
||||
thd->current_arena= thd;
|
||||
stmt->state= Item_arena::EXECUTED;
|
||||
}
|
||||
cleanup_items(stmt->free_list);
|
||||
reset_stmt_params(stmt);
|
||||
close_thread_tables(thd); // to close derived tables
|
||||
|
@ -1929,7 +1905,7 @@ void mysql_stmt_reset(THD *thd, char *packet)
|
|||
SEND_ERROR)))
|
||||
DBUG_VOID_RETURN;
|
||||
|
||||
stmt->get_longdata_error= 0;
|
||||
stmt->state= Item_arena::PREPARED;
|
||||
|
||||
/*
|
||||
Clear parameters from data which could be set by
|
||||
|
@ -2017,7 +1993,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
|
|||
if (param_number >= stmt->param_count)
|
||||
{
|
||||
/* Error will be sent in execute call */
|
||||
stmt->get_longdata_error= 1;
|
||||
stmt->state= Item_arena::ERROR;
|
||||
stmt->last_errno= ER_WRONG_ARGUMENTS;
|
||||
sprintf(stmt->last_error, ER(ER_WRONG_ARGUMENTS),
|
||||
"mysql_stmt_send_long_data");
|
||||
|
@ -2028,10 +2004,15 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
|
|||
param= stmt->param_array[param_number];
|
||||
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
param->set_longdata(packet, (ulong) (packet_end - packet));
|
||||
if (param->set_longdata(packet, (ulong) (packet_end - packet)))
|
||||
#else
|
||||
param->set_longdata(thd->extra_data, thd->extra_length);
|
||||
if (param->set_longdata(thd->extra_data, thd->extra_length))
|
||||
#endif
|
||||
{
|
||||
stmt->state= Item_arena::ERROR;
|
||||
stmt->last_errno= ER_OUTOFMEMORY;
|
||||
sprintf(stmt->last_error, ER(ER_OUTOFMEMORY), 0);
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -2041,8 +2022,7 @@ Prepared_statement::Prepared_statement(THD *thd_arg)
|
|||
thd(thd_arg),
|
||||
param_array(0),
|
||||
param_count(0),
|
||||
last_errno(0),
|
||||
get_longdata_error(0)
|
||||
last_errno(0)
|
||||
{
|
||||
*last_error= '\0';
|
||||
}
|
||||
|
@ -2076,7 +2056,7 @@ Prepared_statement::~Prepared_statement()
|
|||
}
|
||||
|
||||
|
||||
Statement::Type Prepared_statement::type() const
|
||||
Item_arena::Type Prepared_statement::type() const
|
||||
{
|
||||
return PREPARED_STATEMENT;
|
||||
}
|
||||
|
|
|
@ -4379,25 +4379,39 @@ COND *eliminate_not_funcs(THD *thd, COND *cond)
|
|||
static COND *
|
||||
optimize_cond(THD *thd, COND *conds, Item::cond_result *cond_value)
|
||||
{
|
||||
SELECT_LEX *select= thd->lex->current_select;
|
||||
DBUG_ENTER("optimize_cond");
|
||||
if (!conds)
|
||||
if (conds)
|
||||
{
|
||||
DBUG_EXECUTE("where", print_where(conds, "original"););
|
||||
/* Eliminate NOT operators; in case of PS/SP do it once */
|
||||
if (thd->current_arena->is_first_stmt_execute())
|
||||
{
|
||||
Item_arena *arena= thd->current_arena, backup;
|
||||
thd->set_n_backup_item_arena(arena, &backup);
|
||||
conds= eliminate_not_funcs(thd, conds);
|
||||
select->prep_where= conds->copy_andor_structure(thd);
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
}
|
||||
else
|
||||
conds= eliminate_not_funcs(thd, conds);
|
||||
DBUG_EXECUTE("where", print_where(conds, "after negation elimination"););
|
||||
|
||||
/* change field = field to field = const for each found field = const */
|
||||
propagate_cond_constants((I_List<COND_CMP> *) 0, conds, conds);
|
||||
/*
|
||||
Remove all instances of item == item
|
||||
Remove all and-levels where CONST item != CONST item
|
||||
*/
|
||||
DBUG_EXECUTE("where", print_where(conds, "after const change"););
|
||||
conds= remove_eq_conds(thd, conds, cond_value);
|
||||
DBUG_EXECUTE("info", print_where(conds, "after remove"););
|
||||
}
|
||||
else
|
||||
{
|
||||
*cond_value= Item::COND_TRUE;
|
||||
DBUG_RETURN(conds);
|
||||
select->prep_where= 0;
|
||||
}
|
||||
DBUG_EXECUTE("where",print_where(conds,"original"););
|
||||
/* eliminate NOT operators */
|
||||
conds= eliminate_not_funcs(thd, conds);
|
||||
DBUG_EXECUTE("where", print_where(conds, "after negation elimination"););
|
||||
/* change field = field to field = const for each found field = const */
|
||||
propagate_cond_constants((I_List<COND_CMP> *) 0,conds,conds);
|
||||
/*
|
||||
Remove all instances of item == item
|
||||
Remove all and-levels where CONST item != CONST item
|
||||
*/
|
||||
DBUG_EXECUTE("where",print_where(conds,"after const change"););
|
||||
conds= remove_eq_conds(thd, conds, cond_value) ;
|
||||
DBUG_EXECUTE("info",print_where(conds,"after remove"););
|
||||
DBUG_RETURN(conds);
|
||||
}
|
||||
|
||||
|
@ -4997,6 +5011,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
|||
blob_count++;
|
||||
}
|
||||
((Item_sum*) item)->args[i]= new Item_field(new_field);
|
||||
if (((Item_sum*) item)->arg_count == 1)
|
||||
((Item_sum*) item)->result_field= new_field;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -287,24 +287,23 @@ 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, backup;
|
||||
if (arena->is_stmt_prepare())
|
||||
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->is_stmt_prepare())
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
}
|
||||
if (stmt)
|
||||
if (arena->is_stmt_prepare())
|
||||
{
|
||||
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);
|
||||
|
|
Loading…
Reference in a new issue