summaryrefslogtreecommitdiff
path: root/sql-common
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2011-06-07 18:13:02 +0200
committerSergei Golubchik <sergii@pisem.net>2011-06-07 18:13:02 +0200
commit9b98cae4cc44fa39813675b361b7aa65d129b29d (patch)
tree7f4baeea245f91006e88c62508c2859ed9390c2d /sql-common
parent29af1aefe914da6aca73498c077f7e37a36d7de4 (diff)
parent4d128777dde904c5f0adab9b093e854c9c580d41 (diff)
downloadmariadb-git-9b98cae4cc44fa39813675b361b7aa65d129b29d.tar.gz
merge with 5.1-micro
Diffstat (limited to 'sql-common')
-rw-r--r--sql-common/my_time.c110
1 files changed, 43 insertions, 67 deletions
diff --git a/sql-common/my_time.c b/sql-common/my_time.c
index f692bd51185..bbac69d9ac9 100644
--- a/sql-common/my_time.c
+++ b/sql-common/my_time.c
@@ -18,6 +18,7 @@
#include <m_ctype.h>
/* Windows version of localtime_r() is declared in my_ptrhead.h */
#include <my_pthread.h>
+#include <mysqld_error.h>
ulonglong log_10_int[20]=
{
@@ -732,7 +733,7 @@ void my_init_time(void)
time_t seconds;
struct tm *l_time,tm_tmp;
MYSQL_TIME my_time;
- my_bool not_used;
+ uint not_used;
seconds= (time_t) time((time_t*) 0);
localtime_r(&seconds,&tm_tmp);
@@ -818,7 +819,11 @@ long calc_daynr(uint year,uint month,uint day)
t - time value to be converted
my_timezone - pointer to long where offset of system time zone
from UTC will be stored for caching
- in_dst_time_gap - set to true if time falls into spring time-gap
+ error_code - 0, if the conversion was successful;
+ ER_WARN_DATA_OUT_OF_RANGE, if t contains datetime value
+ which is out of TIMESTAMP range;
+ ER_WARN_INVALID_TIMESTAMP, if t represents value which
+ doesn't exists (falls into the spring time-gap).
NOTES
The idea is to cache the time zone offset from UTC (including daylight
@@ -832,8 +837,7 @@ long calc_daynr(uint year,uint month,uint day)
Time in UTC seconds since Unix Epoch representation.
*/
my_time_t
-my_system_gmt_sec(const MYSQL_TIME *t_src, long *my_timezone,
- my_bool *in_dst_time_gap)
+my_system_gmt_sec(const MYSQL_TIME *t_src, long *my_timezone, uint *error_code)
{
uint loop;
time_t tmp= 0;
@@ -843,8 +847,6 @@ my_system_gmt_sec(const MYSQL_TIME *t_src, long *my_timezone,
struct tm *l_time,tm_tmp;
long diff, current_timezone;
- *in_dst_time_gap= 0; /* Reset */
-
/*
Use temp variable to avoid trashing input data, which could happen in
case of shift required for boundary dates processing.
@@ -853,9 +855,10 @@ my_system_gmt_sec(const MYSQL_TIME *t_src, long *my_timezone,
if (!validate_timestamp_range(t))
{
- *in_dst_time_gap= 1;
+ *error_code= ER_WARN_DATA_OUT_OF_RANGE;
return 0;
}
+ *error_code= 0;
/*
Calculate the gmt time based on current time and timezone
@@ -1001,7 +1004,7 @@ my_system_gmt_sec(const MYSQL_TIME *t_src, long *my_timezone,
else if (diff == -3600)
tmp-=t->minute*60 + t->second; /* Move to previous hour */
- *in_dst_time_gap= 1;
+ *error_code= ER_WARN_INVALID_TIMESTAMP;
}
*my_timezone= current_timezone;
@@ -1022,7 +1025,7 @@ my_system_gmt_sec(const MYSQL_TIME *t_src, long *my_timezone,
if (!IS_TIME_T_VALID_FOR_TIMESTAMP(tmp))
{
tmp= 0;
- *in_dst_time_gap= 1;
+ *error_code= ER_WARN_DATA_OUT_OF_RANGE;
}
return (my_time_t) tmp;
@@ -1150,7 +1153,7 @@ int my_TIME_to_str(const MYSQL_TIME *l_time, char *to, uint digits)
Datetime value in YYYYMMDDHHMMSS format.
*/
-longlong number_to_datetime(longlong nr, MYSQL_TIME *time_res,
+longlong number_to_datetime(longlong nr, ulong sec_part, MYSQL_TIME *time_res,
uint flags, int *was_cut)
{
long part1,part2;
@@ -1158,7 +1161,7 @@ longlong number_to_datetime(longlong nr, MYSQL_TIME *time_res,
*was_cut= 0;
time_res->time_type=MYSQL_TIMESTAMP_DATE;
- if (nr == LL(0) || nr >= LL(10000101000000))
+ if (nr == 0 || nr >= 10000101000000LL || sec_part)
{
time_res->time_type=MYSQL_TIMESTAMP_DATETIME;
goto ok;
@@ -1208,13 +1211,14 @@ longlong number_to_datetime(longlong nr, MYSQL_TIME *time_res,
time_res->hour= (int) (part2/10000L); part2%=10000L;
time_res->minute=(int) part2 / 100;
time_res->second=(int) part2 % 100;
- time_res->second_part= 0;
+ time_res->second_part= sec_part;
time_res->neg= 0;
if (time_res->year <= 9999 && time_res->month <= 12 &&
time_res->day <= 31 && time_res->hour <= 23 &&
time_res->minute <= 59 && time_res->second <= 59 &&
- !check_date(time_res, (nr != 0), flags, was_cut))
+ sec_part <= TIME_MAX_SECOND_PART &&
+ !check_date(time_res, nr || sec_part, flags, was_cut))
return nr;
/* Don't want to have was_cut get set if NO_ZERO_DATE was violated. */
@@ -1234,7 +1238,7 @@ longlong number_to_datetime(longlong nr, MYSQL_TIME *time_res,
}
/*
- Convert a double to a MYSQL_TIME struct.
+ Convert a pair of integers to a MYSQL_TIME struct.
@param[in] nr a number to convert
@param[out] ltime Date to check.
@@ -1242,81 +1246,53 @@ longlong number_to_datetime(longlong nr, MYSQL_TIME *time_res,
modified to fit in the valid range. Otherwise 0.
@details
- Takes a number in the [-]HHHMMSS.uuuuuu format.
-
- number_to_datetime() cannot take a double, because double precision is not
- enough for YYYYMMDDHHMMSS.uuuuuu
+ Takes a number in the [-]HHHMMSS.uuuuuu,
+ YYMMDDHHMMSS.uuuuuu, or in the YYYYMMDDHHMMSS.uuuuuu formats.
@return
0 time value is valid, but was possibly truncated
- 1 time value is invalid
+ -1 time value is invalid
*/
-int number_to_time(double nr, MYSQL_TIME *ltime, int *was_cut)
+int number_to_time(my_bool neg, longlong nr, ulong sec_part,
+ MYSQL_TIME *ltime, int *was_cut)
{
- ulong tmp;
+ if (nr > 9999999 && neg == 0)
+ {
+ if (number_to_datetime(nr, sec_part, ltime,
+ TIME_FUZZY_DATE | TIME_INVALID_DATES, was_cut) < 0)
+ return -1;
+
+ ltime->year= ltime->month= ltime->day= 0;
+ ltime->time_type= MYSQL_TIMESTAMP_TIME;
+ *was_cut= MYSQL_TIME_WARN_TRUNCATED;
+ return 0;
+ }
+
*was_cut= 0;
ltime->year= ltime->month= ltime->day= 0;
ltime->time_type= MYSQL_TIMESTAMP_TIME;
- if ((ltime->neg= nr < 0))
- nr= -nr;
+ ltime->neg= neg;
if (nr > TIME_MAX_VALUE)
{
nr= TIME_MAX_VALUE;
+ sec_part= TIME_MAX_SECOND_PART;
*was_cut= MYSQL_TIME_WARN_OUT_OF_RANGE;
}
- tmp=(ulong)floor(nr);
- ltime->hour = tmp/100/100;
- ltime->minute= tmp/100%100;
- ltime->second= tmp%100;
- ltime->second_part= (ulong)((nr-tmp)*TIME_SECOND_PART_FACTOR);
+ ltime->hour = nr/100/100;
+ ltime->minute= nr/100%100;
+ ltime->second= nr%100;
+ ltime->second_part= sec_part;
- if (ltime->minute < 60 && ltime->second < 60)
+ if (ltime->minute < 60 && ltime->second < 60 && sec_part <= TIME_MAX_SECOND_PART)
return 0;
*was_cut= MYSQL_TIME_WARN_TRUNCATED;
- return 1;
+ return -1;
}
-/*
- Convert a double to a date/datetime
-
- Note that for sub seconds, the precision of double is not good enough!
-
- RESULT:
- 0 ok
- 1 error ; ltime is zeroed
-*/
-
-my_bool double_to_datetime(double value, MYSQL_TIME *ltime,
- uint fuzzydate)
-{
- double datepart_value;
- int was_cut;
-
- if (value < 0 || value > 99991231235959.0)
- {
- bzero((char*) ltime, sizeof(*ltime));
- return 1;
- }
-
- datepart_value= floor(value);
- if (number_to_datetime((longlong) datepart_value, ltime, fuzzydate,
- &was_cut) == LL(-1))
- return 1;
- if (ltime->time_type == MYSQL_TIMESTAMP_DATETIME ||
- ltime->time_type == MYSQL_TIMESTAMP_TIME)
- {
- /* Add sub seconds to results */
- ltime->second_part= (ulong) (floor((value - datepart_value) *
- TIME_SECOND_PART_FACTOR));
- }
- return 0;
-}
-
-
/* Convert time value to integer in YYYYMMDDHHMMSS format */
ulonglong TIME_to_ulonglong_datetime(const MYSQL_TIME *my_time)