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;
#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
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
SYNOPSIS
my_init()
void my_init(void)
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
}
/*
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; }
;
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