mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Merge bk-internal.mysql.com:/home/bk/mysql-4.1
into mysql.com:/media/sda1/mysql/mysql-4.1-5985 sql/sql_class.h: Auto merged
This commit is contained in:
@ -336,3 +336,42 @@ id select_type table type possible_keys key key_len ref rows Extra
|
|||||||
- - - - - - - - NULL Impossible WHERE
|
- - - - - - - - NULL Impossible WHERE
|
||||||
drop table t1;
|
drop table t1;
|
||||||
deallocate prepare stmt;
|
deallocate prepare stmt;
|
||||||
|
create table t1 (a int);
|
||||||
|
insert into t1 (a) values (1), (2), (3), (4);
|
||||||
|
set @precision=10000000000;
|
||||||
|
select rand(),
|
||||||
|
cast(rand(10)*@precision as unsigned integer),
|
||||||
|
cast(rand(a)*@precision as unsigned integer) from t1;
|
||||||
|
rand() cast(rand(10)*@precision as unsigned integer) cast(rand(a)*@precision as unsigned integer)
|
||||||
|
- 6570515219 -
|
||||||
|
- 1282061302 -
|
||||||
|
- 6698761160 -
|
||||||
|
- 9647622201 -
|
||||||
|
prepare stmt from
|
||||||
|
"select rand(),
|
||||||
|
cast(rand(10)*@precision as unsigned integer),
|
||||||
|
cast(rand(a)*@precision as unsigned integer),
|
||||||
|
cast(rand(?)*@precision as unsigned integer) from t1";
|
||||||
|
set @var=1;
|
||||||
|
execute stmt using @var;
|
||||||
|
rand() cast(rand(10)*@precision as unsigned integer) cast(rand(a)*@precision as unsigned integer) cast(rand(?)*@precision as unsigned integer)
|
||||||
|
- 6570515219 - 4054035371
|
||||||
|
- 1282061302 - 8716141803
|
||||||
|
- 6698761160 - 1418603212
|
||||||
|
- 9647622201 - 944590960
|
||||||
|
set @var=2;
|
||||||
|
execute stmt using @var;
|
||||||
|
rand() cast(rand(10)*@precision as unsigned integer) cast(rand(a)*@precision as unsigned integer) cast(rand(?)*@precision as unsigned integer)
|
||||||
|
- 6570515219 1559528654 6555866465
|
||||||
|
- 1282061302 6238114970 1223466192
|
||||||
|
- 6698761160 6511989195 6449731873
|
||||||
|
- 9647622201 3845601374 8578261098
|
||||||
|
set @var=3;
|
||||||
|
execute stmt using @var;
|
||||||
|
rand() cast(rand(10)*@precision as unsigned integer) cast(rand(a)*@precision as unsigned integer) cast(rand(?)*@precision as unsigned integer)
|
||||||
|
- 6570515219 1559528654 9057697559
|
||||||
|
- 1282061302 6238114970 3730790581
|
||||||
|
- 6698761160 6511989195 1480860534
|
||||||
|
- 9647622201 3845601374 6211931236
|
||||||
|
drop table t1;
|
||||||
|
deallocate prepare stmt;
|
||||||
|
@ -363,4 +363,30 @@ execute stmt using @v;
|
|||||||
drop table t1;
|
drop table t1;
|
||||||
deallocate prepare stmt;
|
deallocate prepare stmt;
|
||||||
|
|
||||||
|
#
|
||||||
|
# A test case for Bug#5985 prepare stmt from "select rand(?)" crashes
|
||||||
|
# server. Check that Item_func_rand is prepared-statements friendly.
|
||||||
|
#
|
||||||
|
create table t1 (a int);
|
||||||
|
insert into t1 (a) values (1), (2), (3), (4);
|
||||||
|
set @precision=10000000000;
|
||||||
|
--replace_column 1 - 3 -
|
||||||
|
select rand(),
|
||||||
|
cast(rand(10)*@precision as unsigned integer),
|
||||||
|
cast(rand(a)*@precision as unsigned integer) from t1;
|
||||||
|
prepare stmt from
|
||||||
|
"select rand(),
|
||||||
|
cast(rand(10)*@precision as unsigned integer),
|
||||||
|
cast(rand(a)*@precision as unsigned integer),
|
||||||
|
cast(rand(?)*@precision as unsigned integer) from t1";
|
||||||
|
set @var=1;
|
||||||
|
--replace_column 1 - 3 -
|
||||||
|
execute stmt using @var;
|
||||||
|
set @var=2;
|
||||||
|
--replace_column 1 -
|
||||||
|
execute stmt using @var;
|
||||||
|
set @var=3;
|
||||||
|
--replace_column 1 -
|
||||||
|
execute stmt using @var;
|
||||||
|
drop table t1;
|
||||||
|
deallocate prepare stmt;
|
||||||
|
@ -1010,21 +1010,38 @@ double Item_func_round::val()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Item_func_rand::fix_length_and_dec()
|
bool Item_func_rand::fix_fields(THD *thd, struct st_table_list *tables,
|
||||||
|
Item **ref)
|
||||||
{
|
{
|
||||||
decimals=NOT_FIXED_DEC;
|
Item_real_func::fix_fields(thd, tables, ref);
|
||||||
max_length=float_length(decimals);
|
|
||||||
used_tables_cache|= RAND_TABLE_BIT;
|
used_tables_cache|= RAND_TABLE_BIT;
|
||||||
if (arg_count)
|
if (arg_count)
|
||||||
{ // Only use argument once in query
|
{ // Only use argument once in query
|
||||||
uint32 tmp= (uint32) (args[0]->val_int());
|
/*
|
||||||
if ((rand= (struct rand_struct*) sql_alloc(sizeof(*rand))))
|
Allocate rand structure once: we must use thd->current_arena
|
||||||
randominit(rand,(uint32) (tmp*0x10001L+55555555L),
|
to create rand in proper mem_root if it's a prepared statement or
|
||||||
(uint32) (tmp*0x10000001L));
|
stored procedure.
|
||||||
|
*/
|
||||||
|
if (!rand && !(rand= (struct rand_struct*)
|
||||||
|
thd->current_arena->alloc(sizeof(*rand))))
|
||||||
|
return TRUE;
|
||||||
|
/*
|
||||||
|
PARAM_ITEM is returned if we're in statement prepare and consequently
|
||||||
|
no placeholder value is set yet.
|
||||||
|
*/
|
||||||
|
if (args[0]->type() != PARAM_ITEM)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
TODO: do not do reinit 'rand' for every execute of PS/SP if
|
||||||
|
args[0] is a constant.
|
||||||
|
*/
|
||||||
|
uint32 tmp= (uint32) args[0]->val_int();
|
||||||
|
randominit(rand, (uint32) (tmp*0x10001L+55555555L),
|
||||||
|
(uint32) (tmp*0x10000001L));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
THD *thd= current_thd;
|
|
||||||
/*
|
/*
|
||||||
No need to send a Rand log event if seed was given eg: RAND(seed),
|
No need to send a Rand log event if seed was given eg: RAND(seed),
|
||||||
as it will be replicated in the query as such.
|
as it will be replicated in the query as such.
|
||||||
@ -1038,6 +1055,7 @@ void Item_func_rand::fix_length_and_dec()
|
|||||||
thd->rand_saved_seed2=thd->rand.seed2;
|
thd->rand_saved_seed2=thd->rand.seed2;
|
||||||
rand= &thd->rand;
|
rand= &thd->rand;
|
||||||
}
|
}
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item_func_rand::update_used_tables()
|
void Item_func_rand::update_used_tables()
|
||||||
|
@ -512,13 +512,13 @@ class Item_func_rand :public Item_real_func
|
|||||||
{
|
{
|
||||||
struct rand_struct *rand;
|
struct rand_struct *rand;
|
||||||
public:
|
public:
|
||||||
Item_func_rand(Item *a) :Item_real_func(a) {}
|
Item_func_rand(Item *a) :Item_real_func(a), rand(0) {}
|
||||||
Item_func_rand() :Item_real_func() {}
|
Item_func_rand() :Item_real_func() {}
|
||||||
double val();
|
double val();
|
||||||
const char *func_name() const { return "rand"; }
|
const char *func_name() const { return "rand"; }
|
||||||
bool const_item() const { return 0; }
|
bool const_item() const { return 0; }
|
||||||
void update_used_tables();
|
void update_used_tables();
|
||||||
void fix_length_and_dec();
|
bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -447,6 +447,7 @@ bool is_update_query(enum enum_sql_command command);
|
|||||||
bool alloc_query(THD *thd, char *packet, ulong packet_length);
|
bool alloc_query(THD *thd, char *packet, ulong packet_length);
|
||||||
void mysql_init_select(LEX *lex);
|
void mysql_init_select(LEX *lex);
|
||||||
void mysql_init_query(THD *thd, uchar *buf, uint length);
|
void mysql_init_query(THD *thd, uchar *buf, uint length);
|
||||||
|
void mysql_reset_thd_for_next_command(THD *thd);
|
||||||
bool mysql_new_select(LEX *lex, bool move_down);
|
bool mysql_new_select(LEX *lex, bool move_down);
|
||||||
void create_select_for_variable(const char *var_name);
|
void create_select_for_variable(const char *var_name);
|
||||||
void mysql_init_multi_delete(LEX *lex);
|
void mysql_init_multi_delete(LEX *lex);
|
||||||
|
@ -1498,7 +1498,7 @@ void Statement::restore_backup_statement(Statement *stmt, Statement *backup)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Statement::end_statement()
|
void THD::end_statement()
|
||||||
{
|
{
|
||||||
/* Cleanup SQL processing state to resuse this statement in next query. */
|
/* Cleanup SQL processing state to resuse this statement in next query. */
|
||||||
lex_end(lex);
|
lex_end(lex);
|
||||||
|
@ -582,12 +582,6 @@ public:
|
|||||||
void restore_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;
|
||||||
|
|
||||||
/*
|
|
||||||
Cleanup statement parse state (parse tree, lex) after execution of
|
|
||||||
a non-prepared SQL statement.
|
|
||||||
*/
|
|
||||||
void end_statement();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1063,6 +1057,12 @@ public:
|
|||||||
void nocheck_register_item_tree_change(Item **place, Item *old_value,
|
void nocheck_register_item_tree_change(Item **place, Item *old_value,
|
||||||
MEM_ROOT *runtime_memroot);
|
MEM_ROOT *runtime_memroot);
|
||||||
void rollback_item_tree_changes();
|
void rollback_item_tree_changes();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Cleanup statement parse state (parse tree, lex) and execution
|
||||||
|
state after execution of a non-prepared SQL statement.
|
||||||
|
*/
|
||||||
|
void end_statement();
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Flags for the THD::system_thread (bitmap) variable */
|
/* Flags for the THD::system_thread (bitmap) variable */
|
||||||
|
@ -117,7 +117,30 @@ void lex_free(void)
|
|||||||
void lex_start(THD *thd, uchar *buf,uint length)
|
void lex_start(THD *thd, uchar *buf,uint length)
|
||||||
{
|
{
|
||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
|
lex->unit.init_query();
|
||||||
|
lex->unit.init_select();
|
||||||
lex->thd= thd;
|
lex->thd= thd;
|
||||||
|
lex->unit.thd= thd;
|
||||||
|
lex->select_lex.init_query();
|
||||||
|
lex->value_list.empty();
|
||||||
|
lex->param_list.empty();
|
||||||
|
lex->unit.next= lex->unit.master=
|
||||||
|
lex->unit.link_next= lex->unit.return_to= 0;
|
||||||
|
lex->unit.prev= lex->unit.link_prev= 0;
|
||||||
|
lex->unit.slave= lex->unit.global_parameters= lex->current_select=
|
||||||
|
lex->all_selects_list= &lex->select_lex;
|
||||||
|
lex->select_lex.master= &lex->unit;
|
||||||
|
lex->select_lex.prev= &lex->unit.slave;
|
||||||
|
lex->select_lex.link_next= lex->select_lex.slave= lex->select_lex.next= 0;
|
||||||
|
lex->select_lex.link_prev= (st_select_lex_node**)&(lex->all_selects_list);
|
||||||
|
lex->select_lex.options= 0;
|
||||||
|
lex->describe= 0;
|
||||||
|
lex->derived_tables= FALSE;
|
||||||
|
lex->lock_option= TL_READ;
|
||||||
|
lex->found_colon= 0;
|
||||||
|
lex->safe_to_cache_query= 1;
|
||||||
|
lex->time_zone_tables_used= 0;
|
||||||
|
lex->select_lex.select_number= 1;
|
||||||
lex->next_state=MY_LEX_START;
|
lex->next_state=MY_LEX_START;
|
||||||
lex->end_of_query=(lex->ptr=buf)+length;
|
lex->end_of_query=(lex->ptr=buf)+length;
|
||||||
lex->yylineno = 1;
|
lex->yylineno = 1;
|
||||||
|
@ -369,7 +369,7 @@ public:
|
|||||||
ulong init_prepare_fake_select_lex(THD *thd);
|
ulong init_prepare_fake_select_lex(THD *thd);
|
||||||
int change_result(select_subselect *result, select_subselect *old_result);
|
int change_result(select_subselect *result, select_subselect *old_result);
|
||||||
|
|
||||||
friend void mysql_init_query(THD *thd, uchar *buf, uint length);
|
friend void lex_start(THD *thd, uchar *buf, uint length);
|
||||||
friend int subselect_union_engine::exec();
|
friend int subselect_union_engine::exec();
|
||||||
private:
|
private:
|
||||||
bool create_total_list_n_last_return(THD *thd, st_lex *lex,
|
bool create_total_list_n_last_return(THD *thd, st_lex *lex,
|
||||||
@ -508,7 +508,7 @@ public:
|
|||||||
|
|
||||||
bool test_limit();
|
bool test_limit();
|
||||||
|
|
||||||
friend void mysql_init_query(THD *thd, uchar *buf, uint length);
|
friend void lex_start(THD *thd, uchar *buf, uint length);
|
||||||
st_select_lex() {}
|
st_select_lex() {}
|
||||||
void make_empty_select()
|
void make_empty_select()
|
||||||
{
|
{
|
||||||
|
@ -1001,16 +1001,15 @@ pthread_handler_decl(handle_one_connection,arg)
|
|||||||
net->compress=1; // Use compression
|
net->compress=1; // Use compression
|
||||||
|
|
||||||
thd->version= refresh_version;
|
thd->version= refresh_version;
|
||||||
|
thd->proc_info= 0;
|
||||||
|
thd->set_time();
|
||||||
|
thd->init_for_queries();
|
||||||
if (sys_init_connect.value_length && !(thd->master_access & SUPER_ACL))
|
if (sys_init_connect.value_length && !(thd->master_access & SUPER_ACL))
|
||||||
{
|
{
|
||||||
execute_init_command(thd, &sys_init_connect, &LOCK_sys_init_connect);
|
execute_init_command(thd, &sys_init_connect, &LOCK_sys_init_connect);
|
||||||
if (thd->query_error)
|
if (thd->query_error)
|
||||||
thd->killed= 1;
|
thd->killed= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
thd->proc_info=0;
|
|
||||||
thd->set_time();
|
|
||||||
thd->init_for_queries();
|
|
||||||
while (!net->error && net->vio != 0 && !thd->killed)
|
while (!net->error && net->vio != 0 && !thd->killed)
|
||||||
{
|
{
|
||||||
if (do_command(thd))
|
if (do_command(thd))
|
||||||
@ -3854,7 +3853,6 @@ bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
Initialize global thd variables needed for query
|
Initialize global thd variables needed for query
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -3863,33 +3861,30 @@ void
|
|||||||
mysql_init_query(THD *thd, uchar *buf, uint length)
|
mysql_init_query(THD *thd, uchar *buf, uint length)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("mysql_init_query");
|
DBUG_ENTER("mysql_init_query");
|
||||||
LEX *lex= thd->lex;
|
|
||||||
lex->unit.init_query();
|
|
||||||
lex->unit.init_select();
|
|
||||||
lex->unit.thd= thd;
|
|
||||||
lex->select_lex.init_query();
|
|
||||||
lex->value_list.empty();
|
|
||||||
lex->param_list.empty();
|
|
||||||
lex->unit.next= lex->unit.master=
|
|
||||||
lex->unit.link_next= lex->unit.return_to=0;
|
|
||||||
lex->unit.prev= lex->unit.link_prev= 0;
|
|
||||||
lex->unit.slave= lex->unit.global_parameters= lex->current_select=
|
|
||||||
lex->all_selects_list= &lex->select_lex;
|
|
||||||
lex->select_lex.master= &lex->unit;
|
|
||||||
lex->select_lex.prev= &lex->unit.slave;
|
|
||||||
lex->select_lex.link_next= lex->select_lex.slave= lex->select_lex.next= 0;
|
|
||||||
lex->select_lex.link_prev= (st_select_lex_node**)&(lex->all_selects_list);
|
|
||||||
lex->select_lex.options=0;
|
|
||||||
lex->describe= 0;
|
|
||||||
lex->derived_tables= FALSE;
|
|
||||||
lex->lock_option= TL_READ;
|
|
||||||
lex->found_colon= 0;
|
|
||||||
lex->safe_to_cache_query= 1;
|
|
||||||
lex->time_zone_tables_used= 0;
|
|
||||||
lex_start(thd, buf, length);
|
lex_start(thd, buf, length);
|
||||||
thd->select_number= lex->select_lex.select_number= 1;
|
mysql_reset_thd_for_next_command(thd);
|
||||||
thd->free_list= 0;
|
DBUG_VOID_RETURN;
|
||||||
thd->total_warn_count=0; // Warnings for this query
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Reset THD part responsible for command processing state.
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
This needs to be called before execution of every statement
|
||||||
|
(prepared or conventional).
|
||||||
|
|
||||||
|
TODO
|
||||||
|
Make it a method of THD and align its name with the rest of
|
||||||
|
reset/end/start/init methods.
|
||||||
|
Call it after we use THD for queries, not before.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void mysql_reset_thd_for_next_command(THD *thd)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("mysql_reset_thd_for_next_command");
|
||||||
|
thd->select_number= 1;
|
||||||
|
thd->total_warn_count= 0; // Warnings for this query
|
||||||
thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0;
|
thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0;
|
||||||
thd->sent_row_count= thd->examined_row_count= 0;
|
thd->sent_row_count= thd->examined_row_count= 0;
|
||||||
thd->is_fatal_error= thd->rand_used= thd->time_zone_used= 0;
|
thd->is_fatal_error= thd->rand_used= thd->time_zone_used= 0;
|
||||||
|
@ -1760,6 +1760,8 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
|
|||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DBUG_ASSERT(thd->free_list == NULL);
|
||||||
|
mysql_reset_thd_for_next_command(thd);
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
if (stmt->param_count)
|
if (stmt->param_count)
|
||||||
{
|
{
|
||||||
@ -1778,7 +1780,6 @@ 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
|
||||||
@ -1823,7 +1824,8 @@ void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
DBUG_ASSERT(thd->free_list == NULL);
|
DBUG_ASSERT(thd->free_list == NULL);
|
||||||
|
/* Must go before setting variables, as it clears thd->user_var_events */
|
||||||
|
mysql_reset_thd_for_next_command(thd);
|
||||||
thd->set_n_backup_statement(stmt, &thd->stmt_backup);
|
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,
|
||||||
@ -1932,6 +1934,7 @@ void mysql_stmt_reset(THD *thd, char *packet)
|
|||||||
*/
|
*/
|
||||||
reset_stmt_params(stmt);
|
reset_stmt_params(stmt);
|
||||||
|
|
||||||
|
mysql_reset_thd_for_next_command(thd);
|
||||||
send_ok(thd);
|
send_ok(thd);
|
||||||
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
Reference in New Issue
Block a user