diff options
author | Sergei Golubchik <sergii@pisem.net> | 2011-06-06 20:28:15 +0200 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2011-06-06 20:28:15 +0200 |
commit | 4d128777dde904c5f0adab9b093e854c9c580d41 (patch) | |
tree | 36875e84e65be596def46c5d7ce621e60abcbdae /sql-common | |
parent | c1a92f9caeb368021d5ffbe0df237ded29692c1a (diff) | |
download | mariadb-git-4d128777dde904c5f0adab9b093e854c9c580d41.tar.gz |
revert a suggested "optimization" that introduced a bug
compilation error in mysys/my_getsystime.c fixed
some redundant code removed
sec_to_time, time_to_sec, from_unixtime, unix_timestamp, @@timestamp now
use decimal, not double for numbers with a fractional part.
purge_master_logs_before_date() fixed
many bugs in corner cases fixed
mysys/my_getsystime.c:
compilation failure fixed
sql/sql_parse.cc:
don't cut corners. it backfires.
Diffstat (limited to 'sql-common')
-rw-r--r-- | sql-common/my_time.c | 47 |
1 files changed, 28 insertions, 19 deletions
diff --git a/sql-common/my_time.c b/sql-common/my_time.c index 264fc5b957b..6958c8e3517 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]= { @@ -730,7 +731,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); @@ -811,7 +812,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 @@ -825,8 +830,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,7 +847,11 @@ my_system_gmt_sec(const MYSQL_TIME *t_src, long *my_timezone, memcpy(&tmp_time, t_src, sizeof(MYSQL_TIME)); if (!validate_timestamp_range(t)) + { + *error_code= ER_WARN_DATA_OUT_OF_RANGE; return 0; + } + *error_code= 0; /* Calculate the gmt time based on current time and timezone @@ -989,7 +997,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; @@ -1130,7 +1138,7 @@ int my_TIME_to_str(const MYSQL_TIME *l_time, char *to, int 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; @@ -1139,7 +1147,7 @@ longlong number_to_datetime(longlong nr, MYSQL_TIME *time_res, bzero((char*) time_res, sizeof(*time_res)); 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; @@ -1189,11 +1197,13 @@ 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= sec_part; 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. */ @@ -1206,7 +1216,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. @@ -1223,28 +1233,27 @@ longlong number_to_datetime(longlong nr, MYSQL_TIME *time_res, 0 time value is valid, but was possibly truncated 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; *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; |