Commit 287661e6 authored by unknown's avatar unknown

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)


include/config-win.h:
  Ensure that USE_SYMDIR is set for all windows versions
  (This is set in makefiles, so this is just an extra safety measure)
include/my_pthread.h:
  Fixed a possible memory leak on MacOSX when using the shared libmysql.so library (Bug #2061)
include/my_sys.h:
  my_init() now returns error code if something went wrong
include/mysql.h:
  mysql_once_init() now returns error code if something went wrong
include/mysql_com.h:
  my_init() now returns error code if something went wrong
libmysql/libmysql.c:
  mysql_server_init() and mysql_once_init() now returns error code if something went wrong (Bug #2062)
mysql-test/r/limit.result:
  Update results
mysql-test/r/select_found.result:
  Update results
mysql-test/r/union.result:
  Update results
mysql-test/t/limit.test:
  Added test for DELETE ... ORDER BY ... LIMIT (bug #1024)
mysql-test/t/select_found.test:
  Added test for problem with impossible WHERE (Bug #1468)
mysql-test/t/union.test:
  Added test for problem with alias '*' (Bug #1249)
mysys/mf_pack.c:
  Don't use my_fopen() when reading symlink information as this may cause problems when a lot of files are opened.
mysys/my_init.c:
  my_init() now returns error code if something went wrong
mysys/my_lib.c:
  More debug information
mysys/my_thr_init.c:
  Free thread keys with pthread_key_delete() instead of relying on automatic free. (Bug #2062)
sql/sql_base.cc:
  Fixed bug in UNION statement with alias '*'. (Bug #1249)
sql/sql_delete.cc:
  Fixed a bug in DELETE ... ORDER BY ... LIMIT where the rows where not deleted in the proper order. (Bug #1024).
sql/sql_select.cc:
  FOUND_ROWS() could return incorrect number of rows after a query with an impossible WHERE condition.
sql/sql_show.cc:
  SHOW DATABASES doesn't anymore show .sym files (on windows) that doesn't point to a valid directory. (Bug #1385)
sql/sql_yacc.yy:
  Allow syntax UNION DISTINCT
parent 4119451b
...@@ -151,6 +151,10 @@ typedef uint rf_SetTimer; ...@@ -151,6 +151,10 @@ typedef uint rf_SetTimer;
#define USE_MB_IDENT 1 #define USE_MB_IDENT 1
#define USE_STRCOLL 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 */ /* If LOAD DATA LOCAL INFILE should be enabled by default */
#define ENABLED_LOCAL_INFILE 1 #define ENABLED_LOCAL_INFILE 1
......
...@@ -115,6 +115,7 @@ void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/ ...@@ -115,6 +115,7 @@ void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/
#undef SAFE_MUTEX /* This will cause conflicts */ #undef SAFE_MUTEX /* This will cause conflicts */
#define pthread_key(T,V) DWORD V #define pthread_key(T,V) DWORD V
#define pthread_key_create(A,B) ((*A=TlsAlloc())==0xFFFFFFFF) #define pthread_key_create(A,B) ((*A=TlsAlloc())==0xFFFFFFFF)
#define pthread_key_delete(A) TlsFree(A)
#define pthread_getspecific(A) (TlsGetValue(A)) #define pthread_getspecific(A) (TlsGetValue(A))
#define my_pthread_getspecific(T,A) ((T) TlsGetValue(A)) #define my_pthread_getspecific(T,A) ((T) TlsGetValue(A))
#define my_pthread_getspecific_ptr(T,V) ((T) TlsGetValue(V)) #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)*/ ...@@ -123,6 +124,7 @@ void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/
#else #else
#define pthread_key(T,V) __declspec(thread) T V #define pthread_key(T,V) __declspec(thread) T V
#define pthread_key_create(A,B) pthread_dummy(0) #define pthread_key_create(A,B) pthread_dummy(0)
#define pthread_key_delete(A) pthread_dummy(0)
#define pthread_getspecific(A) (&(A)) #define pthread_getspecific(A) (&(A))
#define my_pthread_getspecific(T,A) (&(A)) #define my_pthread_getspecific(T,A) (&(A))
#define my_pthread_getspecific_ptr(T,V) (V) #define my_pthread_getspecific_ptr(T,V) (V)
...@@ -178,6 +180,7 @@ extern int pthread_mutex_destroy (pthread_mutex_t *); ...@@ -178,6 +180,7 @@ extern int pthread_mutex_destroy (pthread_mutex_t *);
typedef int pthread_attr_t; /* Needed by Unixware 7.0.0 */ typedef int pthread_attr_t; /* Needed by Unixware 7.0.0 */
#define pthread_key_create(A,B) thr_keycreate((A),(B)) #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_handler_decl(A,B) void *A(void *B)
#define pthread_key(T,V) pthread_key_t V #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, ...); ...@@ -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(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_no_curses(uint my_err, const char *str,myf MyFlags);
extern int my_message_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 void my_end(int infoflag);
extern int my_redel(const char *from, const char *to, int MyFlags); extern int my_redel(const char *from, const char *to, int MyFlags);
extern int my_copystat(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); ...@@ -426,7 +426,7 @@ int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB);
int simple_command(MYSQL *mysql,enum enum_server_command command, int simple_command(MYSQL *mysql,enum enum_server_command command,
const char *arg, unsigned long length, my_bool skipp_check); const char *arg, unsigned long length, my_bool skipp_check);
unsigned long net_safe_read(MYSQL* mysql); unsigned long net_safe_read(MYSQL* mysql);
void mysql_once_init(void); int mysql_once_init(void);
extern my_bool server_inited; extern my_bool server_inited;
......
...@@ -241,7 +241,7 @@ void hash_password(unsigned long *result, const char *password); ...@@ -241,7 +241,7 @@ void hash_password(unsigned long *result, const char *password);
/* Some other useful functions */ /* Some other useful functions */
void my_init(void); my_bool my_init(void);
int load_defaults(const char *conf_file, const char **groups, int load_defaults(const char *conf_file, const char **groups,
int *argc, char ***argv); int *argc, char ***argv);
my_bool my_thread_init(void); my_bool my_thread_init(void);
......
...@@ -102,8 +102,7 @@ int STDCALL mysql_server_init(int argc __attribute__((unused)), ...@@ -102,8 +102,7 @@ int STDCALL mysql_server_init(int argc __attribute__((unused)),
char **argv __attribute__((unused)), char **argv __attribute__((unused)),
char **groups __attribute__((unused))) char **groups __attribute__((unused)))
{ {
mysql_once_init(); return (int) mysql_once_init();
return 0;
} }
void STDCALL mysql_server_end() void STDCALL mysql_server_end()
...@@ -1436,7 +1435,8 @@ STDCALL mysql_rpl_query_type(const char* q, int len) ...@@ -1436,7 +1435,8 @@ STDCALL mysql_rpl_query_type(const char* q, int len)
MYSQL * STDCALL MYSQL * STDCALL
mysql_init(MYSQL *mysql) mysql_init(MYSQL *mysql)
{ {
mysql_once_init(); if (mysql_once_init())
return 0;
if (!mysql) if (!mysql)
{ {
if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL)))) if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL))))
...@@ -1476,15 +1476,20 @@ mysql_init(MYSQL *mysql) ...@@ -1476,15 +1476,20 @@ mysql_init(MYSQL *mysql)
This function is called by mysql_init() and indirectly called This function is called by mysql_init() and indirectly called
by mysql_query(), so one should never have to call this from an by mysql_query(), so one should never have to call this from an
outside program. 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) if (!mysql_client_init)
{ {
mysql_client_init=1; mysql_client_init=1;
org_my_init_done=my_init_done; org_my_init_done=my_init_done;
my_init(); /* Will init threads */ if (my_init()) /* Will init threads */
return 1;
init_client_errs(); init_client_errs();
if (!mysql_port) if (!mysql_port)
{ {
...@@ -1518,10 +1523,15 @@ void mysql_once_init(void) ...@@ -1518,10 +1523,15 @@ void mysql_once_init(void)
} }
#ifdef THREAD #ifdef THREAD
else else
my_thread_init(); /* Init if new thread */ {
if (my_thread_init()) /* Init if new thread */
return 1;
}
#endif #endif
return 0;
} }
/************************************************************************** /**************************************************************************
Fill in SSL part of MYSQL structure and set 'use_ssl' flag. Fill in SSL part of MYSQL structure and set 'use_ssl' flag.
NB! Errors are not reported until you do mysql_real_connect. NB! Errors are not reported until you do mysql_real_connect.
......
...@@ -36,9 +36,7 @@ a b ...@@ -36,9 +36,7 @@ a b
3 4 3 4
drop table t1; drop table t1;
create table t1 (i int); create table t1 (i int);
insert into t1 (i) values(1); insert into t1 (i) values(1),(1),(1);
insert into t1 (i) values(1);
insert into t1 (i) values(1);
delete from t1 limit 1; delete from t1 limit 1;
update t1 set i=2 limit 1; update t1 set i=2 limit 1;
delete from t1 limit 0; delete from t1 limit 0;
...@@ -50,3 +48,22 @@ i ...@@ -50,3 +48,22 @@ i
drop table t1; drop table t1;
select 0 limit 0; select 0 limit 0;
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(); ...@@ -169,3 +169,22 @@ SELECT FOUND_ROWS();
FOUND_ROWS() FOUND_ROWS()
2 2
drop table t1; 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); ...@@ -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'); insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c');
CREATE TABLE t2 (a int not null, b char (10) not null); CREATE TABLE t2 (a int not null, b char (10) not null);
insert into t2 values (3,'c'),(4,'d'),(5,'f'),(6,'e'); 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 a b
1 a 1 a
2 b 2 b
...@@ -423,3 +423,7 @@ create temporary table t1 select a from t1 union select a from t2; ...@@ -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; create table t1 select a from t1 union select a from t2;
INSERT TABLE 't1' isn't allowed in FROM table list INSERT TABLE 't1' isn't allowed in FROM table list
drop table t1,t2; drop table t1,t2;
select length(version()) > 1 as `*` UNION select 2;
*
1
2
...@@ -19,9 +19,7 @@ select * from t1; ...@@ -19,9 +19,7 @@ select * from t1;
drop table t1; drop table t1;
create table t1 (i int); create table t1 (i int);
insert into t1 (i) values(1); insert into t1 (i) values(1),(1),(1);
insert into t1 (i) values(1);
insert into t1 (i) values(1);
delete from t1 limit 1; delete from t1 limit 1;
update t1 set i=2 limit 1; update t1 set i=2 limit 1;
delete from t1 limit 0; delete from t1 limit 0;
...@@ -29,4 +27,22 @@ update t1 set i=3 limit 0; ...@@ -29,4 +27,22 @@ update t1 set i=3 limit 0;
select * from t1; select * from t1;
drop table t1; drop table t1;
# LIMIT 0
select 0 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 ...@@ -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 SQL_CALC_FOUND_ROWS titre,numeropost,maxnumrep FROM t1 WHERE numeropost IN (1,2) ORDER BY maxnumrep DESC LIMIT 0, 1;
SELECT FOUND_ROWS(); SELECT FOUND_ROWS();
drop table t1; 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'); ...@@ -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); CREATE TABLE t2 (a int not null, b char (10) not null);
insert into t2 values (3,'c'),(4,'d'),(5,'f'),(6,'e'); 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;
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 order by b;
select a,b from t1 union all select a,b from t2 union select 7,'g'; 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; ...@@ -227,3 +227,10 @@ create temporary table t1 select a from t1 union select a from t2;
--error 1093 --error 1093
create table t1 select a from t1 union select a from t2; create table t1 select a from t1 union select a from t2;
drop table t1,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) ...@@ -210,13 +210,13 @@ uint cleanup_dirname(register my_string to, const char *from)
} /* cleanup_dirname */ } /* cleanup_dirname */
/* /*
On system where you don't have symbolic links, the following On system where you don't have symbolic links, the following
code will allow you to create a file: code will allow you to create a file:
directory-name.lnk that should contain the real path directory-name.sym that should contain the real path
to the directory. This will be used if the directory name to the directory. This will be used if the directory name
doesn't exists doesn't exists
*/ */
my_bool my_use_symdir=0; /* Set this if you want to use symdirs */ my_bool my_use_symdir=0; /* Set this if you want to use symdirs */
...@@ -228,16 +228,17 @@ void symdirget(char *dir) ...@@ -228,16 +228,17 @@ void symdirget(char *dir)
char *pos=strend(dir); char *pos=strend(dir);
if (dir[0] && pos[-1] != FN_DEVCHAR && access(dir, F_OK)) if (dir[0] && pos[-1] != FN_DEVCHAR && access(dir, F_OK))
{ {
FILE *fp; File file;
uint length;
char temp= *(--pos); /* May be "/" or "\" */ char temp= *(--pos); /* May be "/" or "\" */
strmov(pos,".sym"); 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 */ *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 > buff && (iscntrl(pos[-1]) || isspace(pos[-1])) ;
pos --); pos --);
...@@ -247,7 +248,7 @@ void symdirget(char *dir) ...@@ -247,7 +248,7 @@ void symdirget(char *dir)
strmake(dir,buff, (uint) (pos-buff)); 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) ...@@ -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
SYNOPSIS
my_init()
void my_init(void) RETURN
0 ok
1 Couldn't initialize environment
*/
my_bool my_init(void)
{ {
my_string str; my_string str;
if (my_init_done) if (my_init_done)
return; return 0;
my_init_done=1; my_init_done=1;
#if defined(THREAD) && defined(SAFE_MUTEX) #if defined(THREAD) && defined(SAFE_MUTEX)
safe_mutex_global_init(); /* Must be called early */ safe_mutex_global_init(); /* Must be called early */
...@@ -78,7 +87,8 @@ void my_init(void) ...@@ -78,7 +87,8 @@ void my_init(void)
#if defined(HAVE_PTHREAD_INIT) #if defined(HAVE_PTHREAD_INIT)
pthread_init(); /* Must be called before DBUG_ENTER */ pthread_init(); /* Must be called before DBUG_ENTER */
#endif #endif
my_thread_global_init(); if (my_thread_global_init())
return 1;
#if !defined( __WIN__) && !defined(OS2) && !defined(__NETWARE__) #if !defined( __WIN__) && !defined(OS2) && !defined(__NETWARE__)
sigfillset(&my_signals); /* signals blocked by mf_brkhant */ sigfillset(&my_signals); /* signals blocked by mf_brkhant */
#endif #endif
...@@ -110,7 +120,7 @@ void my_init(void) ...@@ -110,7 +120,7 @@ void my_init(void)
#ifdef __WIN__ #ifdef __WIN__
win32_init_tcp_ip(); win32_init_tcp_ip();
#endif #endif
DBUG_VOID_RETURN; DBUG_RETURN(0);
} }
} /* my_init */ } /* my_init */
......
...@@ -602,9 +602,11 @@ MY_STAT *my_stat(const char *path, MY_STAT *stat_area, myf my_flags) ...@@ -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 ((m_used= (stat_area == NULL)))
if (!(stat_area = (MY_STAT *) my_malloc(sizeof(MY_STAT), my_flags))) if (!(stat_area = (MY_STAT *) my_malloc(sizeof(MY_STAT), my_flags)))
goto error; goto error;
if ( ! stat((my_string) path, (struct stat *) stat_area) ) if (! stat((my_string) path, (struct stat *) stat_area) )
DBUG_RETURN(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 */ if (m_used) /* Free if new area */
my_free((gptr) stat_area,MYF(0)); my_free((gptr) stat_area,MYF(0));
......
...@@ -44,12 +44,23 @@ pthread_mutexattr_t my_fast_mutexattr; ...@@ -44,12 +44,23 @@ pthread_mutexattr_t my_fast_mutexattr;
pthread_mutexattr_t my_errchk_mutexattr; pthread_mutexattr_t my_errchk_mutexattr;
#endif #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) 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); fprintf(stderr,"Can't initialize threads: error %d\n",errno);
exit(1); return 1;
} }
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP #ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
pthread_mutexattr_init(&my_fast_mutexattr); pthread_mutexattr_init(&my_fast_mutexattr);
...@@ -79,15 +90,18 @@ my_bool my_thread_global_init(void) ...@@ -79,15 +90,18 @@ my_bool my_thread_global_init(void)
#ifndef HAVE_GETHOSTBYNAME_R #ifndef HAVE_GETHOSTBYNAME_R
pthread_mutex_init(&LOCK_gethostbyname_r,MY_MUTEX_INIT_SLOW); pthread_mutex_init(&LOCK_gethostbyname_r,MY_MUTEX_INIT_SLOW);
#endif #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) void my_thread_global_end(void)
{ {
#if defined(USE_TLS) pthread_key_delete(THR_KEY_mysys);
(void) TlsFree(THR_KEY_mysys);
#endif
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP #ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
pthread_mutexattr_destroy(&my_fast_mutexattr); pthread_mutexattr_destroy(&my_fast_mutexattr);
#endif #endif
......
...@@ -1868,8 +1868,13 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields, ...@@ -1868,8 +1868,13 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
while ((item=it++)) 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 && 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; uint elem=fields.elements;
if (insert_fields(thd,tables,((Item_field*) item)->db_name, if (insert_fields(thd,tables,((Item_field*) item)->db_name,
......
...@@ -78,7 +78,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, ...@@ -78,7 +78,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
DBUG_RETURN(-1); DBUG_RETURN(-1);
if ((select && select->check_quick(thd, if ((select && select->check_quick(thd,
test(thd->options & OPTION_SAFE_UPDATES), test(thd->options & OPTION_SAFE_UPDATES),
limit)) || limit)) ||
!limit) !limit)
{ {
delete select; delete select;
...@@ -117,13 +117,19 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, ...@@ -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) || if (setup_order(thd, &tables, fields, all_fields, order) ||
!(sortorder=make_unireg_sortorder(order, &length)) || !(sortorder=make_unireg_sortorder(order, &length)) ||
(table->found_records = filesort(table, sortorder, length, (table->found_records = filesort(table, sortorder, length,
(SQL_SELECT *) 0, 0L, HA_POS_ERROR, select, 0L, HA_POS_ERROR,
&examined_rows)) &examined_rows))
== HA_POS_ERROR) == HA_POS_ERROR)
{ {
delete select; 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); init_read_record(&info,thd,table,select,1,1);
......
...@@ -3273,6 +3273,8 @@ return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables, ...@@ -3273,6 +3273,8 @@ return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables,
} }
result->send_eof(); // Should be safe 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); DBUG_RETURN(0);
} }
......
...@@ -197,7 +197,19 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path, ...@@ -197,7 +197,19 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
#ifdef USE_SYMDIR #ifdef USE_SYMDIR
char *ext; char *ext;
if (my_use_symdir && !strcmp(ext=fn_ext(file->name), ".sym")) 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 */ *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 else
#endif #endif
{ {
......
...@@ -4014,5 +4014,6 @@ optional_order_or_limit: ...@@ -4014,5 +4014,6 @@ optional_order_or_limit:
union_option: union_option:
/* empty */ {} /* empty */ {}
| DISTINCT {}
| ALL { Lex->union_option=1; } | ALL { Lex->union_option=1; }
; ;
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