WL#530&531: TIMESTAMPADD, TIMESTAMPDIFF functions

Syntax for TIMESTAMPADD:

TIMESTAMPADD(interval, integer_expression, datetime_expression)

interval:= FRAC_SECOND | SECOND | MINUTE | HOUR | DAY | WEEK | MONTH | 
QUARTER | YEAR

Supported SQL_TSI_  prefix  (like SQL_TSI_SECOND)

Syntax for TIMESTAMPDIFF:

TIMESTAMPDIFF(interval, datetime_expression1, datetime_expression2)

interval:= FRAC_SECOND | SECOND | MINUTE | HOUR | DAY | WEEK | MONTH | 
QUARTER | YEAR

Supported SQL_TSI_  prefix  (like SQL_TSI_SECOND)
parent e8634f80
......@@ -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;
......@@ -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
......
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);
......
......@@ -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;
......@@ -219,6 +219,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;
......
......@@ -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);
......
......@@ -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);
......
......@@ -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);
......
......@@ -421,9 +421,15 @@ static bool get_interval_value(Item *args,interval_type int_type,
case INTERVAL_YEAR:
t->year=value;
break;
case INTERVAL_QUARTER:
t->month=value*3;
break;
case INTERVAL_MONTH:
t->month=value;
break;
case INTERVAL_WEEK:
t->day=value*7;
break;
case INTERVAL_DAY:
t->day=value;
break;
......@@ -1286,6 +1292,7 @@ bool Item_date_add_interval::get_date(TIME *ltime, bool 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
......@@ -1301,6 +1308,7 @@ bool Item_date_add_interval::get_date(TIME *ltime, bool 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);
......@@ -1367,7 +1375,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;
......@@ -1390,6 +1400,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)
{
......@@ -1412,7 +1424,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+
......@@ -1740,6 +1761,79 @@ null_date:
return 0;
}
/*
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.
......@@ -1765,39 +1859,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, seconds, microseconds);
if (make_datetime(str, &l_time3,
......@@ -1860,3 +1931,163 @@ longlong Item_func_microsecond::val_int()
return ltime.second_part;
return 0;
}
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(')');
}
......@@ -543,11 +543,12 @@ 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_MINUTE_MICROSECOND, INTERVAL_SECOND_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
};
......@@ -763,3 +764,20 @@ public:
maybe_null=1;
}
};
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);
};
......@@ -176,6 +176,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},
......@@ -335,6 +336,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},
......@@ -397,6 +399,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},
......@@ -416,6 +427,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},
......@@ -451,6 +464,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},
......@@ -637,7 +651,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},
......@@ -683,7 +696,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)},
......
......@@ -82,7 +82,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;
st_select_lex *select_lex;
chooser_compare_func_creator boolfunc2creator;
struct sp_cond_type *spcondtype;
......@@ -452,6 +452,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
......@@ -494,6 +496,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
......@@ -538,6 +541,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
......@@ -679,6 +683,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <interval> interval
%type <interval_time_st> interval_time_st
%type <db_type> table_types
%type <row_type> row_types
......@@ -3453,6 +3459,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();}
| RAND '(' ')'
......@@ -3486,6 +3494,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 ')'
......@@ -3926,23 +3938,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; };
table_alias:
......@@ -5414,6 +5432,7 @@ keyword:
| PREV_SYM {}
| PROCESS {}
| PROCESSLIST_SYM {}
| QUARTER_SYM {}
| QUERY_SYM {}
| QUICK {}
| RAID_0_SYM {}
......@@ -5463,6 +5482,8 @@ keyword:
| TRANSACTION_SYM {}
| TRUNCATE_SYM {}
| TIMESTAMP {}
| TIMESTAMP_ADD {}
| TIMESTAMP_DIFF {}
| TIME_SYM {}
| TYPE_SYM {}
| FUNCTION_SYM {}
......@@ -5474,6 +5495,7 @@ keyword:
| VARIABLES {}
| VALUE_SYM {}
| WARNINGS {}
| WEEK_SYM {}
| WORK_SYM {}
| X509_SYM {}
| YEAR_SYM {}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment