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
|
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
|
||||||
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;
|
||||||
|
|
|
@ -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 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;
|
||||||
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,
|
||||||
/*
|
/*
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
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
|
||||||
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):
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
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)
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
{
|
{
|
||||||
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:
|
||||||
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);
|
||||||
|
|
||||||
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,
|
||||||
{
|
{
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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)
|
||||||
!(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)
|
||||||
}
|
}
|
||||||
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)
|
||||||
{
|
{
|
||||||
*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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
** 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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()
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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)
|
||||||
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()
|
||||||
|
|
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);
|
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);
|
||||||
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:
|
||||||
*/
|
*/
|
||||||
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:
|
||||||
|
|
||||||
/* 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:
|
||||||
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:
|
||||||
}
|
}
|
||||||
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,
|
||||||
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)
|
||||||
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,
|
||||||
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)
|
||||||
}
|
}
|
||||||
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)
|
||||||
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;
|
||||||
|
|
|
@ -88,7 +88,6 @@ public:
|
||||||
uint param_count;
|
uint param_count;
|
||||||
uint last_errno;
|
uint last_errno;
|
||||||
char last_error[MYSQL_ERRMSG_SIZE];
|
char last_error[MYSQL_ERRMSG_SIZE];
|
||||||
bool get_longdata_error;
|
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
bool (*set_params)(Prepared_statement *st, uchar *data, uchar *data_end,
|
bool (*set_params)(Prepared_statement *st, uchar *data, uchar *data_end,
|
||||||
uchar *read_pos, String *expanded_query);
|
uchar *read_pos, String *expanded_query);
|
||||||
|
@ -102,7 +101,7 @@ public:
|
||||||
Prepared_statement(THD *thd_arg);
|
Prepared_statement(THD *thd_arg);
|
||||||
virtual ~Prepared_statement();
|
virtual ~Prepared_statement();
|
||||||
void setup_set_params();
|
void setup_set_params();
|
||||||
virtual Statement::Type type() const;
|
virtual Item_arena::Type type() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void execute_stmt(THD *thd, Prepared_statement *stmt,
|
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);
|
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];
|
char llbuf[22];
|
||||||
my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), 22, llstr(id, llbuf), where);
|
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
|
open temporary memory pool for temporary data allocated by derived
|
||||||
tables & preparation procedure
|
tables & preparation procedure
|
||||||
*/
|
*/
|
||||||
thd->allocate_temporary_memory_pool_for_ps_preparing();
|
|
||||||
if (open_and_lock_tables(thd, table_list))
|
if (open_and_lock_tables(thd, table_list))
|
||||||
{
|
{
|
||||||
thd->free_temporary_memory_pool_for_ps_preparing();
|
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -934,7 +931,6 @@ static int mysql_test_insert(Prepared_statement *stmt,
|
||||||
res= 0;
|
res= 0;
|
||||||
error:
|
error:
|
||||||
lex->unit.cleanup();
|
lex->unit.cleanup();
|
||||||
thd->free_temporary_memory_pool_for_ps_preparing();
|
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -963,12 +959,6 @@ static int mysql_test_update(Prepared_statement *stmt,
|
||||||
if ((res= update_precheck(thd, table_list)))
|
if ((res= update_precheck(thd, table_list)))
|
||||||
DBUG_RETURN(res);
|
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))
|
if (open_and_lock_tables(thd, table_list))
|
||||||
res= -1;
|
res= -1;
|
||||||
else
|
else
|
||||||
|
@ -988,7 +978,6 @@ static int mysql_test_update(Prepared_statement *stmt,
|
||||||
}
|
}
|
||||||
stmt->lex->unit.cleanup();
|
stmt->lex->unit.cleanup();
|
||||||
}
|
}
|
||||||
thd->free_temporary_memory_pool_for_ps_preparing();
|
|
||||||
/* TODO: here we should send types of placeholders to the client. */
|
/* TODO: here we should send types of placeholders to the client. */
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
@ -1018,12 +1007,6 @@ static int mysql_test_delete(Prepared_statement *stmt,
|
||||||
if ((res= delete_precheck(thd, table_list)))
|
if ((res= delete_precheck(thd, table_list)))
|
||||||
DBUG_RETURN(res);
|
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))
|
if (open_and_lock_tables(thd, table_list))
|
||||||
res= -1;
|
res= -1;
|
||||||
else
|
else
|
||||||
|
@ -1031,7 +1014,6 @@ static int mysql_test_delete(Prepared_statement *stmt,
|
||||||
res= mysql_prepare_delete(thd, table_list, &lex->select_lex.where);
|
res= mysql_prepare_delete(thd, table_list, &lex->select_lex.where);
|
||||||
lex->unit.cleanup();
|
lex->unit.cleanup();
|
||||||
}
|
}
|
||||||
thd->free_temporary_memory_pool_for_ps_preparing();
|
|
||||||
/* TODO: here we should send types of placeholders to the client. */
|
/* TODO: here we should send types of placeholders to the client. */
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
@ -1073,11 +1055,6 @@ static int mysql_test_select(Prepared_statement *stmt,
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
#endif
|
#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))
|
if (open_and_lock_tables(thd, tables))
|
||||||
{
|
{
|
||||||
send_error(thd);
|
send_error(thd);
|
||||||
|
@ -1092,33 +1069,30 @@ static int mysql_test_select(Prepared_statement *stmt,
|
||||||
send_error(thd);
|
send_error(thd);
|
||||||
goto err_prep;
|
goto err_prep;
|
||||||
}
|
}
|
||||||
if (lex->describe)
|
if (!text_protocol)
|
||||||
{
|
{
|
||||||
if (!text_protocol && send_prep_stmt(stmt, 0))
|
if (lex->describe)
|
||||||
goto err_prep;
|
{
|
||||||
unit->cleanup();
|
if (send_prep_stmt(stmt, 0))
|
||||||
}
|
goto err_prep;
|
||||||
else
|
}
|
||||||
{
|
else
|
||||||
if (!text_protocol)
|
|
||||||
{
|
{
|
||||||
if (send_prep_stmt(stmt, lex->select_lex.item_list.elements) ||
|
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
|
#ifndef EMBEDDED_LIBRARY
|
||||||
|| net_flush(&thd->net)
|
|| net_flush(&thd->net)
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
goto err_prep;
|
goto err_prep;
|
||||||
}
|
}
|
||||||
unit->cleanup();
|
|
||||||
}
|
}
|
||||||
thd->free_temporary_memory_pool_for_ps_preparing();
|
unit->cleanup();
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
err_prep:
|
err_prep:
|
||||||
unit->cleanup();
|
unit->cleanup();
|
||||||
err:
|
err:
|
||||||
thd->free_temporary_memory_pool_for_ps_preparing();
|
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1147,19 +1121,13 @@ static int mysql_test_do_fields(Prepared_statement *stmt,
|
||||||
int res= 0;
|
int res= 0;
|
||||||
if (tables && (res= check_table_access(thd, SELECT_ACL, tables, 0)))
|
if (tables && (res= check_table_access(thd, SELECT_ACL, tables, 0)))
|
||||||
DBUG_RETURN(res);
|
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)))
|
if (tables && (res= open_and_lock_tables(thd, tables)))
|
||||||
{
|
{
|
||||||
thd->free_temporary_memory_pool_for_ps_preparing();
|
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
res= setup_fields(thd, 0, 0, *values, 0, 0, 0);
|
res= setup_fields(thd, 0, 0, *values, 0, 0, 0);
|
||||||
stmt->lex->unit.cleanup();
|
stmt->lex->unit.cleanup();
|
||||||
thd->free_temporary_memory_pool_for_ps_preparing();
|
|
||||||
if (res)
|
if (res)
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
DBUG_RETURN(0);
|
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)))
|
if (tables && (res= check_table_access(thd, SELECT_ACL, tables, 0)))
|
||||||
DBUG_RETURN(res);
|
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)))
|
if (tables && (res= open_and_lock_tables(thd, tables)))
|
||||||
goto error;
|
goto error;
|
||||||
while ((var= it++))
|
while ((var= it++))
|
||||||
|
@ -1210,7 +1174,6 @@ static int mysql_test_set_fields(Prepared_statement *stmt,
|
||||||
}
|
}
|
||||||
error:
|
error:
|
||||||
stmt->lex->unit.cleanup();
|
stmt->lex->unit.cleanup();
|
||||||
thd->free_temporary_memory_pool_for_ps_preparing();
|
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1235,11 +1198,7 @@ static int select_like_statement_test(Prepared_statement *stmt,
|
||||||
THD *thd= stmt->thd;
|
THD *thd= stmt->thd;
|
||||||
LEX *lex= stmt->lex;
|
LEX *lex= stmt->lex;
|
||||||
int res= 0;
|
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)))
|
if (tables && (res= open_and_lock_tables(thd, tables)))
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
|
@ -1252,7 +1211,6 @@ static int select_like_statement_test(Prepared_statement *stmt,
|
||||||
}
|
}
|
||||||
end:
|
end:
|
||||||
lex->unit.cleanup();
|
lex->unit.cleanup();
|
||||||
thd->free_temporary_memory_pool_for_ps_preparing();
|
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1596,17 +1554,13 @@ int mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
thd->stmt_backup.set_statement(thd);
|
thd->set_n_backup_statement(stmt, &thd->stmt_backup);
|
||||||
thd->stmt_backup.set_item_arena(thd);
|
thd->set_n_backup_item_arena(stmt, &thd->stmt_backup);
|
||||||
thd->set_statement(stmt);
|
|
||||||
thd->set_item_arena(stmt);
|
|
||||||
|
|
||||||
if (alloc_query(thd, packet, packet_length))
|
if (alloc_query(thd, packet, packet_length))
|
||||||
{
|
{
|
||||||
stmt->set_statement(thd);
|
thd->restore_backup_statement(stmt, &thd->stmt_backup);
|
||||||
stmt->set_item_arena(thd);
|
thd->restore_backup_item_arena(stmt, &thd->stmt_backup);
|
||||||
thd->set_statement(&thd->stmt_backup);
|
|
||||||
thd->set_item_arena(&thd->stmt_backup);
|
|
||||||
/* Statement map deletes statement on erase */
|
/* Statement map deletes statement on erase */
|
||||||
thd->stmt_map.erase(stmt);
|
thd->stmt_map.erase(stmt);
|
||||||
send_error(thd, ER_OUT_OF_RESOURCES);
|
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);
|
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);
|
mysql_init_query(thd, (uchar *) thd->query, thd->query_length);
|
||||||
lex= thd->lex;
|
lex= thd->lex;
|
||||||
lex->safe_to_cache_query= 0;
|
lex->safe_to_cache_query= 0;
|
||||||
|
|
||||||
error= yyparse((void *)thd) || thd->is_fatal_error ||
|
error= yyparse((void *)thd) || thd->is_fatal_error ||
|
||||||
init_param_array(stmt) ||
|
init_param_array(stmt);
|
||||||
send_prepare_results(stmt, test(name));
|
/*
|
||||||
|
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 */
|
/* restore to WAIT_PRIOR: QUERY_PRIOR is set inside alloc_query */
|
||||||
if (!(specialflag & SPECIAL_NO_PRIOR))
|
if (!(specialflag & SPECIAL_NO_PRIOR))
|
||||||
my_pthread_setprio(pthread_self(),WAIT_PRIOR);
|
my_pthread_setprio(pthread_self(),WAIT_PRIOR);
|
||||||
lex_end(lex);
|
lex_end(lex);
|
||||||
stmt->set_statement(thd);
|
thd->restore_backup_statement(stmt, &thd->stmt_backup);
|
||||||
stmt->set_item_arena(thd);
|
cleanup_items(stmt->free_list);
|
||||||
thd->set_statement(&thd->stmt_backup);
|
close_thread_tables(thd);
|
||||||
thd->set_item_arena(&thd->stmt_backup);
|
free_items(thd->free_list);
|
||||||
thd->current_statement= 0;
|
thd->free_list= 0;
|
||||||
|
thd->current_arena= thd;
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
|
@ -1653,7 +1619,7 @@ int mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
|
||||||
{
|
{
|
||||||
sl->prep_where= sl->where;
|
sl->prep_where= sl->where;
|
||||||
}
|
}
|
||||||
|
stmt->state= Prepared_statement::PREPARED;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_RETURN(!stmt);
|
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));
|
DBUG_PRINT("exec_query:", ("%s", stmt->query));
|
||||||
|
|
||||||
/* Check if we got an error when sending long data */
|
/* 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);
|
send_error(thd, stmt->last_errno, stmt->last_error);
|
||||||
DBUG_VOID_RETURN;
|
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))
|
if (stmt->param_count && stmt->set_params_data(stmt, &expanded_query))
|
||||||
goto set_params_data_err;
|
goto set_params_data_err;
|
||||||
#endif
|
#endif
|
||||||
|
DBUG_ASSERT(thd->free_list == NULL);
|
||||||
thd->protocol= &thd->protocol_prep; // Switch to binary protocol
|
thd->protocol= &thd->protocol_prep; // Switch to binary protocol
|
||||||
execute_stmt(thd, stmt, &expanded_query, true);
|
execute_stmt(thd, stmt, &expanded_query, true);
|
||||||
thd->protocol= &thd->protocol_simple; // Use normal protocol
|
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;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
thd->free_list= NULL;
|
DBUG_ASSERT(thd->free_list == NULL);
|
||||||
thd->stmt_backup.set_statement(thd);
|
|
||||||
thd->set_statement(stmt);
|
thd->set_n_backup_statement(stmt, &thd->stmt_backup);
|
||||||
if (stmt->set_params_from_vars(stmt,
|
if (stmt->set_params_from_vars(stmt,
|
||||||
thd->stmt_backup.lex->prepared_stmt_params,
|
thd->stmt_backup.lex->prepared_stmt_params,
|
||||||
&expanded_query))
|
&expanded_query))
|
||||||
|
@ -1868,11 +1835,7 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt,
|
||||||
{
|
{
|
||||||
DBUG_ENTER("execute_stmt");
|
DBUG_ENTER("execute_stmt");
|
||||||
if (set_context)
|
if (set_context)
|
||||||
{
|
thd->set_n_backup_statement(stmt, &thd->stmt_backup);
|
||||||
thd->free_list= NULL;
|
|
||||||
thd->stmt_backup.set_statement(thd);
|
|
||||||
thd->set_statement(stmt);
|
|
||||||
}
|
|
||||||
reset_stmt_for_execute(stmt);
|
reset_stmt_for_execute(stmt);
|
||||||
|
|
||||||
if (expanded_query->length() &&
|
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());
|
my_error(ER_OUTOFMEMORY, 0, expanded_query->length());
|
||||||
DBUG_VOID_RETURN;
|
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))
|
if (!(specialflag & SPECIAL_NO_PRIOR))
|
||||||
my_pthread_setprio(pthread_self(),QUERY_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 that were created during this execution of the PS. */
|
||||||
free_items(thd->free_list);
|
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);
|
cleanup_items(stmt->free_list);
|
||||||
reset_stmt_params(stmt);
|
reset_stmt_params(stmt);
|
||||||
close_thread_tables(thd); // to close derived tables
|
close_thread_tables(thd); // to close derived tables
|
||||||
|
@ -1929,7 +1905,7 @@ void mysql_stmt_reset(THD *thd, char *packet)
|
||||||
SEND_ERROR)))
|
SEND_ERROR)))
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
stmt->get_longdata_error= 0;
|
stmt->state= Item_arena::PREPARED;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Clear parameters from data which could be set by
|
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)
|
if (param_number >= stmt->param_count)
|
||||||
{
|
{
|
||||||
/* Error will be sent in execute call */
|
/* Error will be sent in execute call */
|
||||||
stmt->get_longdata_error= 1;
|
stmt->state= Item_arena::ERROR;
|
||||||
stmt->last_errno= ER_WRONG_ARGUMENTS;
|
stmt->last_errno= ER_WRONG_ARGUMENTS;
|
||||||
sprintf(stmt->last_error, ER(ER_WRONG_ARGUMENTS),
|
sprintf(stmt->last_error, ER(ER_WRONG_ARGUMENTS),
|
||||||
"mysql_stmt_send_long_data");
|
"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];
|
param= stmt->param_array[param_number];
|
||||||
|
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
param->set_longdata(packet, (ulong) (packet_end - packet));
|
if (param->set_longdata(packet, (ulong) (packet_end - packet)))
|
||||||
#else
|
#else
|
||||||
param->set_longdata(thd->extra_data, thd->extra_length);
|
if (param->set_longdata(thd->extra_data, thd->extra_length))
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
stmt->state= Item_arena::ERROR;
|
||||||
|
stmt->last_errno= ER_OUTOFMEMORY;
|
||||||
|
sprintf(stmt->last_error, ER(ER_OUTOFMEMORY), 0);
|
||||||
|
}
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2041,8 +2022,7 @@ Prepared_statement::Prepared_statement(THD *thd_arg)
|
||||||
thd(thd_arg),
|
thd(thd_arg),
|
||||||
param_array(0),
|
param_array(0),
|
||||||
param_count(0),
|
param_count(0),
|
||||||
last_errno(0),
|
last_errno(0)
|
||||||
get_longdata_error(0)
|
|
||||||
{
|
{
|
||||||
*last_error= '\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;
|
return PREPARED_STATEMENT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
{
|
||||||
|
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;
|
*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);
|
DBUG_RETURN(conds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
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);
|
||||||
|
|
Loading…
Reference in a new issue