Commit 6232a6e1 authored by tomas@poseidon.ndb.mysql.com's avatar tomas@poseidon.ndb.mysql.com

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

into poseidon.ndb.mysql.com:/home/tomas/mysql-4.1-ndb-merge
parents 17328541 ce0cbf14
...@@ -24,6 +24,7 @@ bar@bar.udmsearch.izhnet.ru ...@@ -24,6 +24,7 @@ bar@bar.udmsearch.izhnet.ru
bar@deer.(none) bar@deer.(none)
bar@gw.udmsearch.izhnet.ru bar@gw.udmsearch.izhnet.ru
bar@mysql.com bar@mysql.com
bar@noter.intranet.mysql.r18.ru
bell@laptop.sanja.is.com.ua bell@laptop.sanja.is.com.ua
bell@sanja.is.com.ua bell@sanja.is.com.ua
bk@admin.bk bk@admin.bk
......
...@@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script. ...@@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script.
AC_INIT(sql/mysqld.cc) AC_INIT(sql/mysqld.cc)
AC_CANONICAL_SYSTEM AC_CANONICAL_SYSTEM
# The Docs Makefile.am parses this line! # The Docs Makefile.am parses this line!
AM_INIT_AUTOMAKE(mysql, 4.1.5-gamma) AM_INIT_AUTOMAKE(mysql, 4.1.6-gamma)
AM_CONFIG_HEADER(config.h) AM_CONFIG_HEADER(config.h)
PROTOCOL_VERSION=10 PROTOCOL_VERSION=10
......
...@@ -47,6 +47,7 @@ my_bool _hash_init(HASH *hash, CHARSET_INFO *charset, ...@@ -47,6 +47,7 @@ my_bool _hash_init(HASH *hash, CHARSET_INFO *charset,
uint key_length, hash_get_key get_key, uint key_length, hash_get_key get_key,
void (*free_element)(void*), uint flags CALLER_INFO_PROTO); void (*free_element)(void*), uint flags CALLER_INFO_PROTO);
void hash_free(HASH *tree); void hash_free(HASH *tree);
void hash_reset(HASH *hash);
byte *hash_element(HASH *hash,uint idx); byte *hash_element(HASH *hash,uint idx);
gptr hash_search(HASH *info,const byte *key,uint length); gptr hash_search(HASH *info,const byte *key,uint length);
gptr hash_next(HASH *info,const byte *key,uint length); gptr hash_next(HASH *info,const byte *key,uint length);
...@@ -56,7 +57,6 @@ my_bool hash_update(HASH *hash,byte *record,byte *old_key,uint old_key_length); ...@@ -56,7 +57,6 @@ my_bool hash_update(HASH *hash,byte *record,byte *old_key,uint old_key_length);
void hash_replace(HASH *hash, uint idx, byte *new_row); void hash_replace(HASH *hash, uint idx, byte *new_row);
my_bool hash_check(HASH *hash); /* Only in debug library */ my_bool hash_check(HASH *hash); /* Only in debug library */
#define hash_clear(H) bzero((char*) (H),sizeof(*(H)))
#define hash_inited(H) ((H)->array.buffer != 0) #define hash_inited(H) ((H)->array.buffer != 0)
#ifdef __cplusplus #ifdef __cplusplus
......
...@@ -725,7 +725,8 @@ extern void my_free_lock(byte *ptr,myf flags); ...@@ -725,7 +725,8 @@ extern void my_free_lock(byte *ptr,myf flags);
#define my_free_lock(A,B) my_free((A),(B)) #define my_free_lock(A,B) my_free((A),(B))
#endif #endif
#define alloc_root_inited(A) ((A)->min_malloc != 0) #define alloc_root_inited(A) ((A)->min_malloc != 0)
#define clear_alloc_root(A) bzero((void *) (A), sizeof(MEM_ROOT)) #define ALLOC_ROOT_MIN_BLOCK_SIZE (MALLOC_OVERHEAD + sizeof(USED_MEM) + 8)
#define clear_alloc_root(A) do { (A)->free= (A)->used= (A)->pre_alloc= 0; } while(0)
extern void init_alloc_root(MEM_ROOT *mem_root, uint block_size, extern void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
uint pre_alloc_size); uint pre_alloc_size);
extern gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size); extern gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size);
......
...@@ -42,6 +42,7 @@ my_bool handle_local_infile(MYSQL *mysql, const char *net_filename); ...@@ -42,6 +42,7 @@ my_bool handle_local_infile(MYSQL *mysql, const char *net_filename);
void mysql_read_default_options(struct st_mysql_options *options, void mysql_read_default_options(struct st_mysql_options *options,
const char *filename,const char *group); const char *filename,const char *group);
void mysql_detach_stmt_list(LIST **stmt_list);
MYSQL * STDCALL MYSQL * STDCALL
cli_mysql_real_connect(MYSQL *mysql,const char *host, const char *user, cli_mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
const char *passwd, const char *db, const char *passwd, const char *db,
......
...@@ -662,6 +662,7 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, ...@@ -662,6 +662,7 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
const char *passwd, const char *db) const char *passwd, const char *db)
{ {
char buff[512],*end=buff; char buff[512],*end=buff;
int rc;
DBUG_ENTER("mysql_change_user"); DBUG_ENTER("mysql_change_user");
if (!user) if (!user)
...@@ -695,18 +696,26 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, ...@@ -695,18 +696,26 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
/* Write authentication package */ /* Write authentication package */
simple_command(mysql,COM_CHANGE_USER, buff,(ulong) (end-buff),1); simple_command(mysql,COM_CHANGE_USER, buff,(ulong) (end-buff),1);
if ((*mysql->methods->read_change_user_result)(mysql, buff, passwd)) rc= (*mysql->methods->read_change_user_result)(mysql, buff, passwd);
DBUG_RETURN(1);
/* Free old connect information */ /*
my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR)); The server will close all statements no matter was the attempt
my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR)); to change user successful or not.
my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR)); */
mysql_detach_stmt_list(&mysql->stmts);
/* alloc new connect information */ if (rc == 0)
mysql->user= my_strdup(user,MYF(MY_WME)); {
mysql->passwd=my_strdup(passwd,MYF(MY_WME)); /* Free old connect information */
mysql->db= db ? my_strdup(db,MYF(MY_WME)) : 0; my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
DBUG_RETURN(0); my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
/* alloc new connect information */
mysql->user= my_strdup(user,MYF(MY_WME));
mysql->passwd=my_strdup(passwd,MYF(MY_WME));
mysql->db= db ? my_strdup(db,MYF(MY_WME)) : 0;
}
DBUG_RETURN(rc);
} }
#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL) #if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL)
......
...@@ -485,3 +485,10 @@ MBRContains(GeomFromText('Polygon((0 0, 0 7, 7 7, 7 0, 0 0))'), a); ...@@ -485,3 +485,10 @@ MBRContains(GeomFromText('Polygon((0 0, 0 7, 7 7, 7 0, 0 0))'), a);
AsText(a) AsText(a)
POINT(1 1) POINT(1 1)
drop table t1; drop table t1;
create table t1 select POINT(1,3);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`POINT(1,3)` longblob NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
...@@ -289,3 +289,11 @@ execute stmt using @var; ...@@ -289,3 +289,11 @@ execute stmt using @var;
select * from t1; select * from t1;
deallocate prepare stmt; deallocate prepare stmt;
drop table t1; drop table t1;
prepare stmt from "select 'abc' like convert('abc' using utf8)";
execute stmt;
'abc' like convert('abc' using utf8)
1
execute stmt;
'abc' like convert('abc' using utf8)
1
deallocate prepare stmt;
...@@ -198,4 +198,12 @@ CDF32C20E7E020F0FBE1E0EBEAF3 CDF32C20E7E020F0FBE1E0EBEAF3 ...@@ -198,4 +198,12 @@ CDF32C20E7E020F0FBE1E0EBEAF3 CDF32C20E7E020F0FBE1E0EBEAF3
select hex(c1), hex(c2) from t1; select hex(c1), hex(c2) from t1;
hex(c1) hex(c2) hex(c1) hex(c2)
CDF32C20E7E020F0FBE1E0EBEAF3 CDF32C20E7E020F0FBE1E0EBEAF3 CDF32C20E7E020F0FBE1E0EBEAF3 CDF32C20E7E020F0FBE1E0EBEAF3
stop slave;
delete from t1;
change master to master_log_pos=5801;
start slave until master_log_file='master-bin.000001', master_log_pos=5937;
start slave;
select hex(c1), hex(c2) from t1;
hex(c1) hex(c2)
CDF32C20E7E020F0FBE1E0EBEAF3 CDF32C20E7E020F0FBE1E0EBEAF3
drop table t1; drop table t1;
...@@ -1661,3 +1661,19 @@ t1 CREATE TABLE `t1` ( ...@@ -1661,3 +1661,19 @@ t1 CREATE TABLE `t1` (
`a` enum('','1','2') NOT NULL default '' `a` enum('','1','2') NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
set names latin1;
CREATE TABLE t1 (
a INT default 1,
b ENUM('value','_value','') character set latin1 NOT NULL
);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) default '1',
`b` enum('value','_value','') NOT NULL default 'value'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
show columns from t1;
Field Type Null Key Default Extra
a int(11) YES 1
b enum('value','_value','') value
drop table t1;
...@@ -190,3 +190,7 @@ select AsText(a) from t1 where ...@@ -190,3 +190,7 @@ select AsText(a) from t1 where
and and
MBRContains(GeomFromText('Polygon((0 0, 0 7, 7 7, 7 0, 0 0))'), a); MBRContains(GeomFromText('Polygon((0 0, 0 7, 7 7, 7 0, 0 0))'), a);
drop table t1; drop table t1;
create table t1 select POINT(1,3);
show create table t1;
drop table t1;
...@@ -304,3 +304,13 @@ select * from t1; ...@@ -304,3 +304,13 @@ select * from t1;
deallocate prepare stmt; deallocate prepare stmt;
drop table t1; drop table t1;
#
# BUG#5688 "Upgraded 4.1.5 Server seg faults" # (prepared statements)
# The test case speaks for itself.
# Just another place where we used wrong memory root for Items created
# during statement prepare.
#
prepare stmt from "select 'abc' like convert('abc' using utf8)";
execute stmt;
execute stmt;
deallocate prepare stmt;
...@@ -148,6 +148,24 @@ INSERT INTO t1 (c1, c2) VALUES (' ...@@ -148,6 +148,24 @@ INSERT INTO t1 (c1, c2) VALUES ('
select hex(c1), hex(c2) from t1; select hex(c1), hex(c2) from t1;
sync_slave_with_master; sync_slave_with_master;
select hex(c1), hex(c2) from t1; select hex(c1), hex(c2) from t1;
# Now test for BUG##5705: SET CHARATER_SET_SERVERetc will be lost if
# STOP SLAVE before following query
stop slave;
delete from t1;
change master to master_log_pos=5801;
start slave until master_log_file='master-bin.000001', master_log_pos=5937;
# Slave is supposed to stop _after_ the INSERT, even though 5937 is
# the position of the beginning of the INSERT; after SET slave is not
# supposed to increment position.
wait_for_slave_to_stop;
# When you merge this into 5.0 you will have to adjust positions
# above; the first master_log_pos above should be the one of the SET,
# the second should be the one of the INSERT.
start slave;
sync_with_master;
select hex(c1), hex(c2) from t1;
connection master; connection master;
drop table t1; drop table t1;
sync_slave_with_master; sync_slave_with_master;
...@@ -45,3 +45,17 @@ create table t1 (a enum(0xE4, '1', '2') not null default 0xE4); ...@@ -45,3 +45,17 @@ create table t1 (a enum(0xE4, '1', '2') not null default 0xE4);
show columns from t1; show columns from t1;
show create table t1; show create table t1;
drop table t1; drop table t1;
#
# Bug #5628 German characters in field-defs will be '?'
# with some table definitions
#
set names latin1;
CREATE TABLE t1 (
a INT default 1,
b ENUM('value','_value','') character set latin1 NOT NULL
);
show create table t1;
show columns from t1;
drop table t1;
...@@ -88,6 +88,32 @@ void hash_free(HASH *hash) ...@@ -88,6 +88,32 @@ void hash_free(HASH *hash)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
/*
Delete all elements from the hash (the hash itself is to be reused).
SYNOPSIS
hash_reset()
hash the hash to delete elements of
*/
void hash_reset(HASH *hash)
{
DBUG_ENTER("hash_reset");
if (hash->free)
{
HASH_LINK *link= dynamic_element(&hash->array, 0, HASH_LINK*);
HASH_LINK *end= link + hash->records;
for (; link < end; ++link)
(*hash->free)(link->data);
}
reset_dynamic(&hash->array);
hash->records= 0;
hash->blength= 1;
hash->current_record= NO_RECORD;
DBUG_VOID_RETURN;
}
/* some helper functions */ /* some helper functions */
/* /*
......
...@@ -22,6 +22,27 @@ ...@@ -22,6 +22,27 @@
#undef EXTRA_DEBUG #undef EXTRA_DEBUG
#define EXTRA_DEBUG #define EXTRA_DEBUG
/*
Initialize memory root
SYNOPSIS
init_alloc_root()
mem_root - memory root to initialize
block_size - size of chunks (blocks) used for memory allocation
(It is external size of chunk i.e. it should include
memory required for internal structures, thus it
should be no less than ALLOC_ROOT_MIN_BLOCK_SIZE)
pre_alloc_size - if non-0, then size of block that should be
pre-allocated during memory root initialization.
DESCRIPTION
This function prepares memory root for further use, sets initial size of
chunk for memory allocation and pre-allocates first block if specified.
Altough error can happen during execution of this function if pre_alloc_size
is non-0 it won't be reported. Instead it will be reported as error in first
alloc_root() on this memory root.
*/
void init_alloc_root(MEM_ROOT *mem_root, uint block_size, void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
uint pre_alloc_size __attribute__((unused))) uint pre_alloc_size __attribute__((unused)))
{ {
...@@ -29,7 +50,7 @@ void init_alloc_root(MEM_ROOT *mem_root, uint block_size, ...@@ -29,7 +50,7 @@ void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
DBUG_PRINT("enter",("root: 0x%lx", mem_root)); DBUG_PRINT("enter",("root: 0x%lx", mem_root));
mem_root->free= mem_root->used= mem_root->pre_alloc= 0; mem_root->free= mem_root->used= mem_root->pre_alloc= 0;
mem_root->min_malloc= 32; mem_root->min_malloc= 32;
mem_root->block_size= block_size-MALLOC_OVERHEAD-sizeof(USED_MEM)-8; mem_root->block_size= block_size - ALLOC_ROOT_MIN_BLOCK_SIZE;
mem_root->error_handler= 0; mem_root->error_handler= 0;
mem_root->block_num= 4; /* We shift this with >>2 */ mem_root->block_num= 4; /* We shift this with >>2 */
mem_root->first_block_usage= 0; mem_root->first_block_usage= 0;
...@@ -54,9 +75,9 @@ void init_alloc_root(MEM_ROOT *mem_root, uint block_size, ...@@ -54,9 +75,9 @@ void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
SYNOPSIS SYNOPSIS
reset_root_defaults() reset_root_defaults()
mem_root memory root to change defaults of mem_root memory root to change defaults of
block_size new value of block size. Must be block_size new value of block size. Must be greater or equal
greater than ~68 bytes (the exact value depends on than ALLOC_ROOT_MIN_BLOCK_SIZE (this value is about
platform and compilation flags) 68 bytes and depends on platform and compilation flags)
pre_alloc_size new size of preallocated block. If not zero, pre_alloc_size new size of preallocated block. If not zero,
must be equal to or greater than block size, must be equal to or greater than block size,
otherwise means 'no prealloc'. otherwise means 'no prealloc'.
...@@ -70,7 +91,9 @@ void init_alloc_root(MEM_ROOT *mem_root, uint block_size, ...@@ -70,7 +91,9 @@ void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
void reset_root_defaults(MEM_ROOT *mem_root, uint block_size, void reset_root_defaults(MEM_ROOT *mem_root, uint block_size,
uint pre_alloc_size __attribute__((unused))) uint pre_alloc_size __attribute__((unused)))
{ {
mem_root->block_size= block_size-MALLOC_OVERHEAD-sizeof(USED_MEM)-8; DBUG_ASSERT(alloc_root_inited(mem_root));
mem_root->block_size= block_size - ALLOC_ROOT_MIN_BLOCK_SIZE;
#if !(defined(HAVE_purify) && defined(EXTRA_DEBUG)) #if !(defined(HAVE_purify) && defined(EXTRA_DEBUG))
if (pre_alloc_size) if (pre_alloc_size)
{ {
...@@ -123,6 +146,8 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size) ...@@ -123,6 +146,8 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
DBUG_ENTER("alloc_root"); DBUG_ENTER("alloc_root");
DBUG_PRINT("enter",("root: 0x%lx", mem_root)); DBUG_PRINT("enter",("root: 0x%lx", mem_root));
DBUG_ASSERT(alloc_root_inited(mem_root));
Size+=ALIGN_SIZE(sizeof(USED_MEM)); Size+=ALIGN_SIZE(sizeof(USED_MEM));
if (!(next = (USED_MEM*) my_malloc(Size,MYF(MY_WME)))) if (!(next = (USED_MEM*) my_malloc(Size,MYF(MY_WME))))
{ {
...@@ -140,6 +165,8 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size) ...@@ -140,6 +165,8 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
reg1 USED_MEM *next= 0; reg1 USED_MEM *next= 0;
reg2 USED_MEM **prev; reg2 USED_MEM **prev;
DBUG_ASSERT(alloc_root_inited(mem_root));
Size= ALIGN_SIZE(Size); Size= ALIGN_SIZE(Size);
if ((*(prev= &mem_root->free)) != NULL) if ((*(prev= &mem_root->free)) != NULL)
{ {
......
...@@ -2239,6 +2239,32 @@ static void mysql_close_free(MYSQL *mysql) ...@@ -2239,6 +2239,32 @@ static void mysql_close_free(MYSQL *mysql)
} }
/*
Clear connection pointer of every statement: this is necessary
to give error on attempt to use a prepared statement of closed
connection.
SYNOPSYS
mysql_detach_stmt_list()
stmt_list pointer to mysql->stmts
*/
void mysql_detach_stmt_list(LIST **stmt_list)
{
#ifdef MYSQL_CLIENT
/* Reset connection handle in all prepared statements. */
LIST *element= *stmt_list;
for (; element; element= element->next)
{
MYSQL_STMT *stmt= (MYSQL_STMT *) element->data;
stmt->mysql= 0;
/* No need to call list_delete for statement here */
}
*stmt_list= 0;
#endif /* MYSQL_CLIENT */
}
void STDCALL mysql_close(MYSQL *mysql) void STDCALL mysql_close(MYSQL *mysql)
{ {
DBUG_ENTER("mysql_close"); DBUG_ENTER("mysql_close");
...@@ -2255,20 +2281,7 @@ void STDCALL mysql_close(MYSQL *mysql) ...@@ -2255,20 +2281,7 @@ void STDCALL mysql_close(MYSQL *mysql)
} }
mysql_close_free_options(mysql); mysql_close_free_options(mysql);
mysql_close_free(mysql); mysql_close_free(mysql);
#ifdef MYSQL_CLIENT mysql_detach_stmt_list(&mysql->stmts);
if (mysql->stmts)
{
/* Reset connection handle in all prepared statements. */
LIST *element;
for (element= mysql->stmts; element; element= element->next)
{
MYSQL_STMT *stmt= (MYSQL_STMT *) element->data;
stmt->mysql= 0;
/* No need to call list_delete for statement here */
}
mysql->stmts= 0;
}
#endif /*MYSQL_CLIENT*/
#ifndef TO_BE_DELETED #ifndef TO_BE_DELETED
/* free/close slave list */ /* free/close slave list */
if (mysql->rpl_pivot) if (mysql->rpl_pivot)
......
...@@ -188,17 +188,27 @@ void Item_bool_func2::fix_length_and_dec() ...@@ -188,17 +188,27 @@ void Item_bool_func2::fix_length_and_dec()
{ {
uint strong= 0; uint strong= 0;
uint weak= 0; uint weak= 0;
uint32 dummy_offset;
DTCollation coll; DTCollation coll;
if (args[0]->result_type() == STRING_RESULT && if (args[0]->result_type() == STRING_RESULT &&
args[1]->result_type() == STRING_RESULT && args[1]->result_type() == STRING_RESULT &&
!my_charset_same(args[0]->collation.collation, String::needs_conversion(0, args[0]->collation.collation,
args[1]->collation.collation) && args[1]->collation.collation,
&dummy_offset) &&
!coll.set(args[0]->collation, args[1]->collation, TRUE)) !coll.set(args[0]->collation, args[1]->collation, TRUE))
{ {
Item* conv= 0; Item* conv= 0;
THD *thd= current_thd;
Item_arena *arena= thd->current_arena, backup;
strong= coll.strong; strong= coll.strong;
weak= strong ? 0 : 1; weak= strong ? 0 : 1;
/*
In case we're in statement prepare, create conversion item
in its memory: it will be reused on each execute.
*/
if (arena->is_stmt_prepare())
thd->set_n_backup_item_arena(arena, &backup);
if (args[weak]->type() == STRING_ITEM) if (args[weak]->type() == STRING_ITEM)
{ {
String tmp, cstr; String tmp, cstr;
...@@ -211,21 +221,13 @@ void Item_bool_func2::fix_length_and_dec() ...@@ -211,21 +221,13 @@ void Item_bool_func2::fix_length_and_dec()
} }
else else
{ {
THD *thd= current_thd;
/*
In case we're in statement prepare, create conversion item
in its memory: it will be reused on each execute.
*/
Item_arena *arena= thd->current_arena, backup;
if (arena->is_stmt_prepare())
thd->set_n_backup_item_arena(arena, &backup);
conv= new Item_func_conv_charset(args[weak], conv= new Item_func_conv_charset(args[weak],
args[strong]->collation.collation); args[strong]->collation.collation);
if (arena->is_stmt_prepare())
thd->restore_backup_item_arena(arena, &backup);
conv->collation.set(args[weak]->collation.derivation); conv->collation.set(args[weak]->collation.derivation);
conv->fix_fields(thd, 0, &conv); conv->fix_fields(thd, 0, &conv);
} }
if (arena->is_stmt_prepare())
thd->restore_backup_item_arena(arena, &backup);
args[weak]= conv ? conv : args[weak]; args[weak]= conv ? conv : args[weak];
} }
} }
......
...@@ -27,6 +27,13 @@ ...@@ -27,6 +27,13 @@
#include "sql_acl.h" #include "sql_acl.h"
#include <m_ctype.h> #include <m_ctype.h>
void Item_geometry_func::fix_length_and_dec()
{
collation.set(&my_charset_bin);
decimals=0;
max_length=MAX_BLOB_WIDTH;
}
String *Item_func_geometry_from_text::val_str(String *str) String *Item_func_geometry_from_text::val_str(String *str)
{ {
...@@ -44,6 +51,7 @@ String *Item_func_geometry_from_text::val_str(String *str) ...@@ -44,6 +51,7 @@ String *Item_func_geometry_from_text::val_str(String *str)
if ((arg_count == 2) && !args[1]->null_value) if ((arg_count == 2) && !args[1]->null_value)
srid= (uint32)args[1]->val_int(); srid= (uint32)args[1]->val_int();
str->set_charset(&my_charset_bin);
if (str->reserve(SRID_SIZE, 512)) if (str->reserve(SRID_SIZE, 512))
return 0; return 0;
str->length(0); str->length(0);
...@@ -54,12 +62,6 @@ String *Item_func_geometry_from_text::val_str(String *str) ...@@ -54,12 +62,6 @@ String *Item_func_geometry_from_text::val_str(String *str)
} }
void Item_func_geometry_from_text::fix_length_and_dec()
{
max_length=MAX_BLOB_WIDTH;
}
String *Item_func_geometry_from_wkb::val_str(String *str) String *Item_func_geometry_from_wkb::val_str(String *str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
...@@ -71,6 +73,7 @@ String *Item_func_geometry_from_wkb::val_str(String *str) ...@@ -71,6 +73,7 @@ String *Item_func_geometry_from_wkb::val_str(String *str)
if ((arg_count == 2) && !args[1]->null_value) if ((arg_count == 2) && !args[1]->null_value)
srid= (uint32)args[1]->val_int(); srid= (uint32)args[1]->val_int();
str->set_charset(&my_charset_bin);
if (str->reserve(SRID_SIZE, 512)) if (str->reserve(SRID_SIZE, 512))
return 0; return 0;
str->length(0); str->length(0);
...@@ -84,12 +87,6 @@ String *Item_func_geometry_from_wkb::val_str(String *str) ...@@ -84,12 +87,6 @@ String *Item_func_geometry_from_wkb::val_str(String *str)
} }
void Item_func_geometry_from_wkb::fix_length_and_dec()
{
max_length=MAX_BLOB_WIDTH;
}
String *Item_func_as_wkt::val_str(String *str) String *Item_func_as_wkt::val_str(String *str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
...@@ -138,12 +135,6 @@ String *Item_func_as_wkb::val_str(String *str) ...@@ -138,12 +135,6 @@ String *Item_func_as_wkb::val_str(String *str)
} }
void Item_func_as_wkb::fix_length_and_dec()
{
max_length= MAX_BLOB_WIDTH;
}
String *Item_func_geometry_type::val_str(String *str) String *Item_func_geometry_type::val_str(String *str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
...@@ -180,6 +171,7 @@ String *Item_func_envelope::val_str(String *str) ...@@ -180,6 +171,7 @@ String *Item_func_envelope::val_str(String *str)
return 0; return 0;
srid= uint4korr(swkb->ptr()); srid= uint4korr(swkb->ptr());
str->set_charset(&my_charset_bin);
str->length(0); str->length(0);
if (str->reserve(SRID_SIZE, 512)) if (str->reserve(SRID_SIZE, 512))
return 0; return 0;
...@@ -202,6 +194,7 @@ String *Item_func_centroid::val_str(String *str) ...@@ -202,6 +194,7 @@ String *Item_func_centroid::val_str(String *str)
swkb->length() - SRID_SIZE)))) swkb->length() - SRID_SIZE))))
return 0; return 0;
str->set_charset(&my_charset_bin);
if (str->reserve(SRID_SIZE, 512)) if (str->reserve(SRID_SIZE, 512))
return 0; return 0;
str->length(0); str->length(0);
...@@ -232,6 +225,7 @@ String *Item_func_spatial_decomp::val_str(String *str) ...@@ -232,6 +225,7 @@ String *Item_func_spatial_decomp::val_str(String *str)
return 0; return 0;
srid= uint4korr(swkb->ptr()); srid= uint4korr(swkb->ptr());
str->set_charset(&my_charset_bin);
if (str->reserve(SRID_SIZE, 512)) if (str->reserve(SRID_SIZE, 512))
goto err; goto err;
str->length(0); str->length(0);
...@@ -279,6 +273,7 @@ String *Item_func_spatial_decomp_n::val_str(String *str) ...@@ -279,6 +273,7 @@ String *Item_func_spatial_decomp_n::val_str(String *str)
swkb->length() - SRID_SIZE))))) swkb->length() - SRID_SIZE)))))
return 0; return 0;
str->set_charset(&my_charset_bin);
if (str->reserve(SRID_SIZE, 512)) if (str->reserve(SRID_SIZE, 512))
goto err; goto err;
srid= uint4korr(swkb->ptr()); srid= uint4korr(swkb->ptr());
...@@ -333,6 +328,7 @@ String *Item_func_point::val_str(String *str) ...@@ -333,6 +328,7 @@ String *Item_func_point::val_str(String *str)
str->realloc(1 + 4 + SIZEOF_STORED_DOUBLE*2)))) str->realloc(1 + 4 + SIZEOF_STORED_DOUBLE*2))))
return 0; return 0;
str->set_charset(&my_charset_bin);
str->length(0); str->length(0);
str->q_append((char)Geometry::wkb_ndr); str->q_append((char)Geometry::wkb_ndr);
str->q_append((uint32)Geometry::wkb_point); str->q_append((uint32)Geometry::wkb_point);
...@@ -358,6 +354,7 @@ String *Item_func_spatial_collection::val_str(String *str) ...@@ -358,6 +354,7 @@ String *Item_func_spatial_collection::val_str(String *str)
String arg_value; String arg_value;
uint i; uint i;
str->set_charset(&my_charset_bin);
str->length(0); str->length(0);
if (str->reserve(1 + 4 + 4, 512)) if (str->reserve(1 + 4 + 4, 512))
goto err; goto err;
......
...@@ -23,24 +23,33 @@ ...@@ -23,24 +23,33 @@
#pragma interface /* gcc class implementation */ #pragma interface /* gcc class implementation */
#endif #endif
class Item_func_geometry_from_text: public Item_str_func class Item_geometry_func: public Item_str_func
{ {
public: public:
Item_func_geometry_from_text(Item *a) :Item_str_func(a) {} Item_geometry_func() :Item_str_func() {}
Item_func_geometry_from_text(Item *a, Item *srid) :Item_str_func(a, srid) {} Item_geometry_func(Item *a) :Item_str_func(a) {}
Item_geometry_func(Item *a,Item *b) :Item_str_func(a,b) {}
Item_geometry_func(Item *a,Item *b,Item *c) :Item_str_func(a,b,c) {}
Item_geometry_func(List<Item> &list) :Item_str_func(list) {}
void fix_length_and_dec();
};
class Item_func_geometry_from_text: public Item_geometry_func
{
public:
Item_func_geometry_from_text(Item *a) :Item_geometry_func(a) {}
Item_func_geometry_from_text(Item *a, Item *srid) :Item_geometry_func(a, srid) {}
const char *func_name() const { return "geometryfromtext"; } const char *func_name() const { return "geometryfromtext"; }
String *val_str(String *); String *val_str(String *);
void fix_length_and_dec();
}; };
class Item_func_geometry_from_wkb: public Item_str_func class Item_func_geometry_from_wkb: public Item_geometry_func
{ {
public: public:
Item_func_geometry_from_wkb(Item *a): Item_str_func(a) {} Item_func_geometry_from_wkb(Item *a): Item_geometry_func(a) {}
Item_func_geometry_from_wkb(Item *a, Item *srid): Item_str_func(a, srid) {} Item_func_geometry_from_wkb(Item *a, Item *srid): Item_geometry_func(a, srid) {}
const char *func_name() const { return "geometryfromwkb"; } const char *func_name() const { return "geometryfromwkb"; }
String *val_str(String *); String *val_str(String *);
void fix_length_and_dec();
}; };
class Item_func_as_wkt: public Item_str_func class Item_func_as_wkt: public Item_str_func
...@@ -52,13 +61,12 @@ class Item_func_as_wkt: public Item_str_func ...@@ -52,13 +61,12 @@ class Item_func_as_wkt: public Item_str_func
void fix_length_and_dec(); void fix_length_and_dec();
}; };
class Item_func_as_wkb: public Item_str_func class Item_func_as_wkb: public Item_geometry_func
{ {
public: public:
Item_func_as_wkb(Item *a): Item_str_func(a) {} Item_func_as_wkb(Item *a): Item_geometry_func(a) {}
const char *func_name() const { return "aswkb"; } const char *func_name() const { return "aswkb"; }
String *val_str(String *); String *val_str(String *);
void fix_length_and_dec();
}; };
class Item_func_geometry_type: public Item_str_func class Item_func_geometry_type: public Item_str_func
...@@ -73,40 +81,37 @@ class Item_func_geometry_type: public Item_str_func ...@@ -73,40 +81,37 @@ class Item_func_geometry_type: public Item_str_func
}; };
}; };
class Item_func_centroid: public Item_str_func class Item_func_centroid: public Item_geometry_func
{ {
public: public:
Item_func_centroid(Item *a): Item_str_func(a) {} Item_func_centroid(Item *a): Item_geometry_func(a) {}
const char *func_name() const { return "centroid"; } const char *func_name() const { return "centroid"; }
String *val_str(String *); String *val_str(String *);
void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
}; };
class Item_func_envelope: public Item_str_func class Item_func_envelope: public Item_geometry_func
{ {
public: public:
Item_func_envelope(Item *a): Item_str_func(a) {} Item_func_envelope(Item *a): Item_geometry_func(a) {}
const char *func_name() const { return "envelope"; } const char *func_name() const { return "envelope"; }
String *val_str(String *); String *val_str(String *);
void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
}; };
class Item_func_point: public Item_str_func class Item_func_point: public Item_geometry_func
{ {
public: public:
Item_func_point(Item *a, Item *b): Item_str_func(a, b) {} Item_func_point(Item *a, Item *b): Item_geometry_func(a, b) {}
Item_func_point(Item *a, Item *b, Item *srid): Item_str_func(a, b, srid) {} Item_func_point(Item *a, Item *b, Item *srid): Item_geometry_func(a, b, srid) {}
const char *func_name() const { return "point"; } const char *func_name() const { return "point"; }
String *val_str(String *); String *val_str(String *);
void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
}; };
class Item_func_spatial_decomp: public Item_str_func class Item_func_spatial_decomp: public Item_geometry_func
{ {
enum Functype decomp_func; enum Functype decomp_func;
public: public:
Item_func_spatial_decomp(Item *a, Item_func::Functype ft) : Item_func_spatial_decomp(Item *a, Item_func::Functype ft) :
Item_str_func(a) { decomp_func = ft; } Item_geometry_func(a) { decomp_func = ft; }
const char *func_name() const const char *func_name() const
{ {
switch (decomp_func) switch (decomp_func)
...@@ -123,15 +128,14 @@ class Item_func_spatial_decomp: public Item_str_func ...@@ -123,15 +128,14 @@ class Item_func_spatial_decomp: public Item_str_func
} }
} }
String *val_str(String *); String *val_str(String *);
void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
}; };
class Item_func_spatial_decomp_n: public Item_str_func class Item_func_spatial_decomp_n: public Item_geometry_func
{ {
enum Functype decomp_func_n; enum Functype decomp_func_n;
public: public:
Item_func_spatial_decomp_n(Item *a, Item *b, Item_func::Functype ft): Item_func_spatial_decomp_n(Item *a, Item *b, Item_func::Functype ft):
Item_str_func(a, b) { decomp_func_n = ft; } Item_geometry_func(a, b) { decomp_func_n = ft; }
const char *func_name() const const char *func_name() const
{ {
switch (decomp_func_n) switch (decomp_func_n)
...@@ -148,10 +152,9 @@ class Item_func_spatial_decomp_n: public Item_str_func ...@@ -148,10 +152,9 @@ class Item_func_spatial_decomp_n: public Item_str_func
} }
} }
String *val_str(String *); String *val_str(String *);
void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
}; };
class Item_func_spatial_collection: public Item_str_func class Item_func_spatial_collection: public Item_geometry_func
{ {
String tmp_value; String tmp_value;
enum Geometry::wkbType coll_type; enum Geometry::wkbType coll_type;
...@@ -159,13 +162,12 @@ class Item_func_spatial_collection: public Item_str_func ...@@ -159,13 +162,12 @@ class Item_func_spatial_collection: public Item_str_func
public: public:
Item_func_spatial_collection( Item_func_spatial_collection(
List<Item> &list, enum Geometry::wkbType ct, enum Geometry::wkbType it): List<Item> &list, enum Geometry::wkbType ct, enum Geometry::wkbType it):
Item_str_func(list) Item_geometry_func(list)
{ {
coll_type=ct; coll_type=ct;
item_type=it; item_type=it;
} }
String *val_str(String *); String *val_str(String *);
void fix_length_and_dec(){max_length=MAX_BLOB_WIDTH;}
const char *func_name() const { return "multipoint"; } const char *func_name() const { return "multipoint"; }
}; };
......
...@@ -1091,7 +1091,15 @@ Default database: '%s'. Query: '%s'", ...@@ -1091,7 +1091,15 @@ Default database: '%s'. Query: '%s'",
VOID(pthread_mutex_unlock(&LOCK_thread_count)); VOID(pthread_mutex_unlock(&LOCK_thread_count));
close_thread_tables(thd); close_thread_tables(thd);
free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC)); free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC));
return (thd->query_error ? thd->query_error : Log_event::exec_event(rli)); /*
If there was an error we stop. Otherwise we increment positions. Note that
we will not increment group* positions if we are just after a SET
ONE_SHOT, because SET ONE_SHOT should not be separated from its following
updating query.
*/
return (thd->query_error ? thd->query_error :
(thd->one_shot_set ? (rli->inc_event_relay_log_pos(get_event_len()),0) :
Log_event::exec_event(rli)));
} }
#endif #endif
......
...@@ -2554,7 +2554,8 @@ static bool null_part_in_key(KEY_PART *key_part, const char *key, uint length) ...@@ -2554,7 +2554,8 @@ static bool null_part_in_key(KEY_PART *key_part, const char *key, uint length)
QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref) QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref)
{ {
QUICK_SELECT *quick=new QUICK_SELECT(thd, table, ref->key, 1); MEM_ROOT *old_root= my_pthread_getspecific_ptr(MEM_ROOT*, THR_MALLOC);
QUICK_SELECT *quick= new QUICK_SELECT(thd, table, ref->key);
KEY *key_info = &table->key_info[ref->key]; KEY *key_info = &table->key_info[ref->key];
KEY_PART *key_part; KEY_PART *key_part;
QUICK_RANGE *range; QUICK_RANGE *range;
...@@ -2566,7 +2567,7 @@ QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref) ...@@ -2566,7 +2567,7 @@ QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref)
{ {
if (thd->is_fatal_error) if (thd->is_fatal_error)
goto err; // out of memory goto err; // out of memory
return quick; // empty range goto ok; // empty range
} }
if (!(range= new QUICK_RANGE())) if (!(range= new QUICK_RANGE()))
...@@ -2613,9 +2614,12 @@ QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref) ...@@ -2613,9 +2614,12 @@ QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref)
goto err; goto err;
} }
ok:
my_pthread_setspecific_ptr(THR_MALLOC, old_root);
return quick; return quick;
err: err:
my_pthread_setspecific_ptr(THR_MALLOC, old_root);
delete quick; delete quick;
return 0; return 0;
} }
......
...@@ -221,7 +221,6 @@ THD::THD() ...@@ -221,7 +221,6 @@ THD::THD()
init(); init();
/* Initialize sub structures */ /* Initialize sub structures */
clear_alloc_root(&transaction.mem_root);
init_alloc_root(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE); init_alloc_root(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
user_connect=(USER_CONN *)0; user_connect=(USER_CONN *)0;
hash_init(&user_vars, &my_charset_bin, USER_VARS_HASH_SIZE, 0, 0, hash_init(&user_vars, &my_charset_bin, USER_VARS_HASH_SIZE, 0, 0,
...@@ -258,6 +257,7 @@ THD::THD() ...@@ -258,6 +257,7 @@ THD::THD()
transaction.trans_log.end_of_file= max_binlog_cache_size; transaction.trans_log.end_of_file= max_binlog_cache_size;
} }
#endif #endif
init_alloc_root(&transaction.mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
{ {
ulong tmp=sql_rnd_with_mutex(); ulong tmp=sql_rnd_with_mutex();
randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::query_id); randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::query_id);
...@@ -303,12 +303,12 @@ void THD::init(void) ...@@ -303,12 +303,12 @@ void THD::init(void)
void THD::init_for_queries() void THD::init_for_queries()
{ {
ha_enable_transaction(this,TRUE); ha_enable_transaction(this,TRUE);
init_sql_alloc(&mem_root,
variables.query_alloc_block_size, reset_root_defaults(&mem_root, variables.query_alloc_block_size,
variables.query_prealloc_size); variables.query_prealloc_size);
init_sql_alloc(&transaction.mem_root, reset_root_defaults(&transaction.mem_root,
variables.trans_alloc_block_size, variables.trans_alloc_block_size,
variables.trans_prealloc_size); variables.trans_prealloc_size);
} }
...@@ -328,6 +328,7 @@ void THD::change_user(void) ...@@ -328,6 +328,7 @@ void THD::change_user(void)
cleanup(); cleanup();
cleanup_done= 0; cleanup_done= 0;
init(); init();
stmt_map.reset();
hash_init(&user_vars, &my_charset_bin, USER_VARS_HASH_SIZE, 0, 0, hash_init(&user_vars, &my_charset_bin, USER_VARS_HASH_SIZE, 0, 0,
(hash_get_key) get_var_key, (hash_get_key) get_var_key,
(hash_free_key) free_user_var, 0); (hash_free_key) free_user_var, 0);
...@@ -1331,6 +1332,17 @@ void select_dumpvar::cleanup() ...@@ -1331,6 +1332,17 @@ void select_dumpvar::cleanup()
} }
/*
Create arena for already constructed THD.
SYNOPSYS
Item_arena()
thd - thread for which arena is created
DESCRIPTION
Create arena for already existing THD using its variables as parameters
for memory root initialization.
*/
Item_arena::Item_arena(THD* thd) Item_arena::Item_arena(THD* thd)
:free_list(0), :free_list(0),
state(INITIALIZED) state(INITIALIZED)
...@@ -1341,24 +1353,31 @@ Item_arena::Item_arena(THD* thd) ...@@ -1341,24 +1353,31 @@ Item_arena::Item_arena(THD* thd)
} }
/* This constructor is called when Item_arena is a subobject of THD */ /*
Create arena and optionally initialize memory root.
Item_arena::Item_arena() SYNOPSYS
:free_list(0), Item_arena()
state(CONVENTIONAL_EXECUTION) init_mem_root - whenever we need to initialize memory root
{
clear_alloc_root(&mem_root);
}
DESCRIPTION
Create arena and optionally initialize memory root with minimal
possible parameters.
NOTE
We use this constructor when arena is part of THD, but reinitialize
its memory root in THD::init_for_queries() before execution of real
statements.
*/
Item_arena::Item_arena(bool init_mem_root) Item_arena::Item_arena(bool init_mem_root)
:free_list(0), :free_list(0),
state(INITIALIZED) state(CONVENTIONAL_EXECUTION)
{ {
if (init_mem_root) if (init_mem_root)
clear_alloc_root(&mem_root); init_alloc_root(&mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
} }
Item_arena::Type Item_arena::type() const Item_arena::Type Item_arena::type() const
{ {
DBUG_ASSERT("Item_arena::type()" == "abstract"); DBUG_ASSERT("Item_arena::type()" == "abstract");
...@@ -1366,10 +1385,6 @@ Item_arena::Type Item_arena::type() const ...@@ -1366,10 +1385,6 @@ Item_arena::Type Item_arena::type() const
} }
Item_arena::~Item_arena()
{}
/* /*
Statement functions Statement functions
*/ */
...@@ -1393,7 +1408,8 @@ Statement::Statement(THD *thd) ...@@ -1393,7 +1408,8 @@ Statement::Statement(THD *thd)
*/ */
Statement::Statement() Statement::Statement()
:id(0), :Item_arena((bool)TRUE),
id(0),
set_query_id(1), set_query_id(1),
allow_sum_func(0), /* initialized later */ allow_sum_func(0), /* initialized later */
lex(&main_lex), lex(&main_lex),
...@@ -1461,8 +1477,16 @@ void Item_arena::restore_backup_item_arena(Item_arena *set, Item_arena *backup) ...@@ -1461,8 +1477,16 @@ 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);
// reset backup mem_root to avoid its freeing #ifdef NOT_NEEDED_NOW
init_alloc_root(&backup->mem_root, 0, 0); /*
Reset backup mem_root to avoid its freeing.
Since Item_arena's mem_root is freed only when it is part of Statement
we need this only if we use some Statement's arena as backup storage.
But we do this only with THD::stmt_backup and this Statement is specially
handled in this respect. So this code is not really needed now.
*/
clear_alloc_root(&backup->mem_root);
#endif
} }
void Item_arena::set_item_arena(Item_arena *set) void Item_arena::set_item_arena(Item_arena *set)
......
...@@ -441,11 +441,23 @@ class Item_arena ...@@ -441,11 +441,23 @@ class Item_arena
STATEMENT, PREPARED_STATEMENT, STORED_PROCEDURE STATEMENT, PREPARED_STATEMENT, STORED_PROCEDURE
}; };
/*
This constructor is used only when Item_arena is created as
backup storage for another instance of Item_arena.
*/
Item_arena() {};
/*
Create arena for already constructed THD using its variables as
parameters for memory root initialization.
*/
Item_arena(THD *thd); Item_arena(THD *thd);
Item_arena(); /*
Create arena and optionally init memory root with minimal values.
Particularly used if Item_arena is part of Statement.
*/
Item_arena(bool init_mem_root); Item_arena(bool init_mem_root);
virtual Type type() const; virtual Type type() const;
virtual ~Item_arena(); virtual ~Item_arena() {};
inline bool is_stmt_prepare() const { return (int)state < (int)PREPARED; } inline bool is_stmt_prepare() const { return (int)state < (int)PREPARED; }
inline bool is_first_stmt_execute() const { return state == PREPARED; } inline bool is_first_stmt_execute() const { return state == PREPARED; }
...@@ -566,7 +578,7 @@ class Statement: public Item_arena ...@@ -566,7 +578,7 @@ class Statement: public Item_arena
assignment in Statement::Statement) assignment in Statement::Statement)
Non-empty statement names are unique too: attempt to insert a new statement Non-empty statement names are unique too: attempt to insert a new statement
with duplicate name causes older statement to be deleted with duplicate name causes older statement to be deleted
Statements are auto-deleted when they are removed from the map and when the Statements are auto-deleted when they are removed from the map and when the
map is deleted. map is deleted.
*/ */
...@@ -575,7 +587,7 @@ class Statement_map ...@@ -575,7 +587,7 @@ class Statement_map
{ {
public: public:
Statement_map(); Statement_map();
int insert(Statement *statement); int insert(Statement *statement);
Statement *find_by_name(LEX_STRING *name) Statement *find_by_name(LEX_STRING *name)
...@@ -608,11 +620,18 @@ class Statement_map ...@@ -608,11 +620,18 @@ class Statement_map
} }
hash_delete(&st_hash, (byte *) statement); hash_delete(&st_hash, (byte *) statement);
} }
/* Erase all statements (calls Statement destructor) */
void reset()
{
hash_reset(&names_hash);
hash_reset(&st_hash);
last_found_statement= 0;
}
~Statement_map() ~Statement_map()
{ {
hash_free(&st_hash);
hash_free(&names_hash); hash_free(&names_hash);
hash_free(&st_hash);
} }
private: private:
HASH st_hash; HASH st_hash;
......
...@@ -1265,6 +1265,8 @@ store_create_info(THD *thd, TABLE *table, String *packet) ...@@ -1265,6 +1265,8 @@ store_create_info(THD *thd, TABLE *table, String *packet)
// check for surprises from the previous call to Field::sql_type() // check for surprises from the previous call to Field::sql_type()
if (type.ptr() != tmp) if (type.ptr() != tmp)
type.set(tmp, sizeof(tmp), system_charset_info); type.set(tmp, sizeof(tmp), system_charset_info);
else
type.set_charset(system_charset_info);
field->sql_type(type); field->sql_type(type);
packet->append(type.ptr(), type.length(), system_charset_info); packet->append(type.ptr(), type.length(), system_charset_info);
......
...@@ -10251,7 +10251,7 @@ static void test_bug5194() ...@@ -10251,7 +10251,7 @@ static void test_bug5194()
/* Number of columns per row */ /* Number of columns per row */
const int COLUMN_COUNT= sizeof(float_array)/sizeof(*float_array); const int COLUMN_COUNT= sizeof(float_array)/sizeof(*float_array);
/* Number of rows per bulk insert to start with */ /* Number of rows per bulk insert to start with */
const int MIN_ROWS_PER_INSERT= 260; const int MIN_ROWS_PER_INSERT= 262;
/* Max number of rows per bulk insert to end with */ /* Max number of rows per bulk insert to end with */
const int MAX_ROWS_PER_INSERT= 300; const int MAX_ROWS_PER_INSERT= 300;
const int MAX_PARAM_COUNT= COLUMN_COUNT*MAX_ROWS_PER_INSERT; const int MAX_PARAM_COUNT= COLUMN_COUNT*MAX_ROWS_PER_INSERT;
...@@ -10391,6 +10391,34 @@ static void test_bug5194() ...@@ -10391,6 +10391,34 @@ static void test_bug5194()
} }
static void test_bug5315()
{
MYSQL_STMT *stmt;
const char *stmt_text;
int rc;
myheader("test_bug5315");
stmt_text= "SELECT 1";
stmt= mysql_stmt_init(mysql);
rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
DBUG_ASSERT(rc == 0);
mysql_change_user(mysql, opt_user, opt_password, current_db);
rc= mysql_stmt_execute(stmt);
DBUG_ASSERT(rc != 0);
if (rc)
printf("Got error (as expected):\n%s", mysql_stmt_error(stmt));
/* check that connection is OK */
mysql_stmt_close(stmt);
stmt= mysql_stmt_init(mysql);
rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
DBUG_ASSERT(rc == 0);
rc= mysql_stmt_execute(stmt);
DBUG_ASSERT(rc == 0);
mysql_stmt_close(stmt);
}
/* /*
Read and parse arguments and MySQL options from my.cnf Read and parse arguments and MySQL options from my.cnf
*/ */
...@@ -10694,6 +10722,8 @@ int main(int argc, char **argv) ...@@ -10694,6 +10722,8 @@ int main(int argc, char **argv)
test_bug5399(); /* check that statement id uniquely identifies test_bug5399(); /* check that statement id uniquely identifies
statement */ statement */
test_bug5194(); /* bulk inserts in prepared mode */ test_bug5194(); /* bulk inserts in prepared mode */
test_bug5315(); /* check that mysql_change_user closes all
prepared statements */
/* /*
XXX: PLEASE RUN THIS PROGRAM UNDER VALGRIND AND VERIFY THAT YOUR TEST XXX: PLEASE RUN THIS PROGRAM UNDER VALGRIND AND VERIFY THAT YOUR TEST
DOESN'T CONTAIN WARNINGS/ERRORS BEFORE YOU PUSH. DOESN'T CONTAIN WARNINGS/ERRORS BEFORE YOU PUSH.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment