mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 20:12:31 +01:00
Merge sanja.is.com.ua:/home/bell/mysql/bk/mysql-4.1
into sanja.is.com.ua:/home/bell/mysql/bk/work-4.1
This commit is contained in:
commit
b7403e8bb2
14 changed files with 214 additions and 59 deletions
|
@ -750,3 +750,32 @@ SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterd");
|
|||
id
|
||||
4
|
||||
DROP TABLE t1;
|
||||
SET NAMES latin1;
|
||||
CREATE TABLE t1 (
|
||||
id int unsigned NOT NULL auto_increment,
|
||||
list_id smallint unsigned NOT NULL,
|
||||
term text NOT NULL,
|
||||
PRIMARY KEY(id),
|
||||
INDEX(list_id, term(19))
|
||||
) TYPE=MyISAM CHARSET=utf8;
|
||||
Warnings:
|
||||
Warning 1287 'TYPE=storage_engine' is deprecated; use 'ENGINE=storage_engine' instead
|
||||
INSERT INTO t1 set list_id = 1, term = "testétest";
|
||||
INSERT INTO t1 set list_id = 1, term = "testetest";
|
||||
INSERT INTO t1 set list_id = 1, term = "testètest";
|
||||
SELECT id, term FROM t1 where (list_id = 1) AND (term = "testétest");
|
||||
id term
|
||||
1 testétest
|
||||
2 testetest
|
||||
3 testètest
|
||||
SELECT id, term FROM t1 where (list_id = 1) AND (term = "testetest");
|
||||
id term
|
||||
1 testétest
|
||||
2 testetest
|
||||
3 testètest
|
||||
SELECT id, term FROM t1 where (list_id = 1) AND (term = "testètest");
|
||||
id term
|
||||
1 testétest
|
||||
2 testetest
|
||||
3 testètest
|
||||
DROP TABLE t1;
|
||||
|
|
|
@ -336,3 +336,42 @@ id select_type table type possible_keys key key_len ref rows Extra
|
|||
- - - - - - - - NULL Impossible WHERE
|
||||
drop table t1;
|
||||
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;
|
||||
|
|
|
@ -592,3 +592,23 @@ SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterb");
|
|||
SELECT id FROM t1 WHERE (list_id = 1) AND (term = "lettera");
|
||||
SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterd");
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
#
|
||||
# Bug #6043 erratic searching for diacriticals in indexed MyISAM UTF-8 table
|
||||
#
|
||||
SET NAMES latin1;
|
||||
CREATE TABLE t1 (
|
||||
id int unsigned NOT NULL auto_increment,
|
||||
list_id smallint unsigned NOT NULL,
|
||||
term text NOT NULL,
|
||||
PRIMARY KEY(id),
|
||||
INDEX(list_id, term(19))
|
||||
) TYPE=MyISAM CHARSET=utf8;
|
||||
INSERT INTO t1 set list_id = 1, term = "testétest";
|
||||
INSERT INTO t1 set list_id = 1, term = "testetest";
|
||||
INSERT INTO t1 set list_id = 1, term = "testètest";
|
||||
SELECT id, term FROM t1 where (list_id = 1) AND (term = "testétest");
|
||||
SELECT id, term FROM t1 where (list_id = 1) AND (term = "testetest");
|
||||
SELECT id, term FROM t1 where (list_id = 1) AND (term = "testètest");
|
||||
DROP TABLE t1;
|
||||
|
|
|
@ -363,4 +363,30 @@ execute stmt using @v;
|
|||
drop table t1;
|
||||
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;
|
||||
|
|
12
sql/field.cc
12
sql/field.cc
|
@ -5000,10 +5000,10 @@ String *Field_blob::val_str(String *val_buffer __attribute__((unused)),
|
|||
int Field_blob::cmp(const char *a,uint32 a_length, const char *b,
|
||||
uint32 b_length)
|
||||
{
|
||||
int diff=my_strnncoll(field_charset,
|
||||
(const uchar*)a,min(a_length,b_length),
|
||||
(const uchar*)b,min(a_length,b_length));
|
||||
return diff ? diff : (int) (a_length - b_length);
|
||||
return field_charset->coll->strnncoll(field_charset,
|
||||
(const uchar*)a, a_length,
|
||||
(const uchar*)b, b_length,
|
||||
0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -5087,8 +5087,8 @@ void Field_blob::get_key_image(char *buff,uint length,
|
|||
|
||||
get_ptr(&blob);
|
||||
uint char_length= length / cs->mbmaxlen;
|
||||
char_length= my_charpos(cs, blob, blob + length, char_length);
|
||||
set_if_smaller(length, char_length);
|
||||
char_length= my_charpos(cs, blob, blob + blob_length, char_length);
|
||||
set_if_smaller(blob_length, char_length);
|
||||
|
||||
if ((uint32) length > blob_length)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
max_length=float_length(decimals);
|
||||
Item_real_func::fix_fields(thd, tables, ref);
|
||||
used_tables_cache|= RAND_TABLE_BIT;
|
||||
if (arg_count)
|
||||
{ // Only use argument once in query
|
||||
uint32 tmp= (uint32) (args[0]->val_int());
|
||||
if ((rand= (struct rand_struct*) sql_alloc(sizeof(*rand))))
|
||||
randominit(rand,(uint32) (tmp*0x10001L+55555555L),
|
||||
(uint32) (tmp*0x10000001L));
|
||||
/*
|
||||
Allocate rand structure once: we must use thd->current_arena
|
||||
to create rand in proper mem_root if it's a prepared statement or
|
||||
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
|
||||
{
|
||||
THD *thd= current_thd;
|
||||
/*
|
||||
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.
|
||||
|
@ -1038,6 +1055,7 @@ void Item_func_rand::fix_length_and_dec()
|
|||
thd->rand_saved_seed2=thd->rand.seed2;
|
||||
rand= &thd->rand;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void Item_func_rand::update_used_tables()
|
||||
|
|
|
@ -512,13 +512,13 @@ class Item_func_rand :public Item_real_func
|
|||
{
|
||||
struct rand_struct *rand;
|
||||
public:
|
||||
Item_func_rand(Item *a) :Item_real_func(a) {}
|
||||
Item_func_rand() :Item_real_func() {}
|
||||
Item_func_rand(Item *a) :Item_real_func(a), rand(0) {}
|
||||
Item_func_rand() :Item_real_func() {}
|
||||
double val();
|
||||
const char *func_name() const { return "rand"; }
|
||||
bool const_item() const { return 0; }
|
||||
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);
|
||||
void mysql_init_select(LEX *lex);
|
||||
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);
|
||||
void create_select_for_variable(const char *var_name);
|
||||
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. */
|
||||
lex_end(lex);
|
||||
|
|
|
@ -582,12 +582,6 @@ public:
|
|||
void restore_backup_statement(Statement *stmt, Statement *backup);
|
||||
/* return class type */
|
||||
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,
|
||||
MEM_ROOT *runtime_memroot);
|
||||
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 */
|
||||
|
|
|
@ -117,7 +117,30 @@ void lex_free(void)
|
|||
void lex_start(THD *thd, uchar *buf,uint length)
|
||||
{
|
||||
LEX *lex= thd->lex;
|
||||
lex->unit.init_query();
|
||||
lex->unit.init_select();
|
||||
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->end_of_query=(lex->ptr=buf)+length;
|
||||
lex->yylineno = 1;
|
||||
|
|
|
@ -369,7 +369,7 @@ public:
|
|||
ulong init_prepare_fake_select_lex(THD *thd);
|
||||
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();
|
||||
private:
|
||||
bool create_total_list_n_last_return(THD *thd, st_lex *lex,
|
||||
|
@ -508,7 +508,7 @@ public:
|
|||
|
||||
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() {}
|
||||
void make_empty_select()
|
||||
{
|
||||
|
|
|
@ -1001,16 +1001,15 @@ pthread_handler_decl(handle_one_connection,arg)
|
|||
net->compress=1; // Use compression
|
||||
|
||||
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))
|
||||
{
|
||||
execute_init_command(thd, &sys_init_connect, &LOCK_sys_init_connect);
|
||||
if (thd->query_error)
|
||||
thd->killed= 1;
|
||||
}
|
||||
|
||||
thd->proc_info=0;
|
||||
thd->set_time();
|
||||
thd->init_for_queries();
|
||||
while (!net->error && net->vio != 0 && !thd->killed)
|
||||
{
|
||||
if (do_command(thd))
|
||||
|
@ -3854,7 +3853,6 @@ bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Initialize global thd variables needed for query
|
||||
****************************************************************************/
|
||||
|
@ -3863,33 +3861,31 @@ void
|
|||
mysql_init_query(THD *thd, uchar *buf, uint length)
|
||||
{
|
||||
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);
|
||||
thd->select_number= lex->select_lex.select_number= 1;
|
||||
mysql_reset_thd_for_next_command(thd);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
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->free_list= 0;
|
||||
thd->total_warn_count=0; // Warnings for this query
|
||||
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->sent_row_count= thd->examined_row_count= 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_ASSERT(thd->free_list == NULL);
|
||||
mysql_reset_thd_for_next_command(thd);
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
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))
|
||||
goto set_params_data_err;
|
||||
#endif
|
||||
DBUG_ASSERT(thd->free_list == NULL);
|
||||
thd->protocol= &thd->protocol_prep; // Switch to binary protocol
|
||||
execute_stmt(thd, stmt, &expanded_query, true);
|
||||
thd->protocol= &thd->protocol_simple; // Use normal protocol
|
||||
|
@ -1823,7 +1824,8 @@ void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name)
|
|||
}
|
||||
|
||||
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);
|
||||
if (stmt->set_params_from_vars(stmt,
|
||||
thd->stmt_backup.lex->prepared_stmt_params,
|
||||
|
@ -1932,6 +1934,7 @@ void mysql_stmt_reset(THD *thd, char *packet)
|
|||
*/
|
||||
reset_stmt_params(stmt);
|
||||
|
||||
mysql_reset_thd_for_next_command(thd);
|
||||
send_ok(thd);
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
|
|
Loading…
Reference in a new issue