summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/my_getopt.h1
-rw-r--r--include/my_sys.h6
-rw-r--r--include/mysql/plugin.h2
-rw-r--r--libmysql/CMakeLists.txt2
-rw-r--r--libmysql/Makefile.shared2
-rw-r--r--mysql-test/r/variables.result9
-rw-r--r--mysql-test/t/variables.test5
-rw-r--r--mysys/charset.c8
-rw-r--r--mysys/default_modify.c2
-rw-r--r--mysys/hash.c20
-rw-r--r--mysys/mf_getdate.c2
-rw-r--r--mysys/mf_iocache2.c14
-rw-r--r--mysys/mf_pack.c4
-rw-r--r--mysys/mf_path.c2
-rw-r--r--mysys/my_append.c15
-rw-r--r--mysys/my_compress.c13
-rw-r--r--mysys/my_copy.c6
-rw-r--r--mysys/my_gethwaddr.c2
-rw-r--r--mysys/my_getopt.c43
-rw-r--r--mysys/my_getsystime.c186
-rw-r--r--mysys/my_init.c22
-rw-r--r--mysys/my_static.c5
-rw-r--r--mysys/my_static.h2
-rw-r--r--mysys/my_thr_init.c4
-rw-r--r--mysys/mysys_priv.h2
-rw-r--r--mysys/thr_alarm.c12
-rw-r--r--sql-common/client.c4
-rw-r--r--sql/event_data_objects.cc2
-rw-r--r--sql/event_queue.cc2
-rw-r--r--sql/event_scheduler.cc3
-rw-r--r--sql/field.h2
-rw-r--r--sql/item.h7
-rw-r--r--sql/item_cmpfunc.h5
-rw-r--r--sql/item_timefunc.cc2
-rw-r--r--sql/item_xmlfunc.cc2
-rw-r--r--sql/lock.cc2
-rw-r--r--sql/log.cc101
-rw-r--r--sql/log.h16
-rw-r--r--sql/log_event.cc8
-rw-r--r--sql/mysql_priv.h5
-rw-r--r--sql/mysqld.cc59
-rw-r--r--sql/net_serv.cc2
-rw-r--r--sql/parse_file.cc2
-rw-r--r--sql/set_var.cc69
-rw-r--r--sql/set_var.h28
-rw-r--r--sql/slave.cc7
-rw-r--r--sql/sql_cache.h1
-rw-r--r--sql/sql_class.cc3
-rw-r--r--sql/sql_class.h63
-rw-r--r--sql/sql_connect.cc14
-rw-r--r--sql/sql_insert.cc2
-rw-r--r--sql/sql_parse.cc20
-rw-r--r--sql/sql_select.cc8
-rw-r--r--sql/sql_show.cc15
-rw-r--r--sql/sql_table.cc15
-rw-r--r--sql/structs.h10
56 files changed, 625 insertions, 245 deletions
diff --git a/include/my_getopt.h b/include/my_getopt.h
index 115abf00618..c74f3ed672e 100644
--- a/include/my_getopt.h
+++ b/include/my_getopt.h
@@ -31,6 +31,7 @@ C_MODE_START
#define GET_DISABLED 11
#define GET_ENUM 12
#define GET_SET 13
+#define GET_DOUBLE 14
#define GET_ASK_ADDR 128
#define GET_TYPE_MASK 127
diff --git a/include/my_sys.h b/include/my_sys.h
index fb949842e48..c452bd21e15 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -833,7 +833,7 @@ extern my_bool my_compress(uchar *, size_t *, size_t *);
extern my_bool my_uncompress(uchar *, size_t , size_t *);
extern uchar *my_compress_alloc(const uchar *packet, size_t *len,
size_t *complen);
-extern int packfrm(const uchar *, size_t, uchar **, size_t *);
+extern int packfrm(uchar *, size_t, uchar **, size_t *);
extern int unpackfrm(uchar **, size_t *, const uchar *);
extern ha_checksum my_checksum(ha_checksum crc, const uchar *mem,
@@ -846,7 +846,11 @@ extern void my_sleep(ulong m_seconds);
extern uint my_set_max_open_files(uint files);
void my_free_open_file_info(void);
+extern time_t my_time(myf flags);
extern ulonglong my_getsystime(void);
+extern ulonglong my_micro_time();
+extern ulonglong my_micro_time_and_time(time_t *time_arg);
+time_t my_time_possible_from_micro(ulonglong microtime);
extern my_bool my_gethwaddr(uchar *to);
extern int my_getncpus();
diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h
index b87fcc60692..541fa7dfbe6 100644
--- a/include/mysql/plugin.h
+++ b/include/mysql/plugin.h
@@ -110,7 +110,7 @@ enum enum_mysql_show_type
{
SHOW_UNDEF, SHOW_BOOL, SHOW_INT, SHOW_LONG,
SHOW_LONGLONG, SHOW_CHAR, SHOW_CHAR_PTR,
- SHOW_ARRAY, SHOW_FUNC
+ SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE
};
struct st_mysql_show_var {
diff --git a/libmysql/CMakeLists.txt b/libmysql/CMakeLists.txt
index 7d4dcc1e919..c1585e10e25 100644
--- a/libmysql/CMakeLists.txt
+++ b/libmysql/CMakeLists.txt
@@ -63,7 +63,7 @@ ADD_LIBRARY(libmysql SHARED dll.c libmysql.def
../strings/strmov.c ../strings/strnlen.c ../strings/strnmov.c ../strings/strtod.c
../strings/strtoll.c ../strings/strtoull.c ../strings/strxmov.c ../strings/strxnmov.c
../mysys/thr_mutex.c ../mysys/typelib.c ../vio/vio.c ../vio/viosocket.c
- ../vio/viossl.c ../vio/viosslfactories.c ../strings/xml.c)
+ ../vio/viossl.c ../vio/viosslfactories.c ../strings/xml.c ../mysys/my_getsystime.c)
ADD_DEPENDENCIES(libmysql dbug vio mysys strings GenError zlib yassl taocrypt)
TARGET_LINK_LIBRARIES(libmysql mysys strings wsock32)
diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared
index c24c6ab52db..3a2559921f9 100644
--- a/libmysql/Makefile.shared
+++ b/libmysql/Makefile.shared
@@ -68,7 +68,7 @@ mysysobjects1 = my_init.lo my_static.lo my_malloc.lo my_realloc.lo \
mf_iocache2.lo my_seek.lo my_sleep.lo \
my_pread.lo mf_cache.lo md5.lo sha1.lo \
my_getopt.lo my_gethostbyname.lo my_port.lo \
- my_rename.lo my_chsize.lo
+ my_rename.lo my_chsize.lo my_getsystime.lo
sqlobjects = net.lo
sql_cmn_objects = pack.lo client.lo my_time.lo
diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result
index ff43993cfdb..e6d09306fcb 100644
--- a/mysql-test/r/variables.result
+++ b/mysql-test/r/variables.result
@@ -444,7 +444,14 @@ set interactive_timeout=100;
set join_buffer_size=100;
set last_insert_id=1;
set global local_infile=1;
-set long_query_time=100;
+set long_query_time=0.000001;
+select @@long_query_time;
+@@long_query_time
+0.000001
+set long_query_time=100.000001;
+select @@long_query_time;
+@@long_query_time
+100.000001
set low_priority_updates=1;
set max_allowed_packet=100;
set global max_binlog_cache_size=100;
diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test
index efa2ce4a27c..8f55d83c3de 100644
--- a/mysql-test/t/variables.test
+++ b/mysql-test/t/variables.test
@@ -268,7 +268,10 @@ set interactive_timeout=100;
set join_buffer_size=100;
set last_insert_id=1;
set global local_infile=1;
-set long_query_time=100;
+set long_query_time=0.000001;
+select @@long_query_time;
+set long_query_time=100.000001;
+select @@long_query_time;
set low_priority_updates=1;
set max_allowed_packet=100;
set global max_binlog_cache_size=100;
diff --git a/mysys/charset.c b/mysys/charset.c
index 1c81e480404..cc1a238f281 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -323,14 +323,14 @@ static int charset_initialized=0;
static my_bool my_read_charset_file(const char *filename, myf myflags)
{
- char *buf;
+ uchar *buf;
int fd;
uint len, tmp_len;
MY_STAT stat_info;
if (!my_stat(filename, &stat_info, MYF(myflags)) ||
((len= (uint)stat_info.st_size) > MY_MAX_ALLOWED_BUF) ||
- !(buf= (char *)my_malloc(len,myflags)))
+ !(buf= (uchar*) my_malloc(len,myflags)))
return TRUE;
if ((fd=my_open(filename,O_RDONLY,myflags)) < 0)
@@ -340,7 +340,7 @@ static my_bool my_read_charset_file(const char *filename, myf myflags)
if (tmp_len != len)
goto error;
- if (my_parse_charset_xml(buf,len,add_collation))
+ if (my_parse_charset_xml((char*) buf,len,add_collation))
{
#ifdef NOT_YET
printf("ERROR at line %d pos %d '%s'\n",
@@ -350,7 +350,7 @@ static my_bool my_read_charset_file(const char *filename, myf myflags)
#endif
}
- my_free(buf, myflags);
+ my_free(buf, myflags);
return FALSE;
error:
diff --git a/mysys/default_modify.c b/mysys/default_modify.c
index b2a43f511b9..78f6105b071 100644
--- a/mysys/default_modify.c
+++ b/mysys/default_modify.c
@@ -218,7 +218,7 @@ int modify_defaults_file(const char *file_location, const char *option,
if (my_chsize(fileno(cnf_file), (my_off_t) (dst_ptr - file_buffer), 0,
MYF(MY_WME)) ||
my_fseek(cnf_file, 0, MY_SEEK_SET, MYF(0)) ||
- my_fwrite(cnf_file, file_buffer, (size_t) (dst_ptr - file_buffer),
+ my_fwrite(cnf_file, (uchar*) file_buffer, (size_t) (dst_ptr - file_buffer),
MYF(MY_NABP)))
goto err;
}
diff --git a/mysys/hash.c b/mysys/hash.c
index 47ddc5aa97d..4532b06b533 100644
--- a/mysys/hash.c
+++ b/mysys/hash.c
@@ -137,7 +137,7 @@ void my_hash_reset(HASH *hash)
DBUG_VOID_RETURN;
}
- /* some helper functions */
+/* some helper functions */
/*
This function is char* instead of uchar* as HPUX11 compiler can't
@@ -149,9 +149,9 @@ hash_key(const HASH *hash, const uchar *record, size_t *length,
my_bool first)
{
if (hash->get_key)
- return (*hash->get_key)(record,length,first);
+ return (char*) (*hash->get_key)(record,length,first);
*length=hash->key_length;
- return (uchar*) record+hash->key_offset;
+ return (char*) record+hash->key_offset;
}
/* Calculate pos according to keys */
@@ -313,12 +313,14 @@ my_bool my_hash_insert(HASH *info,const uchar *record)
uchar *ptr_to_rec,*ptr_to_rec2;
HASH_LINK *data,*empty,*gpos,*gpos2,*pos;
- LINT_INIT(gpos); LINT_INIT(gpos2);
- LINT_INIT(ptr_to_rec); LINT_INIT(ptr_to_rec2);
+ LINT_INIT(gpos);
+ LINT_INIT(gpos2);
+ LINT_INIT(ptr_to_rec);
+ LINT_INIT(ptr_to_rec2);
if (HASH_UNIQUE & info->flags)
{
- char *key= (char*) hash_key(info, record, &idx, 1);
+ uchar *key= (uchar*) hash_key(info, record, &idx, 1);
if (hash_search(info, key, idx))
return(TRUE); /* Duplicate entry */
}
@@ -544,14 +546,16 @@ my_bool hash_update(HASH *hash, uchar *record, uchar *old_key,
if (HASH_UNIQUE & hash->flags)
{
HASH_SEARCH_STATE state;
- char *found, *new_key= hash_key(hash, record, &idx, 1);
+ uchar *found, *new_key= (uchar*) hash_key(hash, record, &idx, 1);
if ((found= hash_first(hash, new_key, idx, &state)))
+ {
do
{
- if (found != (char*) record)
+ if (found != record)
DBUG_RETURN(1); /* Duplicate entry */
}
while ((found= hash_next(hash, new_key, idx, &state)));
+ }
}
data=dynamic_element(&hash->array,0,HASH_LINK*);
diff --git a/mysys/mf_getdate.c b/mysys/mf_getdate.c
index 2f08027a477..3a8e1be6a0b 100644
--- a/mysys/mf_getdate.c
+++ b/mysys/mf_getdate.c
@@ -42,7 +42,7 @@ void get_date(register char * to, int flag, time_t date)
struct tm tm_tmp;
#endif
- skr=date ? (time_t) date : time((time_t*) 0);
+ skr=date ? (time_t) date : my_time(0);
#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT)
if (flag & GETDATE_GMT)
localtime_r(&skr,&tm_tmp);
diff --git a/mysys/mf_iocache2.c b/mysys/mf_iocache2.c
index 8a5b91661c4..87ea995f518 100644
--- a/mysys/mf_iocache2.c
+++ b/mysys/mf_iocache2.c
@@ -246,7 +246,7 @@ size_t my_b_gets(IO_CACHE *info, char *to, size_t max_length)
for (;;)
{
- char *pos,*end;
+ uchar *pos, *end;
if (length > max_length)
length=max_length;
for (pos=info->read_pos,end=pos+length ; pos < end ;)
@@ -323,7 +323,7 @@ size_t my_b_vprintf(IO_CACHE *info, const char* fmt, va_list args)
length= (size_t) (fmt - start);
out_length+=length;
- if (my_b_write(info, start, length))
+ if (my_b_write(info, (const uchar*) start, length))
goto err;
if (*fmt == '\0') /* End of format */
@@ -378,14 +378,14 @@ size_t my_b_vprintf(IO_CACHE *info, const char* fmt, va_list args)
size_t length2 = strlen(par);
/* TODO: implement minimum width and precision */
out_length+= length2;
- if (my_b_write(info, par, length2))
+ if (my_b_write(info, (uchar*) par, length2))
goto err;
}
else if (*fmt == 'b') /* Sized buffer parameter, only precision makes sense */
{
char *par = va_arg(args, char *);
out_length+= precision;
- if (my_b_write(info, par, precision))
+ if (my_b_write(info, (uchar*) par, precision))
goto err;
}
else if (*fmt == 'd' || *fmt == 'u') /* Integer parameter */
@@ -400,7 +400,7 @@ size_t my_b_vprintf(IO_CACHE *info, const char* fmt, va_list args)
else
length2= (size_t) (int10_to_str((long) (uint) iarg,buff,10)- buff);
out_length+= length2;
- if (my_b_write(info, buff, length2))
+ if (my_b_write(info, (uchar*) buff, length2))
goto err;
}
else if ((*fmt == 'l' && fmt[1] == 'd') || fmt[1] == 'u')
@@ -416,13 +416,13 @@ size_t my_b_vprintf(IO_CACHE *info, const char* fmt, va_list args)
else
length2= (size_t) (int10_to_str(iarg,buff,10)- buff);
out_length+= length2;
- if (my_b_write(info, buff, length2))
+ if (my_b_write(info, (uchar*) buff, length2))
goto err;
}
else
{
/* %% or unknown code */
- if (my_b_write(info, backtrack, fmt-backtrack))
+ if (my_b_write(info, (uchar*) backtrack, (size_t) (fmt-backtrack)))
goto err;
out_length+= fmt-backtrack;
}
diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c
index 99c0c959d94..a31b9595c85 100644
--- a/mysys/mf_pack.c
+++ b/mysys/mf_pack.c
@@ -56,7 +56,7 @@ void pack_dirname(char * to, const char *from)
(buff_length == d_length && !bcmp(buff,start,d_length))) &&
*start != FN_LIBCHAR && *start)
{ /* Put current dir before */
- bchange(to,d_length,buff,buff_length,strlen(to)+1);
+ bchange((uchar*) to, d_length, (uchar*) buff, buff_length, strlen(to)+1);
}
}
@@ -328,7 +328,7 @@ size_t unpack_dirname(char * to, const char *from)
if (buff+h_length < suffix)
bmove(buff+h_length,suffix,length);
else
- bmove_upp(buff+h_length+length,suffix+length,length);
+ bmove_upp((uchar*) buff+h_length+length, (uchar*) suffix+length, length);
bmove(buff,tilde_expansion,h_length);
}
}
diff --git a/mysys/mf_path.c b/mysys/mf_path.c
index 7baded9d715..73e73cb7f76 100644
--- a/mysys/mf_path.c
+++ b/mysys/mf_path.c
@@ -46,7 +46,7 @@ char * my_path(char * to, const char *progname,
if (!test_if_hard_path(to))
{
if (!my_getwd(curr_dir,FN_REFLEN,MYF(0)))
- bchange(to,0,curr_dir, (uint) strlen(curr_dir), (uint) strlen(to)+1);
+ bchange((uchar*) to, 0, (uchar*) curr_dir, strlen(curr_dir), strlen(to)+1);
}
}
else
diff --git a/mysys/my_append.c b/mysys/my_append.c
index ddd3c91e832..35881a959d5 100644
--- a/mysys/my_append.c
+++ b/mysys/my_append.c
@@ -27,21 +27,22 @@ struct utimbuf {
};
#endif
- /* Append a file to another */
-
-int my_append(const char *from, const char *to, myf MyFlags)
+/*
+ Append a file to another
+ NOTES
+ Don't set MY_FNABP or MY_NABP bits on when calling this function
+*/
- /* Dont set MY_FNABP or MY_NABP bits on
- when calling this funktion */
+int my_append(const char *from, const char *to, myf MyFlags)
{
uint Count;
File from_file,to_file;
- char buff[IO_SIZE];
+ uchar buff[IO_SIZE];
DBUG_ENTER("my_append");
DBUG_PRINT("my",("from %s to %s MyFlags %d", from, to, MyFlags));
- from_file=to_file= -1;
+ from_file= to_file= -1;
if ((from_file=my_open(from,O_RDONLY,MyFlags)) >= 0)
{
diff --git a/mysys/my_compress.c b/mysys/my_compress.c
index d495a1c1c6d..bc9f8317487 100644
--- a/mysys/my_compress.c
+++ b/mysys/my_compress.c
@@ -154,17 +154,20 @@ my_bool my_uncompress(uchar *packet, size_t len, size_t *complen)
SYNOPSIS
packfrm()
- data Data reference to frm file data
+ data Data reference to frm file data.
len Length of frm file data
out:pack_data Reference to the pointer to the packed frm data
out:pack_len Length of packed frm file data
+ NOTES
+ data is replaced with compressed content
+
RETURN VALUES
0 Success
>0 Failure
*/
-int packfrm(const uchar *data, size_t len,
+int packfrm(uchar *data, size_t len,
uchar **pack_data, size_t *pack_len)
{
int error;
@@ -178,8 +181,8 @@ int packfrm(const uchar *data, size_t len,
if (my_compress((uchar*)data, &org_len, &comp_len))
goto err;
- DBUG_PRINT("info", ("org_len: %lu comp_len: %lu", org_len, comp_len));
- DBUG_DUMP("compressed", (char*)data, org_len);
+ DBUG_PRINT("info", ("org_len: %lu comp_len: %lu", (ulong) org_len, (ulong) comp_len));
+ DBUG_DUMP("compressed", data, org_len);
error= 2;
blob_len= BLOB_HEADER + org_len;
@@ -235,7 +238,7 @@ int unpackfrm(uchar **unpack_data, size_t *unpack_len,
complen= uint4korr(pack_data+8);
DBUG_PRINT("blob",("ver: %lu complen: %lu orglen: %lu",
- ver, complen, orglen));
+ ver, (ulong) complen, (ulong) orglen));
DBUG_DUMP("blob->data", pack_data + BLOB_HEADER, complen);
if (ver != 1)
diff --git a/mysys/my_copy.c b/mysys/my_copy.c
index 3f8b0695a25..cd741b1eb52 100644
--- a/mysys/my_copy.c
+++ b/mysys/my_copy.c
@@ -54,7 +54,7 @@ int my_copy(const char *from, const char *to, myf MyFlags)
my_bool new_file_stat= 0; /* 1 if we could stat "to" */
int create_flag;
File from_file,to_file;
- char buff[IO_SIZE];
+ uchar buff[IO_SIZE];
MY_STAT stat_buff,new_stat_buff;
DBUG_ENTER("my_copy");
DBUG_PRINT("my",("from %s to %s MyFlags %d", from, to, MyFlags));
@@ -80,10 +80,12 @@ int my_copy(const char *from, const char *to, myf MyFlags)
MyFlags)) < 0)
goto err;
- while ((Count=my_read(from_file,buff,IO_SIZE,MyFlags)) != 0)
+ while ((Count=my_read(from_file, buff, sizeof(buff), MyFlags)) != 0)
+ {
if (Count == (uint) -1 ||
my_write(to_file,buff,Count,MYF(MyFlags | MY_NABP)))
goto err;
+ }
if (my_close(from_file,MyFlags) | my_close(to_file,MyFlags))
DBUG_RETURN(-1); /* Error on close */
diff --git a/mysys/my_gethwaddr.c b/mysys/my_gethwaddr.c
index 01abc02058b..845b5aa4152 100644
--- a/mysys/my_gethwaddr.c
+++ b/mysys/my_gethwaddr.c
@@ -19,7 +19,7 @@
#include "mysys_priv.h"
#include <m_string.h>
-#ifndef MAIN
+#if !defined(__FreeBSD__) || defined(__linux__)
static my_bool memcpy_and_test(uchar *to, uchar *from, uint len)
{
uint i, res=1;
diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c
index 32a5452e451..3a5b130e067 100644
--- a/mysys/my_getopt.c
+++ b/mysys/my_getopt.c
@@ -32,6 +32,7 @@ my_bool getopt_compare_strings(const char *s,
static longlong getopt_ll(char *arg, const struct my_option *optp, int *err);
static ulonglong getopt_ull(char *arg, const struct my_option *optp,
int *err);
+static double getopt_double(char *arg, const struct my_option *optp, int *err);
static void init_variables(const struct my_option *options);
static int setval(const struct my_option *opts, uchar* *value, char *argument,
my_bool set_maximum_value);
@@ -611,6 +612,9 @@ static int setval(const struct my_option *opts, uchar* *value, char *argument,
case GET_ULL:
*((ulonglong*) result_pos)= getopt_ull(argument, opts, &err);
break;
+ case GET_DOUBLE:
+ *((double*) result_pos)= getopt_double(argument, opts, &err);
+ break;
case GET_STR:
*((char**) result_pos)= argument;
break;
@@ -720,7 +724,7 @@ my_bool getopt_compare_strings(register const char *s, register const char *t,
be k|K for kilo, m|M for mega or g|G for giga.
*/
-static longlong eval_num_suffix (char *argument, int *error, char *option_name)
+static longlong eval_num_suffix(char *argument, int *error, char *option_name)
{
char *endchar;
longlong num;
@@ -802,6 +806,37 @@ ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp)
/*
+ Get double value withing ranges
+
+ Evaluates and returns the value that user gave as an argument to a variable.
+
+ RETURN
+ decimal value of arg
+
+ In case of an error, prints an error message and sets *err to
+ EXIT_ARGUMENT_INVALID. Otherwise err is not touched
+*/
+
+static double getopt_double(char *arg, const struct my_option *optp, int *err)
+{
+ double num;
+ int error;
+ char *end= arg + 1000; /* Big enough as *arg is \0 terminated */
+ num= my_strtod(arg, &end, &error);
+ if (end[0] != 0 || error)
+ {
+ fprintf(stderr,
+ "%s: ERROR: Invalid decimal value for option '%s'\n",
+ my_progname, optp->name);
+ *err= EXIT_ARGUMENT_INVALID;
+ return 0.0;
+ }
+ if (optp->max_value && num > (double) optp->max_value)
+ num= (double) optp->max_value;
+ return max(num, (double) optp->min_value);
+}
+
+/*
Init one value to it's default values
SYNOPSIS
@@ -838,6 +873,9 @@ static void init_one_value(const struct my_option *option, uchar* *variable,
case GET_SET:
*((ulonglong*) variable)= (ulonglong) value;
break;
+ case GET_DOUBLE:
+ *((double*) variable)= (double) value;
+ break;
case GET_STR:
/*
Do not clear variable value if it has no default value.
@@ -1052,6 +1090,9 @@ void my_print_variables(const struct my_option *options)
longlong2str(*((ulonglong*) value), buff, 10);
printf("%s\n", buff);
break;
+ case GET_DOUBLE:
+ printf("%g\n", *(double*) value);
+ break;
default:
printf("(Disabled)\n");
break;
diff --git a/mysys/my_getsystime.c b/mysys/my_getsystime.c
index 2fd7eed7778..17ba1232d7a 100644
--- a/mysys/my_getsystime.c
+++ b/mysys/my_getsystime.c
@@ -29,28 +29,17 @@ ulonglong my_getsystime()
clock_gettime(CLOCK_REALTIME, &tp);
return (ulonglong)tp.tv_sec*10000000+(ulonglong)tp.tv_nsec/100;
#elif defined(__WIN__)
-#define OFFSET_TO_EPOC ((__int64) 134774 * 24 * 60 * 60 * 1000 * 1000 * 10)
- static __int64 offset=0, freq;
LARGE_INTEGER t_cnt;
- if (!offset)
+ struct timeval tv;
+ if (query_performance_frequency)
{
- /* strictly speaking there should be a mutex to protect
- initialization section. But my_getsystime() is called from
- UUID() code, and UUID() calls are serialized with a mutex anyway
- */
- LARGE_INTEGER li;
- FILETIME ft;
- GetSystemTimeAsFileTime(&ft);
- li.LowPart=ft.dwLowDateTime;
- li.HighPart=ft.dwHighDateTime;
- offset=li.QuadPart-OFFSET_TO_EPOC;
- QueryPerformanceFrequency(&li);
- freq=li.QuadPart;
QueryPerformanceCounter(&t_cnt);
- offset-=t_cnt.QuadPart/freq*10000000+t_cnt.QuadPart%freq*10000000/freq;
+ return (t_cnt.QuadPart / query_performance_frequency * 10000000+
+ t_cnt.QuadPart % query_performance_frequency * 10000000/
+ query_performance_frequency+query_performance_offset);
}
- QueryPerformanceCounter(&t_cnt);
- return t_cnt.QuadPart/freq*10000000+t_cnt.QuadPart%freq*10000000/freq+offset;
+ gettimeofday(&tv,NULL);
+ return (ulonglong)tv.tv_sec*10000000+(ulonglong)tv.tv_usec*10;
#elif defined(__NETWARE__)
NXTime_t tm;
NXGetTime(NX_SINCE_1970, NX_NSECONDS, &tm);
@@ -62,3 +51,164 @@ ulonglong my_getsystime()
return (ulonglong)tv.tv_sec*10000000+(ulonglong)tv.tv_usec*10;
#endif
}
+
+
+/*
+ Return current time
+
+ SYNOPSIS
+ my_time()
+ flags If MY_WME is set, write error if time call fails
+
+*/
+
+#define DELTA_FOR_SECONDS LL(500000000) /* Half a second */
+
+time_t my_time(myf flags __attribute__((unused)))
+{
+#ifdef HAVE_GETHRTIME
+ static hrtime_t prev_gethrtime= 0;
+ static time_t cur_time= 0;
+
+ hrtime_t cur_gethrtime;
+ pthread_mutex_lock(&THR_LOCK_time);
+ cur_gethrtime= gethrtime();
+ if ((prev_gethrtime - cur_gethrtime) > DELTA_FOR_SECONDS)
+ {
+ cur_time= time(0);
+ prev_gethrtime= cur_gethrtime;
+ }
+ pthread_mutex_unlock(&THR_LOCK_time);
+ return cur_time;
+#else
+ time_t t;
+ /* The following loop is here beacuse time() may fail on some systems */
+ while ((t= time(0)) == (time_t) -1)
+ {
+ if (flags & MY_WME)
+ fprintf(stderr, "%s: Warning: time() call failed\n", my_progname);
+ }
+ return t;
+#endif
+}
+
+
+/*
+ Return time in micro seconds
+
+ SYNOPSIS
+ my_micro_time()
+
+ NOTES
+ This function is to be used to measure performance in micro seconds.
+ As it's not defined whats the start time for the clock, this function
+ us only useful to measure time between two moments.
+
+ For windows platforms we need the frequency value of the CUP. This is
+ initalized in my_init.c through QueryPerformanceFrequency().
+
+ If Windows platform doesn't support QueryPerformanceFrequency() we will
+ obtain the time via GetClockCount, which only supports milliseconds.
+
+ RETURN
+ Value in microseconds from some undefined point in time
+*/
+
+ulonglong my_micro_time()
+{
+ ulonglong newtime;
+#if defined(__WIN__)
+ if (query_performance_frequency)
+ {
+ QueryPerformanceCounter(&newtime);
+ newtime/= (query_performance_frequency * 1000000);
+ }
+ else
+ newtime= (GetTickCount() * 1000; /* GetTickCount only returns milliseconds */
+#elif defined(HAVE_GETHRTIME)
+ return gethrtime()/1000;
+#else
+ struct timeval t;
+ /* The following loop is here because gettimeofday may fail on some systems */
+ while (gettimeofday(&t, NULL) != 0)
+ {}
+ newtime= (ulonglong)t.tv_sec * 1000000 + t.tv_usec;
+#endif /* defined(__WIN__) */
+ return newtime;
+}
+
+
+/*
+ Return time in seconds and timer in microseconds
+
+ SYNOPSIS
+ my_micro_time_and_time()
+ time_arg Will be set to seconds since epoch (00:00:00 UTC, January 1,
+ 1970)
+
+ NOTES
+ This function is to be useful when we need both the time and microtime.
+ For example in MySQL this is used to get the query time start of a query and
+ to measure the time of a query (for the slow query log)
+
+ IMPLEMENTATION
+ Same as my_micro_time()
+
+ RETURN
+ Value in microseconds from some undefined point in time
+*/
+
+ulonglong my_micro_time_and_time(time_t *time_arg)
+{
+ ulonglong newtime;
+#if defined(__WIN__)
+ if (query_performance_frequency)
+ {
+ QueryPerformanceCounter((LARGE_INTEGER *) &newtime);
+ newtime/= (query_performance_frequency * 1000000);
+ }
+ else
+ newtime= (GetTickCount() * 1000; /* GetTickCount only returns milliseconds */
+ (void) time(time_arg);
+#else
+ struct timeval t;
+ /* The following loop is here because gettimeofday may fail on some systems */
+ while (gettimeofday(&t, NULL) != 0)
+ {}
+ *time_arg= t.tv_sec;
+ newtime= (ulonglong)t.tv_sec * 1000000 + t.tv_usec;
+#endif /* defined(__WIN__) */
+ return newtime;
+}
+
+
+/*
+ Returns current time
+
+ SYNOPSIS
+ my_time_possible_from_micro()
+ microtime Value from very recent my_micro_time()
+
+ NOTES
+ This function returns the current time. The microtime argument is only used
+ if my_micro_time() uses a function that can safely be converted to the current
+ time.
+
+ RETURN
+ current time
+*/
+
+time_t my_time_possible_from_micro(ulonglong microtime __attribute__((unused)))
+{
+#if defined(__WIN__)
+ time_t t;
+ while ((t= time(0)) == (time_t) -1)
+ {}
+ return t;
+#elif defined(HAVE_GETHRTIME)
+ return my_time(0); /* Cached time */
+#else
+ return (time_t) (microtime / 1000000);
+#endif /* defined(__WIN__) */
+}
+
diff --git a/mysys/my_init.c b/mysys/my_init.c
index c1337205eb4..8281d7ced99 100644
--- a/mysys/my_init.c
+++ b/mysys/my_init.c
@@ -371,6 +371,28 @@ static void my_win_init(void)
/* chiude la chiave */
RegCloseKey(hSoftMysql) ;
+
+ /* The following is used by time functions */
+#define OFFSET_TO_EPOC ((__int64) 134774 * 24 * 60 * 60 * 1000 * 1000 * 10)
+#define MS 10000000
+ {
+ FILETIME ft;
+ LARGE_INTEGER li, t_cnt;
+ DBUG_ASSERT(sizeof(LARGE_INTEGER) == sizeof(query_performance_frequency));
+ if (QueryPerformanceFrequency((LARGE_INTEGER *)&query_performance_frequency))
+ query_performance_frequency= 0;
+ else
+ {
+ GetSystemTimeAsFileTime(&ft);
+ li.LowPart= ft.dwLowDateTime;
+ li.HighPart= ft.dwHighDateTime;
+ query_performance_offset= li.QuadPart-OFFSET_TO_EPOC;
+ QueryPerformanceCounter(&t_cnt);
+ query_performance_offset-= (t_cnt.QuadPart / query_performance_frequency * MS +
+ t_cnt.QuadPart % query_performance_frequency * MS /
+ query_performance_frequency);
+ }
+ }
DBUG_VOID_RETURN ;
}
diff --git a/mysys/my_static.c b/mysys/my_static.c
index 472cf3b5084..92c959c4c6c 100644
--- a/mysys/my_static.c
+++ b/mysys/my_static.c
@@ -93,6 +93,11 @@ int (*error_handler_hook)(uint error,const char *str,myf MyFlags)=
int (*fatal_error_handler_hook)(uint error,const char *str,myf MyFlags)=
my_message_no_curses;
+#ifdef __WIN__
+/* from my_getsystime.c */
+ulonglong query_performance_frequency, query_performance_offset;
+#endif
+
/* How to disable options */
my_bool NEAR my_disable_locking=0;
my_bool NEAR my_disable_async_io=0;
diff --git a/mysys/my_static.h b/mysys/my_static.h
index 66e6ea1c280..0eca196c1c9 100644
--- a/mysys/my_static.h
+++ b/mysys/my_static.h
@@ -66,6 +66,8 @@ extern struct st_irem *sf_malloc_root;
extern struct st_my_file_info my_file_info_default[MY_NFILE];
+extern ulonglong query_performance_frequency, query_performance_offset;
+
#if defined(THREAD) && !defined(__WIN__)
extern sigset_t my_signals; /* signals blocked by mf_brkhant */
#endif
diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c
index cc33ac3f21c..8b935c895c8 100644
--- a/mysys/my_thr_init.c
+++ b/mysys/my_thr_init.c
@@ -30,7 +30,7 @@ pthread_key(struct st_my_thread_var, THR_KEY_mysys);
#endif /* USE_TLS */
pthread_mutex_t THR_LOCK_malloc,THR_LOCK_open,
THR_LOCK_lock,THR_LOCK_isam,THR_LOCK_myisam,THR_LOCK_heap,
- THR_LOCK_net, THR_LOCK_charset, THR_LOCK_threads;
+ THR_LOCK_net, THR_LOCK_charset, THR_LOCK_threads, THR_LOCK_time;
pthread_cond_t THR_COND_threads;
uint THR_thread_count= 0;
uint my_thread_end_wait_time= 5;
@@ -146,6 +146,7 @@ my_bool my_thread_global_init(void)
pthread_mutex_init(&THR_LOCK_net,MY_MUTEX_INIT_FAST);
pthread_mutex_init(&THR_LOCK_charset,MY_MUTEX_INIT_FAST);
pthread_mutex_init(&THR_LOCK_threads,MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&THR_LOCK_time,MY_MUTEX_INIT_FAST);
pthread_cond_init(&THR_COND_threads, NULL);
#if defined( __WIN__) || defined(OS2)
win_pthread_init();
@@ -202,6 +203,7 @@ void my_thread_global_end(void)
pthread_mutex_destroy(&THR_LOCK_myisam);
pthread_mutex_destroy(&THR_LOCK_heap);
pthread_mutex_destroy(&THR_LOCK_net);
+ pthread_mutex_destroy(&THR_LOCK_time);
pthread_mutex_destroy(&THR_LOCK_charset);
if (all_threads_killed)
{
diff --git a/mysys/mysys_priv.h b/mysys/mysys_priv.h
index 709cfed969a..6e0959ae08c 100644
--- a/mysys/mysys_priv.h
+++ b/mysys/mysys_priv.h
@@ -28,7 +28,7 @@
#include <my_pthread.h>
extern pthread_mutex_t THR_LOCK_malloc, THR_LOCK_open, THR_LOCK_keycache;
extern pthread_mutex_t THR_LOCK_lock, THR_LOCK_isam, THR_LOCK_net;
-extern pthread_mutex_t THR_LOCK_charset;
+extern pthread_mutex_t THR_LOCK_charset, THR_LOCK_time;
#else
#include <my_no_pthread.h>
#endif
diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c
index 81093be3678..2934e724724 100644
--- a/mysys/thr_alarm.c
+++ b/mysys/thr_alarm.c
@@ -157,7 +157,7 @@ my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
DBUG_ENTER("thr_alarm");
DBUG_PRINT("enter",("thread: %s sec: %d",my_thread_name(),sec));
- now=(ulong) time((time_t*) 0);
+ now=(ulong) my_time(0);
pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask);
pthread_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */
if (alarm_aborted > 0)
@@ -351,7 +351,7 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused)))
}
else
{
- ulong now=(ulong) time((time_t*) 0);
+ ulong now=(ulong) my_time(0);
ulong next=now+10-(now%10);
while ((alarm_data=(ALARM*) queue_top(&alarm_queue))->expire_time <= now)
{
@@ -480,7 +480,7 @@ void thr_alarm_info(ALARM_INFO *info)
info->max_used_alarms= max_used_alarms;
if ((info->active_alarms= alarm_queue.elements))
{
- ulong now=(ulong) time((time_t*) 0);
+ ulong now=(ulong) my_time(0);
long time_diff;
ALARM *alarm_data= (ALARM*) queue_top(&alarm_queue);
time_diff= (long) (alarm_data->expire_time - now);
@@ -528,7 +528,7 @@ static void *alarm_handler(void *arg __attribute__((unused)))
{
if (alarm_queue.elements)
{
- ulong sleep_time,now=time((time_t*) 0);
+ ulong sleep_time,now= my_time(0);
if (alarm_aborted)
sleep_time=now+1;
else
@@ -685,7 +685,7 @@ static void *test_thread(void *arg)
for (i=1 ; i <= 10 ; i++)
{
wait_time=param ? 11-i : i;
- start_time=time((time_t*) 0);
+ start_time= my_time(0);
if (thr_alarm(&got_alarm,wait_time,0))
{
printf("Thread: %s Alarms aborted\n",my_thread_name());
@@ -747,7 +747,7 @@ static void *test_thread(void *arg)
}
}
printf("Thread: %s Slept for %d (%d) sec\n",my_thread_name(),
- (int) (time((time_t*) 0)-start_time), wait_time); fflush(stdout);
+ (int) (my_time(0)-start_time), wait_time); fflush(stdout);
thr_end_alarm(&got_alarm);
fflush(stdout);
}
diff --git a/sql-common/client.c b/sql-common/client.c
index 6d63c457390..75b1c9747a5 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -232,7 +232,7 @@ static int wait_for_data(my_socket fd, uint timeout)
implementations of select that don't adjust tv upon
failure to reflect the time remaining
*/
- start_time = time(NULL);
+ start_time= my_time(0);
for (;;)
{
tv.tv_sec = (long) timeout;
@@ -246,7 +246,7 @@ static int wait_for_data(my_socket fd, uint timeout)
#endif
if (res == 0) /* timeout */
return -1;
- now_time=time(NULL);
+ now_time= my_time(0);
timeout-= (uint) (now_time - start_time);
if (errno != EINTR || (int) timeout <= 0)
return -1;
diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc
index 7b58c10079a..17924ee0e42 100644
--- a/sql/event_data_objects.cc
+++ b/sql/event_data_objects.cc
@@ -1644,7 +1644,7 @@ err:
void
Event_queue_element::mark_last_executed(THD *thd)
{
- thd->end_time();
+ thd->set_current_time();
last_executed= (my_time_t) thd->query_start();
last_executed_changed= TRUE;
diff --git a/sql/event_queue.cc b/sql/event_queue.cc
index 634cc764d74..71dd6a0833f 100644
--- a/sql/event_queue.cc
+++ b/sql/event_queue.cc
@@ -550,7 +550,7 @@ Event_queue::get_top_for_execution_if_time(THD *thd,
top= ((Event_queue_element*) queue_element(&queue, 0));
- thd->end_time(); /* Get current time */
+ thd->set_current_time(); /* Get current time */
next_activation_at= top->execute_at;
if (next_activation_at > thd->query_start())
diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc
index c552b22e942..3092521fd4c 100644
--- a/sql/event_scheduler.cc
+++ b/sql/event_scheduler.cc
@@ -283,8 +283,7 @@ Event_worker_thread::run(THD *thd, Event_queue_element_for_exec *event)
res= post_init_event_thread(thd);
DBUG_ENTER("Event_worker_thread::run");
- DBUG_PRINT("info", ("Time is %ld, THD: 0x%lx",
- (long) time(NULL), (long) thd));
+ DBUG_PRINT("info", ("Time is %ld, THD: 0x%lx", (long) my_time(0), (long) thd));
if (res)
goto end;
diff --git a/sql/field.h b/sql/field.h
index 8bf087c7ebd..2782042e911 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1394,6 +1394,8 @@ public:
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
uint32 max_display_length();
uint is_equal(Create_field *new_field);
+ inline bool in_read_set() { return bitmap_is_set(table->read_set, field_index); }
+ inline bool in_write_set() { return bitmap_is_set(table->write_set, field_index); }
};
diff --git a/sql/item.h b/sql/item.h
index 432da6c3a1c..c15b74a265d 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1712,8 +1712,11 @@ public:
max_length=length;
fixed= 1;
}
- Item_float(double value_par) :presentation(0), value(value_par) { fixed= 1; }
-
+ Item_float(double value_par, uint decimal_par) :presentation(0), value(value_par)
+ {
+ decimals= (uint8) decimal_par;
+ fixed= 1;
+ }
int save_in_field(Field *field, bool no_conversions);
enum Type type() const { return REAL_ITEM; }
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index fcbacc32d88..47914c59b4c 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -853,6 +853,7 @@ public:
friend int cmp_longlong(void *cmp_arg, packed_longlong *a,packed_longlong *b);
};
+
class in_double :public in_vector
{
double tmp;
@@ -862,16 +863,16 @@ public:
uchar *get_value(Item *item);
Item *create_item()
{
- return new Item_float(0.0);
+ return new Item_float(0.0, 0);
}
void value_to_item(uint pos, Item *item)
{
((Item_float*)item)->value= ((double*) base)[pos];
}
Item_result result_type() { return REAL_RESULT; }
-
};
+
class in_decimal :public in_vector
{
my_decimal val;
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index a87efa9e68c..7cee8088026 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -1594,7 +1594,7 @@ int Item_func_now::save_in_field(Field *to, bool no_conversions)
void Item_func_sysdate_local::store_now_in_TIME(MYSQL_TIME *now_time)
{
THD *thd= current_thd;
- thd->variables.time_zone->gmt_sec_to_TIME(now_time, (my_time_t) time(NULL));
+ thd->variables.time_zone->gmt_sec_to_TIME(now_time, (my_time_t) my_time(0));
thd->time_zone_used= 1;
}
diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc
index f8457a1ae50..6bc73f49a5a 100644
--- a/sql/item_xmlfunc.cc
+++ b/sql/item_xmlfunc.cc
@@ -2767,7 +2767,7 @@ String *Item_xml_str_func::parse_xml(String *raw_xml, String *parsed_xml_buf)
if ((rc= my_xml_parse(&p, raw_xml->ptr(), raw_xml->length())) != MY_XML_OK)
{
char buf[128];
- my_snprintf(buf, sizeof(buf)-1, "parse error at line %d pos %lu: %s",
+ my_snprintf(buf, sizeof(buf)-1, "parse error at line %d pos %u: %s",
my_xml_error_lineno(&p) + 1,
my_xml_error_pos(&p) + 1,
my_xml_error_string(&p));
diff --git a/sql/lock.cc b/sql/lock.cc
index 4260a031def..e04be568a29 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -246,7 +246,7 @@ retry:
}
}
- thd->lock_time();
+ thd->set_time_after_lock();
DBUG_RETURN (sql_lock);
}
diff --git a/sql/log.cc b/sql/log.cc
index 0bf77d68410..207c248c9e8 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -524,8 +524,8 @@ err:
user_host the pointer to the string with user@host info
user_host_len length of the user_host string. this is computed once
and passed to all general log event handlers
- query_time Amount of time the query took to execute (in seconds)
- lock_time Amount of time the query was locked (in seconds)
+ query_time Amount of time the query took to execute (in microseconds)
+ lock_time Amount of time the query was locked (in microseconds)
is_command The flag, which determines, whether the sql_text is a
query or an administrator command (these are treated
differently by the old logging routines)
@@ -545,13 +545,12 @@ err:
bool Log_to_csv_event_handler::
log_slow(THD *thd, time_t current_time, time_t query_start_arg,
const char *user_host, uint user_host_len,
- longlong query_time, longlong lock_time, bool is_command,
+ ulonglong query_utime, ulonglong lock_utime, bool is_command,
const char *sql_text, uint sql_text_len)
{
/* table variables */
TABLE *table= slow_log.table;
CHARSET_INFO *client_cs= thd->variables.character_set_client;
-
DBUG_ENTER("log_slow");
/* below should never happen */
@@ -582,6 +581,8 @@ bool Log_to_csv_event_handler::
if (query_start_arg)
{
+ longlong query_time= (longlong) (query_utime/1000000);
+ longlong lock_time= (longlong) (lock_utime/1000000);
/*
A TIME field can not hold the full longlong range; query_time or
lock_time may be truncated without warning here, if greater than
@@ -694,12 +695,12 @@ void Log_to_file_event_handler::init_pthread_objects()
bool Log_to_file_event_handler::
log_slow(THD *thd, time_t current_time, time_t query_start_arg,
const char *user_host, uint user_host_len,
- longlong query_time, longlong lock_time, bool is_command,
+ ulonglong query_utime, ulonglong lock_utime, bool is_command,
const char *sql_text, uint sql_text_len)
{
return mysql_slow_log.write(thd, current_time, query_start_arg,
user_host, user_host_len,
- query_time, lock_time, is_command,
+ query_utime, lock_utime, is_command,
sql_text, sql_text_len);
}
@@ -774,10 +775,10 @@ bool LOGGER::error_log_print(enum loglevel level, const char *format,
va_list args)
{
bool error= FALSE;
- Log_event_handler **current_handler= error_log_handler_list;
+ Log_event_handler **current_handler;
/* currently we don't need locking here as there is no error_log table */
- while (*current_handler)
+ for (current_handler= error_log_handler_list ; *current_handler ;)
error= (*current_handler++)->log_error(level, format, args) || error;
return error;
@@ -904,28 +905,27 @@ bool LOGGER::flush_logs(THD *thd)
SYNOPSIS
slow_log_print()
- thd THD of the query being logged
- query The query being logged
- query_length The length of the query string
- query_start_arg Query start timestamp
+ thd THD of the query being logged
+ query The query being logged
+ query_length The length of the query string
+ current_utime Current time in microseconds (from undefined start)
RETURN
- FALSE - OK
- TRUE - error occured
+ FALSE OK
+ TRUE error occured
*/
bool LOGGER::slow_log_print(THD *thd, const char *query, uint query_length,
- time_t query_start_arg)
+ ulonglong current_utime)
+
{
bool error= FALSE;
- Log_event_handler **current_handler= slow_log_handler_list;
+ Log_event_handler **current_handler;
bool is_command= FALSE;
char user_host_buff[MAX_USER_HOST_SIZE];
-
- time_t current_time;
Security_context *sctx= thd->security_ctx;
uint user_host_len= 0;
- longlong query_time= 0, lock_time= 0;
+ ulonglong query_utime, lock_utime;
/*
Print the message to the buffer if we have slow log enabled
@@ -933,10 +933,10 @@ bool LOGGER::slow_log_print(THD *thd, const char *query, uint query_length,
if (*slow_log_handler_list)
{
- current_time= time(NULL);
+ time_t current_time;
/* do not log slow queries from replication threads */
- if (thd->slave_thread)
+ if (thd->slave_thread && !opt_log_slow_slave_statements)
return 0;
lock();
@@ -947,17 +947,22 @@ bool LOGGER::slow_log_print(THD *thd, const char *query, uint query_length,
}
/* fill in user_host value: the format is "%s[%s] @ %s [%s]" */
- user_host_len= strxnmov(user_host_buff, MAX_USER_HOST_SIZE,
- sctx->priv_user ? sctx->priv_user : "", "[",
- sctx->user ? sctx->user : "", "] @ ",
- sctx->host ? sctx->host : "", " [",
- sctx->ip ? sctx->ip : "", "]", NullS) -
- user_host_buff;
-
- if (query_start_arg)
+ user_host_len= (strxnmov(user_host_buff, MAX_USER_HOST_SIZE,
+ sctx->priv_user ? sctx->priv_user : "", "[",
+ sctx->user ? sctx->user : "", "] @ ",
+ sctx->host ? sctx->host : "", " [",
+ sctx->ip ? sctx->ip : "", "]", NullS) -
+ user_host_buff);
+
+ current_time= my_time_possible_from_micro(current_utime);
+ if (thd->start_utime)
+ {
+ query_utime= (current_utime - thd->start_utime);
+ lock_utime= (thd->utime_after_lock - thd->start_utime);
+ }
+ else
{
- query_time= (longlong) (current_time - query_start_arg);
- lock_time= (longlong) (thd->time_after_lock - query_start_arg);
+ query_utime= lock_utime= 0;
}
if (!query)
@@ -967,10 +972,10 @@ bool LOGGER::slow_log_print(THD *thd, const char *query, uint query_length,
query_length= command_name[thd->command].length;
}
- while (*current_handler)
- error= (*current_handler++)->log_slow(thd, current_time, query_start_arg,
+ for (current_handler= slow_log_handler_list; *current_handler ;)
+ error= (*current_handler++)->log_slow(thd, current_time, thd->start_time,
user_host_buff, user_host_len,
- query_time, lock_time, is_command,
+ query_utime, lock_utime, is_command,
query, query_length) || error;
unlock();
@@ -995,7 +1000,7 @@ bool LOGGER::general_log_print(THD *thd, enum enum_server_command command,
Security_context *sctx= thd->security_ctx;
ulong id;
uint message_buff_len= 0, user_host_len= 0;
-
+ time_t current_time;
if (thd)
{ /* Normal thread */
if ((thd->options & OPTION_LOG_OFF)
@@ -1017,8 +1022,6 @@ bool LOGGER::general_log_print(THD *thd, enum enum_server_command command,
unlock();
return 0;
}
- time_t current_time= time(NULL);
-
user_host_len= strxnmov(user_host_buff, MAX_USER_HOST_SIZE,
sctx->priv_user ? sctx->priv_user : "", "[",
sctx->user ? sctx->user : "", "] @ ",
@@ -1033,6 +1036,7 @@ bool LOGGER::general_log_print(THD *thd, enum enum_server_command command,
else
message_buff[0]= '\0';
+ current_time= my_time(0);
while (*current_handler)
error+= (*current_handler++)->
log_general(current_time, user_host_buff,
@@ -2165,8 +2169,8 @@ err:
user_host the pointer to the string with user@host info
user_host_len length of the user_host string. this is computed once
and passed to all general log event handlers
- query_time Amount of time the query took to execute (in seconds)
- lock_time Amount of time the query was locked (in seconds)
+ query_utime Amount of time the query took to execute (in microseconds)
+ lock_utime Amount of time the query was locked (in microseconds)
is_command The flag, which determines, whether the sql_text is a
query or an administrator command.
sql_text the very text of the query or administrator command
@@ -2184,8 +2188,8 @@ err:
bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time,
time_t query_start_arg, const char *user_host,
- uint user_host_len, longlong query_time,
- longlong lock_time, bool is_command,
+ uint user_host_len, ulonglong query_utime,
+ ulonglong lock_utime, bool is_command,
const char *sql_text, uint sql_text_len)
{
bool error= 0;
@@ -2198,6 +2202,7 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time,
{ // Safety agains reopen
int tmp_errno= 0;
char buff[80], *end;
+ char query_time_buff[22+7], lock_time_buff[22+7];
uint buff_len;
end= buff;
@@ -2228,10 +2233,12 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time,
tmp_errno= errno;
}
/* For slow query log */
+ sprintf(query_time_buff, "%.6f", ulonglong2double(query_utime)/1000000.0);
+ sprintf(lock_time_buff, "%.6f", ulonglong2double(lock_utime)/1000000.0);
if (my_b_printf(&log_file,
- "# Query_time: %lu Lock_time: %lu"
+ "# Query_time: %s Lock_time: %s"
" Rows_sent: %lu Rows_examined: %lu\n",
- (ulong) query_time, (ulong) lock_time,
+ query_time_buff, lock_time_buff,
(ulong) thd->sent_row_count,
(ulong) thd->examined_row_count) == (uint) -1)
tmp_errno= errno;
@@ -3872,9 +3879,9 @@ int error_log_print(enum loglevel level, const char *format,
bool slow_log_print(THD *thd, const char *query, uint query_length,
- time_t query_start_arg)
+ ulonglong current_utime)
{
- return logger.slow_log_print(thd, query, query_length, query_start_arg);
+ return logger.slow_log_print(thd, query, query_length, current_utime);
}
@@ -3902,7 +3909,7 @@ void MYSQL_BIN_LOG::rotate_and_purge(uint flags)
#ifdef HAVE_REPLICATION
if (expire_logs_days)
{
- time_t purge_time= time(0) - expire_logs_days*24*60*60;
+ time_t purge_time= my_time(0) - expire_logs_days*24*60*60;
if (purge_time >= 0)
purge_logs_before_date(purge_time);
}
@@ -4499,7 +4506,7 @@ static void print_buffer_to_file(enum loglevel level, const char *buffer)
VOID(pthread_mutex_lock(&LOCK_error_log));
- skr=time(NULL);
+ skr= my_time(0);
localtime_r(&skr, &tm_tmp);
start=&tm_tmp;
diff --git a/sql/log.h b/sql/log.h
index d92e0117bcc..2a796ef89e7 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -198,7 +198,7 @@ public:
const char *sql_text, uint sql_text_len);
bool write(THD *thd, time_t current_time, time_t query_start_arg,
const char *user_host, uint user_host_len,
- longlong query_time, longlong lock_time, bool is_command,
+ ulonglong query_utime, ulonglong lock_utime, bool is_command,
const char *sql_text, uint sql_text_len);
bool open_slow_log(const char *log_name)
{
@@ -393,8 +393,8 @@ public:
virtual bool log_slow(THD *thd, time_t current_time,
time_t query_start_arg, const char *user_host,
- uint user_host_len, longlong query_time,
- longlong lock_time, bool is_command,
+ uint user_host_len, ulonglong query_utime,
+ ulonglong lock_utime, bool is_command,
const char *sql_text, uint sql_text_len)= 0;
virtual bool log_error(enum loglevel level, const char *format,
va_list args)= 0;
@@ -442,8 +442,8 @@ public:
virtual bool log_slow(THD *thd, time_t current_time,
time_t query_start_arg, const char *user_host,
- uint user_host_len, longlong query_time,
- longlong lock_time, bool is_command,
+ uint user_host_len, ulonglong query_utime,
+ ulonglong lock_utime, bool is_command,
const char *sql_text, uint sql_text_len);
virtual bool log_error(enum loglevel level, const char *format,
va_list args);
@@ -479,8 +479,8 @@ public:
virtual bool log_slow(THD *thd, time_t current_time,
time_t query_start_arg, const char *user_host,
- uint user_host_len, longlong query_time,
- longlong lock_time, bool is_command,
+ uint user_host_len, ulonglong query_utime,
+ ulonglong lock_utime, bool is_command,
const char *sql_text, uint sql_text_len);
virtual bool log_error(enum loglevel level, const char *format,
va_list args);
@@ -564,7 +564,7 @@ public:
bool error_log_print(enum loglevel level, const char *format,
va_list args);
bool slow_log_print(THD *thd, const char *query, uint query_length,
- time_t query_start_arg);
+ ulonglong current_utime);
bool general_log_print(THD *thd,enum enum_server_command command,
const char *format, va_list args);
diff --git a/sql/log_event.cc b/sql/log_event.cc
index c062aa99b4e..db8729c8318 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -456,7 +456,7 @@ Log_event::Log_event()
thd(0)
{
server_id= ::server_id;
- when= time(NULL);
+ when= my_time(0);
log_pos= 0;
}
#endif /* !MYSQL_CLIENT */
@@ -2073,7 +2073,7 @@ int Query_log_event::do_apply_event(RELAY_LOG_INFO const *rli,
/* Execute the query (note that we bypass dispatch_command()) */
const char* found_semicolon= NULL;
mysql_parse(thd, thd->query, thd->query_length, &found_semicolon);
-
+ log_slow_statement(thd);
}
else
{
@@ -4349,7 +4349,7 @@ int User_var_log_event::do_apply_event(RELAY_LOG_INFO const *rli)
switch (type) {
case REAL_RESULT:
float8get(real_val, val);
- it= new Item_float(real_val);
+ it= new Item_float(real_val, 0);
val= (char*) &real_val; // Pointer to value in native format
val_len= 8;
break;
@@ -6173,7 +6173,7 @@ int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli)
problem. When WL#2975 is implemented, just remove the member
st_relay_log_info::last_event_start_time and all its occurences.
*/
- const_cast<RELAY_LOG_INFO*>(rli)->last_event_start_time= time(0);
+ const_cast<RELAY_LOG_INFO*>(rli)->last_event_start_time= my_time(0);
}
DBUG_RETURN(0);
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 7b7bc81957e..0678189b388 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -167,6 +167,7 @@ public:
void restore_env(THD *thd, Object_creation_ctx *backup_ctx);
protected:
+ Object_creation_ctx() {}
virtual Object_creation_ctx *create_backup_ctx(THD *thd) = 0;
virtual void change_env(THD *thd) const = 0;
@@ -734,7 +735,7 @@ int error_log_print(enum loglevel level, const char *format,
va_list args);
bool slow_log_print(THD *thd, const char *query, uint query_length,
- time_t query_start_arg);
+ ulonglong current_utime);
bool general_log_print(THD *thd, enum enum_server_command command,
const char *format,...);
@@ -1791,7 +1792,7 @@ extern my_bool opt_readonly, lower_case_file_system;
extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs;
extern my_bool opt_secure_auth;
extern char* opt_secure_file_priv;
-extern my_bool opt_log_slow_admin_statements;
+extern my_bool opt_log_slow_admin_statements, opt_log_slow_slave_statements;
extern my_bool sp_automatic_privileges, opt_noacl;
extern my_bool opt_old_style_user_limits, trust_function_creators;
extern uint opt_crash_binlog_innodb;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 6d22047b9db..33cd55170ea 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -338,6 +338,7 @@ static char *default_collation_name;
static char *default_storage_engine_str;
static char compiled_default_collation_name[]= MYSQL_DEFAULT_COLLATION_NAME;
static I_List<THD> thread_cache;
+static double long_query_time;
static pthread_cond_t COND_thread_cache, COND_flush_thread_cache;
@@ -406,6 +407,7 @@ my_bool opt_sync_frm, opt_allow_suspicious_udfs;
my_bool opt_secure_auth= 0;
char* opt_secure_file_priv= 0;
my_bool opt_log_slow_admin_statements= 0;
+my_bool opt_log_slow_slave_statements= 0;
my_bool lower_case_file_system= 0;
my_bool opt_large_pages= 0;
my_bool opt_myisam_use_mmap= 0;
@@ -1143,7 +1145,7 @@ extern "C" void unireg_abort(int exit_code)
sql_print_error("Aborting\n");
else if (opt_help)
usage();
- clean_up(exit_code || !opt_bootstrap); /* purecov: inspected */
+ clean_up(!opt_help && (exit_code || !opt_bootstrap)); /* purecov: inspected */
DBUG_PRINT("quit",("done with cleanup in unireg_abort"));
wait_for_signal_thread_to_end();
clean_up_mutexes();
@@ -1240,12 +1242,12 @@ void clean_up(bool print_message)
my_regex_end();
#endif
- if (print_message && errmesg)
- sql_print_information(ER(ER_SHUTDOWN_COMPLETE),my_progname);
#if !defined(EMBEDDED_LIBRARY)
if (!opt_bootstrap)
(void) my_delete(pidfile_name,MYF(0)); // This may not always exist
#endif
+ if (print_message && errmesg && server_start_time)
+ sql_print_information(ER(ER_SHUTDOWN_COMPLETE),my_progname);
thread_scheduler.end();
finish_client_errs();
my_free((uchar*) my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST),
@@ -1797,7 +1799,7 @@ static bool cache_thread()
this thread for handling of new THD object/connection.
*/
thd->mysys_var->abort= 0;
- thd->thr_create_time= time(NULL);
+ thd->thr_create_utime= my_micro_time();
threads.append(thd);
return(1);
}
@@ -2174,7 +2176,7 @@ extern "C" sig_handler handle_segfault(int sig)
segfaulted = 1;
- curr_time= time(NULL);
+ curr_time= my_time(0);
localtime_r(&curr_time, &tm);
fprintf(stderr,"\
@@ -2717,7 +2719,7 @@ static int init_common_variables(const char *conf_file_name, int argc,
tzset(); // Set tzname
max_system_variables.pseudo_thread_id= (ulong)~0;
- server_start_time= time((time_t*) 0);
+ server_start_time= my_time(0);
rpl_filter= new Rpl_filter;
binlog_filter= new Rpl_filter;
if (!rpl_filter || !binlog_filter)
@@ -2952,7 +2954,7 @@ static int init_common_variables(const char *conf_file_name, int argc,
&& !(log_output_options & LOG_NONE))
sql_print_warning("Although a path was specified for the "
"--log-slow-queries option, log tables are used. "
- "To enable logging to files use the --log-output option.");
+ "To enable logging to files use the --log-output=file option.");
s= opt_logname ? opt_logname : make_default_log_name(buff, ".log");
sys_var_general_log_path.value= my_strdup(s, MYF(0));
@@ -3540,7 +3542,7 @@ server.");
#ifdef HAVE_REPLICATION
if (opt_bin_log && expire_logs_days)
{
- time_t purge_time= time(0) - expire_logs_days*24*60*60;
+ time_t purge_time= server_start_time - expire_logs_days*24*60*60;
if (purge_time >= 0)
mysql_bin_log.purge_logs_before_date(purge_time);
}
@@ -4289,7 +4291,7 @@ void create_thread_to_handle_connection(THD *thd)
thread_created++;
threads.append(thd);
DBUG_PRINT("info",(("creating thread %lu"), thd->thread_id));
- thd->connect_time = time(NULL);
+ thd->connect_utime= thd->start_utime= my_micro_time();
if ((error=pthread_create(&thd->real_id,&connection_attrib,
handle_one_connection,
(void*) thd)))
@@ -5076,6 +5078,8 @@ enum options_mysqld
OPT_THREAD_HANDLING,
OPT_INNODB_ROLLBACK_ON_TIMEOUT,
OPT_SECURE_FILE_PRIV,
+ OPT_MIN_EXAMINED_ROW_LIMIT,
+ OPT_LOG_SLOW_SLAVE_STATEMENTS,
OPT_OLD_MODE
};
@@ -5377,8 +5381,13 @@ Disable with --skip-large-pages.",
(uchar**) &opt_log_slow_admin_statements,
(uchar**) &opt_log_slow_admin_statements,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"log-slow-slave-statements", OPT_LOG_SLOW_SLAVE_STATEMENTS,
+ "Log slow statements executed by slave thread to the slow log if it is open.",
+ (uchar**) &opt_log_slow_slave_statements,
+ (uchar**) &opt_log_slow_slave_statements,
+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"log-slow-queries", OPT_SLOW_QUERY_LOG,
- "Log slow queries to this log file. Defaults logging to hostname-slow.log file. Must be enabled to activate other slow log options.",
+ "Log slow queries to a table or log file. Defaults logging to table mysql.slow_log or hostname-slow.log if --log-output=file is used. Must be enabled to activate other slow log options.",
(uchar**) &opt_slow_logname, (uchar**) &opt_slow_logname, 0, GET_STR, OPT_ARG,
0, 0, 0, 0, 0, 0},
{"log-tc", OPT_LOG_TC,
@@ -5967,10 +5976,10 @@ log and this option does nothing anymore.",
0, (GET_ULONG | GET_ASK_ADDR) , REQUIRED_ARG, 100,
1, 100, 0, 1, 0},
{"long_query_time", OPT_LONG_QUERY_TIME,
- "Log all queries that have taken more than long_query_time seconds to execute to file.",
- (uchar**) &global_system_variables.long_query_time,
- (uchar**) &max_system_variables.long_query_time, 0, GET_ULONG,
- REQUIRED_ARG, 10, 1, LONG_TIMEOUT, 0, 1, 0},
+ "Log all queries that have taken more than long_query_time seconds to execute to file. "
+ "The argument will be treated as a decimal value with microsecond precission.",
+ (uchar**) &long_query_time, (uchar**) &long_query_time, 0, GET_DOUBLE,
+ REQUIRED_ARG, 10, 0, LONG_TIMEOUT, 0, 0, 0},
{"lower_case_table_names", OPT_LOWER_CASE_TABLE_NAMES,
"If set to 1 table names are stored in lowercase on disk and table names will be case-insensitive. Should be set to 2 if you are using a case insensitive file system",
(uchar**) &lower_case_table_names,
@@ -6068,6 +6077,11 @@ The minimum value for this variable is 4096.",
"After this many write locks, allow some read locks to run in between.",
(uchar**) &max_write_lock_count, (uchar**) &max_write_lock_count, 0, GET_ULONG,
REQUIRED_ARG, ~0L, 1, ~0L, 0, 1, 0},
+ {"min_examined_row_limit", OPT_MIN_EXAMINED_ROW_LIMIT,
+ "Don't log queries which examine less than min_examined_row_limit rows to file.",
+ (uchar**) &global_system_variables.min_examined_row_limit,
+ (uchar**) &max_system_variables.min_examined_row_limit, 0, GET_ULONG,
+ REQUIRED_ARG, 0, 0, ~0L, 0, 1L, 0},
{"multi_range_count", OPT_MULTI_RANGE_COUNT,
"Number of key ranges to request at once.",
(uchar**) &global_system_variables.multi_range_count,
@@ -6959,7 +6973,7 @@ Starts the MySQL database server\n");
printf("Usage: %s [OPTIONS]\n", my_progname);
if (!opt_verbose)
- puts("\nFor more help options (several pages), use mysqld --verbose --help\n");
+ puts("\nFor more help options (several pages), use mysqld --verbose --help");
else
{
#ifdef __WIN__
@@ -6984,7 +6998,7 @@ Starts the MySQL database server\n");
puts("\n\
To see what values a running MySQL server is using, type\n\
-'mysqladmin variables' instead of 'mysqld --verbose --help'.\n");
+'mysqladmin variables' instead of 'mysqld --verbose --help'.");
}
}
#endif /*!EMBEDDED_LIBRARY*/
@@ -7714,7 +7728,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
}
return 0;
}
- /* Initiates DEBUG - but no debugging here ! */
+
+
+/* Handle arguments for multiple key caches */
static uchar* *
mysql_getopt_value(const char *keyname, uint key_length,
@@ -7772,9 +7788,10 @@ static void get_options(int *argc,char **argv)
(*argc)++; /* add back one for the progname handle_options removes */
/* no need to do this for argv as we are discarding it. */
- if ((opt_log_slow_admin_statements || opt_log_queries_not_using_indexes) &&
+ if ((opt_log_slow_admin_statements || opt_log_queries_not_using_indexes ||
+ opt_log_slow_slave_statements) &&
!opt_slow_log)
- sql_print_warning("options --log-slow-admin-statements and --log-queries-not-using-indexes have no effect if --log-slow-queries is not set");
+ sql_print_warning("options --log-slow-admin-statements, --log-queries-not-using-indexes and --log-slow-slave-statements have no effect if --log-slow-queries is not set");
#if defined(HAVE_BROKEN_REALPATH)
my_use_symdir=0;
@@ -7818,6 +7835,10 @@ static void get_options(int *argc,char **argv)
/* Set global variables based on startup options */
myisam_block_size=(uint) 1 << my_bit_log2(opt_myisam_block_size);
+ /* long_query_time is in microseconds */
+ global_system_variables.long_query_time= max_system_variables.long_query_time=
+ (longlong) (long_query_time * 1000000.0);
+
if (opt_short_log_format)
opt_specialflag|= SPECIAL_SHORT_LOG_FORMAT;
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index bd273145782..1f75d7ab1d7 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -437,7 +437,7 @@ net_write_command(NET *net,uchar command,
uchar buff[NET_HEADER_SIZE+1];
uint header_size=NET_HEADER_SIZE+1;
DBUG_ENTER("net_write_command");
- DBUG_PRINT("enter",("length: %lu", len));
+ DBUG_PRINT("enter",("length: %lu", (ulong) len));
buff[4]=command; /* For first packet */
diff --git a/sql/parse_file.cc b/sql/parse_file.cc
index 5ea49396cb4..19fb11ac0cc 100644
--- a/sql/parse_file.cc
+++ b/sql/parse_file.cc
@@ -135,7 +135,7 @@ write_parameter(IO_CACHE *file, uchar* base, File_option *parameter,
{
/* string have to be allocated already */
LEX_STRING *val_s= (LEX_STRING *)(base + parameter->offset);
- time_t tm= time(NULL);
+ time_t tm= my_time(0);
get_date(val_s->str, GETDATE_DATE_TIME|GETDATE_GMT|GETDATE_FIXEDLENGTH,
tm);
diff --git a/sql/set_var.cc b/sql/set_var.cc
index bd5234b42be..0ff561191ae 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -250,8 +250,8 @@ static sys_var_bool_ptr
sys_log_queries_not_using_indexes(&vars, "log_queries_not_using_indexes",
&opt_log_queries_not_using_indexes);
static sys_var_thd_ulong sys_log_warnings(&vars, "log_warnings", &SV::log_warnings);
-static sys_var_thd_ulong sys_long_query_time(&vars, "long_query_time",
- &SV::long_query_time);
+static sys_var_microseconds sys_var_long_query_time(&vars, "long_query_time",
+ &SV::long_query_time);
static sys_var_thd_bool sys_low_priority_updates(&vars, "low_priority_updates",
&SV::low_priority_updates,
fix_low_priority_updates);
@@ -315,6 +315,8 @@ static sys_var_thd_ulong sys_max_tmp_tables(&vars, "max_tmp_tables",
&SV::max_tmp_tables);
static sys_var_long_ptr sys_max_write_lock_count(&vars, "max_write_lock_count",
&max_write_lock_count);
+static sys_var_thd_ulong sys_min_examined_row_limit(&vars, "min_examined_row_limit",
+ &SV::min_examined_row_limit);
static sys_var_thd_ulong sys_multi_range_count(&vars, "multi_range_count",
&SV::multi_range_count);
static sys_var_long_ptr sys_myisam_data_pointer_size(&vars, "myisam_data_pointer_size",
@@ -1473,6 +1475,15 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base)
pthread_mutex_unlock(&LOCK_global_system_variables);
return new Item_int(value);
}
+ case SHOW_DOUBLE:
+ {
+ double value;
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ value= *(double*) value_ptr(thd, var_type, base);
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ /* 6, as this is for now only used with microseconds */
+ return new Item_float(value, 6);
+ }
case SHOW_HA_ROWS:
{
ha_rows value;
@@ -2533,6 +2544,60 @@ void sys_var_thd_lc_time_names::set_default(THD *thd, enum_var_type type)
}
/*
+ Handling of microseoncds given as seconds.part_seconds
+
+ NOTES
+ The argument to long query time is in seconds in decimal
+ which is converted to ulonglong integer holding microseconds for storage.
+ This is used for handling long_query_time
+*/
+
+bool sys_var_microseconds::update(THD *thd, set_var *var)
+{
+ double num= var->value->val_real();
+ longlong microseconds;
+ if (num > (double) option_limits->max_value)
+ num= (double) option_limits->max_value;
+ if (num < (double) option_limits->min_value)
+ num= (double) option_limits->min_value;
+ microseconds= (longlong) (num * 1000000.0 + 0.5);
+ if (var->type == OPT_GLOBAL)
+ {
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ (global_system_variables.*offset)= microseconds;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ }
+ else
+ thd->variables.*offset= microseconds;
+ return 0;
+}
+
+
+void sys_var_microseconds::set_default(THD *thd, enum_var_type type)
+{
+ longlong microseconds= (longlong) (option_limits->def_value * 1000000.0);
+ if (type == OPT_GLOBAL)
+ {
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ global_system_variables.*offset= microseconds;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ }
+ else
+ thd->variables.*offset= microseconds;
+}
+
+
+uchar *sys_var_microseconds::value_ptr(THD *thd, enum_var_type type,
+ LEX_STRING *base)
+{
+ thd->tmp_double_value= (double) ((type == OPT_GLOBAL) ?
+ global_system_variables.*offset :
+ thd->variables.*offset) / 1000000.0;
+ return (uchar*) &thd->tmp_double_value;
+}
+
+
+/*
Functions to update thd->options bits
*/
diff --git a/sql/set_var.h b/sql/set_var.h
index a998dc93b84..67ec449a02f 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -113,9 +113,10 @@ class sys_var_long_ptr_global: public sys_var_global
{
public:
ulong *value;
- sys_var_long_ptr_global(sys_var_chain *chain, const char *name_arg, ulong *value_ptr_arg,
- pthread_mutex_t *guard_arg,
- sys_after_update_func after_update_arg= NULL)
+ sys_var_long_ptr_global(sys_var_chain *chain, const char *name_arg,
+ ulong *value_ptr_arg,
+ pthread_mutex_t *guard_arg,
+ sys_after_update_func after_update_arg= NULL)
:sys_var_global(name_arg, after_update_arg, guard_arg),
value(value_ptr_arg)
{ chain_sys_var(chain); }
@@ -911,6 +912,27 @@ public:
uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
};
+
+class sys_var_microseconds :public sys_var_thd
+{
+ ulonglong SV::*offset;
+public:
+ sys_var_microseconds(sys_var_chain *chain, const char *name_arg,
+ ulonglong SV::*offset_arg):
+ sys_var_thd(name_arg), offset(offset_arg)
+ { chain_sys_var(chain); }
+ bool check(THD *thd, set_var *var) {return 0;}
+ bool update(THD *thd, set_var *var);
+ void set_default(THD *thd, enum_var_type type);
+ SHOW_TYPE show_type() { return SHOW_DOUBLE; }
+ bool check_update_type(Item_result type)
+ {
+ return (type != INT_RESULT && type != REAL_RESULT && type != DECIMAL_RESULT);
+ }
+ uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
+};
+
+
class sys_var_trust_routine_creators :public sys_var_bool_ptr
{
/* We need a derived class only to have a warn_deprecated() */
diff --git a/sql/slave.cc b/sql/slave.cc
index 2e8e3f582de..6fb7d666703 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -1460,6 +1460,7 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
thd->variables.max_allowed_packet= global_system_variables.max_allowed_packet
+ MAX_LOG_EVENT_HEADER; /* note, incr over the global not session var */
thd->slave_thread = 1;
+ thd->enable_slow_log= opt_log_slow_slave_statements;
set_slave_thread_options(thd);
thd->client_capabilities = CLIENT_LOCAL_FILES;
pthread_mutex_lock(&LOCK_thread_count);
@@ -1491,7 +1492,7 @@ static int safe_sleep(THD* thd, int sec, CHECK_KILLED_FUNC thread_killed,
DBUG_ENTER("safe_sleep");
thr_alarm_init(&alarmed);
- time_t start_time= time((time_t*) 0);
+ time_t start_time= my_time(0);
time_t end_time= start_time+sec;
while ((nap_time= (int) (end_time - start_time)) > 0)
@@ -1508,7 +1509,7 @@ static int safe_sleep(THD* thd, int sec, CHECK_KILLED_FUNC thread_killed,
if ((*thread_killed)(thd,thread_killed_arg))
DBUG_RETURN(1);
- start_time=time((time_t*) 0);
+ start_time= my_time(0);
}
DBUG_RETURN(0);
}
@@ -1796,7 +1797,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
thd->set_time(); // time the query
thd->lex->current_select= 0;
if (!ev->when)
- ev->when = time(NULL);
+ ev->when= my_time(0);
ev->thd = thd; // because up to this point, ev->thd == 0
int reason= ev->shall_skip(rli);
diff --git a/sql/sql_cache.h b/sql/sql_cache.h
index c4c7e1dbc5e..645807eecbf 100644
--- a/sql/sql_cache.h
+++ b/sql/sql_cache.h
@@ -142,6 +142,7 @@ struct Query_cache_query
uint8 tbls_type;
unsigned int last_pkt_nr;
+ Query_cache_query() {} /* Remove gcc warning */
inline void init_n_lock();
void unlock_n_destroy();
inline ulonglong found_rows() { return limit_found_rows; }
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index da975ee3103..4fe68721ae5 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -407,7 +407,8 @@ THD::THD()
// Must be reset to handle error with THD's created for init of mysqld
lex->current_select= 0;
start_time=(time_t) 0;
- time_after_lock=(time_t) 0;
+ start_utime= 0L;
+ utime_after_lock= 0L;
current_linfo = 0;
slave_thread = 0;
bzero(&variables, sizeof(variables));
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 7fa66893f69..6c3400ef08c 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -249,18 +249,19 @@ struct system_variables
ulonglong myisam_max_sort_file_size;
ulonglong max_heap_table_size;
ulonglong tmp_table_size;
+ ulonglong long_query_time;
ha_rows select_limit;
ha_rows max_join_size;
ulong auto_increment_increment, auto_increment_offset;
ulong bulk_insert_buff_size;
ulong join_buff_size;
- ulong long_query_time;
ulong max_allowed_packet;
ulong max_error_count;
ulong max_length_for_sort_data;
ulong max_sort_length;
ulong max_tmp_tables;
ulong max_insert_delayed_threads;
+ ulong min_examined_row_limit;
ulong multi_range_count;
ulong myisam_repair_threads;
ulong myisam_sort_buff_size;
@@ -1025,8 +1026,6 @@ public:
Security_context main_security_ctx;
Security_context *security_ctx;
- /* remote (peer) port */
- uint16 peer_port;
/*
Points to info-string that we show in SHOW PROCESSLIST
You are supposed to update thd->proc_info only if you have coded
@@ -1034,6 +1033,14 @@ public:
*/
const char *proc_info;
+ /*
+ Used in error messages to tell user in what part of MySQL we found an
+ error. E. g. when where= "having clause", if fix_fields() fails, user
+ will know that the error was in having clause.
+ */
+ const char *where;
+
+ double tmp_double_value; /* Used in set_var.cc */
ulong client_capabilities; /* What the client supports */
ulong max_client_packet_length;
@@ -1055,14 +1062,12 @@ public:
enum enum_server_command command;
uint32 server_id;
uint32 file_id; // for LOAD DATA INFILE
- /*
- Used in error messages to tell user in what part of MySQL we found an
- error. E. g. when where= "having clause", if fix_fields() fails, user
- will know that the error was in having clause.
- */
- const char *where;
- time_t start_time,time_after_lock,user_time;
- time_t connect_time,thr_create_time; // track down slow pthread_create
+ /* remote (peer) port */
+ uint16 peer_port;
+ time_t start_time, user_time;
+ ulonglong connect_utime, thr_create_utime; // track down slow pthread_create
+ ulonglong start_utime, utime_after_lock;
+
thr_lock_type update_lock_default;
Delayed_insert *di;
@@ -1570,27 +1575,25 @@ public:
proc_info = old_msg;
pthread_mutex_unlock(&mysys_var->mutex);
}
-
- static inline void safe_time(time_t *t)
+ inline time_t query_start() { query_start_used=1; return start_time; }
+ inline void set_time()
{
- /**
- Wrapper around time() which retries on error (-1)
-
- @details
- This is needed because, despite the documentation, time() may fail
- in some circumstances. Here we retry time() until it succeeds, and
- log the failure so that performance problems related to this can be
- identified.
- */
- while(unlikely(time(t) == ((time_t) -1)))
- sql_print_information("time() failed with %d", errno);
+ if (user_time)
+ {
+ start_time= user_time;
+ start_utime= utime_after_lock= my_micro_time();
+ }
+ else
+ start_utime= utime_after_lock= my_micro_time_and_time(&start_time);
}
-
- inline time_t query_start() { query_start_used=1; return start_time; }
- inline void set_time() { if (user_time) start_time=time_after_lock=user_time; else { safe_time(&start_time); time_after_lock= start_time; }}
- inline void end_time() { safe_time(&start_time); }
- inline void set_time(time_t t) { time_after_lock=start_time=user_time=t; }
- inline void lock_time() { safe_time(&time_after_lock); }
+ inline void set_current_time() { start_time= my_time(MY_WME); }
+ inline void set_time(time_t t)
+ {
+ start_time= user_time= t;
+ start_utime= utime_after_lock= my_micro_time();
+ }
+ void set_time_after_lock() { utime_after_lock= my_micro_time(); }
+ ulonglong current_utime() { return my_micro_time(); }
inline ulonglong found_rows(void)
{
return limit_found_rows;
diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc
index 26b7098e27c..03b9908c1ad 100644
--- a/sql/sql_connect.cc
+++ b/sql/sql_connect.cc
@@ -97,7 +97,7 @@ static int get_or_create_user_conn(THD *thd, const char *user,
uc->len= temp_len;
uc->connections= uc->questions= uc->updates= uc->conn_per_hour= 0;
uc->user_resources= *mqh;
- uc->intime= thd->thr_create_time;
+ uc->reset_utime= thd->thr_create_utime;
if (my_hash_insert(&hash_user_connections, (uchar*) uc))
{
my_free((char*) uc,0);
@@ -223,16 +223,16 @@ void decrease_user_connections(USER_CONN *uc)
void time_out_user_resource_limits(THD *thd, USER_CONN *uc)
{
- time_t check_time = thd->start_time ? thd->start_time : time(NULL);
+ ulonglong check_time= thd->start_utime;
DBUG_ENTER("time_out_user_resource_limits");
/* If more than a hour since last check, reset resource checking */
- if (check_time - uc->intime >= 3600)
+ if (check_time - uc->reset_utime >= LL(3600000000))
{
uc->questions=1;
uc->updates=0;
uc->conn_per_hour=0;
- uc->intime=check_time;
+ uc->reset_utime= check_time;
}
DBUG_VOID_RETURN;
@@ -1053,8 +1053,8 @@ void prepare_new_connection_state(THD* thd)
pthread_handler_t handle_one_connection(void *arg)
{
THD *thd= (THD*) arg;
- uint launch_time =
- (uint) ((thd->thr_create_time = time(NULL)) - thd->connect_time);
+ ulong launch_time= (ulong) ((thd->thr_create_utime= my_micro_time()) -
+ thd->connect_utime);
if (thread_scheduler.init_new_connection_thread())
{
@@ -1063,7 +1063,7 @@ pthread_handler_t handle_one_connection(void *arg)
thread_scheduler.end_thread(thd,0);
return 0;
}
- if (launch_time >= slow_launch_time)
+ if (launch_time >= slow_launch_time*1000000L)
statistic_increment(slow_launch_threads,&LOCK_status);
/*
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index b14241bbef3..12483044cb9 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -2196,7 +2196,7 @@ pthread_handler_t handle_delayed_insert(void *arg)
/* Add thread to THD list so that's it's visible in 'show processlist' */
pthread_mutex_lock(&LOCK_thread_count);
thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
- thd->end_time();
+ thd->set_current_time();
threads.append(thd);
thd->killed=abort_loop ? THD::KILL_CONNECTION : THD::NOT_KILLED;
pthread_mutex_unlock(&LOCK_thread_count);
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index f2a61b7f7c5..a13e3d3f624 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1297,7 +1297,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
void log_slow_statement(THD *thd)
{
- time_t start_of_query;
DBUG_ENTER("log_slow_statement");
/*
@@ -1308,25 +1307,24 @@ void log_slow_statement(THD *thd)
if (unlikely(thd->in_sub_stmt))
DBUG_VOID_RETURN; // Don't set time for sub stmt
- start_of_query= thd->start_time;
- thd->end_time(); // Set start time
-
/*
Do not log administrative statements unless the appropriate option is
set; do not log into slow log if reading from backup.
*/
if (thd->enable_slow_log && !thd->user_time)
{
- thd->proc_info="logging slow query";
+ ulonglong end_utime_of_query= thd->current_utime();
- if ((ulong) (thd->start_time - thd->time_after_lock) >
- thd->variables.long_query_time ||
- ((thd->server_status &
- (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) &&
- opt_log_queries_not_using_indexes))
+ thd->proc_info="logging slow query";
+ if (((end_utime_of_query - thd->utime_after_lock) >
+ thd->variables.long_query_time ||
+ ((thd->server_status &
+ (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) &&
+ opt_log_queries_not_using_indexes)) &&
+ thd->examined_row_count >= thd->variables.min_examined_row_limit)
{
thd->status_var.long_query_count++;
- slow_log_print(thd, thd->query, thd->query_length, start_of_query);
+ slow_log_print(thd, thd->query, thd->query_length, end_utime_of_query);
}
}
DBUG_VOID_RETURN;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 6c7949fc8d7..b3203592cbe 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -15508,15 +15508,11 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
/* Add "filtered" field to item_list. */
if (join->thd->lex->describe & DESCRIBE_EXTENDED)
{
- Item_float *filtered;
- float f;
+ float f= 0.0;
if (examined_rows)
f= (float) (100.0 * join->best_positions[i].records_read /
examined_rows);
- else
- f= 0.0;
- item_list.push_back((filtered= new Item_float(f)));
- filtered->decimals= 2;
+ item_list.push_back(new Item_float(f, 2));
}
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 5b8cb93baab..6c5a408f2c8 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1663,11 +1663,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
if (mysys_var)
pthread_mutex_unlock(&mysys_var->mutex);
-#ifdef EXTRA_DEBUG
- thd_info->start_time= tmp->time_after_lock;
-#else
thd_info->start_time= tmp->start_time;
-#endif
thd_info->query=0;
if (tmp->query)
{
@@ -1686,7 +1682,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
VOID(pthread_mutex_unlock(&LOCK_thread_count));
thread_info *thd_info;
- time_t now= time(0);
+ time_t now= my_time(0);
while ((thd_info=thread_infos.get()))
{
protocol->prepare_for_resend();
@@ -1716,7 +1712,7 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond)
TABLE *table= tables->table;
CHARSET_INFO *cs= system_charset_info;
char *user;
- time_t now= time(0);
+ time_t now= my_time(0);
DBUG_ENTER("fill_process_list");
user= thd->security_ctx->master_access & PROCESS_ACL ?
@@ -2069,11 +2065,11 @@ static bool show_status_array(THD *thd, const char *wild,
*/
switch (show_type) {
case SHOW_DOUBLE_STATUS:
- {
value= ((char *) status_var + (ulong) value);
- end= buff + sprintf(buff, "%f", *(double*) value);
+ /* fall through */
+ case SHOW_DOUBLE:
+ end= buff + my_sprintf(buff, (buff, "%f", *(double*) value));
break;
- }
case SHOW_LONG_STATUS:
value= ((char *) status_var + (ulong) value);
/* fall through */
@@ -2083,6 +2079,7 @@ static bool show_status_array(THD *thd, const char *wild,
break;
case SHOW_LONGLONG_STATUS:
value= ((char *) status_var + (ulonglong) value);
+ /* fall through */
case SHOW_LONGLONG:
end= longlong10_to_str(*(longlong*) value, buff, 10);
break;
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index dc3e72554fa..0ed7ebe631f 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -54,6 +54,20 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
HA_CREATE_INFO *create_info,
Alter_info *alter_info);
+#ifndef DBUG_OFF
+
+/* Wait until we get a 'mysql_kill' signal */
+
+static void wait_for_kill_signal(THD *thd)
+{
+ while (thd->killed == 0)
+ sleep(1);
+ // Reset signal and continue as if nothing happend
+ thd->killed= THD::NOT_KILLED;
+}
+#endif
+
+
/*
Translate a file name to a table name (WL #1324).
@@ -4111,6 +4125,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
RTFC_WAIT_OTHER_THREAD_FLAG |
RTFC_CHECK_KILLED_FLAG);
thd->exit_cond(old_message);
+ DBUG_EXECUTE_IF("wait_in_mysql_admin_table", wait_for_kill_signal(thd););
if (thd->killed)
goto err;
/* Flush entries in the query cache involving this table. */
diff --git a/sql/structs.h b/sql/structs.h
index da2339d27f8..09a3c4d7285 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -209,6 +209,11 @@ typedef struct user_conn {
char *user;
/* Pointer to host part of the key. */
char *host;
+ /*
+ The moment of time when per hour counters were reset last time
+ (i.e. start of "hour" for conn_per_hour, updates, questions counters).
+ */
+ ulonglong reset_utime;
/* Total length of the key. */
uint len;
/* Current amount of concurrent connections for this account. */
@@ -220,11 +225,6 @@ typedef struct user_conn {
uint conn_per_hour, updates, questions;
/* Maximum amount of resources which account is allowed to consume. */
USER_RESOURCES user_resources;
- /*
- The moment of time when per hour counters were reset last time
- (i.e. start of "hour" for conn_per_hour, updates, questions counters).
- */
- time_t intime;
} USER_CONN;
/* Bits in form->update */