diff options
-rw-r--r-- | mysql-test/r/timezone.result | 6 | ||||
-rw-r--r-- | mysql-test/t/timezone.test | 7 | ||||
-rw-r--r-- | sql/field.cc | 14 | ||||
-rw-r--r-- | sql/mysql_priv.h | 3 | ||||
-rw-r--r-- | sql/time.cc | 19 |
5 files changed, 32 insertions, 17 deletions
diff --git a/mysql-test/r/timezone.result b/mysql-test/r/timezone.result index 20706408075..15f0d4121c7 100644 --- a/mysql-test/r/timezone.result +++ b/mysql-test/r/timezone.result @@ -32,3 +32,9 @@ ts from_unixtime(ts) 1048989599 2003-03-30 03:59:59 1048989601 2003-03-30 04:00:01 DROP TABLE t1; +select unix_timestamp('1970-01-01 01:00:00'), +unix_timestamp('1970-01-01 01:00:01'), +unix_timestamp('2038-01-01 00:59:59'), +unix_timestamp('2038-01-01 01:00:00'); +unix_timestamp('1970-01-01 01:00:00') unix_timestamp('1970-01-01 01:00:01') unix_timestamp('2038-01-01 00:59:59') unix_timestamp('2038-01-01 01:00:00') +0 1 2145916799 0 diff --git a/mysql-test/t/timezone.test b/mysql-test/t/timezone.test index ab732c11a34..ba65eb72fe6 100644 --- a/mysql-test/t/timezone.test +++ b/mysql-test/t/timezone.test @@ -38,3 +38,10 @@ INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 04:00:01')); SELECT ts,from_unixtime(ts) FROM t1; DROP TABLE t1; +# +# Test for fix for Bug#2523 +# +select unix_timestamp('1970-01-01 01:00:00'), + unix_timestamp('1970-01-01 01:00:01'), + unix_timestamp('2038-01-01 00:59:59'), + unix_timestamp('2038-01-01 01:00:00'); diff --git a/sql/field.cc b/sql/field.cc index 687c22bb69b..ac3ebb4bfc7 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2583,22 +2583,18 @@ static longlong fix_datetime(longlong nr, TIME *time_res) void Field_timestamp::store(longlong nr) { TIME l_time; - time_t timestamp; + time_t timestamp= 0; if ((nr= fix_datetime(nr, &l_time))) { long not_used; - if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR-1) - { + timestamp= my_gmt_sec(&l_time, ¬_used); + + if (!timestamp) current_thd->cuted_fields++; - timestamp=0; - } - else - timestamp=my_gmt_sec(&l_time, ¬_used); } - else - timestamp=0; + #ifdef WORDS_BIGENDIAN if (table->db_low_byte_first) { diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index acb7005c26c..46f7ece8641 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -116,6 +116,9 @@ char* query_table_status(THD *thd,const char *db,const char *table_name); /* Time handling defaults */ #define TIMESTAMP_MAX_YEAR 2038 #define YY_PART_YEAR 70 +#define TIMESTAMP_MIN_YEAR (1900 + YY_PART_YEAR - 1) +#define TIMESTAMP_MAX_VALUE 2145916799 +#define TIMESTAMP_MIN_VALUE 1 #define PRECISION_FOR_DOUBLE 53 #define PRECISION_FOR_FLOAT 24 diff --git a/sql/time.cc b/sql/time.cc index 5dc229b1d88..0363d764100 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -63,6 +63,9 @@ long my_gmt_sec(TIME *t, long *my_timezone) struct tm *l_time,tm_tmp; long diff, current_timezone; + if (t->year > TIMESTAMP_MAX_YEAR || t->year < TIMESTAMP_MIN_YEAR) + return 0; + if (t->hour >= 24) { /* Fix for time-loop */ t->day+=t->hour/24; @@ -125,8 +128,10 @@ long my_gmt_sec(TIME *t, long *my_timezone) tmp-=t->minute*60 + t->second; // Move to previous hour } *my_timezone= current_timezone; - if (tmp < 0 && t->year <= 1900+YY_PART_YEAR) + + if (tmp < TIMESTAMP_MIN_VALUE || tmp > TIMESTAMP_MAX_VALUE) tmp= 0; + return (long) tmp; } /* my_gmt_sec */ @@ -444,15 +449,13 @@ time_t str_to_timestamp(const char *str,uint length) { TIME l_time; long not_used; + time_t timestamp= 0; - if (str_to_TIME(str,length,&l_time,0) == TIMESTAMP_NONE) - return(0); - if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR-1) - { + if (str_to_TIME(str,length,&l_time,0) != TIMESTAMP_NONE && + !(timestamp= my_gmt_sec(&l_time, ¬_used))) current_thd->cuted_fields++; - return(0); - } - return(my_gmt_sec(&l_time, ¬_used)); + + return timestamp; } |