diff options
Diffstat (limited to 'sql/field.cc')
-rw-r--r-- | sql/field.cc | 76 |
1 files changed, 50 insertions, 26 deletions
diff --git a/sql/field.cc b/sql/field.cc index 43481ca0963..1070d0f7b7d 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2520,31 +2520,60 @@ void Field_timestamp::store(double nr) ** function. */ -static longlong fix_datetime(longlong nr) +static longlong fix_datetime(longlong nr, TIME *time_res) { + long part1,part2; + if (nr == LL(0) || nr >= LL(10000101000000)) - return nr; // Normal datetime >= Year 1000 + goto ok; if (nr < 101) goto err; if (nr <= (YY_PART_YEAR-1)*10000L+1231L) - return (nr+20000000L)*1000000L; // YYMMDD, year: 2000-2069 + { + nr= (nr+20000000L)*1000000L; // YYMMDD, year: 2000-2069 + goto ok; + } if (nr < (YY_PART_YEAR)*10000L+101L) goto err; if (nr <= 991231L) - return (nr+19000000L)*1000000L; // YYMMDD, year: 1970-1999 + { + nr= (nr+19000000L)*1000000L; // YYMMDD, year: 1970-1999 + goto ok; + } if (nr < 10000101L) goto err; if (nr <= 99991231L) - return nr*1000000L; + { + nr= nr*1000000L; + goto ok; + } if (nr < 101000000L) goto err; if (nr <= (YY_PART_YEAR-1)*LL(10000000000)+LL(1231235959)) - return nr+LL(20000000000000); // YYMMDDHHMMSS, 2000-2069 + { + nr= nr+LL(20000000000000); // YYMMDDHHMMSS, 2000-2069 + goto ok; + } if (nr < YY_PART_YEAR*LL(10000000000)+ LL(101000000)) goto err; if (nr <= LL(991231235959)) - return nr+LL(19000000000000); // YYMMDDHHMMSS, 1970-1999 - + nr= nr+LL(19000000000000); // YYMMDDHHMMSS, 1970-1999 + + ok: + part1=(long) (nr/LL(1000000)); + part2=(long) (nr - (longlong) part1*LL(1000000)); + time_res->year= (int) (part1/10000L); part1%=10000L; + time_res->month= (int) part1 / 100; + time_res->day= (int) part1 % 100; + time_res->hour= (int) (part2/10000L); part2%=10000L; + time_res->minute=(int) part2 / 100; + time_res->second=(int) part2 % 100; + + 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) + return nr; + err: current_thd->cuted_fields++; return LL(0); @@ -2555,20 +2584,18 @@ void Field_timestamp::store(longlong nr) { TIME l_time; time_t timestamp; - long part1,part2; - if ((nr=fix_datetime(nr))) + if ((nr= fix_datetime(nr, &l_time))) { long not_used; - part1=(long) (nr/LL(1000000)); - part2=(long) (nr - (longlong) part1*LL(1000000)); - l_time.year= (int) (part1/10000L); part1%=10000L; - l_time.month= (int) part1 / 100; - l_time.day= (int) part1 % 100; - l_time.hour= (int) (part2/10000L); part2%=10000L; - l_time.minute=(int) part2 / 100; - l_time.second=(int) part2 % 100; - timestamp=my_gmt_sec(&l_time, ¬_used); + + if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR) + { + current_thd->cuted_fields++; + timestamp=0; + } + else + timestamp=my_gmt_sec(&l_time, ¬_used); } else timestamp=0; @@ -3406,13 +3433,10 @@ void Field_datetime::store(double nr) void Field_datetime::store(longlong nr) { - if (nr < 0 || nr > LL(99991231235959)) - { - nr=0; - current_thd->cuted_fields++; - } - else - nr=fix_datetime(nr); + TIME not_used; + + nr= fix_datetime(nr, ¬_used); + #ifdef WORDS_BIGENDIAN if (table->db_low_byte_first) { |