summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/cast.result4
-rw-r--r--mysql-test/r/func_sapdb.result12
-rw-r--r--mysql-test/t/func_sapdb.test6
-rw-r--r--sql/item_create.cc4
-rw-r--r--sql/item_timefunc.cc322
-rw-r--r--sql/item_timefunc.h82
-rw-r--r--sql/mysql_priv.h2
-rw-r--r--sql/protocol.cc13
-rw-r--r--sql/sql_string.cc17
-rw-r--r--sql/sql_string.h2
-rw-r--r--sql/sql_yacc.yy9
-rw-r--r--sql/time.cc1
12 files changed, 238 insertions, 236 deletions
diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result
index a14ea4d61a6..5d185bee005 100644
--- a/mysql-test/r/cast.result
+++ b/mysql-test/r/cast.result
@@ -44,10 +44,10 @@ t1 CREATE TABLE `t1` (
drop table t1;
select cast("2001-1-1" as date) = "2001-01-01";
cast("2001-1-1" as date) = "2001-01-01"
-0
+1
select cast("2001-1-1" as datetime) = "2001-01-01 00:00:00";
cast("2001-1-1" as datetime) = "2001-01-01 00:00:00"
-0
+1
select cast("1:2:3" as TIME) = "1:02:03";
cast("1:2:3" as TIME) = "1:02:03"
0
diff --git a/mysql-test/r/func_sapdb.result b/mysql-test/r/func_sapdb.result
index 5c044d00726..e330c73727b 100644
--- a/mysql-test/r/func_sapdb.result
+++ b/mysql-test/r/func_sapdb.result
@@ -101,8 +101,8 @@ timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002")
select timediff("1997-12-31 23:59:59.000001","23:59:59.000001");
timediff("1997-12-31 23:59:59.000001","23:59:59.000001")
NULL
-select timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.1");
-timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.1")
+select timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.000001");
+timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.000001")
-00:00:00.000001
select maketime(10,11,12);
maketime(10,11,12)
@@ -122,6 +122,12 @@ NULL
select timestamp("2001-12-01", "25:01:01");
timestamp("2001-12-01", "25:01:01")
2001-12-02 01:01:01
+select timestamp("2001-12-01 01:01:01.000100");
+timestamp("2001-12-01 01:01:01.000100")
+2001-12-01 01:01:01.000100
+select timestamp("2001-12-01");
+timestamp("2001-12-01")
+2001-12-01 00:00:00
select day("1997-12-31 23:59:59.000001");
day("1997-12-31 23:59:59.000001")
31
@@ -147,7 +153,7 @@ addtime(cast("23:59:59.999999" as time) , "1 1:1:1.000002") as f3,
timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002") as f4,
timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002") as f5,
maketime(10,11,12) as f6,
-timestamp("2001-12-01", "01:01:01") as f7,
+timestamp(cast("2001-12-01" as date), "01:01:01") as f7,
date("1997-12-31 23:59:59.000001") as f8,
time("1997-12-31 23:59:59.000001") as f9;
describe t1;
diff --git a/mysql-test/t/func_sapdb.test b/mysql-test/t/func_sapdb.test
index 05e1f20fe1e..afd84fe9630 100644
--- a/mysql-test/t/func_sapdb.test
+++ b/mysql-test/t/func_sapdb.test
@@ -51,7 +51,7 @@ select timediff("1997-01-01 23:59:59.000001","1995-12-31 23:59:59.000002");
select timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002");
select timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002");
select timediff("1997-12-31 23:59:59.000001","23:59:59.000001");
-select timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.1");
+select timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.000001");
select maketime(10,11,12);
select maketime(25,11,12);
@@ -61,6 +61,8 @@ select maketime(-25,11,12);
select timestamp("2001-12-01", "01:01:01.999999");
select timestamp("2001-13-01", "01:01:01.000001");
select timestamp("2001-12-01", "25:01:01");
+select timestamp("2001-12-01 01:01:01.000100");
+select timestamp("2001-12-01");
select day("1997-12-31 23:59:59.000001");
select date("1997-12-31 23:59:59.000001");
select date("1997-13-31 23:59:59.000001");
@@ -75,7 +77,7 @@ select makedate(1997,1) as f1,
timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002") as f4,
timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002") as f5,
maketime(10,11,12) as f6,
- timestamp("2001-12-01", "01:01:01") as f7,
+ timestamp(cast("2001-12-01" as date), "01:01:01") as f7,
date("1997-12-31 23:59:59.000001") as f8,
time("1997-12-31 23:59:59.000001") as f9;
describe t1;
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 402428d40cb..eaa27c1009d 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -709,12 +709,12 @@ Item *create_func_makedate(Item* a,Item* b)
Item *create_func_addtime(Item* a,Item* b)
{
- return new Item_func_add_time(a, b, 0);
+ return new Item_func_add_time(a, b, 0, 0);
}
Item *create_func_subtime(Item* a,Item* b)
{
- return new Item_func_add_time(a, b, 1);
+ return new Item_func_add_time(a, b, 0, 1);
}
Item *create_func_timediff(Item* a,Item* b)
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index fd2bca591a7..4fdb1b13d24 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -29,6 +29,8 @@
** Todo: Move month and days to language files
*/
+#define MAX_DAY_NUMBER 3652424L
+
static String month_names[] =
{
String("January", &my_charset_latin1),
@@ -55,10 +57,14 @@ static String day_names[] =
String("Sunday", &my_charset_latin1)
};
-enum date_time_format_types { TIME_ONLY= 0, TIME_MICROSECOND,
- DATE_ONLY, DATE_TIME, DATE_TIME_MICROSECOND};
+enum date_time_format_types
+{
+ TIME_ONLY= 0, TIME_MICROSECOND,
+ DATE_ONLY, DATE_TIME, DATE_TIME_MICROSECOND
+};
-typedef struct date_time_format {
+typedef struct date_time_format
+{
const char* format_str;
uint length;
};
@@ -73,6 +79,14 @@ static struct date_time_format date_time_formats[]=
};
+/*
+ OPTIMIZATION TODO:
+ - Replace the switch with a function that should be called for each
+ date type.
+ - Remove sprintf and opencode the conversion, like we do in
+ Field_datetime.
+*/
+
String *make_datetime(String *str, TIME *ltime,
enum date_time_format_types format)
{
@@ -898,8 +912,8 @@ String *Item_func_date_format::val_str(String *str)
null_value=1;
return 0;
}
- length= my_sprintf(intbuff, (intbuff,"%d",l_time.day));
- str->append(intbuff, length);
+ length= int10_to_str(l_time.day, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
if (l_time.day >= 10 && l_time.day <= 19)
str->append("th");
else
@@ -921,45 +935,45 @@ String *Item_func_date_format::val_str(String *str)
}
break;
case 'Y':
- sprintf(intbuff,"%04d",l_time.year);
- str->append(intbuff,4);
+ length= int10_to_str(l_time.year, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 4, '0');
break;
case 'y':
- sprintf(intbuff,"%02d",l_time.year%100);
- str->append(intbuff,2);
+ length= int10_to_str(l_time.year%100, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'm':
- sprintf(intbuff,"%02d",l_time.month);
- str->append(intbuff,2);
+ length= int10_to_str(l_time.month, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'c':
- sprintf(intbuff,"%d",l_time.month);
- str->append(intbuff);
+ length= int10_to_str(l_time.month, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
break;
case 'd':
- sprintf(intbuff,"%02d",l_time.day);
- str->append(intbuff,2);
+ length= int10_to_str(l_time.day, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'e':
- sprintf(intbuff,"%d",l_time.day);
- str->append(intbuff);
+ length= int10_to_str(l_time.day, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
break;
case 'f':
- sprintf(intbuff,"%06ld",l_time.second_part);
- str->append(intbuff);
+ length= int10_to_str(l_time.second_part, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 6, '0');
break;
case 'H':
- sprintf(intbuff,"%02d",l_time.hour);
- str->append(intbuff,2);
+ length= int10_to_str(l_time.hour, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'h':
case 'I':
- sprintf(intbuff,"%02d", (l_time.hour+11)%12+1);
- str->append(intbuff,2);
+ length= int10_to_str((l_time.hour+11)%12+1, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'i': /* minutes */
- sprintf(intbuff,"%02d",l_time.minute);
- str->append(intbuff,2);
+ length= int10_to_str(l_time.minute, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'j':
if (date_or_time)
@@ -967,52 +981,60 @@ String *Item_func_date_format::val_str(String *str)
null_value=1;
return 0;
}
- sprintf(intbuff,"%03d",
- (int) (calc_daynr(l_time.year,l_time.month,l_time.day) -
- calc_daynr(l_time.year,1,1)) + 1);
- str->append(intbuff,3);
+ length= int10_to_str(calc_daynr(l_time.year,l_time.month,l_time.day) -
+ calc_daynr(l_time.year,1,1) + 1, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 3, '0');
break;
case 'k':
- sprintf(intbuff,"%d",l_time.hour);
- str->append(intbuff);
+ length= int10_to_str(l_time.hour, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
break;
case 'l':
- sprintf(intbuff,"%d", (l_time.hour+11)%12+1);
- str->append(intbuff);
+ length= int10_to_str((l_time.hour+11)%12+1, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
break;
case 'p':
str->append(l_time.hour < 12 ? "AM" : "PM",2);
break;
case 'r':
- sprintf(intbuff,(l_time.hour < 12) ? "%02d:%02d:%02d AM" :
- "%02d:%02d:%02d PM",(l_time.hour+11)%12+1,l_time.minute,
- l_time.second);
- str->append(intbuff);
+ length= my_sprintf(intbuff,
+ (intbuff,
+ (l_time.hour < 12) ? "%02d:%02d:%02d AM" : "%02d:%02d:%02d PM",
+ (l_time.hour+11)%12+1,
+ l_time.minute,
+ l_time.second));
+ str->append(intbuff, length);
break;
case 'S':
case 's':
- sprintf(intbuff,"%02d",l_time.second);
- str->append(intbuff);
+ length= int10_to_str(l_time.second, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
break;
case 'T':
- sprintf(intbuff,"%02d:%02d:%02d", l_time.hour, l_time.minute,
- l_time.second);
- str->append(intbuff);
+ length= my_sprintf(intbuff,
+ (intbuff,
+ "%02d:%02d:%02d",
+ l_time.hour,
+ l_time.minute,
+ l_time.second));
+ str->append(intbuff, length);
break;
case 'U':
case 'u':
{
uint year;
- sprintf(intbuff,"%02d",calc_week(&l_time, 0, (*ptr) == 'U', &year));
- str->append(intbuff,2);
+ length= int10_to_str(calc_week(&l_time, 0, (*ptr) == 'U', &year),
+ intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
}
break;
case 'v':
case 'V':
{
uint year;
- sprintf(intbuff,"%02d",calc_week(&l_time, 1, (*ptr) == 'V', &year));
- str->append(intbuff,2);
+ length= int10_to_str(calc_week(&l_time, 1, (*ptr) == 'V', &year),
+ intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 2, '0');
}
break;
case 'x':
@@ -1020,14 +1042,15 @@ String *Item_func_date_format::val_str(String *str)
{
uint year;
(void) calc_week(&l_time, 1, (*ptr) == 'X', &year);
- sprintf(intbuff,"%04d",year);
- str->append(intbuff,4);
+ length= int10_to_str(year, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 4, '0');
}
break;
case 'w':
weekday=calc_weekday(calc_daynr(l_time.year,l_time.month,l_time.day),1);
- sprintf(intbuff,"%d",weekday);
- str->append(intbuff,1);
+ length= int10_to_str(weekday, intbuff, 10) - intbuff;
+ str->append_with_prefill(intbuff, length, 1, '0');
+
break;
default:
str->append(*ptr);
@@ -1109,7 +1132,7 @@ void Item_date_add_interval::fix_length_and_dec()
enum_field_types arg0_field_type;
set_charset(default_charset());
maybe_null=1;
- max_length=26*default_charset()->mbmaxlen;
+ max_length=26*MY_CHARSET_BIN_MB_MAXLEN;
value.alloc(32);
/*
@@ -1197,13 +1220,13 @@ bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date)
ltime->hour=sec/3600;
daynr= calc_daynr(ltime->year,ltime->month,1) + days;
get_date_from_daynr(daynr,&ltime->year,&ltime->month,&ltime->day);
- if (daynr < 0 || daynr >= 3652424) // Day number from year 0 to 9999-12-31
+ if (daynr < 0 || daynr >= MAX_DAY_NUMBER) // Day number from year 0 to 9999-12-31
goto null_date;
break;
case INTERVAL_DAY:
period= calc_daynr(ltime->year,ltime->month,ltime->day) +
sign*interval.day;
- if (period < 0 || period >= 3652424) // Daynumber from year 0 to 9999-12-31
+ if (period < 0 || period >= MAX_DAY_NUMBER) // Daynumber from year 0 to 9999-12-31
goto null_date;
get_date_from_daynr((long) period,&ltime->year,&ltime->month,&ltime->day);
break;
@@ -1375,6 +1398,63 @@ void Item_typecast::print(String *str)
str->append(')');
}
+String *Item_datetime_typecast::val_str(String *str)
+{
+ TIME ltime;
+
+ if (!get_arg0_date(&ltime,1) &&
+ make_datetime(str, &ltime, ltime.second_part ?
+ DATE_TIME_MICROSECOND : DATE_TIME))
+ return str;
+
+null_date:
+ null_value=1;
+ return 0;
+}
+
+
+bool Item_time_typecast::get_time(TIME *ltime)
+{
+ bool res= get_arg0_time(ltime);
+ ltime->time_type= TIMESTAMP_TIME;
+ return res;
+}
+
+
+String *Item_time_typecast::val_str(String *str)
+{
+ TIME ltime;
+
+ if (!get_arg0_time(&ltime) &&
+ make_datetime(str, &ltime, ltime.second_part ? TIME_MICROSECOND : TIME_ONLY))
+ return str;
+
+ null_value=1;
+ return 0;
+}
+
+
+bool Item_date_typecast::get_date(TIME *ltime, bool fuzzy_date)
+{
+ bool res= get_arg0_date(ltime,1);
+ ltime->time_type= TIMESTAMP_DATE;
+ return res;
+}
+
+
+String *Item_date_typecast::val_str(String *str)
+{
+ TIME ltime;
+
+ if (!get_arg0_date(&ltime,1) &&
+ make_datetime(str, &ltime, DATE_ONLY))
+ return str;
+
+null_date:
+ null_value=1;
+ return 0;
+}
+
/*
MAKEDATE(a,b) is a date function that creates a date value
from a year and day value.
@@ -1392,7 +1472,7 @@ String *Item_func_makedate::val_str(String *str)
goto null_date;
days= calc_daynr(yearnr,1,1) + daynr - 1;
- if (days > 0 || days < 3652424L) // Day number from year 0 to 9999-12-31
+ if (days > 0 || days < MAX_DAY_NUMBER) // Day number from year 0 to 9999-12-31
{
null_value=0;
get_date_from_daynr(days,&l_time.year,&l_time.month,&l_time.day);
@@ -1410,7 +1490,7 @@ void Item_func_add_time::fix_length_and_dec()
{
enum_field_types arg0_field_type;
decimals=0;
- max_length=26*my_charset_bin.mbmaxlen;
+ max_length=26*MY_CHARSET_BIN_MB_MAXLEN;
/*
The field type for the result of an Item_func_add_time function is defined as
@@ -1424,7 +1504,8 @@ void Item_func_add_time::fix_length_and_dec()
cached_field_type= MYSQL_TYPE_STRING;
arg0_field_type= args[0]->field_type();
- if (arg0_field_type == MYSQL_TYPE_DATETIME ||
+ if (arg0_field_type == MYSQL_TYPE_DATE ||
+ arg0_field_type == MYSQL_TYPE_DATETIME ||
arg0_field_type == MYSQL_TYPE_TIMESTAMP)
cached_field_type= MYSQL_TYPE_DATETIME;
else if (arg0_field_type == MYSQL_TYPE_TIME)
@@ -1443,20 +1524,28 @@ void Item_func_add_time::fix_length_and_dec()
String *Item_func_add_time::val_str(String *str)
{
TIME l_time1, l_time2, l_time3;
- bool is_time;
+ bool is_time= 0;
long microseconds, seconds, days= 0;
int l_sign= sign;
null_value=0;
- if (args[0]->get_time(&l_time1) ||
- args[1]->get_time(&l_time2) ||
- l_time2.time_type == TIMESTAMP_FULL)
- goto null_date;
- is_time= (l_time1.time_type == TIMESTAMP_TIME);
l_time3.neg= 0;
- if (is_time)
+ if (is_date) // TIMESTAMP function
+ {
+ if (get_arg0_date(&l_time1,1) ||
+ args[1]->get_time(&l_time2) ||
+ l_time1.time_type == TIMESTAMP_TIME ||
+ l_time2.time_type != TIMESTAMP_TIME)
+ goto null_date;
+ }
+ else // ADDTIME function
{
- if ((l_time2.neg == l_time1.neg) && l_time1.neg)
+ if (args[0]->get_time(&l_time1) ||
+ args[1]->get_time(&l_time2) ||
+ l_time2.time_type == TIMESTAMP_FULL)
+ goto null_date;
+ is_time= (l_time1.time_type == TIMESTAMP_TIME);
+ if (is_time && (l_time2.neg == l_time1.neg && l_time1.neg))
l_time3.neg= 1;
}
if (l_time1.neg != l_time2.neg)
@@ -1504,13 +1593,17 @@ String *Item_func_add_time::val_str(String *str)
{
get_date_from_daynr(days,&l_time3.year,&l_time3.month,&l_time3.day);
if (l_time3.day &&
- make_datetime(str, &l_time3, DATE_TIME_MICROSECOND))
+ make_datetime(str, &l_time3,
+ l_time1.second_part || l_time2.second_part ?
+ DATE_TIME_MICROSECOND : DATE_TIME))
return str;
goto null_date;
}
l_time3.hour+= days*24;
- if (make_datetime(str, &l_time3, TIME_MICROSECOND))
+ if (make_datetime(str, &l_time3,
+ l_time1.second_part || l_time2.second_part ?
+ TIME_MICROSECOND : TIME_ONLY))
return str;
null_date:
@@ -1578,7 +1671,9 @@ String *Item_func_timediff::val_str(String *str)
l_time3.neg= l_time3.neg ? 0 : 1;
calc_time_from_sec(&l_time3, seconds, microseconds);
- if (make_datetime(str, &l_time3, TIME_MICROSECOND))
+ if (make_datetime(str, &l_time3,
+ l_time1.second_part || l_time2.second_part ?
+ TIME_MICROSECOND : TIME_ONLY))
return str;
null_date:
@@ -1624,99 +1719,6 @@ null_date:
}
/*
- TIMESTAMP(a,b) is a function ( extraction) that calculates a datetime value
- comprising a date value, time value.
-
- a: Date_or_datetime value
- b: Time value
- Result: Datetime value
-*/
-
-String *Item_func_timestamp::val_str(String *str)
-{
- TIME l_time1 ,l_time2, l_time3;
- long seconds;
- long microseconds;
- long days;
- int l_sign;
-
- if (get_arg0_date(&l_time1,1) ||
- args[1]->get_time(&l_time2) ||
- l_time1.time_type == TIMESTAMP_TIME ||
- l_time2.time_type != TIMESTAMP_TIME)
- goto null_date;
-
- l_sign= l_time2.neg ? -1 : 1;
- days= (calc_daynr((uint) l_time1.year,(uint) l_time1.month,
- (uint) l_time1.day) + l_sign*l_time2.day);
-
- microseconds= l_time1.second_part + l_sign*l_time2.second_part;
- seconds= (l_time1.hour*3600L + l_time1.minute*60L + l_time1.second +
- (l_time2.day*86400L + l_time2.hour*3600L +
- l_time2.minute*60L + l_time2.second)*l_sign);
- days+= seconds/86400L;
- seconds%= 86400L;
- if (microseconds < 0)
- {
- microseconds+= 1000000L;
- seconds--;
- }
- if (seconds < 0)
- {
- days--;
- seconds+= 86400L;
- }
- if (days < 0)
- goto null_date;
-
- calc_time_from_sec(&l_time3, seconds, microseconds);
- get_date_from_daynr(days,&l_time3.year,&l_time3.month,&l_time3.day);
- make_datetime(str, &l_time3, DATE_TIME_MICROSECOND);
- return str;
-
-null_date:
- null_value=1;
- return 0;
-}
-
-/*
- DATE(a) is a function ( extraction) that calculates a date value.
-
- a: Datetime value
- Result: Date value
-*/
-String *Item_func_date::val_str(String *str)
-{
- TIME ltime;
-
- if (!get_arg0_date(&ltime,1) &&
- make_datetime(str, &ltime, DATE_ONLY))
- return str;
-
-null_date:
- null_value=1;
- return 0;
-}
-
-/*
- TIME(a) is a function ( extraction) that calculates a time value.
-
- a: Datetime value
- Result: Time value
-*/
-String *Item_func_time::val_str(String *str)
-{
- TIME ltime;
-
- if (!get_arg0_time(&ltime) &&
- make_datetime(str, &ltime, TIME_MICROSECOND))
- return str;
-
- null_value=1;
- return 0;
-}
-
-/*
MICROSECOND(a) is a function ( extraction) that extracts the microseconds from a.
a: Datetime or time value
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index ea29731fe35..20b95f8e22d 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -557,6 +557,8 @@ class Item_date_typecast :public Item_typecast
{
public:
Item_date_typecast(Item *a) :Item_typecast(a) {}
+ String *val_str(String *str);
+ bool get_date(TIME *ltime, bool fuzzy_date);
const char *func_name() const { return "date"; }
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
Field *tmp_table_field() { return result_field; }
@@ -571,6 +573,8 @@ class Item_time_typecast :public Item_typecast
{
public:
Item_time_typecast(Item *a) :Item_typecast(a) {}
+ String *val_str(String *str);
+ bool get_time(TIME *ltime);
const char *func_name() const { return "time"; }
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
Field *tmp_table_field() { return result_field; }
@@ -585,6 +589,7 @@ class Item_datetime_typecast :public Item_typecast
{
public:
Item_datetime_typecast(Item *a) :Item_typecast(a) {}
+ String *val_str(String *str);
const char *func_name() const { return "datetime"; }
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
Field *tmp_table_field() { return result_field; }
@@ -604,7 +609,7 @@ public:
void fix_length_and_dec()
{
decimals=0;
- max_length=8*my_charset_bin.mbmaxlen;
+ max_length=8*MY_CHARSET_BIN_MB_MAXLEN;
}
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
@@ -613,18 +618,26 @@ public:
}
};
+
class Item_func_add_time :public Item_str_func
{
+ const bool is_date;
int sign;
enum_field_types cached_field_type;
public:
- Item_func_add_time(Item *a, Item *b, bool neg_arg)
- :Item_str_func(a, b) { sign= neg_arg ? -1 : 1; }
+ Item_func_add_time(Item *a, Item *b, bool type_arg, bool neg_arg)
+ :Item_str_func(a, b), is_date(type_arg) { sign= neg_arg ? -1 : 1; }
String *val_str(String *str);
const char *func_name() const { return "addtime"; }
enum_field_types field_type() const { return cached_field_type; }
void fix_length_and_dec();
+
+/*
+ TODO:
+ Change this when we support
+ microseconds in TIME/DATETIME
+*/
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
@@ -647,7 +660,7 @@ public:
void fix_length_and_dec()
{
decimals=0;
- max_length=17*my_charset_bin.mbmaxlen;
+ max_length=17*MY_CHARSET_BIN_MB_MAXLEN;
}
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
@@ -667,66 +680,7 @@ public:
void fix_length_and_dec()
{
decimals=0;
- max_length=8*my_charset_bin.mbmaxlen;
- }
- Field *tmp_table_field() { return result_field; }
- Field *tmp_table_field(TABLE *t_arg)
- {
- return (new Field_time(maybe_null, name, t_arg, &my_charset_bin));
- }
-};
-
-class Item_func_timestamp :public Item_str_func
-{
-public:
- Item_func_timestamp(Item *a, Item *b) :Item_str_func(a, b) {}
- String *val_str(String *str);
- const char *func_name() const { return "timestamp"; }
- enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
- void fix_length_and_dec()
- {
- decimals=0;
- max_length=26*my_charset_bin.mbmaxlen;
- }
- Field *tmp_table_field() { return result_field; }
- Field *tmp_table_field(TABLE *t_arg)
- {
- return (new Field_datetime(maybe_null, name, t_arg, &my_charset_bin));
- }
-};
-
-class Item_func_date :public Item_str_func
-{
-public:
- Item_func_date(Item *a)
- :Item_str_func(a) {}
- String *val_str(String *str);
- const char *func_name() const { return "date"; }
- enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
- void fix_length_and_dec()
- {
- decimals=0;
- max_length=10*my_charset_bin.mbmaxlen;
- }
- Field *tmp_table_field() { return result_field; }
- Field *tmp_table_field(TABLE *t_arg)
- {
- return (new Field_date(maybe_null, name, t_arg, &my_charset_bin));
- }
-};
-
-class Item_func_time :public Item_str_func
-{
-public:
- Item_func_time(Item *a)
- :Item_str_func(a) {}
- String *val_str(String *str);
- const char *func_name() const { return "time"; }
- enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
- void fix_length_and_dec()
- {
- decimals=0;
- max_length=15*my_charset_bin.mbmaxlen;
+ max_length=8*MY_CHARSET_BIN_MB_MAXLEN;
}
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 8aeb18dcf26..ea3c2d45333 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -224,6 +224,8 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
#define RAID_BLOCK_SIZE 1024
+#define MY_CHARSET_BIN_MB_MAXLEN 1
+
#ifdef EXTRA_DEBUG
/*
Sync points allow us to force the server to reach a certain line of code
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 3d214e6f86d..1b9256c7723 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -823,6 +823,13 @@ bool Protocol_simple::store(Field *field)
}
+/*
+ TODO:
+ Second_part format ("%06") needs to change when
+ we support 0-6 decimals for time.
+*/
+
+
bool Protocol_simple::store(TIME *tm)
{
#ifndef DEBUG_OFF
@@ -863,6 +870,12 @@ bool Protocol_simple::store_date(TIME *tm)
}
+/*
+ TODO:
+ Second_part format ("%06") needs to change when
+ we support 0-6 decimals for time.
+*/
+
bool Protocol_simple::store_time(TIME *tm)
{
#ifndef DEBUG_OFF
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 0a3e8d0db9f..e7d7b08c93c 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -390,6 +390,23 @@ bool String::append(IO_CACHE* file, uint32 arg_length)
return FALSE;
}
+bool String::append_with_prefill(const char *s,uint32 arg_length,
+ uint32 full_length, char fill_char)
+{
+ int t_length= arg_length > full_length ? arg_length : full_length;
+
+ if (realloc(str_length + t_length))
+ return TRUE;
+ t_length= full_length - arg_length;
+ if (t_length > 0)
+ {
+ bfill(Ptr+str_length, t_length, fill_char);
+ str_length=str_length + t_length;
+ }
+ append(s, arg_length);
+ return FALSE;
+}
+
uint32 String::numchars()
{
return str_charset->cset->numchars(str_charset, Ptr, Ptr+str_length);
diff --git a/sql/sql_string.h b/sql/sql_string.h
index e88c9389589..d446d26298b 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -189,6 +189,8 @@ public:
bool append(const char *s,uint32 arg_length=0);
bool append(const char *s,uint32 arg_length, CHARSET_INFO *cs);
bool append(IO_CACHE* file, uint32 arg_length);
+ bool append_with_prefill(const char *s, uint32 arg_length,
+ uint32 full_length, char fill_char);
int strstr(const String &search,uint32 offset=0); // Returns offset to substring or -1
int strstr_case(const String &s,uint32 offset=0);
int strrstr(const String &search,uint32 offset=0); // Returns offset to substring or -1
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 873257116b9..4aa5b70407e 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -2381,7 +2381,7 @@ simple_expr:
Lex->safe_to_cache_query=0;
}
| DATE_SYM '(' expr ')'
- { $$= new Item_func_date($3); }
+ { $$= new Item_date_typecast($3); }
| DAY_SYM '(' expr ')'
{ $$= new Item_func_dayofmonth($3); }
| ELT_FUNC '(' expr ',' expr_list ')'
@@ -2580,9 +2580,11 @@ simple_expr:
| SUBSTRING_INDEX '(' expr ',' expr ',' expr ')'
{ $$= new Item_func_substr_index($3,$5,$7); }
| TIME_SYM '(' expr ')'
- { $$= new Item_func_time($3); }
+ { $$= new Item_time_typecast($3); }
+ | TIMESTAMP '(' expr ')'
+ { $$= new Item_datetime_typecast($3); }
| TIMESTAMP '(' expr ',' expr ')'
- { $$= new Item_func_timestamp($3, $5); }
+ { $$= new Item_func_add_time($3, $5, 1, 0); }
| TRIM '(' expr ')'
{ $$= new Item_func_trim($3); }
| TRIM '(' LEADING expr FROM expr ')'
@@ -4427,6 +4429,7 @@ keyword:
| MEDIUM_SYM {}
| MERGE_SYM {}
| MEMORY_SYM {}
+ | MICROSECOND_SYM {}
| MINUTE_SYM {}
| MIN_ROWS {}
| MODIFY_SYM {}
diff --git a/sql/time.cc b/sql/time.cc
index 056adf050ce..70ae8dcd8ed 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -432,6 +432,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
l_time->minute=date[4];
l_time->second=date[5];
l_time->second_part=date[6];
+ l_time->neg= 0;
DBUG_RETURN(l_time->time_type=
(number_of_fields <= 3 ? TIMESTAMP_DATE : TIMESTAMP_FULL));
}