diff options
author | unknown <petr/cps@owlet.local> | 2006-11-01 18:18:01 +0300 |
---|---|---|
committer | unknown <petr/cps@owlet.local> | 2006-11-01 18:18:01 +0300 |
commit | 60e315c53d60d1337f71405472189bb353100237 (patch) | |
tree | 7a5f2fe23939ea4eb1a8b2fdd922f3d3a91fb230 /sql | |
parent | 3ce0cadd05e00b31934af0bbf3b1f18891404a8e (diff) | |
parent | b2c40c169869f7df93342b434b84af4fb26acbe2 (diff) | |
download | mariadb-git-60e315c53d60d1337f71405472189bb353100237.tar.gz |
Merge mysql.com:/home/cps/mysql/trees/5.0-runtime-bug9191
into mysql.com:/home/cps/mysql/trees/5.1-runtime-bug9191
configure.in:
Auto merged
mysql-test/r/func_time.result:
Auto merged
mysql-test/r/timezone2.result:
Auto merged
mysql-test/t/func_time.test:
Auto merged
mysql-test/t/timezone2.test:
Auto merged
sql/item_timefunc.cc:
Auto merged
sql-common/my_time.c:
Auto merged
sql/mysql_priv.h:
Auto merged
sql/time.cc:
Auto merged
sql/tztime.cc:
Auto merged
include/my_time.h:
manual merge
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item_timefunc.cc | 9 | ||||
-rw-r--r-- | sql/mysql_priv.h | 6 | ||||
-rw-r--r-- | sql/time.cc | 9 | ||||
-rw-r--r-- | sql/tztime.cc | 77 |
4 files changed, 75 insertions, 26 deletions
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index d32adde5e64..77d7ae61c70 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1906,17 +1906,14 @@ bool Item_func_convert_tz::get_date(TIME *ltime, return 1; } - /* Check if we in range where we treat datetime values as non-UTC */ - if (ltime->year < TIMESTAMP_MAX_YEAR && ltime->year > TIMESTAMP_MIN_YEAR || - ltime->year==TIMESTAMP_MAX_YEAR && ltime->month==1 && ltime->day==1 || - ltime->year==TIMESTAMP_MIN_YEAR && ltime->month==12 && ltime->day==31) { my_bool not_used; my_time_tmp= from_tz->TIME_to_gmt_sec(ltime, ¬_used); - if (my_time_tmp >= TIMESTAMP_MIN_VALUE && my_time_tmp <= TIMESTAMP_MAX_VALUE) + /* my_time_tmp is guranteed to be in the allowed range */ + if (my_time_tmp) to_tz->gmt_sec_to_TIME(ltime, my_time_tmp); } - + null_value= 0; return 0; } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 6ddec155edb..de1077b9dc4 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -221,12 +221,6 @@ MY_LOCALE *my_locale_by_name(const char *name); /* Characters shown for the command in 'information_schema.processlist' */ #define PROCESS_LIST_INFO_WIDTH 65535 -/* 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 0461f7723c6..3e400046764 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -253,14 +253,11 @@ my_time_t TIME_to_timestamp(THD *thd, const TIME *t, my_bool *in_dst_time_gap) *in_dst_time_gap= 0; - if (t->year < TIMESTAMP_MAX_YEAR && t->year > TIMESTAMP_MIN_YEAR || - t->year == TIMESTAMP_MAX_YEAR && t->month == 1 && t->day == 1 || - t->year == TIMESTAMP_MIN_YEAR && t->month == 12 && t->day == 31) + timestamp= thd->variables.time_zone->TIME_to_gmt_sec(t, in_dst_time_gap); + if (timestamp) { thd->time_zone_used= 1; - timestamp= thd->variables.time_zone->TIME_to_gmt_sec(t, in_dst_time_gap); - if (timestamp >= TIMESTAMP_MIN_VALUE && timestamp <= TIMESTAMP_MAX_VALUE) - return timestamp; + return timestamp; } /* If we are here we have range error. */ diff --git a/sql/tztime.cc b/sql/tztime.cc index a1bcf25bb51..8c44e4e4f9f 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -898,8 +898,14 @@ TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp, my_time_t local_t; uint saved_seconds; uint i; + int shift= 0; + DBUG_ENTER("TIME_to_gmt_sec"); + if (!validate_timestamp_range(t)) + return 0; + + /* We need this for correct leap seconds handling */ if (t->second < SECS_PER_MIN) saved_seconds= 0; @@ -907,11 +913,29 @@ TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp, saved_seconds= t->second; /* - NOTE If we want to convert full my_time_t range without MySQL - restrictions we should catch overflow here somehow. + NOTE: to convert full my_time_t range we do a shift of the + boundary dates here to avoid overflow of my_time_t. + We use alike approach in my_system_gmt_sec(). + + However in that function we also have to take into account + overflow near 0 on some platforms. That's because my_system_gmt_sec + uses localtime_r(), which doesn't work with negative values correctly + on platforms with unsigned time_t (QNX). Here we don't use localtime() + => we negative values of local_t are ok. */ - local_t= sec_since_epoch(t->year, t->month, t->day, + if ((t->year == TIMESTAMP_MAX_YEAR) && (t->month == 1) && t->day > 4) + { + /* + We will pass (t->day - shift) to sec_since_epoch(), and + want this value to be a positive number, so we shift + only dates > 4.01.2038 (to avoid owerflow). + */ + shift= 2; + } + + + local_t= sec_since_epoch(t->year, t->month, (t->day - shift), t->hour, t->minute, saved_seconds ? 0 : t->second); @@ -930,6 +954,22 @@ TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp, /* binary search for our range */ i= find_time_range(local_t, sp->revts, sp->revcnt); + /* + As there are no offset switches at the end of TIMESTAMP range, + we could simply check for overflow here (and don't need to bother + about DST gaps etc) + */ + if (shift) + { + if (local_t > (TIMESTAMP_MAX_VALUE - shift*86400L + + sp->revtis[i].rt_offset - saved_seconds)) + { + DBUG_RETURN(0); /* my_time_t overflow */ + } + else + local_t+= shift*86400L; + } + if (sp->revtis[i].rt_type) { /* @@ -939,10 +979,16 @@ TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp, beginning of the gap. */ *in_dst_time_gap= 1; - DBUG_RETURN(sp->revts[i] - sp->revtis[i].rt_offset + saved_seconds); + local_t= sp->revts[i] - sp->revtis[i].rt_offset + saved_seconds; } else - DBUG_RETURN(local_t - sp->revtis[i].rt_offset + saved_seconds); + local_t= local_t - sp->revtis[i].rt_offset + saved_seconds; + + /* check for TIMESTAMP_MAX_VALUE was already done above */ + if (local_t < TIMESTAMP_MIN_VALUE) + local_t= 0; + + DBUG_RETURN(local_t); } @@ -1308,9 +1354,24 @@ Time_zone_offset::Time_zone_offset(long tz_offset_arg): my_time_t Time_zone_offset::TIME_to_gmt_sec(const TIME *t, my_bool *in_dst_time_gap) const { - return sec_since_epoch(t->year, t->month, t->day, - t->hour, t->minute, t->second) - - offset; + my_time_t local_t; + + /* + Check timestamp range.we have to do this as calling function relies on + us to make all validation checks here. + */ + if (!validate_timestamp_range(t)) + return 0; + + local_t= sec_since_epoch(t->year, t->month, t->day, + t->hour, t->minute, t->second) - + offset; + + if (local_t >= TIMESTAMP_MIN_VALUE && local_t <= TIMESTAMP_MAX_VALUE) + return local_t; + + /* range error*/ + return 0; } |