summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <gluh@gluh.mysql.r18.ru>2003-12-08 15:18:29 +0400
committerunknown <gluh@gluh.mysql.r18.ru>2003-12-08 15:18:29 +0400
commit4429ed7ec75c9a91a8171d2be66d0fe81544eb9f (patch)
tree7b91366685d8d680ce56a1da4b23547de32a184b
parent7f9ba01f9918d43742fc7de6fb4550d34e8f3541 (diff)
parent417354eaa127934f5aadcc9b245561a1519ba998 (diff)
downloadmariadb-git-4429ed7ec75c9a91a8171d2be66d0fe81544eb9f.tar.gz
post-merge fixes
mysql-test/r/func_time.result: Auto merged mysql-test/t/func_time.test: Auto merged sql/item_create.cc: Auto merged sql/item_create.h: Auto merged sql/lex.h: Auto merged
-rw-r--r--mysql-test/r/func_sapdb.result19
-rw-r--r--mysql-test/r/func_time.result57
-rw-r--r--mysql-test/r/keywords.result16
-rw-r--r--mysql-test/t/func_sapdb.test3
-rw-r--r--mysql-test/t/func_time.test24
-rw-r--r--mysql-test/t/keywords.test8
-rw-r--r--sql/item_create.cc5
-rw-r--r--sql/item_create.h1
-rw-r--r--sql/item_timefunc.cc294
-rw-r--r--sql/item_timefunc.h27
-rw-r--r--sql/lex.h16
-rw-r--r--sql/sql_yacc.yy34
12 files changed, 433 insertions, 71 deletions
diff --git a/mysql-test/r/func_sapdb.result b/mysql-test/r/func_sapdb.result
index e330c73727b..6bd4c6f46a2 100644
--- a/mysql-test/r/func_sapdb.result
+++ b/mysql-test/r/func_sapdb.result
@@ -188,13 +188,14 @@ ttt qqq
NULL NULL
NULL NULL
2001-01-01 02:02:02 26:02:02
-SELECT TIMEDIFF(t1,t4) As ttt, TIMEDIFF(t2, t3) As qqq from test;
-ttt qqq
--744:00:00 NULL
-26305:01:02 22:58:58
--26305:01:02 -22:58:58
-NULL 26:02:02
-NULL NULL
-NULL NULL
-00:00:00 -24:00:00
+SELECT TIMEDIFF(t1, t4) As ttt, TIMEDIFF(t2, t3) As qqq,
+TIMEDIFF(t3, t2) As eee, TIMEDIFF(t2, t4) As rrr from test;
+ttt qqq eee rrr
+-744:00:00 NULL NULL NULL
+26305:01:02 22:58:58 -22:58:58 NULL
+-26305:01:02 -22:58:58 22:58:58 NULL
+NULL 26:02:02 26:02:02 NULL
+NULL NULL NULL NULL
+NULL NULL NULL NULL
+00:00:00 -24:00:00 24:00:00 NULL
drop table t1, test;
diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result
index feaebc9b514..e4804790ed0 100644
--- a/mysql-test/r/func_time.result
+++ b/mysql-test/r/func_time.result
@@ -464,6 +464,63 @@ date_add(date,INTERVAL "1 1:1" DAY_MINUTE)
select date_add(date,INTERVAL "1 1:1:1" DAY_SECOND) from t1;
date_add(date,INTERVAL "1 1:1:1" DAY_SECOND)
2003-01-03 01:01:01
+select date_add(date,INTERVAL "1" WEEK) from t1;
+date_add(date,INTERVAL "1" WEEK)
+2003-01-09 00:00:00
+select date_add(date,INTERVAL "1" QUARTER) from t1;
+date_add(date,INTERVAL "1" QUARTER)
+2003-04-02
+select timestampadd(MINUTE, 1, date) from t1;
+timestampadd(MINUTE, 1, date)
+2003-01-02 00:01:00
+select timestampadd(WEEK, 1, date) from t1;
+timestampadd(WEEK, 1, date)
+2003-01-09 00:00:00
+select timestampadd(SQL_TSI_SECOND, 1, date) from t1;
+timestampadd(SQL_TSI_SECOND, 1, date)
+2003-01-02 00:00:01
+select timestampadd(SQL_TSI_FRAC_SECOND, 1, date) from t1;
+timestampadd(SQL_TSI_FRAC_SECOND, 1, date)
+2003-01-02 00:00:00.000001
+select timestampdiff(MONTH, '2001-02-01', '2001-05-01') as a;
+a
+3
+select timestampdiff(YEAR, '2002-05-01', '2001-01-01') as a;
+a
+-1
+select timestampdiff(QUARTER, '2002-05-01', '2001-01-01') as a;
+a
+-5
+select timestampdiff(MONTH, '2000-03-28', '2000-02-29') as a;
+a
+0
+select timestampdiff(MONTH, '1991-03-28', '2000-02-29') as a;
+a
+107
+select timestampdiff(SQL_TSI_WEEK, '2001-02-01', '2001-05-01') as a;
+a
+12
+select timestampdiff(SQL_TSI_HOUR, '2001-02-01', '2001-05-01') as a;
+a
+2136
+select timestampdiff(SQL_TSI_DAY, '2001-02-01', '2001-05-01') as a;
+a
+89
+select timestampdiff(SQL_TSI_MINUTE, '2001-02-01 12:59:59', '2001-05-01 12:58:59') as a;
+a
+128159
+select timestampdiff(SQL_TSI_SECOND, '2001-02-01 12:59:59', '2001-05-01 12:58:58') as a;
+a
+7689539
+select timestampdiff(SQL_TSI_FRAC_SECOND, '2001-02-01 12:59:59.120000', '2001-05-01 12:58:58.119999') as a;
+a
+7689538999999
+select timestampdiff(SQL_TSI_DAY, '1986-02-01', '1986-03-01') as a1,
+timestampdiff(SQL_TSI_DAY, '1900-02-01', '1900-03-01') as a2,
+timestampdiff(SQL_TSI_DAY, '1996-02-01', '1996-03-01') as a3,
+timestampdiff(SQL_TSI_DAY, '2000-02-01', '2000-03-01') as a4;
+a1 a2 a3 a4
+28 28 29 29
select date_add(time,INTERVAL 1 SECOND) from t1;
date_add(time,INTERVAL 1 SECOND)
2006-07-08 00:00:01
diff --git a/mysql-test/r/keywords.result b/mysql-test/r/keywords.result
index c218379110f..88a0ab8abd5 100644
--- a/mysql-test/r/keywords.result
+++ b/mysql-test/r/keywords.result
@@ -1,12 +1,14 @@
drop table if exists t1;
-create table t1 (time time, date date, timestamp timestamp);
-insert into t1 values ("12:22:22","97:02:03","1997-01-02");
+create table t1 (time time, date date, timestamp timestamp,
+quarter int, week int, year int, timestampadd int, timestampdiff int);
+insert into t1 values ("12:22:22","97:02:03","1997-01-02",1,2,3,4,5);
select * from t1;
-time date timestamp
-12:22:22 1997-02-03 1997-01-02 00:00:00
-select t1.time+0,t1.date+0,t1.timestamp+0,concat(date," ",time) from t1;
-t1.time+0 t1.date+0 t1.timestamp+0 concat(date," ",time)
-122222 19970203 19970102000000 1997-02-03 12:22:22
+time date timestamp quarter week year timestampadd timestampdiff
+12:22:22 1997-02-03 1997-01-02 00:00:00 1 2 3 4 5
+select t1.time+0,t1.date+0,t1.timestamp+0,concat(date," ",time),
+t1.quarter+t1.week, t1.year+timestampadd, timestampdiff from t1;
+t1.time+0 t1.date+0 t1.timestamp+0 concat(date," ",time) t1.quarter+t1.week t1.year+timestampadd timestampdiff
+122222 19970203 19970102000000 1997-02-03 12:22:22 3 7 5
drop table t1;
create table events(binlog int);
insert into events values(1);
diff --git a/mysql-test/t/func_sapdb.test b/mysql-test/t/func_sapdb.test
index afd84fe9630..ba64e13873d 100644
--- a/mysql-test/t/func_sapdb.test
+++ b/mysql-test/t/func_sapdb.test
@@ -94,6 +94,7 @@ insert into test values
('2001-01-01 01:01:01', '01:01:01', '1 01:01:01', '2001-01-01 01:01:01');
SELECT ADDTIME(t1,t2) As ttt, ADDTIME(t2, t3) As qqq from test;
-SELECT TIMEDIFF(t1,t4) As ttt, TIMEDIFF(t2, t3) As qqq from test;
+SELECT TIMEDIFF(t1, t4) As ttt, TIMEDIFF(t2, t3) As qqq,
+ TIMEDIFF(t3, t2) As eee, TIMEDIFF(t2, t4) As rrr from test;
drop table t1, test;
diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test
index f1a24a4c3cb..955b0358ae3 100644
--- a/mysql-test/t/func_time.test
+++ b/mysql-test/t/func_time.test
@@ -220,6 +220,30 @@ select date_add(date,INTERVAL "1:1:1" HOUR_SECOND) from t1;
select date_add(date,INTERVAL "1 1:1" DAY_MINUTE) from t1;
select date_add(date,INTERVAL "1 1:1:1" DAY_SECOND) from t1;
+select date_add(date,INTERVAL "1" WEEK) from t1;
+select date_add(date,INTERVAL "1" QUARTER) from t1;
+select timestampadd(MINUTE, 1, date) from t1;
+select timestampadd(WEEK, 1, date) from t1;
+select timestampadd(SQL_TSI_SECOND, 1, date) from t1;
+select timestampadd(SQL_TSI_FRAC_SECOND, 1, date) from t1;
+
+select timestampdiff(MONTH, '2001-02-01', '2001-05-01') as a;
+select timestampdiff(YEAR, '2002-05-01', '2001-01-01') as a;
+select timestampdiff(QUARTER, '2002-05-01', '2001-01-01') as a;
+select timestampdiff(MONTH, '2000-03-28', '2000-02-29') as a;
+select timestampdiff(MONTH, '1991-03-28', '2000-02-29') as a;
+select timestampdiff(SQL_TSI_WEEK, '2001-02-01', '2001-05-01') as a;
+select timestampdiff(SQL_TSI_HOUR, '2001-02-01', '2001-05-01') as a;
+select timestampdiff(SQL_TSI_DAY, '2001-02-01', '2001-05-01') as a;
+select timestampdiff(SQL_TSI_MINUTE, '2001-02-01 12:59:59', '2001-05-01 12:58:59') as a;
+select timestampdiff(SQL_TSI_SECOND, '2001-02-01 12:59:59', '2001-05-01 12:58:58') as a;
+select timestampdiff(SQL_TSI_FRAC_SECOND, '2001-02-01 12:59:59.120000', '2001-05-01 12:58:58.119999') as a;
+
+select timestampdiff(SQL_TSI_DAY, '1986-02-01', '1986-03-01') as a1,
+ timestampdiff(SQL_TSI_DAY, '1900-02-01', '1900-03-01') as a2,
+ timestampdiff(SQL_TSI_DAY, '1996-02-01', '1996-03-01') as a3,
+ timestampdiff(SQL_TSI_DAY, '2000-02-01', '2000-03-01') as a4;
+
# The following is not as one would expect...
select date_add(time,INTERVAL 1 SECOND) from t1;
drop table t1;
diff --git a/mysql-test/t/keywords.test b/mysql-test/t/keywords.test
index e7ec63afe54..3392bfa1b3b 100644
--- a/mysql-test/t/keywords.test
+++ b/mysql-test/t/keywords.test
@@ -6,10 +6,12 @@
drop table if exists t1;
--enable_warnings
-create table t1 (time time, date date, timestamp timestamp);
-insert into t1 values ("12:22:22","97:02:03","1997-01-02");
+create table t1 (time time, date date, timestamp timestamp,
+quarter int, week int, year int, timestampadd int, timestampdiff int);
+insert into t1 values ("12:22:22","97:02:03","1997-01-02",1,2,3,4,5);
select * from t1;
-select t1.time+0,t1.date+0,t1.timestamp+0,concat(date," ",time) from t1;
+select t1.time+0,t1.date+0,t1.timestamp+0,concat(date," ",time),
+ t1.quarter+t1.week, t1.year+timestampadd, timestampdiff from t1;
drop table t1;
create table events(binlog int);
insert into events values(1);
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 1ddb1fcb080..7a548962cde 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -312,11 +312,6 @@ Item *create_func_current_user()
system_charset_info);
}
-Item *create_func_quarter(Item* a)
-{
- return new Item_func_quarter(a);
-}
-
Item *create_func_radians(Item *a)
{
return new Item_func_units((char*) "radians",a,M_PI/180,0.0);
diff --git a/sql/item_create.h b/sql/item_create.h
index 083868d87a6..b445eab3bac 100644
--- a/sql/item_create.h
+++ b/sql/item_create.h
@@ -72,7 +72,6 @@ Item *create_func_period_diff(Item* a, Item *b);
Item *create_func_pi(void);
Item *create_func_pow(Item* a, Item *b);
Item *create_func_current_user(void);
-Item *create_func_quarter(Item* a);
Item *create_func_radians(Item *a);
Item *create_func_release_lock(Item* a);
Item *create_func_repeat(Item* a, Item *b);
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index a5372a4ae60..66190371575 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -869,9 +869,15 @@ static bool get_interval_value(Item *args,interval_type int_type,
case INTERVAL_YEAR:
interval->year=value;
break;
+ case INTERVAL_QUARTER:
+ interval->month=value*3;
+ break;
case INTERVAL_MONTH:
interval->month=value;
break;
+ case INTERVAL_WEEK:
+ interval->day=value*7;
+ break;
case INTERVAL_DAY:
interval->day=value;
break;
@@ -1547,6 +1553,7 @@ bool Item_date_add_interval::get_date(TIME *ltime, uint fuzzy_date)
goto null_date;
break;
case INTERVAL_DAY:
+ case INTERVAL_WEEK:
period= calc_daynr(ltime->year,ltime->month,ltime->day) +
sign*interval.day;
if (period < 0 || period >= MAX_DAY_NUMBER) // Daynumber from year 0 to 9999-12-31
@@ -1562,6 +1569,7 @@ bool Item_date_add_interval::get_date(TIME *ltime, uint fuzzy_date)
ltime->day=28; // Was leap-year
break;
case INTERVAL_YEAR_MONTH:
+ case INTERVAL_QUARTER:
case INTERVAL_MONTH:
period= (ltime->year*12 + sign*interval.year*12 +
ltime->month-1 + sign*interval.month);
@@ -1659,7 +1667,9 @@ void Item_extract::fix_length_and_dec()
switch (int_type) {
case INTERVAL_YEAR: max_length=4; date_value=1; break;
case INTERVAL_YEAR_MONTH: max_length=6; date_value=1; break;
+ case INTERVAL_QUARTER: max_length=2; date_value=1; break;
case INTERVAL_MONTH: max_length=2; date_value=1; break;
+ case INTERVAL_WEEK: max_length=2; date_value=1; break;
case INTERVAL_DAY: max_length=2; date_value=1; break;
case INTERVAL_DAY_HOUR: max_length=9; date_value=0; break;
case INTERVAL_DAY_MINUTE: max_length=11; date_value=0; break;
@@ -1682,6 +1692,8 @@ void Item_extract::fix_length_and_dec()
longlong Item_extract::val_int()
{
TIME ltime;
+ uint year;
+ ulong week_format;
long neg;
if (date_value)
{
@@ -1703,7 +1715,16 @@ longlong Item_extract::val_int()
switch (int_type) {
case INTERVAL_YEAR: return ltime.year;
case INTERVAL_YEAR_MONTH: return ltime.year*100L+ltime.month;
+ case INTERVAL_QUARTER: return ltime.month/3 + 1;
case INTERVAL_MONTH: return ltime.month;
+ case INTERVAL_WEEK:
+ {
+ week_format= current_thd->variables.default_week_format;
+ return calc_week(&ltime,
+ (week_format & 2) != 0,
+ (week_format & 1) == 0,
+ &year);
+ }
case INTERVAL_DAY: return ltime.day;
case INTERVAL_DAY_HOUR: return (long) (ltime.day*100L+ltime.hour)*neg;
case INTERVAL_DAY_MINUTE: return (long) (ltime.day*10000L+
@@ -2086,6 +2107,79 @@ void Item_func_add_time::print(String *str)
/*
+ SYNOPSIS
+ calc_time_diff()
+ l_time1 TIME/DATE/DATETIME value
+ l_time2 TIME/DATE/DATETIME value
+ l_sign Can be 1 (operation of addition)
+ or -1 (substraction)
+ seconds_out Returns count of seconds bitween
+ l_time1 and l_time2
+ microseconds_out Returns count of microseconds bitween
+ l_time1 and l_time2.
+
+ DESCRIPTION
+ Calculates difference in seconds(seconds_out)
+ and microseconds(microseconds_out)
+ bitween two TIME/DATE/DATETIME values.
+
+ RETURN VALUES
+ Rertuns sign of difference.
+ 1 means negative result
+ 0 means positive result
+
+*/
+
+bool calc_time_diff(TIME *l_time1,TIME *l_time2, int l_sign,
+ longlong *seconds_out, long *microseconds_out)
+{
+ long days;
+ bool neg;
+ longlong seconds= *seconds_out;
+ long microseconds= *microseconds_out;
+
+ /*
+ We suppose that if first argument is TIMESTAMP_TIME
+ the second argument should be TIMESTAMP_TIME also.
+ We should check it before calc_time_diff call.
+ */
+ if (l_time1->time_type == TIMESTAMP_TIME) // Time value
+ days= l_time1->day - l_sign*l_time2->day;
+ else // DateTime value
+ days= (calc_daynr((uint) l_time1->year,
+ (uint) l_time1->month,
+ (uint) l_time1->day) -
+ l_sign*calc_daynr((uint) l_time2->year,
+ (uint) l_time2->month,
+ (uint) l_time2->day));
+
+ microseconds= l_time1->second_part - l_sign*l_time2->second_part;
+ seconds= ((longlong) days*86400L + l_time1->hour*3600L +
+ l_time1->minute*60L + l_time1->second + microseconds/1000000L -
+ (longlong)l_sign*(l_time2->hour*3600L+l_time2->minute*60L+l_time2->second));
+
+ neg= 0;
+ if (seconds < 0)
+ {
+ seconds= -seconds;
+ neg= 1;
+ }
+ else if (seconds == 0 && microseconds < 0)
+ {
+ microseconds= -microseconds;
+ neg= 1;
+ }
+ if (microseconds < 0)
+ {
+ microseconds+= 1000000L;
+ seconds--;
+ }
+ *seconds_out= seconds;
+ *microseconds_out= microseconds;
+ return neg;
+}
+
+/*
TIMEDIFF(t,s) is a time function that calculates the
time value between a start and end time.
@@ -2110,40 +2204,16 @@ String *Item_func_timediff::val_str(String *str)
if (l_time1.neg != l_time2.neg)
l_sign= -l_sign;
- if (l_time1.time_type == TIMESTAMP_TIME) // Time value
- days= l_time1.day - l_sign*l_time2.day;
- else // DateTime value
- days= (calc_daynr((uint) l_time1.year,
- (uint) l_time1.month,
- (uint) l_time1.day) -
- l_sign*calc_daynr((uint) l_time2.year,
- (uint) l_time2.month,
- (uint) l_time2.day));
-
- microseconds= l_time1.second_part - l_sign*l_time2.second_part;
- seconds= ((longlong) days*86400L + l_time1.hour*3600L +
- l_time1.minute*60L + l_time1.second + microseconds/1000000L -
- (longlong)l_sign*(l_time2.hour*3600L+l_time2.minute*60L+
- l_time2.second));
+ l_time3.neg= calc_time_diff(&l_time1,&l_time2, l_sign,
+ &seconds, &microseconds);
- l_time3.neg= 0;
- if (seconds < 0)
- {
- seconds= -seconds;
- l_time3.neg= 1;
- }
- else if (seconds == 0 && microseconds < 0)
- {
- microseconds= -microseconds;
- l_time3.neg= 1;
- }
- if (microseconds < 0)
- {
- microseconds+= 1000000L;
- seconds--;
- }
+ /*
+ For TIMESTAMP_TIME only:
+ If both argumets are negative values and diff between them
+ is negative we need to swap sign as result should be positive.
+ */
if ((l_time2.neg == l_time1.neg) && l_time1.neg)
- l_time3.neg= l_time3.neg ? 0 : 1;
+ l_time3.neg= 1-l_time3.neg; // Swap sign of result
calc_time_from_sec(&l_time3, (long) seconds, microseconds);
@@ -2210,6 +2280,166 @@ longlong Item_func_microsecond::val_int()
}
+longlong Item_func_timestamp_diff::val_int()
+{
+ TIME ltime1, ltime2;
+ longlong seconds;
+ long microseconds;
+ long months= 0;
+ int neg= 1;
+
+ null_value= 0;
+ if (args[0]->get_date(&ltime1, 0) ||
+ args[1]->get_date(&ltime2, 0))
+ goto null_date;
+
+ if (calc_time_diff(&ltime2,&ltime1, 1,
+ &seconds, &microseconds))
+ neg= -1;
+
+ if (int_type == INTERVAL_YEAR ||
+ int_type == INTERVAL_QUARTER ||
+ int_type == INTERVAL_MONTH)
+ {
+ uint year, year_tmp;
+ uint year_beg, year_end, month_beg, month_end;
+ uint diff_days= seconds/86400L;
+ uint diff_months= 0;
+ uint diff_years= 0;
+ if (neg == -1)
+ {
+ year_beg= ltime2.year;
+ year_end= ltime1.year;
+ month_beg= ltime2.month;
+ month_end= ltime1.month;
+ }
+ else
+ {
+ year_beg= ltime1.year;
+ year_end= ltime2.year;
+ month_beg= ltime1.month;
+ month_end= ltime2.month;
+ }
+ /* calc years*/
+ for (year= year_beg;year < year_end; year++)
+ {
+ uint days=calc_days_in_year(year);
+ if (days > diff_days)
+ break;
+ diff_days-= days;
+ diff_years++;
+ }
+
+ /* calc months; Current year is in the 'year' variable */
+ month_beg--; /* Change months to be 0-11 for easier calculation */
+ month_end--;
+
+ months= 12*diff_years;
+ while (month_beg != month_end)
+ {
+ uint m_days= (uint) days_in_month[month_beg];
+ if (month_beg == 1)
+ {
+ /* This is only calculated once so there is no reason to cache it*/
+ uint leap= (uint) ((year & 3) == 0 && (year%100 ||
+ (year%400 == 0 && year)));
+ m_days+= leap;
+ }
+ if (m_days > diff_days)
+ break;
+ diff_days-= m_days;
+ months++;
+ if (month_beg++ == 11) /* if we wrap to next year */
+ {
+ month_beg= 0;
+ year++;
+ }
+ }
+ if (neg == -1)
+ months= -months;
+ }
+
+ switch (int_type) {
+ case INTERVAL_YEAR:
+ return months/12;
+ case INTERVAL_QUARTER:
+ return months/3;
+ case INTERVAL_MONTH:
+ return months;
+ case INTERVAL_WEEK:
+ return seconds/86400L/7L*neg;
+ case INTERVAL_DAY:
+ return seconds/86400L*neg;
+ case INTERVAL_HOUR:
+ return seconds/3600L*neg;
+ case INTERVAL_MINUTE:
+ return seconds/60L*neg;
+ case INTERVAL_SECOND:
+ return seconds*neg;
+ case INTERVAL_MICROSECOND:
+ {
+ longlong max_sec= LONGLONG_MAX/1000000;
+ if (max_sec > seconds ||
+ max_sec == seconds && LONGLONG_MAX%1000000 >= microseconds)
+ return (longlong) (seconds*1000000L+microseconds)*neg;
+ goto null_date;
+ }
+ default:
+ break;
+ }
+
+null_date:
+ null_value=1;
+ return 0;
+}
+
+
+void Item_func_timestamp_diff::print(String *str)
+{
+ str->append(func_name());
+ str->append('(');
+
+ switch (int_type) {
+ case INTERVAL_YEAR:
+ str->append("YEAR");
+ break;
+ case INTERVAL_QUARTER:
+ str->append("QUARTER");
+ break;
+ case INTERVAL_MONTH:
+ str->append("MONTH");
+ break;
+ case INTERVAL_WEEK:
+ str->append("WEEK");
+ break;
+ case INTERVAL_DAY:
+ str->append("DAY");
+ break;
+ case INTERVAL_HOUR:
+ str->append("HOUR");
+ break;
+ case INTERVAL_MINUTE:
+ str->append("MINUTE");
+ break;
+ case INTERVAL_SECOND:
+ str->append("SECOND");
+ break;
+ case INTERVAL_MICROSECOND:
+ str->append("SECOND_FRAC");
+ break;
+ default:
+ break;
+ }
+
+ for (uint i=0 ; i < 2 ; i++)
+ {
+ str->append(',');
+ args[i]->print(str);
+ }
+ str->append(')');
+}
+
+
String *Item_func_get_format::val_str(String *str)
{
const char *format_name;
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index a81b9f28d92..9f1d7dbd85a 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -543,11 +543,11 @@ public:
enum interval_type
{
- INTERVAL_YEAR, INTERVAL_MONTH, INTERVAL_DAY, INTERVAL_HOUR, INTERVAL_MINUTE,
- INTERVAL_SECOND, INTERVAL_MICROSECOND ,INTERVAL_YEAR_MONTH,
- INTERVAL_DAY_HOUR, INTERVAL_DAY_MINUTE, INTERVAL_DAY_SECOND,
- INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND, INTERVAL_MINUTE_SECOND,
- INTERVAL_DAY_MICROSECOND, INTERVAL_HOUR_MICROSECOND,
+ INTERVAL_YEAR, INTERVAL_QUARTER, INTERVAL_MONTH, INTERVAL_DAY, INTERVAL_HOUR,
+ INTERVAL_MINUTE, INTERVAL_WEEK, INTERVAL_SECOND, INTERVAL_MICROSECOND ,
+ INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR, INTERVAL_DAY_MINUTE,
+ INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND,
+ INTERVAL_MINUTE_SECOND, INTERVAL_DAY_MICROSECOND, INTERVAL_HOUR_MICROSECOND,
INTERVAL_MINUTE_MICROSECOND, INTERVAL_SECOND_MICROSECOND
};
@@ -769,6 +769,23 @@ public:
};
+class Item_func_timestamp_diff :public Item_int_func
+{
+ const interval_type int_type;
+public:
+ Item_func_timestamp_diff(Item *a,Item *b,interval_type type_arg)
+ :Item_int_func(a,b), int_type(type_arg) {}
+ const char *func_name() const { return "timestamp_diff"; }
+ longlong val_int();
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ maybe_null=1;
+ }
+ void print(String *str);
+};
+
+
enum date_time_format
{
USA_FORMAT, JIS_FORMAT, ISO_FORMAT, EUR_FORMAT, INTERNAL_FORMAT
diff --git a/sql/lex.h b/sql/lex.h
index a3cf1ab79be..9334b7e22cf 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -179,6 +179,7 @@ static SYMBOL symbols[] = {
{ "FOREIGN", SYM(FOREIGN),0,0},
{ "FORCE", SYM(FORCE_SYM),0,0},
{ "FOUND", SYM(FOUND_SYM),0,0},
+ { "FRAC_SECOND", SYM(FRAC_SECOND_SYM),0,0},
{ "RAID_TYPE", SYM(RAID_TYPE),0,0},
{ "RAID_CHUNKS", SYM(RAID_CHUNKS),0,0},
{ "RAID_CHUNKSIZE", SYM(RAID_CHUNKSIZE),0,0},
@@ -336,6 +337,7 @@ static SYMBOL symbols[] = {
{ "PROCESS" , SYM(PROCESS),0,0},
{ "PROCESSLIST", SYM(PROCESSLIST_SYM),0,0},
{ "PRIVILEGES", SYM(PRIVILEGES),0,0},
+ { "QUARTER", SYM(QUARTER_SYM),0,0},
{ "QUERY", SYM(QUERY_SYM),0,0},
{ "QUICK", SYM(QUICK),0,0},
{ "RAID0", SYM(RAID_0_SYM),0,0},
@@ -401,6 +403,15 @@ static SYMBOL symbols[] = {
{ "SQL_NO_CACHE", SYM(SQL_NO_CACHE_SYM), 0, 0},
{ "SQL_SMALL_RESULT", SYM(SQL_SMALL_RESULT),0,0},
{ "SQL_THREAD", SYM(SQL_THREAD),0,0},
+ { "SQL_TSI_FRAC_SECOND", SYM(FRAC_SECOND_SYM),0,0},
+ { "SQL_TSI_SECOND", SYM(SECOND_SYM),0,0},
+ { "SQL_TSI_MINUTE", SYM(MINUTE_SYM),0,0},
+ { "SQL_TSI_HOUR", SYM(HOUR_SYM),0,0},
+ { "SQL_TSI_DAY", SYM(DAY_SYM),0,0},
+ { "SQL_TSI_WEEK", SYM(WEEK_SYM),0,0},
+ { "SQL_TSI_MONTH", SYM(MONTH_SYM),0,0},
+ { "SQL_TSI_QUARTER", SYM(QUARTER_SYM),0,0},
+ { "SQL_TSI_YEAR", SYM(YEAR_SYM),0,0},
{ "SOUNDS", SYM(SOUNDS_SYM),0,0},
{ "SSL", SYM(SSL_SYM),0,0},
{ "STRAIGHT_JOIN", SYM(STRAIGHT_JOIN),0,0},
@@ -421,6 +432,8 @@ static SYMBOL symbols[] = {
{ "THEN", SYM(THEN_SYM),0,0},
{ "TIME", SYM(TIME_SYM),0,0},
{ "TIMESTAMP", SYM(TIMESTAMP),0,0},
+ { "TIMESTAMPADD", SYM(TIMESTAMP_ADD),0,0},
+ { "TIMESTAMPDIFF", SYM(TIMESTAMP_DIFF),0,0},
{ "TINYBLOB", SYM(TINYBLOB),0,0},
{ "TINYTEXT", SYM(TINYTEXT),0,0},
{ "TINYINT", SYM(TINYINT),0,0},
@@ -456,6 +469,7 @@ static SYMBOL symbols[] = {
{ "VARYING", SYM(VARYING),0,0},
{ "VARBINARY", SYM(VARBINARY),0,0},
{ "WARNINGS", SYM(WARNINGS),0,0},
+ { "WEEK", SYM(WEEK_SYM),0,0},
{ "WITH", SYM(WITH),0,0},
{ "WORK", SYM(WORK_SYM),0,0},
{ "WRITE", SYM(WRITE_SYM),0,0},
@@ -644,7 +658,6 @@ static SYMBOL sql_functions[] = {
{ "POSITION", SYM(POSITION_SYM),0,0},
{ "POW", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)},
{ "POWER", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)},
- { "QUARTER", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_quarter)},
{ "QUOTE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_quote)},
{ "RADIANS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_radians)},
{ "RAND", SYM(RAND),0,0},
@@ -691,7 +704,6 @@ static SYMBOL sql_functions[] = {
{ "UPPER", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)},
{ "VARIANCE", SYM(VARIANCE_SYM),0,0},
{ "VERSION", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_version)},
- { "WEEK", SYM(WEEK_SYM),0,0},
{ "WEEKDAY", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekday)},
{ "WEEKOFYEAR", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekofyear)},
{ "WITHIN", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_within)},
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 5796105200a..a9035b18c23 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -81,7 +81,7 @@ inline Item *or_or_concat(THD *thd, Item* A, Item* B)
enum Item_udftype udf_type;
CHARSET_INFO *charset;
thr_lock_type lock_type;
- interval_type interval;
+ interval_type interval, interval_time_st;
timestamp_type date_time_type;
st_select_lex *select_lex;
chooser_compare_func_creator boolfunc2creator;
@@ -459,6 +459,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token STRING_SYM
%token TEXT_SYM
%token TIMESTAMP
+%token TIMESTAMP_ADD
+%token TIMESTAMP_DIFF
%token TIME_SYM
%token TINYBLOB
%token TINYINT
@@ -502,6 +504,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token FIELD_FUNC
%token FORMAT_SYM
%token FOR_SYM
+%token FRAC_SECOND_SYM
%token FROM_UNIXTIME
%token GEOMCOLLFROMTEXT
%token GEOMFROMTEXT
@@ -547,6 +550,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token POLYGON
%token POSITION_SYM
%token PROCEDURE
+%token QUARTER_SYM
%token RAND
%token REPLACE
%token RIGHT
@@ -691,6 +695,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <date_time_type> date_time_type;
%type <interval> interval
+%type <interval_time_st> interval_time_st
+
%type <db_type> table_types
%type <row_type> row_types
@@ -3766,6 +3772,8 @@ simple_expr:
Geometry::wkbPolygon, Geometry::wkbLineString); }
| POSITION_SYM '(' no_in_expr IN_SYM expr ')'
{ $$ = new Item_func_locate($5,$3); }
+ | QUARTER_SYM '(' expr ')'
+ { $$ = new Item_func_quarter($3); }
| RAND '(' expr ')'
{ $$= new Item_func_rand($3); Lex->uncacheable(UNCACHEABLE_RAND);}
| RAND '(' ')'
@@ -3799,6 +3807,10 @@ simple_expr:
{ $$= new Item_datetime_typecast($3); }
| TIMESTAMP '(' expr ',' expr ')'
{ $$= new Item_func_add_time($3, $5, 1, 0); }
+ | TIMESTAMP_ADD '(' interval_time_st ',' expr ',' expr ')'
+ { $$= new Item_date_add_interval($7,$5,$3,0); }
+ | TIMESTAMP_DIFF '(' interval_time_st ',' expr ',' expr ')'
+ { $$= new Item_func_timestamp_diff($5,$7,$3); }
| TRIM '(' expr ')'
{ $$= new Item_func_trim($3); }
| TRIM '(' LEADING expr FROM expr ')'
@@ -4289,23 +4301,29 @@ using_list:
};
interval:
- DAY_HOUR_SYM { $$=INTERVAL_DAY_HOUR; }
+ interval_time_st {}
+ | DAY_HOUR_SYM { $$=INTERVAL_DAY_HOUR; }
| DAY_MICROSECOND_SYM { $$=INTERVAL_DAY_MICROSECOND; }
| DAY_MINUTE_SYM { $$=INTERVAL_DAY_MINUTE; }
| DAY_SECOND_SYM { $$=INTERVAL_DAY_SECOND; }
- | DAY_SYM { $$=INTERVAL_DAY; }
| HOUR_MICROSECOND_SYM { $$=INTERVAL_HOUR_MICROSECOND; }
| HOUR_MINUTE_SYM { $$=INTERVAL_HOUR_MINUTE; }
| HOUR_SECOND_SYM { $$=INTERVAL_HOUR_SECOND; }
- | HOUR_SYM { $$=INTERVAL_HOUR; }
| MICROSECOND_SYM { $$=INTERVAL_MICROSECOND; }
| MINUTE_MICROSECOND_SYM { $$=INTERVAL_MINUTE_MICROSECOND; }
| MINUTE_SECOND_SYM { $$=INTERVAL_MINUTE_SECOND; }
+ | SECOND_MICROSECOND_SYM { $$=INTERVAL_SECOND_MICROSECOND; }
+ | YEAR_MONTH_SYM { $$=INTERVAL_YEAR_MONTH; };
+
+interval_time_st:
+ DAY_SYM { $$=INTERVAL_DAY; }
+ | WEEK_SYM { $$=INTERVAL_WEEK; }
+ | HOUR_SYM { $$=INTERVAL_HOUR; }
+ | FRAC_SECOND_SYM { $$=INTERVAL_MICROSECOND; }
| MINUTE_SYM { $$=INTERVAL_MINUTE; }
| MONTH_SYM { $$=INTERVAL_MONTH; }
- | SECOND_MICROSECOND_SYM { $$=INTERVAL_SECOND_MICROSECOND; }
+ | QUARTER_SYM { $$=INTERVAL_QUARTER; }
| SECOND_SYM { $$=INTERVAL_SECOND; }
- | YEAR_MONTH_SYM { $$=INTERVAL_YEAR_MONTH; }
| YEAR_SYM { $$=INTERVAL_YEAR; };
date_time_type:
@@ -5812,6 +5830,7 @@ keyword:
| PREV_SYM {}
| PROCESS {}
| PROCESSLIST_SYM {}
+ | QUARTER_SYM {}
| QUERY_SYM {}
| QUICK {}
| RAID_0_SYM {}
@@ -5863,6 +5882,8 @@ keyword:
| TRANSACTION_SYM {}
| TRUNCATE_SYM {}
| TIMESTAMP {}
+ | TIMESTAMP_ADD {}
+ | TIMESTAMP_DIFF {}
| TIME_SYM {}
| TYPE_SYM {}
| FUNCTION_SYM {}
@@ -5874,6 +5895,7 @@ keyword:
| VARIABLES {}
| VALUE_SYM {}
| WARNINGS {}
+ | WEEK_SYM {}
| WORK_SYM {}
| X509_SYM {}
| YEAR_SYM {}