merge
BitKeeper/etc/ignore: added scripts/mysql_tableinfo sql/sql_parse.cc: Auto merged
This commit is contained in:
commit
8d07955f3d
@ -472,3 +472,11 @@ vio/viotest-ssl
|
|||||||
mysys/getopt.c
|
mysys/getopt.c
|
||||||
mysys/getopt1.c
|
mysys/getopt1.c
|
||||||
scripts/mysql_secure_installation
|
scripts/mysql_secure_installation
|
||||||
|
mit-pthreads/include/bits
|
||||||
|
mit-pthreads/include/pthread/machdep.h
|
||||||
|
mit-pthreads/include/pthread/posix.h
|
||||||
|
mit-pthreads/include/sys
|
||||||
|
mit-pthreads/machdep.c
|
||||||
|
mit-pthreads/pg++
|
||||||
|
mit-pthreads/pgcc
|
||||||
|
scripts/mysql_tableinfo
|
||||||
|
@ -3951,10 +3951,6 @@ Automatic output from @code{mysql} to Netscape.
|
|||||||
@item
|
@item
|
||||||
@code{LOCK DATABASES} (with various options.)
|
@code{LOCK DATABASES} (with various options.)
|
||||||
@item
|
@item
|
||||||
@code{DECIMAL} and @code{NUMERIC} types can't read exponential numbers;
|
|
||||||
@code{Field_decimal::store(const char *from,uint len)} must be recoded
|
|
||||||
to fix this.
|
|
||||||
@item
|
|
||||||
Functions:
|
Functions:
|
||||||
ADD_TO_SET(value,set) and REMOVE_FROM_SET(value,set).
|
ADD_TO_SET(value,set) and REMOVE_FROM_SET(value,set).
|
||||||
@item
|
@item
|
||||||
@ -49451,6 +49447,9 @@ Emulation of @code{pthread_mutex()} for OS/2.
|
|||||||
@item Benjamin Pflugmann
|
@item Benjamin Pflugmann
|
||||||
Extended @code{MERGE} tables to handle @code{INSERTS}. Active member
|
Extended @code{MERGE} tables to handle @code{INSERTS}. Active member
|
||||||
on the MySQL mailing lists.
|
on the MySQL mailing lists.
|
||||||
|
@item Guilhem Bichot
|
||||||
|
Fixed handling of exponents for @code{DECIMAL}.
|
||||||
|
Author of @code{mysql_tableinfo}.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
Other contributors, bugfinders, and testers: James H. Thompson, Maurizio
|
Other contributors, bugfinders, and testers: James H. Thompson, Maurizio
|
||||||
@ -49579,6 +49578,10 @@ Our TODO section contains what we plan to have in 4.0. @xref{TODO MySQL 4.0}.
|
|||||||
|
|
||||||
@itemize @bullet
|
@itemize @bullet
|
||||||
@item
|
@item
|
||||||
|
Removed @code{mysql_ssl_clear()}, as this was not needed.
|
||||||
|
@item
|
||||||
|
@code{DECIMAL} and @code{NUMERIC} types can now read exponential numbers.
|
||||||
|
@item
|
||||||
Added @code{SHA1()} function to calculate 160 bit hash value as described
|
Added @code{SHA1()} function to calculate 160 bit hash value as described
|
||||||
in RFC 3174 (Secure Hash Algorithm). This function can be considered a
|
in RFC 3174 (Secure Hash Algorithm). This function can be considered a
|
||||||
cryptographically more secure equivalent of @code{MD5()}.
|
cryptographically more secure equivalent of @code{MD5()}.
|
||||||
|
@ -122,17 +122,17 @@ struct st_mysql_options {
|
|||||||
my_bool use_ssl; /* if to use SSL or not */
|
my_bool use_ssl; /* if to use SSL or not */
|
||||||
my_bool compress,named_pipe;
|
my_bool compress,named_pipe;
|
||||||
/*
|
/*
|
||||||
on connect, find out the replication role of the server, and
|
On connect, find out the replication role of the server, and
|
||||||
establish connections to all the peers
|
establish connections to all the peers
|
||||||
*/
|
*/
|
||||||
my_bool rpl_probe;
|
my_bool rpl_probe;
|
||||||
/*
|
/*
|
||||||
each call to mysql_real_query() will parse it to tell if it is a read
|
Each call to mysql_real_query() will parse it to tell if it is a read
|
||||||
or a write, and direct it to the slave or the master
|
or a write, and direct it to the slave or the master
|
||||||
*/
|
*/
|
||||||
my_bool rpl_parse;
|
my_bool rpl_parse;
|
||||||
/*
|
/*
|
||||||
if set, never read from a master,only from slave, when doing
|
If set, never read from a master,only from slave, when doing
|
||||||
a read that is replication-aware
|
a read that is replication-aware
|
||||||
*/
|
*/
|
||||||
my_bool no_master_reads;
|
my_bool no_master_reads;
|
||||||
@ -185,8 +185,10 @@ typedef struct st_mysql {
|
|||||||
added though mysql_rpl_probe() or mysql_set_master()/ mysql_add_slave()
|
added though mysql_rpl_probe() or mysql_set_master()/ mysql_add_slave()
|
||||||
*/
|
*/
|
||||||
my_bool rpl_pivot;
|
my_bool rpl_pivot;
|
||||||
/* pointers to the master, and the next slave
|
/*
|
||||||
connections, points to itself if lone connection */
|
Pointers to the master, and the next slave connections, points to
|
||||||
|
itself if lone connection.
|
||||||
|
*/
|
||||||
struct st_mysql* master, *next_slave;
|
struct st_mysql* master, *next_slave;
|
||||||
|
|
||||||
struct st_mysql* last_used_slave; /* needed for round-robin slave pick */
|
struct st_mysql* last_used_slave; /* needed for round-robin slave pick */
|
||||||
@ -234,21 +236,27 @@ typedef struct st_mysql_manager
|
|||||||
char last_error[MAX_MYSQL_MANAGER_ERR];
|
char last_error[MAX_MYSQL_MANAGER_ERR];
|
||||||
} MYSQL_MANAGER;
|
} MYSQL_MANAGER;
|
||||||
|
|
||||||
/* Set up and bring down the server; to ensure that applications will
|
/*
|
||||||
* work when linked against either the standard client library or the
|
Set up and bring down the server; to ensure that applications will
|
||||||
* embedded server library, these functions should be called. */
|
work when linked against either the standard client library or the
|
||||||
|
embedded server library, these functions should be called.
|
||||||
|
*/
|
||||||
int STDCALL mysql_server_init(int argc, char **argv, char **groups);
|
int STDCALL mysql_server_init(int argc, char **argv, char **groups);
|
||||||
void STDCALL mysql_server_end(void);
|
void STDCALL mysql_server_end(void);
|
||||||
|
|
||||||
/* Set up and bring down a thread; these function should be called
|
/*
|
||||||
* for each thread in an application which opens at least one MySQL
|
Set up and bring down a thread; these function should be called
|
||||||
* connection. All uses of the connection(s) should be between these
|
for each thread in an application which opens at least one MySQL
|
||||||
* function calls. */
|
connection. All uses of the connection(s) should be between these
|
||||||
|
function calls.
|
||||||
|
*/
|
||||||
my_bool STDCALL mysql_thread_init(void);
|
my_bool STDCALL mysql_thread_init(void);
|
||||||
void STDCALL mysql_thread_end(void);
|
void STDCALL mysql_thread_end(void);
|
||||||
|
|
||||||
/* Functions to get information from the MYSQL and MYSQL_RES structures */
|
/*
|
||||||
/* Should definitely be used if one uses shared libraries */
|
Functions to get information from the MYSQL and MYSQL_RES structures
|
||||||
|
Should definitely be used if one uses shared libraries.
|
||||||
|
*/
|
||||||
|
|
||||||
my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res);
|
my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res);
|
||||||
unsigned int STDCALL mysql_num_fields(MYSQL_RES *res);
|
unsigned int STDCALL mysql_num_fields(MYSQL_RES *res);
|
||||||
@ -272,7 +280,6 @@ MYSQL * STDCALL mysql_init(MYSQL *mysql);
|
|||||||
int STDCALL mysql_ssl_set(MYSQL *mysql, const char *key,
|
int STDCALL mysql_ssl_set(MYSQL *mysql, const char *key,
|
||||||
const char *cert, const char *ca,
|
const char *cert, const char *ca,
|
||||||
const char *capath, const char *cipher);
|
const char *capath, const char *cipher);
|
||||||
int STDCALL mysql_ssl_clear(MYSQL *mysql);
|
|
||||||
my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
|
my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
|
||||||
const char *passwd, const char *db);
|
const char *passwd, const char *db);
|
||||||
MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host,
|
MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host,
|
||||||
|
@ -38,6 +38,15 @@ extern "C" {
|
|||||||
#define THR_SERVER_ALARM SIGALRM
|
#define THR_SERVER_ALARM SIGALRM
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef struct st_alarm_info
|
||||||
|
{
|
||||||
|
ulong next_alarm_time;
|
||||||
|
uint active_alarms;
|
||||||
|
uint max_used_alarms;
|
||||||
|
} ALARM_INFO;
|
||||||
|
|
||||||
|
void thr_alarm_info(ALARM_INFO *info);
|
||||||
|
|
||||||
#if defined(DONT_USE_THR_ALARM) || !defined(THREAD)
|
#if defined(DONT_USE_THR_ALARM) || !defined(THREAD)
|
||||||
|
|
||||||
#define USE_ALARM_THREAD
|
#define USE_ALARM_THREAD
|
||||||
|
@ -1448,8 +1448,8 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
|
|||||||
NB! Errors are not reported until you do mysql_real_connect.
|
NB! Errors are not reported until you do mysql_real_connect.
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
int STDCALL
|
static int
|
||||||
mysql_ssl_clear(MYSQL *mysql __attribute__((unused)))
|
mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
|
||||||
{
|
{
|
||||||
#ifdef HAVE_OPENSSL
|
#ifdef HAVE_OPENSSL
|
||||||
my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR));
|
my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR));
|
||||||
@ -2051,7 +2051,7 @@ mysql_close(MYSQL *mysql)
|
|||||||
my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
|
my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
|
||||||
my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
|
my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
|
||||||
#ifdef HAVE_OPENSSL
|
#ifdef HAVE_OPENSSL
|
||||||
mysql_ssl_clear(mysql);
|
mysql_ssl_free(mysql);
|
||||||
#endif /* HAVE_OPENSSL */
|
#endif /* HAVE_OPENSSL */
|
||||||
/* Clear pointers for better safety */
|
/* Clear pointers for better safety */
|
||||||
mysql->host_info=mysql->user=mysql->passwd=mysql->db=0;
|
mysql->host_info=mysql->user=mysql->passwd=mysql->db=0;
|
||||||
|
@ -90,7 +90,7 @@ EXPORTS
|
|||||||
mysql_real_escape_string
|
mysql_real_escape_string
|
||||||
mysql_ssl_set
|
mysql_ssl_set
|
||||||
mysql_ssl_clear
|
mysql_ssl_clear
|
||||||
mysql_real_connect
|
mysql_real_connect
|
||||||
mysql_master_query
|
mysql_master_query
|
||||||
mysql_master_send_query
|
mysql_master_send_query
|
||||||
mysql_slave_query
|
mysql_slave_query
|
||||||
|
@ -63,10 +63,3 @@ EXPORTS
|
|||||||
mysql_refresh
|
mysql_refresh
|
||||||
mysql_odbc_escape_string
|
mysql_odbc_escape_string
|
||||||
myodbc_remove_escape
|
myodbc_remove_escape
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -275,7 +275,7 @@ static void print_version(void)
|
|||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
print_version();
|
print_version();
|
||||||
puts("Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB");
|
puts("Copyright (C) 2002 MySQL AB");
|
||||||
puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,");
|
puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,");
|
||||||
puts("and you are welcome to modify and redistribute it under the GPL license\n");
|
puts("and you are welcome to modify and redistribute it under the GPL license\n");
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ my_bool thr_alarm_inited=0;
|
|||||||
static pthread_mutex_t LOCK_alarm;
|
static pthread_mutex_t LOCK_alarm;
|
||||||
static sigset_t full_signal_set;
|
static sigset_t full_signal_set;
|
||||||
static QUEUE alarm_queue;
|
static QUEUE alarm_queue;
|
||||||
|
static uint max_used_alarms=0;
|
||||||
pthread_t alarm_thread;
|
pthread_t alarm_thread;
|
||||||
|
|
||||||
#ifdef USE_ALARM_THREAD
|
#ifdef USE_ALARM_THREAD
|
||||||
@ -116,10 +117,10 @@ void init_thr_alarm(uint max_alarms)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Request alarm after sec seconds.
|
Request alarm after sec seconds.
|
||||||
** A pointer is returned with points to a non-zero int when the alarm has been
|
A pointer is returned with points to a non-zero int when the alarm has been
|
||||||
** given. This can't be called from the alarm-handling thread.
|
given. This can't be called from the alarm-handling thread.
|
||||||
** Returns 0 if no more alarms are allowed (aborted by process)
|
Returns 0 if no more alarms are allowed (aborted by process)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
|
bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
|
||||||
@ -140,13 +141,17 @@ bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
|
|||||||
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
|
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
if (alarm_queue.elements == alarm_queue.max_elements)
|
if (alarm_queue.elements >= max_used_alarms)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("alarm queue full"));
|
if (alarm_queue.elements == alarm_queue.max_elements)
|
||||||
fprintf(stderr,"Warning: thr_alarm queue is full\n");
|
{
|
||||||
pthread_mutex_unlock(&LOCK_alarm);
|
DBUG_PRINT("info", ("alarm queue full"));
|
||||||
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
|
fprintf(stderr,"Warning: thr_alarm queue is full\n");
|
||||||
DBUG_RETURN(1);
|
pthread_mutex_unlock(&LOCK_alarm);
|
||||||
|
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
max_used_alarms=alarm_queue.elements+1;
|
||||||
}
|
}
|
||||||
reschedule= (!alarm_queue.elements ||
|
reschedule= (!alarm_queue.elements ||
|
||||||
(int) (((ALARM*) queue_top(&alarm_queue))->expire_time - now) >
|
(int) (((ALARM*) queue_top(&alarm_queue))->expire_time - now) >
|
||||||
@ -186,7 +191,7 @@ bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Remove alarm from list of alarms
|
Remove alarm from list of alarms
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void thr_end_alarm(thr_alarm_t *alarmed)
|
void thr_end_alarm(thr_alarm_t *alarmed)
|
||||||
@ -227,13 +232,13 @@ void thr_end_alarm(thr_alarm_t *alarmed)
|
|||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Come here when some alarm in queue is due.
|
Come here when some alarm in queue is due.
|
||||||
Mark all alarms with are finnished in list.
|
Mark all alarms with are finnished in list.
|
||||||
Shedule alarms to be sent again after 1-10 sec (many alarms at once)
|
Shedule alarms to be sent again after 1-10 sec (many alarms at once)
|
||||||
If alarm_aborted is set then all alarms are given and resent
|
If alarm_aborted is set then all alarms are given and resent
|
||||||
every second.
|
every second.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
sig_handler process_alarm(int sig __attribute__((unused)))
|
sig_handler process_alarm(int sig __attribute__((unused)))
|
||||||
{
|
{
|
||||||
@ -334,8 +339,8 @@ sig_handler process_alarm(int sig __attribute__((unused)))
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Shedule all alarms now.
|
Shedule all alarms now.
|
||||||
** When all alarms are given, Free alarm memory and don't allow more alarms.
|
When all alarms are given, Free alarm memory and don't allow more alarms.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void end_thr_alarm(void)
|
void end_thr_alarm(void)
|
||||||
@ -359,7 +364,7 @@ void end_thr_alarm(void)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Remove another thread from the alarm
|
Remove another thread from the alarm
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void thr_alarm_kill(pthread_t thread_id)
|
void thr_alarm_kill(pthread_t thread_id)
|
||||||
@ -382,9 +387,25 @@ void thr_alarm_kill(pthread_t thread_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void thr_alarm_info(ALARM_INFO *info)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&LOCK_alarm);
|
||||||
|
info->next_alarm_time= 0;
|
||||||
|
info->max_used_alarms= max_used_alarms;
|
||||||
|
if ((info->active_alarms= alarm_queue.elements))
|
||||||
|
{
|
||||||
|
ulong now=(ulong) time((time_t*) 0);
|
||||||
|
long time_diff;
|
||||||
|
ALARM *alarm_data= (ALARM*) queue_top(&alarm_queue);
|
||||||
|
time_diff= (long) (alarm_data->expire_time - now);
|
||||||
|
info->next_alarm_time= (ulong) (time_diff < 0 ? 0 : time_diff);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&LOCK_alarm);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This is here for thread to get interruptet from read/write/fcntl
|
This is here for thread to get interruptet from read/write/fcntl
|
||||||
** ARGSUSED
|
ARGSUSED
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD)
|
#if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD)
|
||||||
@ -459,7 +480,7 @@ static void *alarm_handler(void *arg __attribute__((unused)))
|
|||||||
#endif /* USE_ALARM_THREAD */
|
#endif /* USE_ALARM_THREAD */
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
** thr_alarm for OS/2
|
thr_alarm for OS/2
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#elif defined(__EMX__) || defined(OS2)
|
#elif defined(__EMX__) || defined(OS2)
|
||||||
@ -490,7 +511,7 @@ sig_handler process_alarm(int sig __attribute__((unused)))
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Remove another thread from the alarm
|
Remove another thread from the alarm
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void thr_alarm_kill(pthread_t thread_id)
|
void thr_alarm_kill(pthread_t thread_id)
|
||||||
@ -588,8 +609,14 @@ void init_thr_alarm(uint max_alarm)
|
|||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void thr_alarm_info(ALARM_INFO *info)
|
||||||
|
{
|
||||||
|
bzero((char*) info, sizeof(*info));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
** thr_alarm for win95
|
thr_alarm for win95
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#else /* __WIN__ */
|
#else /* __WIN__ */
|
||||||
@ -661,13 +688,18 @@ void init_thr_alarm(uint max_alarm)
|
|||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void thr_alarm_info(ALARM_INFO *info)
|
||||||
|
{
|
||||||
|
bzero((char*) info, sizeof(*info));
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* __WIN__ */
|
#endif /* __WIN__ */
|
||||||
|
|
||||||
#endif /* THREAD */
|
#endif /* THREAD */
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
** Handling of MAIN
|
Handling of test case (when compiled with -DMAIN)
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#ifdef MAIN
|
#ifdef MAIN
|
||||||
@ -867,6 +899,7 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
|
|||||||
pthread_attr_t thr_attr;
|
pthread_attr_t thr_attr;
|
||||||
int i,*param,error;
|
int i,*param,error;
|
||||||
sigset_t set;
|
sigset_t set;
|
||||||
|
ALARM_INFO alarm_info;
|
||||||
MY_INIT(argv[0]);
|
MY_INIT(argv[0]);
|
||||||
|
|
||||||
if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '#')
|
if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '#')
|
||||||
@ -927,6 +960,10 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
|
|||||||
|
|
||||||
pthread_attr_destroy(&thr_attr);
|
pthread_attr_destroy(&thr_attr);
|
||||||
pthread_mutex_lock(&LOCK_thread_count);
|
pthread_mutex_lock(&LOCK_thread_count);
|
||||||
|
thr_alarm_info(&alarm_info);
|
||||||
|
printf("Main_thread: Alarms: %u max_alarms: %u next_alarm_time: %lu\n",
|
||||||
|
alarm_info.active_alarms, alarm_info.max_used_alarms,
|
||||||
|
alarm_info.next_alarm_time);
|
||||||
while (thread_count)
|
while (thread_count)
|
||||||
{
|
{
|
||||||
VOID(pthread_cond_wait(&COND_thread_count,&LOCK_thread_count));
|
VOID(pthread_cond_wait(&COND_thread_count,&LOCK_thread_count));
|
||||||
@ -937,6 +974,10 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&LOCK_thread_count);
|
pthread_mutex_unlock(&LOCK_thread_count);
|
||||||
|
thr_alarm_info(&alarm_info);
|
||||||
|
printf("Main_thread: Alarms: %u max_alarms: %u next_alarm_time: %lu\n",
|
||||||
|
alarm_info.active_alarms, alarm_info.max_used_alarms,
|
||||||
|
alarm_info.next_alarm_time);
|
||||||
printf("Test succeeded\n");
|
printf("Test succeeded\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ bin_SCRIPTS = @server_scripts@ \
|
|||||||
mysqlhotcopy \
|
mysqlhotcopy \
|
||||||
mysqldumpslow \
|
mysqldumpslow \
|
||||||
mysql_explain_log \
|
mysql_explain_log \
|
||||||
|
mysql_tableinfo \
|
||||||
mysqld_multi
|
mysqld_multi
|
||||||
|
|
||||||
EXTRA_SCRIPTS = make_binary_distribution.sh \
|
EXTRA_SCRIPTS = make_binary_distribution.sh \
|
||||||
@ -50,6 +51,7 @@ EXTRA_SCRIPTS = make_binary_distribution.sh \
|
|||||||
mysqldumpslow.sh \
|
mysqldumpslow.sh \
|
||||||
mysql_explain_log.sh \
|
mysql_explain_log.sh \
|
||||||
mysqld_multi.sh \
|
mysqld_multi.sh \
|
||||||
|
mysql_tableinfo.sh \
|
||||||
mysqld_safe.sh
|
mysqld_safe.sh
|
||||||
|
|
||||||
EXTRA_DIST = $(EXTRA_SCRIPTS) \
|
EXTRA_DIST = $(EXTRA_SCRIPTS) \
|
||||||
|
478
scripts/mysql_tableinfo.sh
Normal file
478
scripts/mysql_tableinfo.sh
Normal file
@ -0,0 +1,478 @@
|
|||||||
|
#!@PERL@ -w
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use Getopt::Long;
|
||||||
|
use DBI;
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
mysql_tableinfo - creates and populates information tables with
|
||||||
|
the output of SHOW DATABASES, SHOW TABLES (or SHOW TABLE STATUS),
|
||||||
|
SHOW COLUMNS and SHOW INDEX.
|
||||||
|
|
||||||
|
This is version 1.0.
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
mysql_tableinfo [OPTIONS] database_to_write [database_like_wild] [table_like_wild]
|
||||||
|
|
||||||
|
Do not backquote (``) database_to_write,
|
||||||
|
and do not quote ('') database_like_wild or table_like_wild
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
mysql_tableinfo info
|
||||||
|
|
||||||
|
mysql_tableinfo info this_db
|
||||||
|
|
||||||
|
mysql_tableinfo info %a% b%
|
||||||
|
|
||||||
|
mysql_tableinfo info --clear-only
|
||||||
|
|
||||||
|
mysql_tableinfo info --col --idx --table-status
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
# Documentation continued at end of file
|
||||||
|
|
||||||
|
|
||||||
|
sub usage {
|
||||||
|
die @_,"\nExecute 'perldoc $0' for documentation\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
my %opt = (
|
||||||
|
'user' => scalar getpwuid($>),
|
||||||
|
'host' => "localhost",
|
||||||
|
'prefix' => "", #to avoid 'use of uninitialized value...'
|
||||||
|
);
|
||||||
|
Getopt::Long::Configure(qw(no_ignore_case)); # disambuguate -p and -P
|
||||||
|
GetOptions( \%opt,
|
||||||
|
"help",
|
||||||
|
"user|u=s",
|
||||||
|
"password|p=s",
|
||||||
|
"host|h=s",
|
||||||
|
"port|P=s",
|
||||||
|
"socket|S=s",
|
||||||
|
"tbl-status",
|
||||||
|
"col",
|
||||||
|
"idx",
|
||||||
|
"clear",
|
||||||
|
"clear-only",
|
||||||
|
"prefix=s",
|
||||||
|
"quiet|q",
|
||||||
|
) or usage("Invalid option");
|
||||||
|
|
||||||
|
if ($opt{help}) {usage();}
|
||||||
|
|
||||||
|
my ($db_to_write,$db_like_wild,$tbl_like_wild);
|
||||||
|
if (@ARGV==0)
|
||||||
|
{
|
||||||
|
usage("Not enough arguments");
|
||||||
|
}
|
||||||
|
$db_to_write="`$ARGV[0]`"; shift @ARGV;
|
||||||
|
$db_like_wild=($ARGV[0])?$ARGV[0]:"%"; shift @ARGV;
|
||||||
|
$tbl_like_wild=($ARGV[0])?$ARGV[0]:"%"; shift @ARGV;
|
||||||
|
if (@ARGV>0) { usage("Too many arguments"); }
|
||||||
|
|
||||||
|
my $info_db="`".$opt{'prefix'}."db`";
|
||||||
|
my $info_tbl="`".$opt{'prefix'}."tbl".
|
||||||
|
(($opt{'tbl-status'})?"_status":"")."`";
|
||||||
|
my $info_col="`".$opt{'prefix'}."col`";
|
||||||
|
my $info_idx="`".$opt{'prefix'}."idx`";
|
||||||
|
|
||||||
|
|
||||||
|
# --- connect to the database ---
|
||||||
|
|
||||||
|
my $dsn = ";host=$opt{'host'}";
|
||||||
|
$dsn .= ";port=$opt{port}" if $opt{port};
|
||||||
|
$dsn .= ";mysql_socket=$opt{socket}" if $opt{socket};
|
||||||
|
|
||||||
|
my $dbh = DBI->connect("dbi:mysql:$dsn;mysql_read_default_group=perl",
|
||||||
|
$opt{user}, $opt{password},
|
||||||
|
{
|
||||||
|
RaiseError => 1,
|
||||||
|
PrintError => 0,
|
||||||
|
AutoCommit => 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
$db_like_wild=$dbh->quote($db_like_wild);
|
||||||
|
$tbl_like_wild=$dbh->quote($tbl_like_wild);
|
||||||
|
|
||||||
|
#Ask
|
||||||
|
|
||||||
|
if (!$opt{'quiet'})
|
||||||
|
{
|
||||||
|
print "\n!! This program is doing to do:\n\n";
|
||||||
|
print "**DROP** TABLE ...\n" if ($opt{'clear'} or $opt{'clear-only'});
|
||||||
|
print "**DELETE** FROM ... WHERE `Database LIKE $db_like_wild AND `Table` LIKE $tbl_like_wild
|
||||||
|
**INSERT** INTO ...
|
||||||
|
|
||||||
|
on the following tables :\n";
|
||||||
|
my $i;
|
||||||
|
foreach $i (($info_db, $info_tbl),
|
||||||
|
(($opt{'col'})?$info_col:()),
|
||||||
|
(($opt{'idx'})?$info_idx:()))
|
||||||
|
{
|
||||||
|
print(" $db_to_write.$i\n");
|
||||||
|
}
|
||||||
|
print "\nContinue (you can skip this confirmation step with --quiet) ? (y|n) [n]";
|
||||||
|
my $answer=<STDIN>;
|
||||||
|
unless ($answer =~ /^\s*y\s*$/i)
|
||||||
|
{
|
||||||
|
print "Nothing done!\n";exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($opt{'clear'} or $opt{'clear-only'})
|
||||||
|
{
|
||||||
|
#do not drop the $db_to_write database !
|
||||||
|
my $i;
|
||||||
|
foreach $i (($info_db, $info_tbl),
|
||||||
|
(($opt{'col'})?$info_col:()),
|
||||||
|
(($opt{'idx'})?$info_idx:()))
|
||||||
|
{
|
||||||
|
$dbh->do("DROP TABLE IF EXISTS $db_to_write.$i");
|
||||||
|
}
|
||||||
|
if ($opt{'clear-only'})
|
||||||
|
{
|
||||||
|
print "Wrote to database $db_to_write .\n" unless ($opt{'quiet'});
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
my %sth;
|
||||||
|
my %extra_col_desc;
|
||||||
|
my %row;
|
||||||
|
my %done_create_table;
|
||||||
|
|
||||||
|
#create the $db_to_write database
|
||||||
|
$dbh->do("CREATE DATABASE IF NOT EXISTS $db_to_write");
|
||||||
|
$dbh->do("USE $db_to_write");
|
||||||
|
|
||||||
|
#get databases
|
||||||
|
$sth{db}=$dbh->prepare("SHOW DATABASES LIKE $db_like_wild");
|
||||||
|
$sth{db}->execute;
|
||||||
|
|
||||||
|
#create $info_db which will receive info about databases.
|
||||||
|
#Ensure that the first column to be called "Database" (as SHOW DATABASES LIKE
|
||||||
|
#returns a varying
|
||||||
|
#column name (of the form "Database (%...)") which is not suitable)
|
||||||
|
$extra_col_desc{db}=do_create_table("db",$info_db,undef,"`Database`");
|
||||||
|
#we'll remember the type of the `Database` column (as returned by
|
||||||
|
#SHOW DATABASES), which we will need when creating the next tables.
|
||||||
|
|
||||||
|
#clear out-of-date info from this table
|
||||||
|
$dbh->do("DELETE FROM $info_db WHERE `Database` LIKE $db_like_wild");
|
||||||
|
|
||||||
|
|
||||||
|
while (@{$row{db}}=$sth{db}->fetchrow_array) #go through all databases
|
||||||
|
{
|
||||||
|
|
||||||
|
#insert the database name
|
||||||
|
$dbh->do("INSERT INTO $info_db VALUES("
|
||||||
|
.join_quote(@{$row{db}}).")");
|
||||||
|
|
||||||
|
#for each database, get tables
|
||||||
|
|
||||||
|
$sth{tbl}=$dbh->prepare("SHOW TABLE"
|
||||||
|
.( ($opt{'tbl-status'}) ?
|
||||||
|
" STATUS"
|
||||||
|
: "S" )
|
||||||
|
." from `${$row{db}}[0]` LIKE $tbl_like_wild");
|
||||||
|
$sth{tbl}->execute;
|
||||||
|
unless ($done_create_table{$info_tbl})
|
||||||
|
|
||||||
|
#tables must be created only once, and out-of-date info must be
|
||||||
|
#cleared once
|
||||||
|
{
|
||||||
|
$done_create_table{$info_tbl}=1;
|
||||||
|
$extra_col_desc{table}=
|
||||||
|
do_create_table("tbl",$info_tbl,
|
||||||
|
#add an extra column (database name) at the left
|
||||||
|
#and ensure that the table name will be called "Table"
|
||||||
|
#(this is unncessesary with
|
||||||
|
#SHOW TABLE STATUS, but necessary with SHOW TABLES (which returns a column
|
||||||
|
#named "Tables_in_..."))
|
||||||
|
"`Database` ".$extra_col_desc{db},"`Table`");
|
||||||
|
$dbh->do("DELETE FROM $info_tbl WHERE `Database` LIKE $db_like_wild AND `Table` LIKE $tbl_like_wild");
|
||||||
|
}
|
||||||
|
|
||||||
|
while (@{$row{tbl}}=$sth{tbl}->fetchrow_array)
|
||||||
|
{
|
||||||
|
$dbh->do("INSERT INTO $info_tbl VALUES("
|
||||||
|
.$dbh->quote(${$row{db}}[0]).",".join_quote(@{$row{tbl}}).")");
|
||||||
|
|
||||||
|
#for each table, get columns...
|
||||||
|
|
||||||
|
if ($opt{'col'})
|
||||||
|
{
|
||||||
|
$sth{col}=$dbh->prepare("SHOW COLUMNS FROM `${$row{tbl}}[0]` FROM `${$row{db}}[0]`");
|
||||||
|
$sth{col}->execute;
|
||||||
|
unless ($done_create_table{$info_col})
|
||||||
|
{
|
||||||
|
$done_create_table{$info_col}=1;
|
||||||
|
do_create_table("col",$info_col,
|
||||||
|
"`Database` ".$extra_col_desc{db}.","
|
||||||
|
."`Table` ".$extra_col_desc{table}.","
|
||||||
|
."`Seq_in_table` BIGINT(3)");
|
||||||
|
#We need to add a sequence number (1 for the first column of the table,
|
||||||
|
#2 for the second etc) so that users are able to retrieve columns in order
|
||||||
|
#if they want. This is not needed for INDEX
|
||||||
|
#(where there is already Seq_in_index)
|
||||||
|
$dbh->do("DELETE FROM $info_col WHERE `Database`
|
||||||
|
LIKE $db_like_wild
|
||||||
|
AND `Table` LIKE $tbl_like_wild");
|
||||||
|
}
|
||||||
|
my $col_number=0;
|
||||||
|
while (@{$row{col}}=$sth{col}->fetchrow_array)
|
||||||
|
{
|
||||||
|
$dbh->do("INSERT INTO $info_col VALUES("
|
||||||
|
.$dbh->quote(${$row{db}}[0]).","
|
||||||
|
.$dbh->quote(${$row{tbl}}[0]).","
|
||||||
|
.++$col_number.","
|
||||||
|
.join_quote(@{$row{col}}).")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#and get index.
|
||||||
|
|
||||||
|
if ($opt{'idx'})
|
||||||
|
{
|
||||||
|
$sth{idx}=$dbh->prepare("SHOW INDEX FROM `${$row{tbl}}[0]` FROM `${$row{db}}[0]`");
|
||||||
|
$sth{idx}->execute;
|
||||||
|
unless ($done_create_table{$info_idx})
|
||||||
|
{
|
||||||
|
$done_create_table{$info_idx}=1;
|
||||||
|
do_create_table("idx",$info_idx,
|
||||||
|
"`Database` ".$extra_col_desc{db});
|
||||||
|
$dbh->do("DELETE FROM $info_idx WHERE `Database`
|
||||||
|
LIKE $db_like_wild
|
||||||
|
AND `Table` LIKE $tbl_like_wild");
|
||||||
|
}
|
||||||
|
while (@{$row{idx}}=$sth{idx}->fetchrow_array)
|
||||||
|
{
|
||||||
|
$dbh->do("INSERT INTO $info_idx VALUES("
|
||||||
|
.$dbh->quote(${$row{db}}[0]).","
|
||||||
|
.join_quote(@{$row{idx}}).")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print "Wrote to database $db_to_write .\n" unless ($opt{'quiet'});
|
||||||
|
exit;
|
||||||
|
|
||||||
|
sub join_quote
|
||||||
|
{
|
||||||
|
my (@list)=@_; my $i;
|
||||||
|
foreach $i (@list) { $i=$dbh->quote($i); }
|
||||||
|
return (join ',',@list);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub do_create_table
|
||||||
|
{
|
||||||
|
my ($sth_key,$target_tbl,$extra_col_desc,$first_col_name)=@_;
|
||||||
|
my $create_table_query=$extra_col_desc;
|
||||||
|
my ($i,$type,$first_col_desc,$col_desc);
|
||||||
|
|
||||||
|
for ($i=0;$i<$sth{$sth_key}->{NUM_OF_FIELDS};$i++)
|
||||||
|
{
|
||||||
|
if ($create_table_query) { $create_table_query.=", "; }
|
||||||
|
$type=$sth{$sth_key}->{mysql_type_name}->[$i];
|
||||||
|
$col_desc=$type;
|
||||||
|
if ($type =~ /char|int/i)
|
||||||
|
{
|
||||||
|
$col_desc.="($sth{$sth_key}->{PRECISION}->[$i])";
|
||||||
|
}
|
||||||
|
elsif ($type =~ /decimal|numeric/i) #(never seen that)
|
||||||
|
{
|
||||||
|
$col_desc.=
|
||||||
|
"($sth{$sth_key}->{PRECISION}->[$i],$sth{$sth_key}->{SCALE}->[$i])";
|
||||||
|
}
|
||||||
|
elsif ($type !~ /date/i) #date and datetime are OK,
|
||||||
|
#no precision or scale for them
|
||||||
|
{
|
||||||
|
warn "unexpected column type '$type'
|
||||||
|
(neither 'char','int','decimal|numeric')
|
||||||
|
when creating $target_tbl, hope table creation will go OK\n";
|
||||||
|
}
|
||||||
|
if ($i==0) {$first_col_desc=$col_desc};
|
||||||
|
$create_table_query.=
|
||||||
|
( ($i==0 and $first_col_name) ?
|
||||||
|
"$first_col_name " :"`$sth{$sth_key}->{NAME}->[$i]` " )
|
||||||
|
.$col_desc;
|
||||||
|
}
|
||||||
|
if ($create_table_query)
|
||||||
|
{
|
||||||
|
$dbh->do("CREATE TABLE IF NOT EXISTS $target_tbl ($create_table_query)");
|
||||||
|
}
|
||||||
|
return $first_col_desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
__END__
|
||||||
|
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
mysql_tableinfo asks a MySQL server information about its
|
||||||
|
databases, tables, table columns and index, and stores this
|
||||||
|
in tables called `db`, `tbl` (or `tbl_status`), `col`, `idx`
|
||||||
|
(with an optional prefix specified with --prefix).
|
||||||
|
After that, you can query these information tables, for example
|
||||||
|
to build your admin scripts with SQL queries, like
|
||||||
|
|
||||||
|
SELECT CONCAT("CHECK TABLE ",`database`,".",`table`," EXTENDED;")
|
||||||
|
FROM info.tbl WHERE ... ;
|
||||||
|
|
||||||
|
as people usually do with some other RDBMS
|
||||||
|
(note: to increase the speed of your queries on the info tables,
|
||||||
|
you may add some index on them).
|
||||||
|
|
||||||
|
The database_like_wild and table_like_wild instructs the program
|
||||||
|
to gather information only about databases and tables
|
||||||
|
whose names match these patterns. If the info
|
||||||
|
tables already exist, their rows matching the patterns are simply
|
||||||
|
deleted and replaced by the new ones. That is,
|
||||||
|
old rows not matching the patterns are not touched.
|
||||||
|
If the database_like_wild and table_like_wild arguments
|
||||||
|
are not specified on the command-line they default to "%".
|
||||||
|
|
||||||
|
The program :
|
||||||
|
|
||||||
|
- does CREATE DATABASE IF NOT EXISTS database_to_write
|
||||||
|
where database_to_write is the database name specified on the command-line.
|
||||||
|
|
||||||
|
- does CREATE TABLE IF NOT EXISTS database_to_write.`db`
|
||||||
|
|
||||||
|
- fills database_to_write.`db` with the output of
|
||||||
|
SHOW DATABASES LIKE database_like_wild
|
||||||
|
|
||||||
|
- does CREATE TABLE IF NOT EXISTS database_to_write.`tbl`
|
||||||
|
(respectively database_to_write.`tbl_status`
|
||||||
|
if the --tbl-status option is on)
|
||||||
|
|
||||||
|
- for every found database,
|
||||||
|
fills database_to_write.`tbl` (respectively database_to_write.`tbl_status`)
|
||||||
|
with the output of
|
||||||
|
SHOW TABLES FROM found_db LIKE table_like_wild
|
||||||
|
(respectively SHOW TABLE STATUS FROM found_db LIKE table_like_wild)
|
||||||
|
|
||||||
|
- if the --col option is on,
|
||||||
|
* does CREATE TABLE IF NOT EXISTS database_to_write.`col`
|
||||||
|
* for every found table,
|
||||||
|
fills database_to_write.`col` with the output of
|
||||||
|
SHOW COLUMNS FROM found_tbl FROM found_db
|
||||||
|
|
||||||
|
- if the --idx option is on,
|
||||||
|
* does CREATE TABLE IF NOT EXISTS database_to_write.`idx`
|
||||||
|
* for every found table,
|
||||||
|
fills database_to_write.`idx` with the output of
|
||||||
|
SHOW INDEX FROM found_tbl FROM found_db
|
||||||
|
|
||||||
|
Some options may modify this general scheme (see below).
|
||||||
|
|
||||||
|
As mentioned, the contents of the info tables are the output of
|
||||||
|
SHOW commands. In fact the contents are slightly more complete :
|
||||||
|
|
||||||
|
- the `tbl` (or `tbl_status`) info table
|
||||||
|
has an extra column which contains the database name,
|
||||||
|
|
||||||
|
- the `col` info table
|
||||||
|
has an extra column which contains the table name,
|
||||||
|
and an extra column which contains, for each described column,
|
||||||
|
the number of this column in the table owning it (this extra column
|
||||||
|
is called `Seq_in_table`). `Seq_in_table` makes it possible for you
|
||||||
|
to retrieve your columns in sorted order, when you are querying
|
||||||
|
the `col` table.
|
||||||
|
|
||||||
|
- the `index` info table
|
||||||
|
has an extra column which contains the database name.
|
||||||
|
|
||||||
|
Caution: info tables contain certain columns (e.g.
|
||||||
|
Database, Table, Null...) whose names, as they are MySQL reserved words,
|
||||||
|
need to be backquoted (`...`) when used in SQL statements.
|
||||||
|
|
||||||
|
=head1 OPTIONS
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item --clear
|
||||||
|
|
||||||
|
Does DROP TABLE on the info tables (only those that the program is
|
||||||
|
going to fill, for example if you do not use --col it won't drop
|
||||||
|
the `col` table) and processes normally. Does not drop database_to_write.
|
||||||
|
|
||||||
|
=item --clear-only
|
||||||
|
|
||||||
|
Same as --clear but exits after the DROPs.
|
||||||
|
|
||||||
|
=item --col
|
||||||
|
|
||||||
|
Adds columns information (into table `col`).
|
||||||
|
|
||||||
|
=item --idx
|
||||||
|
|
||||||
|
Adds index information (into table `idx`).
|
||||||
|
|
||||||
|
=item --prefix prefix
|
||||||
|
|
||||||
|
The info tables are named from the concatenation of prefix and,
|
||||||
|
respectively, db, tbl (or tbl_status), col, idx. Do not quote ('')
|
||||||
|
or backquote (``) prefix.
|
||||||
|
|
||||||
|
=item -q, --quiet
|
||||||
|
|
||||||
|
Does not warn you about what the script is going to do (DROP TABLE etc)
|
||||||
|
and does not ask for a confirmation before starting.
|
||||||
|
|
||||||
|
=item --tbl-status
|
||||||
|
|
||||||
|
Instead of using SHOW TABLES, uses SHOW TABLE STATUS
|
||||||
|
(much more complete information, but slower).
|
||||||
|
|
||||||
|
=item --help
|
||||||
|
|
||||||
|
Display helpscreen and exit
|
||||||
|
|
||||||
|
=item -u, --user=#
|
||||||
|
|
||||||
|
user for database login if not current user. Give a user
|
||||||
|
who has sufficient privileges (CREATE, ...).
|
||||||
|
|
||||||
|
=item -p, --password=#
|
||||||
|
|
||||||
|
password to use when connecting to server
|
||||||
|
|
||||||
|
=item -h, --host=#
|
||||||
|
|
||||||
|
host to connect to
|
||||||
|
|
||||||
|
=item -P, --port=#
|
||||||
|
|
||||||
|
port to use when connecting to server
|
||||||
|
|
||||||
|
=item -S, --socket=#
|
||||||
|
|
||||||
|
UNIX domain socket to use when connecting to server
|
||||||
|
|
||||||
|
=head1 WARRANTY
|
||||||
|
|
||||||
|
This software is free and comes without warranty of any kind. You
|
||||||
|
should never trust backup software without studying the code yourself.
|
||||||
|
Study the code inside this script and only rely on it if I<you> believe
|
||||||
|
that it does the right thing for you.
|
||||||
|
|
||||||
|
Patches adding bug fixes, documentation and new features are welcome.
|
||||||
|
|
||||||
|
=head1 TO DO
|
||||||
|
|
||||||
|
Use extended inserts to be faster (for servers with many databases
|
||||||
|
or tables). But to do that, must care about net-buffer-length.
|
||||||
|
|
||||||
|
=head1 AUTHOR
|
||||||
|
|
||||||
|
2002-06-18 Guilhem Bichot (guilhem.bichot@mines-paris.org)
|
||||||
|
|
||||||
|
And all the authors of mysqlhotcopy, which served as a model for
|
||||||
|
the structure of the program.
|
@ -38,7 +38,7 @@
|
|||||||
# as such, and clarify ones such as "mediumint" with comments such as
|
# as such, and clarify ones such as "mediumint" with comments such as
|
||||||
# "3-byte int" or "same as xxx".
|
# "3-byte int" or "same as xxx".
|
||||||
|
|
||||||
$version="1.57";
|
$version="1.58";
|
||||||
|
|
||||||
use DBI;
|
use DBI;
|
||||||
use Getopt::Long;
|
use Getopt::Long;
|
||||||
@ -2186,20 +2186,20 @@ EOF
|
|||||||
print <<EOF;
|
print <<EOF;
|
||||||
|
|
||||||
Some of the tests you are about to execute may require a lot of
|
Some of the tests you are about to execute may require a lot of
|
||||||
memory. Your tests WILL adversely affect system performance. It's
|
memory. Your tests WILL adversely affect system performance. It\'s
|
||||||
not uncommon that either this crash-me test program, or the actual
|
not uncommon that either this crash-me test program, or the actual
|
||||||
database back-end, will DIE with an out-of-memory error. So might
|
database back-end, will DIE with an out-of-memory error. So might
|
||||||
any other program on your system if it requests more memory at the
|
any other program on your system if it requests more memory at the
|
||||||
wrong time.
|
wrong time.
|
||||||
|
|
||||||
Note also that while crash-me tries to find limits for the database server
|
Note also that while crash-me tries to find limits for the database server
|
||||||
it will make a lot of queries that can't be categorized as 'normal'. It's
|
it will make a lot of queries that can\'t be categorized as \'normal\'. It\'s
|
||||||
not unlikely that crash-me finds some limit bug in your server so if you
|
not unlikely that crash-me finds some limit bug in your server so if you
|
||||||
run this test you have to be prepared that your server may die during it!
|
run this test you have to be prepared that your server may die during it!
|
||||||
|
|
||||||
We, the creators of this utility, are not responsible in any way if your
|
We, the creators of this utility, are not responsible in any way if your
|
||||||
database server unexpectedly crashes while this program tries to find the
|
database server unexpectedly crashes while this program tries to find the
|
||||||
limitations of your server. By accepting the following question with 'yes',
|
limitations of your server. By accepting the following question with \'yes\',
|
||||||
you agree to the above!
|
you agree to the above!
|
||||||
|
|
||||||
You have been warned!
|
You have been warned!
|
||||||
@ -2468,7 +2468,6 @@ sub report
|
|||||||
print "$prompt: ";
|
print "$prompt: ";
|
||||||
if (!defined($limits{$limit}))
|
if (!defined($limits{$limit}))
|
||||||
{
|
{
|
||||||
save_config_data($limit,"incompleted",$prompt);
|
|
||||||
save_config_data($limit,safe_query(\@queries) ? "yes" : "no",$prompt);
|
save_config_data($limit,safe_query(\@queries) ? "yes" : "no",$prompt);
|
||||||
}
|
}
|
||||||
print "$limits{$limit}\n";
|
print "$limits{$limit}\n";
|
||||||
@ -2481,7 +2480,6 @@ sub report_fail
|
|||||||
print "$prompt: ";
|
print "$prompt: ";
|
||||||
if (!defined($limits{$limit}))
|
if (!defined($limits{$limit}))
|
||||||
{
|
{
|
||||||
save_config_data($limit,"incompleted",$prompt);
|
|
||||||
save_config_data($limit,safe_query(\@queries) ? "no" : "yes",$prompt);
|
save_config_data($limit,safe_query(\@queries) ? "no" : "yes",$prompt);
|
||||||
}
|
}
|
||||||
print "$limits{$limit}\n";
|
print "$limits{$limit}\n";
|
||||||
@ -2498,7 +2496,7 @@ sub report_one
|
|||||||
print "$prompt: ";
|
print "$prompt: ";
|
||||||
if (!defined($limits{$limit}))
|
if (!defined($limits{$limit}))
|
||||||
{
|
{
|
||||||
save_config_data($limit,"incompleted",$prompt);
|
save_incomplete($limit,$prompt);
|
||||||
$result="no";
|
$result="no";
|
||||||
foreach $query (@$queries)
|
foreach $query (@$queries)
|
||||||
{
|
{
|
||||||
@ -2524,7 +2522,7 @@ sub report_result
|
|||||||
print "$prompt: ";
|
print "$prompt: ";
|
||||||
if (!defined($limits{$limit}))
|
if (!defined($limits{$limit}))
|
||||||
{
|
{
|
||||||
save_config_data($limit,"incompleted",$prompt);
|
save_incomplete($limit,$prompt);
|
||||||
$error=safe_query_result($query,"1",2);
|
$error=safe_query_result($query,"1",2);
|
||||||
save_config_data($limit,$error ? "not supported" : $last_result,$prompt);
|
save_config_data($limit,$error ? "not supported" : $last_result,$prompt);
|
||||||
}
|
}
|
||||||
@ -2537,7 +2535,7 @@ sub report_trans
|
|||||||
my ($limit,$queries,$check,$clear)=@_;
|
my ($limit,$queries,$check,$clear)=@_;
|
||||||
if (!defined($limits{$limit}))
|
if (!defined($limits{$limit}))
|
||||||
{
|
{
|
||||||
save_config_data($limit,"incompleted",$prompt);
|
save_incomplete($limit,$prompt);
|
||||||
eval {undef($dbh->{AutoCommit})};
|
eval {undef($dbh->{AutoCommit})};
|
||||||
if (!$@)
|
if (!$@)
|
||||||
{
|
{
|
||||||
@ -2579,7 +2577,7 @@ sub check_and_report
|
|||||||
print "$prompt: " if (!defined($skip_prompt));
|
print "$prompt: " if (!defined($skip_prompt));
|
||||||
if (!defined($limits{$limit}))
|
if (!defined($limits{$limit}))
|
||||||
{
|
{
|
||||||
save_config_data($limit,"incompleted",$prompt);
|
save_incomplete($limit,$prompt);
|
||||||
$tmp=1-safe_query(\@$pre);
|
$tmp=1-safe_query(\@$pre);
|
||||||
$tmp=safe_query_result($query,$answer,$string_type) if (!$tmp);
|
$tmp=safe_query_result($query,$answer,$string_type) if (!$tmp);
|
||||||
safe_query(\@$post);
|
safe_query(\@$post);
|
||||||
@ -2615,7 +2613,7 @@ sub try_and_report
|
|||||||
|
|
||||||
if (!defined($limits{$limit}))
|
if (!defined($limits{$limit}))
|
||||||
{
|
{
|
||||||
save_config_data($limit,"incompleted",$prompt);
|
save_incomplete($limit,$prompt);
|
||||||
$type="no"; # Not supported
|
$type="no"; # Not supported
|
||||||
foreach $test (@tests)
|
foreach $test (@tests)
|
||||||
{
|
{
|
||||||
@ -2695,7 +2693,8 @@ sub safe_query_result
|
|||||||
$sth->finish;
|
$sth->finish;
|
||||||
return ($result_type == 8) ? 0 : 1;
|
return ($result_type == 8) ? 0 : 1;
|
||||||
}
|
}
|
||||||
if($result_type == 8) {
|
if ($result_type == 8)
|
||||||
|
{
|
||||||
$sth->finish;
|
$sth->finish;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -2787,7 +2786,7 @@ sub find_limit()
|
|||||||
print "$end (cache)\n";
|
print "$end (cache)\n";
|
||||||
return $end;
|
return $end;
|
||||||
}
|
}
|
||||||
save_config_data($limit,"incompleted",$prompt);
|
save_incomplete($limit,$prompt);
|
||||||
|
|
||||||
if (defined($query->{'init'}) && !defined($end=$limits{'restart'}{'tohigh'}))
|
if (defined($query->{'init'}) && !defined($end=$limits{'restart'}{'tohigh'}))
|
||||||
{
|
{
|
||||||
@ -2961,6 +2960,16 @@ sub save_all_config_data
|
|||||||
close CONFIG_FILE;
|
close CONFIG_FILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Save 'incomplete' in the limits file to be able to continue if
|
||||||
|
# crash-me dies because of a bug in perl/DBI
|
||||||
|
|
||||||
|
sub save_incomplete
|
||||||
|
{
|
||||||
|
my ($limit,$prompt)= @_;
|
||||||
|
save_config_data($limit,"incompleted",$prompt) if ($opt_restart);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
sub check_repeat
|
sub check_repeat
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#This file is automaticly generated by crash-me 1.57
|
#This file is automaticly generated by crash-me 1.58
|
||||||
|
|
||||||
NEG=yes # update of column= -column
|
NEG=yes # update of column= -column
|
||||||
Need_cast_for_null=no # Need to cast NULL for arithmetic
|
Need_cast_for_null=no # Need to cast NULL for arithmetic
|
||||||
@ -36,7 +36,7 @@ constraint_check=no # Column constraints
|
|||||||
constraint_check_table=no # Table constraints
|
constraint_check_table=no # Table constraints
|
||||||
constraint_null=yes # NULL constraint (SyBase style)
|
constraint_null=yes # NULL constraint (SyBase style)
|
||||||
crash_me_safe=yes # crash me safe
|
crash_me_safe=yes # crash me safe
|
||||||
crash_me_version=1.57 # crash me version
|
crash_me_version=1.58 # crash me version
|
||||||
create_default=yes # default value for column
|
create_default=yes # default value for column
|
||||||
create_default_func=no # default value function for column
|
create_default_func=no # default value function for column
|
||||||
create_if_not_exists=yes # create table if not exists
|
create_if_not_exists=yes # create table if not exists
|
||||||
@ -333,7 +333,7 @@ max_char_size=255 # max char() size
|
|||||||
max_column_name=64 # column name length
|
max_column_name=64 # column name length
|
||||||
max_columns=3398 # Columns in table
|
max_columns=3398 # Columns in table
|
||||||
max_conditions=85660 # OR and AND in WHERE
|
max_conditions=85660 # OR and AND in WHERE
|
||||||
max_expressions=856 # simple expressions
|
max_expressions=686 # simple expressions
|
||||||
max_index=32 # max index
|
max_index=32 # max index
|
||||||
max_index_length=500 # index length
|
max_index_length=500 # index length
|
||||||
max_index_name=64 # index name length
|
max_index_name=64 # index name length
|
||||||
@ -343,7 +343,7 @@ max_index_varchar_part_length=255 # index varchar part length
|
|||||||
max_row_length=65534 # max table row length (without blobs)
|
max_row_length=65534 # max table row length (without blobs)
|
||||||
max_row_length_with_null=65502 # table row length with nulls (without blobs)
|
max_row_length_with_null=65502 # table row length with nulls (without blobs)
|
||||||
max_select_alias_name=+512 # select alias name length
|
max_select_alias_name=+512 # select alias name length
|
||||||
max_stack_expression=856 # stacked expressions
|
max_stack_expression=490 # stacked expressions
|
||||||
max_table_alias_name=+512 # table alias name length
|
max_table_alias_name=+512 # table alias name length
|
||||||
max_table_name=64 # table name length
|
max_table_name=64 # table name length
|
||||||
max_text_size=1048543 # max text or blob size
|
max_text_size=1048543 # max text or blob size
|
||||||
@ -396,7 +396,7 @@ select_limit2=yes # SELECT with LIMIT #,#
|
|||||||
select_string_size=1048565 # constant string size in SELECT
|
select_string_size=1048565 # constant string size in SELECT
|
||||||
select_table_update=no # Update with sub select
|
select_table_update=no # Update with sub select
|
||||||
select_without_from=yes # SELECT without FROM
|
select_without_from=yes # SELECT without FROM
|
||||||
server_version=MySQL 4.0.2 alpha debug # server version
|
server_version=MySQL 4.0.2 alpha # server version
|
||||||
simple_joins=yes # ANSI SQL simple joins
|
simple_joins=yes # ANSI SQL simple joins
|
||||||
storage_of_float=round # Storage of float values
|
storage_of_float=round # Storage of float values
|
||||||
subqueries=no # subqueries
|
subqueries=no # subqueries
|
||||||
|
@ -57,8 +57,8 @@ void hostname_cache_refresh()
|
|||||||
|
|
||||||
bool hostname_cache_init()
|
bool hostname_cache_init()
|
||||||
{
|
{
|
||||||
host_entry *tmp;
|
host_entry tmp;
|
||||||
uint offset= (uint) ((char*) (&tmp->ip) - (char*) tmp);
|
uint offset= (uint) ((char*) (&tmp.ip) - (char*) &tmp);
|
||||||
(void) pthread_mutex_init(&LOCK_hostname,MY_MUTEX_INIT_SLOW);
|
(void) pthread_mutex_init(&LOCK_hostname,MY_MUTEX_INIT_SLOW);
|
||||||
|
|
||||||
if (!(hostname_cache=new hash_filo(HOST_CACHE_SIZE, offset,
|
if (!(hostname_cache=new hash_filo(HOST_CACHE_SIZE, offset,
|
||||||
|
@ -2047,13 +2047,14 @@ err:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Item_func_match::init_search(bool no_order)
|
void Item_func_match::init_search(bool no_order)
|
||||||
{
|
{
|
||||||
if (ft_handler)
|
if (ft_handler)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (key == NO_SUCH_KEY)
|
if (key == NO_SUCH_KEY)
|
||||||
concat=new Item_func_concat_ws (new Item_string(" ",1), fields);
|
concat= new Item_func_concat_ws(new Item_string(" ",1), fields);
|
||||||
|
|
||||||
if (master)
|
if (master)
|
||||||
{
|
{
|
||||||
@ -2071,7 +2072,7 @@ void Item_func_match::init_search(bool no_order)
|
|||||||
// MATCH ... AGAINST (NULL) is meaningless, but possible
|
// MATCH ... AGAINST (NULL) is meaningless, but possible
|
||||||
if (!(ft_tmp=key_item()->val_str(&tmp2)))
|
if (!(ft_tmp=key_item()->val_str(&tmp2)))
|
||||||
{
|
{
|
||||||
ft_tmp=&tmp2;
|
ft_tmp= &tmp2;
|
||||||
tmp2.set("",0);
|
tmp2.set("",0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2087,6 +2088,7 @@ void Item_func_match::init_search(bool no_order)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist)
|
bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist)
|
||||||
{
|
{
|
||||||
List_iterator<Item> li(fields);
|
List_iterator<Item> li(fields);
|
||||||
|
@ -171,9 +171,22 @@ class Item_num_op :public Item_func
|
|||||||
bool is_null() { (void) val(); return null_value; }
|
bool is_null() { (void) val(); return null_value; }
|
||||||
Field *tmp_table_field(TABLE *t_arg)
|
Field *tmp_table_field(TABLE *t_arg)
|
||||||
{
|
{
|
||||||
if (!t_arg) return result_field;
|
Field *res;
|
||||||
return args[0]->result_type() == INT_RESULT ? ((max_length > 11) ? (Field *)new Field_longlong(max_length,maybe_null,name, t_arg,unsigned_flag) : (Field *)new Field_long(max_length,maybe_null,name, t_arg,unsigned_flag)) : (Field *) new Field_double(max_length, maybe_null, name,t_arg,decimals);
|
if (!t_arg)
|
||||||
}
|
return result_field;
|
||||||
|
if (args[0]->result_type() == INT_RESULT)
|
||||||
|
{
|
||||||
|
if (max_length > 11)
|
||||||
|
res= new Field_longlong(max_length, maybe_null, name, t_arg,
|
||||||
|
unsigned_flag);
|
||||||
|
else
|
||||||
|
res= new Field_long(max_length, maybe_null, name, t_arg,
|
||||||
|
unsigned_flag);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
res= new Field_double(max_length, maybe_null, name, t_arg, decimals);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
|
|||||||
#define MAX_FIELDS_BEFORE_HASH 32
|
#define MAX_FIELDS_BEFORE_HASH 32
|
||||||
#define USER_VARS_HASH_SIZE 16
|
#define USER_VARS_HASH_SIZE 16
|
||||||
#define STACK_MIN_SIZE 8192 // Abort if less stack during eval.
|
#define STACK_MIN_SIZE 8192 // Abort if less stack during eval.
|
||||||
#define STACK_BUFF_ALLOC 32 // For stack overrun checks
|
#define STACK_BUFF_ALLOC 64 // For stack overrun checks
|
||||||
#ifndef MYSQLD_NET_RETRY_COUNT
|
#ifndef MYSQLD_NET_RETRY_COUNT
|
||||||
#define MYSQLD_NET_RETRY_COUNT 10 // Abort read after this many int.
|
#define MYSQLD_NET_RETRY_COUNT 10 // Abort read after this many int.
|
||||||
#endif
|
#endif
|
||||||
|
@ -67,7 +67,9 @@ public:
|
|||||||
SEL_ARG(Field *field, uint8 part, char *min_value, char *max_value,
|
SEL_ARG(Field *field, uint8 part, char *min_value, char *max_value,
|
||||||
uint8 min_flag, uint8 max_flag, uint8 maybe_flag);
|
uint8 min_flag, uint8 max_flag, uint8 maybe_flag);
|
||||||
SEL_ARG(enum Type type_arg)
|
SEL_ARG(enum Type type_arg)
|
||||||
:elements(1),use_count(1),left(0),next_key_part(0),type(type_arg) {}
|
:elements(1),use_count(1),left(0),next_key_part(0),color(BLACK),
|
||||||
|
type(type_arg)
|
||||||
|
{}
|
||||||
inline bool is_same(SEL_ARG *arg)
|
inline bool is_same(SEL_ARG *arg)
|
||||||
{
|
{
|
||||||
if (type != arg->type)
|
if (type != arg->type)
|
||||||
|
@ -345,13 +345,12 @@ char uc_update_queries[SQLCOM_END];
|
|||||||
static bool check_mqh(THD *thd, uint check_command)
|
static bool check_mqh(THD *thd, uint check_command)
|
||||||
{
|
{
|
||||||
bool error=0;
|
bool error=0;
|
||||||
DBUG_ENTER("check_mqh");
|
time_t check_time = thd->start_time ? thd->start_time : time(NULL);
|
||||||
USER_CONN *uc=thd->user_connect;
|
USER_CONN *uc=thd->user_connect;
|
||||||
|
DBUG_ENTER("check_mqh");
|
||||||
DBUG_ASSERT(uc != 0);
|
DBUG_ASSERT(uc != 0);
|
||||||
|
|
||||||
bool my_start = thd->start_time != 0;
|
/* If more than a hour since last check, reset resource checking */
|
||||||
time_t check_time = (my_start) ? thd->start_time : time(NULL);
|
|
||||||
|
|
||||||
if (check_time - uc->intime >= 3600)
|
if (check_time - uc->intime >= 3600)
|
||||||
{
|
{
|
||||||
(void) pthread_mutex_lock(&LOCK_user_conn);
|
(void) pthread_mutex_lock(&LOCK_user_conn);
|
||||||
@ -361,6 +360,7 @@ static bool check_mqh(THD *thd, uint check_command)
|
|||||||
uc->intime=check_time;
|
uc->intime=check_time;
|
||||||
(void) pthread_mutex_unlock(&LOCK_user_conn);
|
(void) pthread_mutex_unlock(&LOCK_user_conn);
|
||||||
}
|
}
|
||||||
|
/* Check that we have not done too many questions / hour */
|
||||||
if (uc->user_resources.questions &&
|
if (uc->user_resources.questions &&
|
||||||
uc->questions++ >= uc->user_resources.questions)
|
uc->questions++ >= uc->user_resources.questions)
|
||||||
{
|
{
|
||||||
@ -371,14 +371,15 @@ static bool check_mqh(THD *thd, uint check_command)
|
|||||||
}
|
}
|
||||||
if (check_command < (uint) SQLCOM_END)
|
if (check_command < (uint) SQLCOM_END)
|
||||||
{
|
{
|
||||||
if (uc->user_resources.updates && uc_update_queries[check_command] &&
|
/* Check that we have not done too many updates / hour */
|
||||||
++(uc->updates) > uc->user_resources.updates)
|
if (uc->user_resources.updates && uc_update_queries[check_command] &&
|
||||||
{
|
uc->updates++ >= uc->user_resources.updates)
|
||||||
net_printf(&thd->net, ER_USER_LIMIT_REACHED, uc->user, "max_updates",
|
{
|
||||||
(long) uc->user_resources.updates);
|
net_printf(&thd->net, ER_USER_LIMIT_REACHED, uc->user, "max_updates",
|
||||||
error=1;
|
(long) uc->user_resources.updates);
|
||||||
goto end;
|
error=1;
|
||||||
}
|
goto end;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
end:
|
end:
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "mysql_priv.h"
|
#include "mysql_priv.h"
|
||||||
#include "sql_select.h"
|
#include "sql_select.h"
|
||||||
#include <hash.h>
|
#include <hash.h>
|
||||||
|
#include <thr_alarm.h>
|
||||||
|
|
||||||
/* Intern key cache variables */
|
/* Intern key cache variables */
|
||||||
extern "C" pthread_mutex_t THR_LOCK_keycache;
|
extern "C" pthread_mutex_t THR_LOCK_keycache;
|
||||||
@ -239,6 +240,17 @@ Open streams: %10lu\n",
|
|||||||
(ulong) cached_tables(),
|
(ulong) cached_tables(),
|
||||||
(ulong) my_file_opened,
|
(ulong) my_file_opened,
|
||||||
(ulong) my_stream_opened);
|
(ulong) my_stream_opened);
|
||||||
|
|
||||||
|
ALARM_INFO alarm_info;
|
||||||
|
thr_alarm_info(&alarm_info);
|
||||||
|
printf("\nAlarm status:\n\
|
||||||
|
Active alarms: %u\n\
|
||||||
|
Max used alarms: %u\n\
|
||||||
|
Next alarm time: %lu\n",
|
||||||
|
alarm_info.active_alarms,
|
||||||
|
alarm_info.max_used_alarms,
|
||||||
|
alarm_info.next_alarm_time);
|
||||||
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
if (thd)
|
if (thd)
|
||||||
thd->proc_info="malloc";
|
thd->proc_info="malloc";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user