summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <petr/cps@owlet.local>2006-11-01 18:18:01 +0300
committerunknown <petr/cps@owlet.local>2006-11-01 18:18:01 +0300
commit60e315c53d60d1337f71405472189bb353100237 (patch)
tree7a5f2fe23939ea4eb1a8b2fdd922f3d3a91fb230 /sql
parent3ce0cadd05e00b31934af0bbf3b1f18891404a8e (diff)
parentb2c40c169869f7df93342b434b84af4fb26acbe2 (diff)
downloadmariadb-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.cc9
-rw-r--r--sql/mysql_priv.h6
-rw-r--r--sql/time.cc9
-rw-r--r--sql/tztime.cc77
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, &not_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;
}