summaryrefslogtreecommitdiff
path: root/sql/item_timefunc.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item_timefunc.cc')
-rw-r--r--sql/item_timefunc.cc63
1 files changed, 28 insertions, 35 deletions
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 4a94c3a5f89..93889f75f83 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -13,7 +13,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
/**
@@ -41,6 +41,7 @@
#include "set_var.h"
#include "sql_locale.h" // MY_LOCALE my_locale_en_US
#include "strfunc.h" // check_word
+#include "sql_type_int.h" // Longlong_hybrid
#include "sql_time.h" // make_truncated_value_warning,
// get_date_from_daynr,
// calc_weekday, calc_week,
@@ -454,7 +455,7 @@ err:
Create a formated date/time value in a string.
*/
-static bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time,
+static bool make_date_time(const LEX_CSTRING &format, MYSQL_TIME *l_time,
timestamp_type type, MY_LOCALE *locale, String *str)
{
char intbuff[15];
@@ -468,7 +469,7 @@ static bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time,
if (l_time->neg)
str->append('-');
- end= (ptr= format->format.str) + format->format.length;
+ end= (ptr= format.str) + format.length;
for (; ptr != end ; ptr++)
{
if (*ptr != '%' || ptr+1 == end)
@@ -576,7 +577,7 @@ static bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time,
str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'j':
- if (type == MYSQL_TIMESTAMP_TIME)
+ if (type == MYSQL_TIMESTAMP_TIME || !l_time->month || !l_time->year)
return 1;
length= (uint) (int10_to_str(calc_daynr(l_time->year,l_time->month,
l_time->day) -
@@ -702,7 +703,7 @@ static bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs,
{
const char *end=str+length;
uint i;
- long msec_length= 0;
+ long field_length= 0;
while (str != end && !my_isdigit(cs,*str))
str++;
@@ -713,7 +714,8 @@ static bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs,
const char *start= str;
for (value= 0; str != end && my_isdigit(cs, *str); str++)
value= value*10 + *str - '0';
- msec_length= 6 - (str - start);
+ if ((field_length= str - start) >= 20)
+ return true;
values[i]= value;
while (str != end && !my_isdigit(cs,*str))
str++;
@@ -728,8 +730,13 @@ static bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs,
}
}
- if (transform_msec && msec_length > 0)
- values[count - 1] *= (long) log_10_int[msec_length];
+ if (transform_msec && field_length > 0)
+ {
+ if (field_length < 6)
+ values[count - 1] *= log_10_int[6 - field_length];
+ else if (field_length > 6)
+ values[count - 1] /= log_10_int[field_length - 6];
+ }
return (str != end);
}
@@ -1942,6 +1949,7 @@ uint Item_func_date_format::format_length(const String *format)
String *Item_func_date_format::val_str(String *str)
{
+ StringBuffer<64> format_buffer;
String *format;
MYSQL_TIME l_time;
uint size;
@@ -1951,7 +1959,7 @@ String *Item_func_date_format::val_str(String *str)
if (get_arg0_date(&l_time, is_time_flag))
return 0;
- if (!(format = args[1]->val_str(str)) || !format->length())
+ if (!(format= args[1]->val_str(&format_buffer)) || !format->length())
goto null_date;
if (fixed_length)
@@ -1962,18 +1970,13 @@ String *Item_func_date_format::val_str(String *str)
if (size < MAX_DATE_STRING_REP_LENGTH)
size= MAX_DATE_STRING_REP_LENGTH;
- if (format == str)
- str= &value; // Save result here
+ DBUG_ASSERT(format != str);
if (str->alloc(size))
goto null_date;
- DATE_TIME_FORMAT date_time_format;
- date_time_format.format.str= (char*) format->ptr();
- date_time_format.format.length= format->length();
-
/* Create the result string */
str->set_charset(collation.collation);
- if (!make_date_time(&date_time_format, &l_time,
+ if (!make_date_time(format->lex_cstring(), &l_time,
is_time_format ? MYSQL_TIMESTAMP_TIME :
MYSQL_TIMESTAMP_DATE,
locale, str))
@@ -2796,8 +2799,7 @@ bool Item_func_timediff::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
bool Item_func_maketime::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
{
DBUG_ASSERT(fixed == 1);
- bool overflow= 0;
- longlong hour= args[0]->val_int();
+ Longlong_hybrid hour(args[0]->val_int(), args[0]->unsigned_flag);
longlong minute= args[1]->val_int();
ulonglong second;
ulong microsecond;
@@ -2809,32 +2811,23 @@ bool Item_func_maketime::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
bzero(ltime, sizeof(*ltime));
ltime->time_type= MYSQL_TIMESTAMP_TIME;
+ ltime->neg= hour.neg();
- /* Check for integer overflows */
- if (hour < 0)
- {
- if (args[0]->unsigned_flag)
- overflow= 1;
- else
- ltime->neg= 1;
- }
- if (-hour > TIME_MAX_HOUR || hour > TIME_MAX_HOUR)
- overflow= 1;
-
- if (!overflow)
+ if (hour.abs() <= TIME_MAX_HOUR)
{
- ltime->hour= (uint) ((hour < 0 ? -hour : hour));
+ ltime->hour= (uint) hour.abs();
ltime->minute= (uint) minute;
ltime->second= (uint) second;
ltime->second_part= microsecond;
}
else
{
- ltime->hour= TIME_MAX_HOUR;
- ltime->minute= TIME_MAX_MINUTE;
- ltime->second= TIME_MAX_SECOND;
+ // use check_time_range() to set ltime to the max value depending on dec
+ int unused;
+ ltime->hour= TIME_MAX_HOUR + 1;
+ check_time_range(ltime, decimals, &unused);
char buf[28];
- char *ptr= longlong10_to_str(hour, buf, args[0]->unsigned_flag ? 10 : -10);
+ char *ptr= longlong10_to_str(hour.value(), buf, hour.is_unsigned() ? 10 : -10);
int len = (int)(ptr - buf) + sprintf(ptr, ":%02u:%02u", (uint)minute, (uint)second);
make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN,
buf, len, MYSQL_TIMESTAMP_TIME,