Commit 8f43d0c4 authored by paul@ice.snake.net's avatar paul@ice.snake.net

Merge paul@bk-internal.mysql.com:/home/bk/mysql-4.1

into ice.snake.net:/Volumes/ice2/MySQL/bk/mysql-4.1
parents db40cfb4 df1d90d1
...@@ -271,3 +271,39 @@ i i COUNT(*) ...@@ -271,3 +271,39 @@ i i COUNT(*)
100 NULL 2 100 NULL 2
NULL NULL 2 NULL NULL 2
drop table t1,t2; 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 ...@@ -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 t1 MyISAM 9 Dynamic 0 0 0 4294967295 1024 0 NULL # # # latin1_swedish_ci NULL
deallocate prepare stmt1 ; deallocate prepare stmt1 ;
drop table t1; 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;
--innodb_lock_wait_timeout=5 --loose-innodb_lock_wait_timeout=5
...@@ -88,3 +88,40 @@ INSERT INTO t2 VALUES (100),(200); ...@@ -88,3 +88,40 @@ INSERT INTO t2 VALUES (100),(200);
SELECT i, COUNT(*) FROM t1 GROUP BY i WITH ROLLUP; 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; SELECT t1.i, t2.i, COUNT(*) FROM t1,t2 GROUP BY t1.i,t2.i WITH ROLLUP;
drop table t1,t2; 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; ...@@ -206,3 +206,15 @@ execute stmt1;
show table status from test like 't1%' ; show table status from test like 't1%' ;
deallocate prepare stmt1 ; deallocate prepare stmt1 ;
drop table t1; 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, ...@@ -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 => 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. 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]); cache->store(args[0]);
if (cache->cols() == 1) if (cache->cols() == 1)
{ {
......
...@@ -125,7 +125,6 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref) ...@@ -125,7 +125,6 @@ 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;
char const *save_where= thd->where; char const *save_where= thd->where;
int res; int res;
...@@ -306,7 +305,10 @@ Item_singlerow_subselect::select_transformer(JOIN *join) ...@@ -306,7 +305,10 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
return RES_OK; return RES_OK;
SELECT_LEX *select_lex= join->select_lex; 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() && if (!select_lex->master_unit()->first_select()->next_select() &&
!select_lex->table_list.elements && !select_lex->table_list.elements &&
...@@ -341,8 +343,8 @@ Item_singlerow_subselect::select_transformer(JOIN *join) ...@@ -341,8 +343,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->is_stmt_prepare())
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;
...@@ -355,15 +357,15 @@ Item_singlerow_subselect::select_transformer(JOIN *join) ...@@ -355,15 +357,15 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
new Item_null()))) new Item_null())))
goto err; goto err;
} }
if (stmt) if (arena->is_stmt_prepare())
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->is_stmt_prepare())
thd->restore_backup_item_arena(stmt, &backup); thd->restore_backup_item_arena(arena, &backup);
return RES_ERROR; return RES_ERROR;
} }
...@@ -640,11 +642,11 @@ Item_in_subselect::single_value_transformer(JOIN *join, ...@@ -640,11 +642,11 @@ Item_in_subselect::single_value_transformer(JOIN *join,
} }
SELECT_LEX *select_lex= join->select_lex; SELECT_LEX *select_lex= join->select_lex;
Statement backup; Item_arena *arena= join->thd->current_arena, backup;
thd->where= "scalar IN/ALL/ANY subquery"; thd->where= "scalar IN/ALL/ANY subquery";
if (stmt) if (arena->is_stmt_prepare())
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)
{ {
...@@ -857,21 +859,21 @@ Item_in_subselect::single_value_transformer(JOIN *join, ...@@ -857,21 +859,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->is_stmt_prepare())
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->is_stmt_prepare())
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->is_stmt_prepare())
thd->restore_backup_item_arena(stmt, &backup); thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(RES_ERROR); DBUG_RETURN(RES_ERROR);
} }
...@@ -885,12 +887,12 @@ Item_in_subselect::row_value_transformer(JOIN *join) ...@@ -885,12 +887,12 @@ Item_in_subselect::row_value_transformer(JOIN *join)
{ {
DBUG_RETURN(RES_OK); DBUG_RETURN(RES_OK);
} }
Statement backup; Item_arena *arena= join->thd->current_arena, backup;
Item *item= 0; Item *item= 0;
thd->where= "row IN/ALL/ANY subquery"; thd->where= "row IN/ALL/ANY subquery";
if (stmt) if (arena->is_stmt_prepare())
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;
...@@ -974,13 +976,13 @@ Item_in_subselect::row_value_transformer(JOIN *join) ...@@ -974,13 +976,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->is_stmt_prepare())
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->is_stmt_prepare())
thd->restore_backup_item_arena(stmt, &backup); thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(RES_ERROR); DBUG_RETURN(RES_ERROR);
} }
......
...@@ -36,8 +36,6 @@ class Item_subselect :public Item_result_field ...@@ -36,8 +36,6 @@ 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 */
Statement *stmt;
/* 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 */
......
...@@ -64,28 +64,28 @@ Item_sum::Item_sum(THD *thd, Item_sum *item): ...@@ -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()) (arguments can be rewritten in get_tmp_table_item())
SYNOPSIS SYNOPSIS
Item_sum::save_args_for_prepared_statements() Item_sum::save_args_for_prepared_statement()
thd - thread handler thd - thread handler
RETURN RETURN
0 - OK 0 - OK
1 - Error 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) if (thd->current_arena->is_stmt_prepare())
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;
...@@ -159,7 +159,10 @@ Item *Item_sum::get_tmp_table_item(THD *thd) ...@@ -159,7 +159,10 @@ Item *Item_sum::get_tmp_table_item(THD *thd)
if (!arg->const_item()) if (!arg->const_item())
{ {
if (arg->type() == Item::FIELD_ITEM) if (arg->type() == Item::FIELD_ITEM)
{
arg->maybe_null= result_field_tmp->maybe_null();
((Item_field*) arg)->field= result_field_tmp++; ((Item_field*) arg)->field= result_field_tmp++;
}
else else
sum_item->args[i]= new Item_field(result_field_tmp++); 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) ...@@ -214,7 +217,7 @@ Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ {
DBUG_ASSERT(fixed == 0); DBUG_ASSERT(fixed == 0);
if (save_args_for_prepared_statements(thd)) if (save_args_for_prepared_statement(thd))
return 1; return 1;
if (!thd->allow_sum_func) if (!thd->allow_sum_func)
...@@ -248,7 +251,7 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -248,7 +251,7 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ {
DBUG_ASSERT(fixed == 0); DBUG_ASSERT(fixed == 0);
if (save_args_for_prepared_statements(thd)) if (save_args_for_prepared_statement(thd))
return 1; return 1;
Item *item= args[0]; Item *item= args[0];
...@@ -1947,7 +1950,7 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -1947,7 +1950,7 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ {
DBUG_ASSERT(fixed == 0); DBUG_ASSERT(fixed == 0);
if (save_args_for_prepared_statements(thd)) if (save_args_for_prepared_statement(thd))
return 1; return 1;
uint i; /* for loop variable */ uint i; /* for loop variable */
......
...@@ -92,8 +92,8 @@ public: ...@@ -92,8 +92,8 @@ public:
virtual bool setup(THD *thd) {return 0;} virtual bool setup(THD *thd) {return 0;}
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_statement(THD *);
bool save_args(Statement* stmt); bool save_args(Item_arena *arena);
bool walk (Item_processor processor, byte *argument); bool walk (Item_processor processor, byte *argument);
}; };
......
...@@ -295,7 +295,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout); ...@@ -295,7 +295,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout);
struct st_table; struct st_table;
class THD; class THD;
class Statement; class Item_arena;
/* Struct to handle simple linked lists */ /* Struct to handle simple linked lists */
......
...@@ -2251,14 +2251,15 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, ...@@ -2251,14 +2251,15 @@ 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->is_stmt_prepare())
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++))
...@@ -2282,8 +2283,8 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, ...@@ -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, else 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->is_stmt_prepare())
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)
...@@ -2298,8 +2299,8 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, ...@@ -2298,8 +2299,8 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
wild_num--; wild_num--;
} }
} }
if (stmt) if (arena->is_stmt_prepare())
thd->restore_backup_item_arena(stmt, &backup); thd->restore_backup_item_arena(arena, &backup);
return 0; return 0;
} }
...@@ -2512,7 +2513,7 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, ...@@ -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) 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; Item_arena *arena= thd->current_arena, backup;
DBUG_ENTER("setup_conds"); DBUG_ENTER("setup_conds");
thd->set_query_id=1; thd->set_query_id=1;
...@@ -2551,12 +2552,12 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) ...@@ -2551,12 +2552,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->is_stmt_prepare())
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->is_stmt_prepare())
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);
...@@ -2564,8 +2565,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) ...@@ -2564,8 +2565,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
} }
if (table->natural_join) if (table->natural_join)
{ {
if (stmt) if (arena->is_stmt_prepare())
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;
...@@ -2606,8 +2607,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) ...@@ -2606,8 +2607,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->is_stmt_prepare())
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))
...@@ -2618,8 +2619,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **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); 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->is_stmt_prepare())
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))
...@@ -2630,7 +2631,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) ...@@ -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 We are in prepared statement preparation code => we should store
...@@ -2643,8 +2644,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) ...@@ -2643,8 +2644,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
DBUG_RETURN(test(thd->net.report_error)); DBUG_RETURN(test(thd->net.report_error));
err: err:
if (stmt) if (arena->is_stmt_prepare())
thd->restore_backup_item_arena(stmt, &backup); thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
......
...@@ -155,7 +155,7 @@ bool foreign_key_prefix(Key *a, Key *b) ...@@ -155,7 +155,7 @@ bool foreign_key_prefix(Key *a, Key *b)
** 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(this), is_fatal_error(0),
last_insert_id_used(0), last_insert_id_used(0),
insert_id_used(0), rand_used(0), time_zone_used(0), insert_id_used(0), rand_used(0), time_zone_used(0),
in_lock_tables(0), global_read_lock(0), bootstrap(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) ...@@ -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 functions
*/ */
Statement::Statement(THD *thd) Statement::Statement(THD *thd)
:id(++thd->statement_id_counter), :Item_arena(thd),
id(++thd->statement_id_counter),
set_query_id(1), set_query_id(1),
allow_sum_func(0), allow_sum_func(0),
lex(&main_lex), lex(&main_lex),
query(0), query(0),
query_length(0), query_length(0)
free_list(0)
{ {
name.str= NULL; 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() ...@@ -1332,14 +1368,12 @@ Statement::Statement()
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));
} }
Statement::Type Statement::type() const Item_arena::Type Statement::type() const
{ {
return STATEMENT; return STATEMENT;
} }
...@@ -1356,14 +1390,29 @@ void Statement::set_statement(Statement *stmt) ...@@ -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); 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);
...@@ -1371,10 +1420,11 @@ void Statement::restore_backup_item_arena(Statement *set, Statement *backup) ...@@ -1371,10 +1420,11 @@ 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;
state= set->state;
} }
Statement::~Statement() Statement::~Statement()
......
...@@ -418,6 +418,61 @@ struct system_variables ...@@ -418,6 +418,61 @@ 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;
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. 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,
...@@ -432,7 +487,7 @@ void free_tmp_table(THD *thd, TABLE *entry); ...@@ -432,7 +487,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 */
...@@ -474,20 +529,8 @@ public: ...@@ -474,20 +529,8 @@ 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. */
enum Type
{
STATEMENT,
PREPARED_STATEMENT
};
/* /*
This constructor is called when statement is a subobject of THD: This constructor is called when statement is a subobject of THD:
...@@ -500,34 +543,10 @@ public: ...@@ -500,34 +543,10 @@ public:
/* Assign execution context (note: not all members) of given stmt to self */ /* Assign execution context (note: not all members) of given stmt to self */
void set_statement(Statement *stmt); 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 */ /* 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);
}; };
...@@ -760,9 +779,9 @@ public: ...@@ -760,9 +779,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
...@@ -983,33 +1002,6 @@ public: ...@@ -983,33 +1002,6 @@ public:
} }
inline CHARSET_INFO *charset() { return variables.character_set_client; } inline CHARSET_INFO *charset() { return variables.character_set_client; }
void update_charset(); 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 */ /* Flags for the THD::system_thread (bitmap) variable */
......
...@@ -151,7 +151,7 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, ...@@ -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 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->current_arena->is_stmt_prepare())
{ {
if (is_union) if (is_union)
{ {
......
...@@ -1527,9 +1527,9 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) ...@@ -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 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;
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;
......
...@@ -1543,6 +1543,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1543,6 +1543,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break; break;
mysqld_list_fields(thd,&table_list,fields); mysqld_list_fields(thd,&table_list,fields);
free_items(thd->free_list); free_items(thd->free_list);
thd->free_list= 0;
break; break;
} }
#endif #endif
...@@ -4047,6 +4048,7 @@ void mysql_parse(THD *thd, char *inBuf, uint length) ...@@ -4047,6 +4048,7 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
} }
thd->proc_info="freeing items"; thd->proc_info="freeing items";
free_items(thd->free_list); /* Free strings used by items */ free_items(thd->free_list); /* Free strings used by items */
thd->free_list= 0;
lex_end(lex); lex_end(lex);
} }
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
...@@ -4073,6 +4075,7 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length) ...@@ -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)) all_tables_not_ok(thd,(TABLE_LIST*) lex->select_lex.table_list.first))
error= 1; /* Ignore question */ error= 1; /* Ignore question */
free_items(thd->free_list); /* Free strings used by items */ free_items(thd->free_list); /* Free strings used by items */
thd->free_list= 0;
lex_end(lex); lex_end(lex);
return error; return error;
......
This diff is collapsed.
...@@ -4379,25 +4379,39 @@ COND *eliminate_not_funcs(THD *thd, COND *cond) ...@@ -4379,25 +4379,39 @@ COND *eliminate_not_funcs(THD *thd, COND *cond)
static COND * static COND *
optimize_cond(THD *thd, COND *conds, Item::cond_result *cond_value) optimize_cond(THD *thd, COND *conds, Item::cond_result *cond_value)
{ {
SELECT_LEX *select= thd->lex->current_select;
DBUG_ENTER("optimize_cond"); DBUG_ENTER("optimize_cond");
if (!conds) if (conds)
{ {
*cond_value= Item::COND_TRUE; DBUG_EXECUTE("where", print_where(conds, "original"););
DBUG_RETURN(conds); /* 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);
} }
DBUG_EXECUTE("where",print_where(conds,"original");); else
/* eliminate NOT operators */
conds= eliminate_not_funcs(thd, conds); conds= eliminate_not_funcs(thd, conds);
DBUG_EXECUTE("where", print_where(conds, "after negation elimination");); DBUG_EXECUTE("where", print_where(conds, "after negation elimination"););
/* change field = field to field = const for each found field = const */ /* change field = field to field = const for each found field = const */
propagate_cond_constants((I_List<COND_CMP> *) 0,conds,conds); propagate_cond_constants((I_List<COND_CMP> *) 0, conds, conds);
/* /*
Remove all instances of item == item Remove all instances of item == item
Remove all and-levels where CONST item != CONST item Remove all and-levels where CONST item != CONST item
*/ */
DBUG_EXECUTE("where",print_where(conds,"after const change");); DBUG_EXECUTE("where", print_where(conds, "after const change"););
conds= remove_eq_conds(thd, conds, cond_value) ; conds= remove_eq_conds(thd, conds, cond_value);
DBUG_EXECUTE("info",print_where(conds,"after remove");); DBUG_EXECUTE("info", print_where(conds, "after remove"););
}
else
{
*cond_value= Item::COND_TRUE;
select->prep_where= 0;
}
DBUG_RETURN(conds); DBUG_RETURN(conds);
} }
...@@ -4997,6 +5011,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ...@@ -4997,6 +5011,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
blob_count++; blob_count++;
} }
((Item_sum*) item)->args[i]= new Item_field(new_field); ((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, ...@@ -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; 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, backup;
Statement backup; if (arena->is_stmt_prepare())
if (stmt) thd->set_n_backup_item_arena(arena, &backup);
thd->set_n_backup_item_arena(stmt, &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->is_stmt_prepare())
thd->restore_backup_item_arena(stmt, &backup); thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(-1); 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 */ /* 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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment