mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Fixed a possible memory leak on MacOSX when using the shared libmysql.so library (Bug #2061)
mysql_server_init() now returns error code if something went wrong (Bug #2062) Don't use my_fopen() when reading symlink information as this may cause problems when a lot of files are opened. Free thread keys with pthread_key_delete() instead of relying on automatic free. (Bug #2062) Fixed bug in UNION statement with alias '*'. (Bug #1249) Fixed a bug in DELETE ... ORDER BY ... LIMIT where the rows where not deleted in the proper order. (Bug #1024). FOUND_ROWS() could return incorrect number of rows after a query with an impossible WHERE condition. HOW DATABASES doesn't anymore show .sym files (on windows) that doesn't point to a valid directory. (Bug #1385)
This commit is contained in:
@ -151,6 +151,10 @@ typedef uint rf_SetTimer;
|
||||
#define USE_MB_IDENT 1
|
||||
#define USE_STRCOLL 1
|
||||
|
||||
/* All windows servers should support .sym files */
|
||||
#undef USE_SYMDIR
|
||||
#define USE_SYMDIR
|
||||
|
||||
/* If LOAD DATA LOCAL INFILE should be enabled by default */
|
||||
#define ENABLED_LOCAL_INFILE 1
|
||||
|
||||
|
@ -115,6 +115,7 @@ void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/
|
||||
#undef SAFE_MUTEX /* This will cause conflicts */
|
||||
#define pthread_key(T,V) DWORD V
|
||||
#define pthread_key_create(A,B) ((*A=TlsAlloc())==0xFFFFFFFF)
|
||||
#define pthread_key_delete(A) TlsFree(A)
|
||||
#define pthread_getspecific(A) (TlsGetValue(A))
|
||||
#define my_pthread_getspecific(T,A) ((T) TlsGetValue(A))
|
||||
#define my_pthread_getspecific_ptr(T,V) ((T) TlsGetValue(V))
|
||||
@ -123,6 +124,7 @@ void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/
|
||||
#else
|
||||
#define pthread_key(T,V) __declspec(thread) T V
|
||||
#define pthread_key_create(A,B) pthread_dummy(0)
|
||||
#define pthread_key_delete(A) pthread_dummy(0)
|
||||
#define pthread_getspecific(A) (&(A))
|
||||
#define my_pthread_getspecific(T,A) (&(A))
|
||||
#define my_pthread_getspecific_ptr(T,V) (V)
|
||||
@ -178,6 +180,7 @@ extern int pthread_mutex_destroy (pthread_mutex_t *);
|
||||
typedef int pthread_attr_t; /* Needed by Unixware 7.0.0 */
|
||||
|
||||
#define pthread_key_create(A,B) thr_keycreate((A),(B))
|
||||
#define pthread_key_delete(A) thr_keydelete(A)
|
||||
|
||||
#define pthread_handler_decl(A,B) void *A(void *B)
|
||||
#define pthread_key(T,V) pthread_key_t V
|
||||
|
@ -577,7 +577,7 @@ extern int my_snprintf(char* to, size_t n, const char* fmt, ...);
|
||||
extern int my_message(uint my_err, const char *str,myf MyFlags);
|
||||
extern int my_message_no_curses(uint my_err, const char *str,myf MyFlags);
|
||||
extern int my_message_curses(uint my_err, const char *str,myf MyFlags);
|
||||
extern void my_init(void);
|
||||
extern my_bool my_init(void);
|
||||
extern void my_end(int infoflag);
|
||||
extern int my_redel(const char *from, const char *to, int MyFlags);
|
||||
extern int my_copystat(const char *from, const char *to, int MyFlags);
|
||||
|
@ -426,7 +426,7 @@ int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB);
|
||||
int simple_command(MYSQL *mysql,enum enum_server_command command,
|
||||
const char *arg, unsigned long length, my_bool skipp_check);
|
||||
unsigned long net_safe_read(MYSQL* mysql);
|
||||
void mysql_once_init(void);
|
||||
int mysql_once_init(void);
|
||||
|
||||
extern my_bool server_inited;
|
||||
|
||||
|
@ -241,7 +241,7 @@ void hash_password(unsigned long *result, const char *password);
|
||||
|
||||
/* Some other useful functions */
|
||||
|
||||
void my_init(void);
|
||||
my_bool my_init(void);
|
||||
int load_defaults(const char *conf_file, const char **groups,
|
||||
int *argc, char ***argv);
|
||||
my_bool my_thread_init(void);
|
||||
|
@ -102,8 +102,7 @@ int STDCALL mysql_server_init(int argc __attribute__((unused)),
|
||||
char **argv __attribute__((unused)),
|
||||
char **groups __attribute__((unused)))
|
||||
{
|
||||
mysql_once_init();
|
||||
return 0;
|
||||
return (int) mysql_once_init();
|
||||
}
|
||||
|
||||
void STDCALL mysql_server_end()
|
||||
@ -1436,7 +1435,8 @@ STDCALL mysql_rpl_query_type(const char* q, int len)
|
||||
MYSQL * STDCALL
|
||||
mysql_init(MYSQL *mysql)
|
||||
{
|
||||
mysql_once_init();
|
||||
if (mysql_once_init())
|
||||
return 0;
|
||||
if (!mysql)
|
||||
{
|
||||
if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL))))
|
||||
@ -1476,15 +1476,20 @@ mysql_init(MYSQL *mysql)
|
||||
This function is called by mysql_init() and indirectly called
|
||||
by mysql_query(), so one should never have to call this from an
|
||||
outside program.
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
1 could not initialize environment (out of memory or thread keys)
|
||||
*/
|
||||
|
||||
void mysql_once_init(void)
|
||||
int mysql_once_init(void)
|
||||
{
|
||||
if (!mysql_client_init)
|
||||
{
|
||||
mysql_client_init=1;
|
||||
org_my_init_done=my_init_done;
|
||||
my_init(); /* Will init threads */
|
||||
if (my_init()) /* Will init threads */
|
||||
return 1;
|
||||
init_client_errs();
|
||||
if (!mysql_port)
|
||||
{
|
||||
@ -1518,10 +1523,15 @@ void mysql_once_init(void)
|
||||
}
|
||||
#ifdef THREAD
|
||||
else
|
||||
my_thread_init(); /* Init if new thread */
|
||||
{
|
||||
if (my_thread_init()) /* Init if new thread */
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
Fill in SSL part of MYSQL structure and set 'use_ssl' flag.
|
||||
NB! Errors are not reported until you do mysql_real_connect.
|
||||
|
@ -36,9 +36,7 @@ a b
|
||||
3 4
|
||||
drop table t1;
|
||||
create table t1 (i int);
|
||||
insert into t1 (i) values(1);
|
||||
insert into t1 (i) values(1);
|
||||
insert into t1 (i) values(1);
|
||||
insert into t1 (i) values(1),(1),(1);
|
||||
delete from t1 limit 1;
|
||||
update t1 set i=2 limit 1;
|
||||
delete from t1 limit 0;
|
||||
@ -50,3 +48,22 @@ i
|
||||
drop table t1;
|
||||
select 0 limit 0;
|
||||
0
|
||||
CREATE TABLE t1(id int auto_increment primary key, id2 int, index(id2));
|
||||
INSERT INTO t1 (id2) values (0),(0),(0);
|
||||
DELETE FROM t1 WHERE id=1;
|
||||
INSERT INTO t1 SET id2=0;
|
||||
SELECT * FROM t1;
|
||||
id id2
|
||||
4 0
|
||||
2 0
|
||||
3 0
|
||||
DELETE FROM t1 WHERE id2 = 0 ORDER BY id LIMIT 1;
|
||||
SELECT * FROM t1;
|
||||
id id2
|
||||
4 0
|
||||
3 0
|
||||
DELETE FROM t1 WHERE id2 = 0 ORDER BY id desc LIMIT 1;
|
||||
SELECT * FROM t1;
|
||||
id id2
|
||||
3 0
|
||||
DROP TABLE t1;
|
||||
|
@ -169,3 +169,22 @@ SELECT FOUND_ROWS();
|
||||
FOUND_ROWS()
|
||||
2
|
||||
drop table t1;
|
||||
create table t1 (id int, primary key (id));
|
||||
insert into t1 values (1), (2), (3), (4), (5);
|
||||
select SQL_CALC_FOUND_ROWS * from t1 where id > 3 limit 0, 1;
|
||||
id
|
||||
4
|
||||
select FOUND_ROWS();
|
||||
FOUND_ROWS()
|
||||
2
|
||||
select SQL_CALC_FOUND_ROWS * from t1 where id > 3 AND 1=2 limit 0, 1;
|
||||
id
|
||||
select FOUND_ROWS();
|
||||
FOUND_ROWS()
|
||||
0
|
||||
select SQL_CALC_FOUND_ROWS * from t1 where id > 6 limit 0, 1;
|
||||
id
|
||||
select FOUND_ROWS();
|
||||
FOUND_ROWS()
|
||||
0
|
||||
drop table t1;
|
||||
|
@ -3,7 +3,7 @@ CREATE TABLE t1 (a int not null, b char (10) not null);
|
||||
insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c');
|
||||
CREATE TABLE t2 (a int not null, b char (10) not null);
|
||||
insert into t2 values (3,'c'),(4,'d'),(5,'f'),(6,'e');
|
||||
select a,b from t1 union select a,b from t2;
|
||||
select a,b from t1 union distinct select a,b from t2;
|
||||
a b
|
||||
1 a
|
||||
2 b
|
||||
@ -423,3 +423,7 @@ create temporary table t1 select a from t1 union select a from t2;
|
||||
create table t1 select a from t1 union select a from t2;
|
||||
INSERT TABLE 't1' isn't allowed in FROM table list
|
||||
drop table t1,t2;
|
||||
select length(version()) > 1 as `*` UNION select 2;
|
||||
*
|
||||
1
|
||||
2
|
||||
|
@ -19,9 +19,7 @@ select * from t1;
|
||||
drop table t1;
|
||||
|
||||
create table t1 (i int);
|
||||
insert into t1 (i) values(1);
|
||||
insert into t1 (i) values(1);
|
||||
insert into t1 (i) values(1);
|
||||
insert into t1 (i) values(1),(1),(1);
|
||||
delete from t1 limit 1;
|
||||
update t1 set i=2 limit 1;
|
||||
delete from t1 limit 0;
|
||||
@ -29,4 +27,22 @@ update t1 set i=3 limit 0;
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
|
||||
# LIMIT 0
|
||||
|
||||
select 0 limit 0;
|
||||
|
||||
#
|
||||
# Test with DELETE, ORDER BY and limit (bug #1024)
|
||||
#
|
||||
|
||||
CREATE TABLE t1(id int auto_increment primary key, id2 int, index(id2));
|
||||
INSERT INTO t1 (id2) values (0),(0),(0);
|
||||
DELETE FROM t1 WHERE id=1;
|
||||
INSERT INTO t1 SET id2=0;
|
||||
SELECT * FROM t1;
|
||||
DELETE FROM t1 WHERE id2 = 0 ORDER BY id LIMIT 1;
|
||||
# should have deleted WHERE id=2
|
||||
SELECT * FROM t1;
|
||||
DELETE FROM t1 WHERE id2 = 0 ORDER BY id desc LIMIT 1;
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
@ -85,3 +85,17 @@ INSERT INTO t1 (titre,maxnumrep) VALUES
|
||||
SELECT SQL_CALC_FOUND_ROWS titre,numeropost,maxnumrep FROM t1 WHERE numeropost IN (1,2) ORDER BY maxnumrep DESC LIMIT 0, 1;
|
||||
SELECT FOUND_ROWS();
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Test problem with impossible WHERE (Bug #1468)
|
||||
#
|
||||
|
||||
create table t1 (id int, primary key (id));
|
||||
insert into t1 values (1), (2), (3), (4), (5);
|
||||
select SQL_CALC_FOUND_ROWS * from t1 where id > 3 limit 0, 1;
|
||||
select FOUND_ROWS();
|
||||
select SQL_CALC_FOUND_ROWS * from t1 where id > 3 AND 1=2 limit 0, 1;
|
||||
select FOUND_ROWS();
|
||||
select SQL_CALC_FOUND_ROWS * from t1 where id > 6 limit 0, 1;
|
||||
select FOUND_ROWS();
|
||||
drop table t1;
|
||||
|
@ -8,7 +8,7 @@ insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c');
|
||||
CREATE TABLE t2 (a int not null, b char (10) not null);
|
||||
insert into t2 values (3,'c'),(4,'d'),(5,'f'),(6,'e');
|
||||
|
||||
select a,b from t1 union select a,b from t2;
|
||||
select a,b from t1 union distinct select a,b from t2;
|
||||
select a,b from t1 union all select a,b from t2;
|
||||
select a,b from t1 union all select a,b from t2 order by b;
|
||||
select a,b from t1 union all select a,b from t2 union select 7,'g';
|
||||
@ -227,3 +227,10 @@ create temporary table t1 select a from t1 union select a from t2;
|
||||
--error 1093
|
||||
create table t1 select a from t1 union select a from t2;
|
||||
drop table t1,t2;
|
||||
|
||||
#
|
||||
# Problem with alias '*' (BUG #1249)
|
||||
#
|
||||
|
||||
select length(version()) > 1 as `*` UNION select 2;
|
||||
|
||||
|
@ -210,13 +210,13 @@ uint cleanup_dirname(register my_string to, const char *from)
|
||||
} /* cleanup_dirname */
|
||||
|
||||
|
||||
/*
|
||||
On system where you don't have symbolic links, the following
|
||||
code will allow you to create a file:
|
||||
directory-name.lnk that should contain the real path
|
||||
to the directory. This will be used if the directory name
|
||||
doesn't exists
|
||||
*/
|
||||
/*
|
||||
On system where you don't have symbolic links, the following
|
||||
code will allow you to create a file:
|
||||
directory-name.sym that should contain the real path
|
||||
to the directory. This will be used if the directory name
|
||||
doesn't exists
|
||||
*/
|
||||
|
||||
|
||||
my_bool my_use_symdir=0; /* Set this if you want to use symdirs */
|
||||
@ -228,16 +228,17 @@ void symdirget(char *dir)
|
||||
char *pos=strend(dir);
|
||||
if (dir[0] && pos[-1] != FN_DEVCHAR && access(dir, F_OK))
|
||||
{
|
||||
FILE *fp;
|
||||
File file;
|
||||
uint length;
|
||||
char temp= *(--pos); /* May be "/" or "\" */
|
||||
strmov(pos,".sym");
|
||||
fp = my_fopen(dir, O_RDONLY,MYF(0));
|
||||
file= my_open(dir, O_RDONLY, MYF(0));
|
||||
*pos++=temp; *pos=0; /* Restore old filename */
|
||||
if (fp)
|
||||
if (file >= 0)
|
||||
{
|
||||
if (fgets(buff, sizeof(buff)-1, fp))
|
||||
if ((length= my_read(file, buff, sizeof(buff), MYF(0))) > 0)
|
||||
{
|
||||
for (pos=strend(buff);
|
||||
for (pos= buff + length ;
|
||||
pos > buff && (iscntrl(pos[-1]) || isspace(pos[-1])) ;
|
||||
pos --);
|
||||
|
||||
@ -247,7 +248,7 @@ void symdirget(char *dir)
|
||||
|
||||
strmake(dir,buff, (uint) (pos-buff));
|
||||
}
|
||||
my_fclose(fp,MYF(0));
|
||||
my_close(file, MYF(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -62,13 +62,22 @@ static ulong atoi_octal(const char *str)
|
||||
}
|
||||
|
||||
|
||||
/* Init my_sys functions and my_sys variabels */
|
||||
/*
|
||||
Init my_sys functions and my_sys variabels
|
||||
|
||||
void my_init(void)
|
||||
SYNOPSIS
|
||||
my_init()
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
1 Couldn't initialize environment
|
||||
*/
|
||||
|
||||
my_bool my_init(void)
|
||||
{
|
||||
my_string str;
|
||||
if (my_init_done)
|
||||
return;
|
||||
return 0;
|
||||
my_init_done=1;
|
||||
#if defined(THREAD) && defined(SAFE_MUTEX)
|
||||
safe_mutex_global_init(); /* Must be called early */
|
||||
@ -78,7 +87,8 @@ void my_init(void)
|
||||
#if defined(HAVE_PTHREAD_INIT)
|
||||
pthread_init(); /* Must be called before DBUG_ENTER */
|
||||
#endif
|
||||
my_thread_global_init();
|
||||
if (my_thread_global_init())
|
||||
return 1;
|
||||
#if !defined( __WIN__) && !defined(OS2) && !defined(__NETWARE__)
|
||||
sigfillset(&my_signals); /* signals blocked by mf_brkhant */
|
||||
#endif
|
||||
@ -110,7 +120,7 @@ void my_init(void)
|
||||
#ifdef __WIN__
|
||||
win32_init_tcp_ip();
|
||||
#endif
|
||||
DBUG_VOID_RETURN;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
} /* my_init */
|
||||
|
||||
|
@ -602,9 +602,11 @@ MY_STAT *my_stat(const char *path, MY_STAT *stat_area, myf my_flags)
|
||||
if ((m_used= (stat_area == NULL)))
|
||||
if (!(stat_area = (MY_STAT *) my_malloc(sizeof(MY_STAT), my_flags)))
|
||||
goto error;
|
||||
if ( ! stat((my_string) path, (struct stat *) stat_area) )
|
||||
if (! stat((my_string) path, (struct stat *) stat_area) )
|
||||
DBUG_RETURN(stat_area);
|
||||
my_errno=errno;
|
||||
|
||||
DBUG_PRINT("error",("Got errno: %d from stat", errno));
|
||||
my_errno= errno;
|
||||
if (m_used) /* Free if new area */
|
||||
my_free((gptr) stat_area,MYF(0));
|
||||
|
||||
|
@ -44,12 +44,23 @@ pthread_mutexattr_t my_fast_mutexattr;
|
||||
pthread_mutexattr_t my_errchk_mutexattr;
|
||||
#endif
|
||||
|
||||
/*
|
||||
initialize thread environment
|
||||
|
||||
SYNOPSIS
|
||||
my_thread_global_init()
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
1 error (Couldn't create THR_KEY_mysys)
|
||||
*/
|
||||
|
||||
my_bool my_thread_global_init(void)
|
||||
{
|
||||
if (pthread_key_create(&THR_KEY_mysys,free))
|
||||
if (pthread_key_create(&THR_KEY_mysys,0))
|
||||
{
|
||||
fprintf(stderr,"Can't initialize threads: error %d\n",errno);
|
||||
exit(1);
|
||||
return 1;
|
||||
}
|
||||
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
|
||||
pthread_mutexattr_init(&my_fast_mutexattr);
|
||||
@ -79,15 +90,18 @@ my_bool my_thread_global_init(void)
|
||||
#ifndef HAVE_GETHOSTBYNAME_R
|
||||
pthread_mutex_init(&LOCK_gethostbyname_r,MY_MUTEX_INIT_SLOW);
|
||||
#endif
|
||||
return my_thread_init();
|
||||
if (my_thread_init())
|
||||
{
|
||||
my_thread_global_end(); /* Clean up */
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void my_thread_global_end(void)
|
||||
{
|
||||
#if defined(USE_TLS)
|
||||
(void) TlsFree(THR_KEY_mysys);
|
||||
#endif
|
||||
pthread_key_delete(THR_KEY_mysys);
|
||||
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
|
||||
pthread_mutexattr_destroy(&my_fast_mutexattr);
|
||||
#endif
|
||||
|
@ -1868,8 +1868,13 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
|
||||
|
||||
while ((item=it++))
|
||||
{
|
||||
/*
|
||||
Expand * to all fields if this is not the temporary table for an
|
||||
a UNION result
|
||||
*/
|
||||
if (item->type() == Item::FIELD_ITEM &&
|
||||
((Item_field*) item)->field_name[0] == '*')
|
||||
((Item_field*) item)->field_name[0] == '*' &&
|
||||
!((Item_field*) item)->field)
|
||||
{
|
||||
uint elem=fields.elements;
|
||||
if (insert_fields(thd,tables,((Item_field*) item)->db_name,
|
||||
|
@ -117,13 +117,19 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
|
||||
if (setup_order(thd, &tables, fields, all_fields, order) ||
|
||||
!(sortorder=make_unireg_sortorder(order, &length)) ||
|
||||
(table->found_records = filesort(table, sortorder, length,
|
||||
(SQL_SELECT *) 0, 0L, HA_POS_ERROR,
|
||||
select, 0L, HA_POS_ERROR,
|
||||
&examined_rows))
|
||||
== HA_POS_ERROR)
|
||||
{
|
||||
delete select;
|
||||
DBUG_RETURN(-1); // This will force out message
|
||||
DBUG_RETURN(-1); // This will force out message
|
||||
}
|
||||
/*
|
||||
Filesort has already found and selected the rows we want to delete,
|
||||
so we don't need the where clause
|
||||
*/
|
||||
delete select;
|
||||
select= 0;
|
||||
}
|
||||
|
||||
init_read_record(&info,thd,table,select,1,1);
|
||||
|
@ -3273,6 +3273,8 @@ return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables,
|
||||
}
|
||||
result->send_eof(); // Should be safe
|
||||
}
|
||||
/* Update results for FOUND_ROWS */
|
||||
join->thd->limit_found_rows= join->thd->examined_row_count= 0;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
@ -197,7 +197,19 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
|
||||
#ifdef USE_SYMDIR
|
||||
char *ext;
|
||||
if (my_use_symdir && !strcmp(ext=fn_ext(file->name), ".sym"))
|
||||
{
|
||||
/* Only show the sym file if it points to a directory */
|
||||
char buff[FN_REFLEN], *end;
|
||||
MY_STAT status;
|
||||
*ext=0; /* Remove extension */
|
||||
unpack_dirname(buff, file->name);
|
||||
end= strend(buff);
|
||||
if (end != buff && end[-1] == FN_LIBCHAR)
|
||||
end[-1]= 0; // Remove end FN_LIBCHAR
|
||||
if (!my_stat(buff, &status, MYF(0)) ||
|
||||
!MY_S_ISDIR(status.st_mode))
|
||||
continue;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
|
@ -4014,5 +4014,6 @@ optional_order_or_limit:
|
||||
|
||||
union_option:
|
||||
/* empty */ {}
|
||||
| DISTINCT {}
|
||||
| ALL { Lex->union_option=1; }
|
||||
;
|
||||
|
Reference in New Issue
Block a user