Commit 8bb6d513 authored by unknown's avatar unknown

Fixed problem with mysql prompt when server disconnect. (Bug 356)

Fixed problem with localtime -> gmt where some times resulted in
different (but correct) timestamps. Now MySQL should use the smallest
possible timestamp value in this case.  (Bug 316)


client/mysql.cc:
  Fixed problem with prompt when server disconnect. (Bug 356)
client/mysqltest.c:
  More debug information
mysql-test/mysql-test-run.sh:
  Added support for --timezone in -master.opt
mysql-test/t/raid.test:
  Fixed test if raid is enabled
sql/field.cc:
  New my_gmt_sec() parameters
sql/mysql_priv.h:
  New my_gmt_sec() parameters
sql/mysqld.cc:
  Remove LOCK_timezone.
  Code cleanup
sql/time.cc:
  Fixed problem with localtime -> gmt where some times resulted in
  different (but correct) timestamps. Now MySQL should use the smallest
  possible timestamp value in this case.  (Bug 316)
parent bdc8fa3d
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
#include <signal.h> #include <signal.h>
#include <violite.h> #include <violite.h>
const char *VER= "12.20"; const char *VER= "12.21";
/* Don't try to make a nice table if the data is too big */ /* Don't try to make a nice table if the data is too big */
#define MAX_COLUMN_LENGTH 1024 #define MAX_COLUMN_LENGTH 1024
...@@ -2613,14 +2613,18 @@ static const char* construct_prompt() ...@@ -2613,14 +2613,18 @@ static const char* construct_prompt()
add_int_to_prompt(++prompt_counter); add_int_to_prompt(++prompt_counter);
break; break;
case 'v': case 'v':
processed_prompt.append(mysql_get_server_info(&mysql)); if (connected)
processed_prompt.append(mysql_get_server_info(&mysql));
else
processed_prompt.append("not_connected");
break; break;
case 'd': case 'd':
processed_prompt.append(current_db ? current_db : "(none)"); processed_prompt.append(current_db ? current_db : "(none)");
break; break;
case 'h': case 'h':
{ {
const char *prompt=mysql_get_host_info(&mysql); const char *prompt;
prompt= connected ? mysql_get_host_info(&mysql) : "not_connected";
if (strstr(prompt, "Localhost")) if (strstr(prompt, "Localhost"))
processed_prompt.append("localhost"); processed_prompt.append("localhost");
else else
...@@ -2631,8 +2635,13 @@ static const char* construct_prompt() ...@@ -2631,8 +2635,13 @@ static const char* construct_prompt()
break; break;
} }
case 'p': case 'p':
if (strstr(mysql_get_host_info(&mysql),"TCP/IP") || if (!connected)
! mysql.unix_socket) {
processed_prompt.append("not_connected");
break;
}
if (strstr(mysql_get_host_info(&mysql),"TCP/IP") || !
mysql.unix_socket)
add_int_to_prompt(mysql.port); add_int_to_prompt(mysql.port);
else else
{ {
......
...@@ -515,8 +515,12 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char* fname) ...@@ -515,8 +515,12 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char* fname)
if (!my_stat(eval_file, &stat_info, MYF(MY_WME))) if (!my_stat(eval_file, &stat_info, MYF(MY_WME)))
die(NullS); die(NullS);
if (!eval_result && stat_info.st_size != ds->length) if (!eval_result && (uint) stat_info.st_size != ds->length)
{
DBUG_PRINT("info",("Size differs: result size: %u file size: %u",
ds->length, stat_info.st_size));
DBUG_RETURN(2); DBUG_RETURN(2);
}
if (!(tmp = (char*) my_malloc(stat_info.st_size + 1, MYF(MY_WME)))) if (!(tmp = (char*) my_malloc(stat_info.st_size + 1, MYF(MY_WME))))
die(NullS); die(NullS);
......
...@@ -13,7 +13,8 @@ DB=test ...@@ -13,7 +13,8 @@ DB=test
DBPASSWD= DBPASSWD=
VERBOSE="" VERBOSE=""
USE_MANAGER=0 USE_MANAGER=0
TZ=GMT-3; export TZ # for UNIX_TIMESTAMP tests to work MY_TZ=GMT-3
TZ=$MY_TZ; export TZ # for UNIX_TIMESTAMP tests to work
#++ #++
# Program Definitions # Program Definitions
...@@ -1161,9 +1162,18 @@ run_testcase () ...@@ -1161,9 +1162,18 @@ run_testcase ()
if [ -f $master_opt_file ] ; if [ -f $master_opt_file ] ;
then then
EXTRA_MASTER_OPT=`$CAT $master_opt_file | $SED -e "s;\\$MYSQL_TEST_DIR;$MYSQL_TEST_DIR;"` EXTRA_MASTER_OPT=`$CAT $master_opt_file | $SED -e "s;\\$MYSQL_TEST_DIR;$MYSQL_TEST_DIR;"`
case "$EXTRA_MASTER_OPT" in
--timezone=*)
TZ=`$ECHO "$EXTRA_MASTER_OPT" | $SED -e "s;--timezone=;;"`
export TZ
# Note that this must be set to space, not "" for test-reset to work
EXTRA_MASTER_OPT=" "
;;
esac
stop_master stop_master
echo "CURRENT_TEST: $tname" >> $MASTER_MYERR echo "CURRENT_TEST: $tname" >> $MASTER_MYERR
start_master start_master
TZ=$MY_TZ; export TZ
else else
if [ ! -z "$EXTRA_MASTER_OPT" ] || [ x$MASTER_RUNNING != x1 ] || [ -f $master_init_script ] if [ ! -z "$EXTRA_MASTER_OPT" ] || [ x$MASTER_RUNNING != x1 ] || [ -f $master_init_script ]
then then
......
Variable_name Value
timezone MEST
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (ts int);
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 01:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 03:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 01:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 02:59:59'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 03:00:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 03:59:59'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 04:00:01'));
SELECT ts,from_unixtime(ts) FROM t1;
ts from_unixtime(ts)
1035673200 2002-10-27 01:00:00
1035680400 2002-10-27 02:00:00
1035684000 2002-10-27 03:00:00
1035680400 2002-10-27 02:00:00
1035673200 2002-10-27 01:00:00
1035680400 2002-10-27 02:00:00
1048986000 2003-03-30 03:00:00
1048986000 2003-03-30 03:00:00
1048989599 2003-03-30 03:59:59
1048989601 2003-03-30 04:00:01
DROP TABLE t1;
-- require r/have_raid.require -- require r/have_raid.require
disable_query_log;
show variables like "have_raid"; show variables like "have_raid";
enable_query_log;
# #
# Test of raided tables # Test of raided tables
......
#
# Test of timezone handling. This script must be run with TZ=MEST
-- require r/have_mest_timezone.require
disable_query_log;
show variables like "timezone";
enable_query_log;
# Initialization
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
CREATE TABLE t1 (ts int);
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 01:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 03:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 01:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 02:59:59'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 03:00:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 03:59:59'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 04:00:01'));
SELECT ts,from_unixtime(ts) FROM t1;
DROP TABLE t1;
...@@ -2552,6 +2552,7 @@ void Field_timestamp::store(longlong nr) ...@@ -2552,6 +2552,7 @@ void Field_timestamp::store(longlong nr)
if ((nr=fix_datetime(nr))) if ((nr=fix_datetime(nr)))
{ {
long not_used;
part1=(long) (nr/LL(1000000)); part1=(long) (nr/LL(1000000));
part2=(long) (nr - (longlong) part1*LL(1000000)); part2=(long) (nr - (longlong) part1*LL(1000000));
l_time.year= (int) (part1/10000L); part1%=10000L; l_time.year= (int) (part1/10000L); part1%=10000L;
...@@ -2560,7 +2561,7 @@ void Field_timestamp::store(longlong nr) ...@@ -2560,7 +2561,7 @@ void Field_timestamp::store(longlong nr)
l_time.hour= (int) (part2/10000L); part2%=10000L; l_time.hour= (int) (part2/10000L); part2%=10000L;
l_time.minute=(int) part2 / 100; l_time.minute=(int) part2 / 100;
l_time.second=(int) part2 % 100; l_time.second=(int) part2 % 100;
timestamp=my_gmt_sec(&l_time); timestamp=my_gmt_sec(&l_time, &not_used);
} }
else else
timestamp=0; timestamp=0;
......
...@@ -755,7 +755,7 @@ uint calc_days_in_year(uint year); ...@@ -755,7 +755,7 @@ uint calc_days_in_year(uint year);
void get_date_from_daynr(long daynr,uint *year, uint *month, void get_date_from_daynr(long daynr,uint *year, uint *month,
uint *day); uint *day);
void init_time(void); void init_time(void);
long my_gmt_sec(TIME *); long my_gmt_sec(TIME *, long *current_timezone);
time_t str_to_timestamp(const char *str,uint length); time_t str_to_timestamp(const char *str,uint length);
bool str_to_time(const char *str,uint length,TIME *l_time); bool str_to_time(const char *str,uint length,TIME *l_time);
longlong str_to_datetime(const char *str,uint length,bool fuzzy_date); longlong str_to_datetime(const char *str,uint length,bool fuzzy_date);
......
...@@ -968,7 +968,6 @@ static void clean_up_mutexes() ...@@ -968,7 +968,6 @@ static void clean_up_mutexes()
(void) pthread_mutex_destroy(&LOCK_crypt); (void) pthread_mutex_destroy(&LOCK_crypt);
(void) pthread_mutex_destroy(&LOCK_bytes_sent); (void) pthread_mutex_destroy(&LOCK_bytes_sent);
(void) pthread_mutex_destroy(&LOCK_bytes_received); (void) pthread_mutex_destroy(&LOCK_bytes_received);
(void) pthread_mutex_destroy(&LOCK_timezone);
(void) pthread_mutex_destroy(&LOCK_user_conn); (void) pthread_mutex_destroy(&LOCK_user_conn);
(void) pthread_mutex_destroy(&LOCK_rpl_status); (void) pthread_mutex_destroy(&LOCK_rpl_status);
(void) pthread_mutex_destroy(&LOCK_active_mi); (void) pthread_mutex_destroy(&LOCK_active_mi);
...@@ -1998,19 +1997,11 @@ int main(int argc, char **argv) ...@@ -1998,19 +1997,11 @@ int main(int argc, char **argv)
} }
#endif #endif
#ifdef HAVE_TZNAME #ifdef HAVE_TZNAME
#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT)
{ {
struct tm tm_tmp; struct tm tm_tmp;
localtime_r(&start_time,&tm_tmp); localtime_r(&start_time,&tm_tmp);
strmov(time_zone,tzname[tm_tmp.tm_isdst != 0 ? 1 : 0]); strmov(time_zone,tzname[tm_tmp.tm_isdst != 0 ? 1 : 0]);
} }
#else
{
struct tm *start_tm;
start_tm=localtime(&start_time);
strmov(time_zone,tzname[start_tm->tm_isdst != 0 ? 1 : 0]);
}
#endif
#endif #endif
if (gethostname(glob_hostname,sizeof(glob_hostname)-4) < 0) if (gethostname(glob_hostname,sizeof(glob_hostname)-4) < 0)
...@@ -2067,7 +2058,6 @@ int main(int argc, char **argv) ...@@ -2067,7 +2058,6 @@ int main(int argc, char **argv)
(void) pthread_mutex_init(&LOCK_crypt,MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_crypt,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_bytes_sent,MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_bytes_sent,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_bytes_received,MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_bytes_received,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_timezone,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_rpl_status, MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_rpl_status, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
......
...@@ -28,7 +28,6 @@ uchar *days_in_month= (uchar*) "\037\034\037\036\037\036\037\037\036\037\036\037 ...@@ -28,7 +28,6 @@ uchar *days_in_month= (uchar*) "\037\034\037\036\037\036\037\037\036\037\036\037
/* Currently only my_time_zone is inited */ /* Currently only my_time_zone is inited */
static long my_time_zone=0; static long my_time_zone=0;
pthread_mutex_t LOCK_timezone;
void init_time(void) void init_time(void)
{ {
...@@ -39,14 +38,14 @@ void init_time(void) ...@@ -39,14 +38,14 @@ void init_time(void)
seconds= (time_t) time((time_t*) 0); seconds= (time_t) time((time_t*) 0);
localtime_r(&seconds,&tm_tmp); localtime_r(&seconds,&tm_tmp);
l_time= &tm_tmp; l_time= &tm_tmp;
my_time_zone=0; my_time_zone= 3600; /* Comp. for -3600 in my_gmt_sec */
my_time.year= (uint) l_time->tm_year+1900; my_time.year= (uint) l_time->tm_year+1900;
my_time.month= (uint) l_time->tm_mon+1; my_time.month= (uint) l_time->tm_mon+1;
my_time.day= (uint) l_time->tm_mday; my_time.day= (uint) l_time->tm_mday;
my_time.hour= (uint) l_time->tm_hour; my_time.hour= (uint) l_time->tm_hour;
my_time.minute= (uint) l_time->tm_min; my_time.minute= (uint) l_time->tm_min;
my_time.second= (uint) l_time->tm_sec; my_time.second= (uint) l_time->tm_sec;
VOID(my_gmt_sec(&my_time)); /* Init my_time_zone */ my_gmt_sec(&my_time, &my_time_zone); /* Init my_time_zone */
} }
/* /*
...@@ -57,26 +56,39 @@ void init_time(void) ...@@ -57,26 +56,39 @@ void init_time(void)
*/ */
long my_gmt_sec(TIME *t) long my_gmt_sec(TIME *t, long *my_timezone)
{ {
uint loop; uint loop;
time_t tmp; time_t tmp;
struct tm *l_time,tm_tmp; struct tm *l_time,tm_tmp;
long diff; long diff, current_timezone;
if (t->hour >= 24) if (t->hour >= 24)
{ /* Fix for time-loop */ { /* Fix for time-loop */
t->day+=t->hour/24; t->day+=t->hour/24;
t->hour%=24; t->hour%=24;
} }
pthread_mutex_lock(&LOCK_timezone);
tmp=(time_t) ((calc_daynr((uint) t->year,(uint) t->month,(uint) t->day) - /*
(long) days_at_timestart)*86400L + (long) t->hour*3600L + Calculate the gmt time based on current time and timezone
(long) (t->minute*60 + t->second)) + (time_t) my_time_zone; The -1 on the end is to ensure that if have a date that exists twice
(like 2002-10-27 02:00:0 MET), we will find the initial date.
By doing -3600 we will have to call localtime_r() several times, but
I couldn't come up with a better way to get a repeatable result :(
We can't use mktime() as it's buggy on many platforms and not thread safe.
*/
tmp=(time_t) (((calc_daynr((uint) t->year,(uint) t->month,(uint) t->day) -
(long) days_at_timestart)*86400L + (long) t->hour*3600L +
(long) (t->minute*60 + t->second)) + (time_t) my_time_zone -
3600);
current_timezone= my_time_zone;
localtime_r(&tmp,&tm_tmp); localtime_r(&tmp,&tm_tmp);
l_time=&tm_tmp; l_time=&tm_tmp;
for (loop=0; for (loop=0;
loop < 3 && loop < 2 &&
(t->hour != (uint) l_time->tm_hour || (t->hour != (uint) l_time->tm_hour ||
t->minute != (uint) l_time->tm_min); t->minute != (uint) l_time->tm_min);
loop++) loop++)
...@@ -89,14 +101,16 @@ long my_gmt_sec(TIME *t) ...@@ -89,14 +101,16 @@ long my_gmt_sec(TIME *t)
days= -1; days= -1;
diff=(3600L*(long) (days*24+((int) t->hour - (int) l_time->tm_hour)) + diff=(3600L*(long) (days*24+((int) t->hour - (int) l_time->tm_hour)) +
(long) (60*((int) t->minute - (int) l_time->tm_min))); (long) (60*((int) t->minute - (int) l_time->tm_min)));
my_time_zone+=diff; current_timezone+= diff+3600; // Compensate for -3600 above
tmp+=(time_t) diff; tmp+= (time_t) diff;
localtime_r(&tmp,&tm_tmp); localtime_r(&tmp,&tm_tmp);
l_time=&tm_tmp; l_time=&tm_tmp;
} }
/* Fix that if we are in the not existing daylight saving time hour /*
we move the start of the next real hour */ Fix that if we are in the not existing daylight saving time hour
if (loop == 3 && t->hour != (uint) l_time->tm_hour) we move the start of the next real hour
*/
if (loop == 2 && t->hour != (uint) l_time->tm_hour)
{ {
int days= t->day - l_time->tm_mday; int days= t->day - l_time->tm_mday;
if (days < -1) if (days < -1)
...@@ -108,11 +122,9 @@ long my_gmt_sec(TIME *t) ...@@ -108,11 +122,9 @@ long my_gmt_sec(TIME *t)
if (diff == 3600) if (diff == 3600)
tmp+=3600 - t->minute*60 - t->second; // Move to next hour tmp+=3600 - t->minute*60 - t->second; // Move to next hour
else if (diff == -3600) else if (diff == -3600)
tmp-=t->minute*60 + t->second; // Move to next hour tmp-=t->minute*60 + t->second; // Move to previous hour
} }
if ((my_time_zone >=0 ? my_time_zone: -my_time_zone) > 3600L*12) *my_timezone= current_timezone;
my_time_zone=0; /* Wrong date */
pthread_mutex_unlock(&LOCK_timezone);
return (long) tmp; return (long) tmp;
} /* my_gmt_sec */ } /* my_gmt_sec */
...@@ -399,6 +411,8 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date) ...@@ -399,6 +411,8 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
time_t str_to_timestamp(const char *str,uint length) time_t str_to_timestamp(const char *str,uint length)
{ {
TIME l_time; TIME l_time;
long not_used;
if (str_to_TIME(str,length,&l_time,0) == TIMESTAMP_NONE) if (str_to_TIME(str,length,&l_time,0) == TIMESTAMP_NONE)
return(0); return(0);
if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR) if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR)
...@@ -406,7 +420,7 @@ time_t str_to_timestamp(const char *str,uint length) ...@@ -406,7 +420,7 @@ time_t str_to_timestamp(const char *str,uint length)
current_thd->cuted_fields++; current_thd->cuted_fields++;
return(0); return(0);
} }
return(my_gmt_sec(&l_time)); return(my_gmt_sec(&l_time, &not_used));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment