Skip to content

Commit

Permalink
builtin: add time function dayname()
Browse files Browse the repository at this point in the history
add builtin time function dayname()
  • Loading branch information
hhkbp2 committed Jan 6, 2016
1 parent 3a63ddc commit b607c85
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 9 deletions.
1 change: 1 addition & 0 deletions expression/builtin/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ var Funcs = map[string]Func{
"curtime": {builtinCurrentTime, 0, 1, false, false},
"date": {builtinDate, 1, 1, true, false},
"day": {builtinDay, 1, 1, true, false},
"dayname": {builtinDayName, 1, 1, true, false},
"dayofmonth": {builtinDayOfMonth, 1, 1, true, false},
"dayofweek": {builtinDayOfWeek, 1, 1, true, false},
"dayofyear": {builtinDayOfYear, 1, 1, true, false},
Expand Down
16 changes: 16 additions & 0 deletions expression/builtin/time.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,22 @@ func builtinNow(args []interface{}, ctx map[interface{}]interface{}) (interface{
return t.RoundFrac(int(fsp))
}

// See http://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_dayname
func builtinDayName(args []interface{}, ctx map[interface{}]interface{}) (interface{}, error) {
v, err := builtinWeekDay(args, ctx)
if err != nil {
return nil, err
}
if types.IsNil(v) {
return nil, nil
}
weekday := v.(int64)
if (weekday < 0) || (weekday >= int64(len(mysql.WeekdayNames))) {
return nil, errors.Errorf("no name for invalid weekday: %d.", weekday)
}
return mysql.WeekdayNames[weekday], nil
}

// See http://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_dayofmonth
func builtinDayOfMonth(args []interface{}, ctx map[interface{}]interface{}) (interface{}, error) {
// TODO: some invalid format like 2000-00-00 will return 0 too.
Expand Down
18 changes: 14 additions & 4 deletions expression/builtin/time_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,13 @@ func (s *testBuiltinSuite) TestDate(c *C) {
DayOfWeek int64
DayOfYear int64
WeekDay int64
DayName string
Week int64
WeekOfYear int64
YearWeek int64
}{
{"2000-01-01", 2000, 1, 1, 7, 1, 5, 52, 52, 199952},
{"2011-11-11", 2011, 11, 11, 6, 315, 4, 45, 45, 201145},
{"2000-01-01", 2000, 1, 1, 7, 1, 5, "Saturday", 52, 52, 199952},
{"2011-11-11", 2011, 11, 11, 6, 315, 4, "Friday", 45, 45, 201145},
}

for _, t := range tbl {
Expand Down Expand Up @@ -87,6 +88,10 @@ func (s *testBuiltinSuite) TestDate(c *C) {
c.Assert(err, IsNil)
c.Assert(v, DeepEquals, t.WeekDay)

v, err = builtinDayName(args, nil)
c.Assert(err, IsNil)
c.Assert(v, DeepEquals, t.DayName)

v, err = builtinWeek(args, nil)
c.Assert(err, IsNil)
c.Assert(v, DeepEquals, t.Week)
Expand All @@ -109,12 +114,13 @@ func (s *testBuiltinSuite) TestDate(c *C) {
DayOfWeek interface{}
DayOfYear interface{}
WeekDay interface{}
DayName interface{}
Week interface{}
WeekOfYear interface{}
YearWeek interface{}
}{
{nil, nil, nil, nil, nil, nil, nil, nil, nil, nil},
{"0000-00-00", int64(0), int64(0), int64(0), nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil},
{"0000-00-00", int64(0), int64(0), int64(0), nil, nil, nil, nil, nil, nil, nil},
}

for _, t := range tblNil {
Expand Down Expand Up @@ -143,6 +149,10 @@ func (s *testBuiltinSuite) TestDate(c *C) {
c.Assert(err, IsNil)
c.Assert(v, DeepEquals, t.WeekDay)

v, err = builtinWeekDay(args, nil)
c.Assert(err, IsNil)
c.Assert(v, DeepEquals, t.DayName)

v, err = builtinWeek(args, nil)
c.Assert(err, IsNil)
c.Assert(v, DeepEquals, t.Week)
Expand Down
11 changes: 11 additions & 0 deletions mysql/time.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,17 @@ var (
MinTimestamp = time.Date(1970, 1, 1, 0, 0, 1, 0, time.UTC)
// MaxTimestamp is the maximum for mysql timestamp type.
MaxTimestamp = time.Date(2038, 1, 19, 3, 14, 7, 999999, time.UTC)

// WeekdayNames lists names of weekdays, which are used in builtin time function `dayname`.
WeekdayNames = []string{
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday",
}
)

// Time is the struct for handling datetime, timestamp and date.
Expand Down
7 changes: 6 additions & 1 deletion parser/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ import (
dateAdd "DATE_ADD"
dateSub "DATE_SUB"
day "DAY"
dayname "DAYNAME"
dayofmonth "DAYOFMONTH"
dayofweek "DAYOFWEEK"
dayofyear "DAYOFYEAR"
Expand Down Expand Up @@ -1688,7 +1689,7 @@ UnReservedKeyword:
| "REPEATABLE" | "COMMITTED" | "UNCOMMITTED" | "ONLY" | "SERIALIZABLE" | "LEVEL" | "VARIABLES"

NotKeywordToken:
"ABS" | "ADDDATE" | "COALESCE" | "CONCAT" | "CONCAT_WS" | "COUNT" | "DAY" | "DATE_ADD" | "DATE_SUB" | "DAYOFMONTH"
"ABS" | "ADDDATE" | "COALESCE" | "CONCAT" | "CONCAT_WS" | "COUNT" | "DAY" | "DATE_ADD" | "DATE_SUB" | "DAYNAME" | "DAYOFMONTH"
| "DAYOFWEEK" | "DAYOFYEAR" | "FOUND_ROWS" | "GROUP_CONCAT"| "HOUR" | "IFNULL" | "LENGTH" | "LOCATE" | "MAX"
| "MICROSECOND" | "MIN" | "MINUTE" | "NULLIF" | "MONTH" | "NOW" | "POW" | "POWER" | "RAND" | "SECOND" | "SQL_CALC_FOUND_ROWS"
| "SUBDATE" | "SUBSTRING" %prec lowerThanLeftParen | "SUBSTRING_INDEX" | "SUM" | "TRIM" | "WEEKDAY" | "WEEKOFYEAR"
Expand Down Expand Up @@ -2182,6 +2183,10 @@ FunctionCallNonKeyword:
{
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1.(string)), Args: []ast.ExprNode{$3.(ast.ExprNode)}}
}
| "DAYNAME" '(' Expression ')'
{
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1.(string)), Args: []ast.ExprNode{$3.(ast.ExprNode)}}
}
| "DAYOFWEEK" '(' Expression ')'
{
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1.(string)), Args: []ast.ExprNode{$3.(ast.ExprNode)}}
Expand Down
30 changes: 26 additions & 4 deletions parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func (s *testParserSuite) TestSimple(c *C) {
"collation", "comment", "avg_row_length", "checksum", "compression", "connection", "key_block_size",
"max_rows", "min_rows", "national", "row", "quarter", "escape", "grants", "status", "fields", "triggers",
"delay_key_write", "isolation", "repeatable", "committed", "uncommitted", "only", "serializable", "level",
"curtime", "variables",
"curtime", "variables", "dayname",
}
for _, kw := range unreservedKws {
src := fmt.Sprintf("SELECT %s FROM tbl;", kw)
Expand Down Expand Up @@ -326,7 +326,6 @@ func (s *testParserSuite) TestExpression(c *C) {
func (s *testParserSuite) TestBuiltin(c *C) {
table := []testCase{
// For buildin functions
{"SELECT DAYOFMONTH('2007-02-03');", true},
{"SELECT POW(1, 2)", true},
{"SELECT POW(1, 0.5)", true},
{"SELECT POW(1, -1)", true},
Expand Down Expand Up @@ -363,8 +362,6 @@ func (s *testParserSuite) TestBuiltin(c *C) {
{`SELECT LOCATE('bar', 'foobarbar');`, true},
{`SELECT LOCATE('bar', 'foobarbar', 5);`, true},

{"select current_date, current_date(), curdate()", true},

// For delete statement
{"DELETE t1, t2 FROM t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.id=t2.id AND t2.id=t3.id;", true},
{"DELETE FROM t1, t2 USING t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.id=t2.id AND t2.id=t3.id;", true},
Expand Down Expand Up @@ -402,6 +399,31 @@ func (s *testParserSuite) TestBuiltin(c *C) {
{"select curtime()", true},
{"select curtime(6)", true},

// for microsecond, second, minute, hour
{"SELECT MICROSECOND('2009-12-31 23:59:59.000010');", true},
{"SELECT SECOND('10:05:03');", true},
{"SELECT MINUTE('2008-02-03 10:05:03');", true},
{"SELECT HOUR('10:05:03');", true},

// for date, day, weekday
{"SELECT DATE('2003-12-31 01:02:03');", true},
{"SELECT CURRENT_DATE, CURRENT_DATE(), CURDATE()", true},
{"SELECT DAY('2007-02-03');", true},
{"SELECT DAYOFMONTH('2007-02-03');", true},
{"SELECT DAYOFWEEK('2007-02-03');", true},
{"SELECT DAYOFYEAR('2007-02-03');", true},
{"SELECT DAYNAME('2007-02-03');", true},
{"SELECT WEEKDAY('2007-02-03');", true},

// for week, month, year
{"SELECT WEEK('2007-02-03');", true},
{"SELECT WEEK('2007-02-03', 0);", true},
{"SELECT WEEKOFYEAR('2007-02-03');", true},
{"SELECT MONTH('2007-02-03');", true},
{"SELECT YEAR('2007-02-03');", true},
{"SELECT YEARWEEK('2007-02-03');", true},
{"SELECT YEARWEEK('2007-02-03', 0);", true},

// For time extract
{`select extract(microsecond from "2011-11-11 10:10:10.123456")`, true},
{`select extract(second from "2011-11-11 10:10:10.123456")`, true},
Expand Down
3 changes: 3 additions & 0 deletions parser/scanner.l
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ databases {d}{a}{t}{a}{b}{a}{s}{e}{s}
date_add {d}{a}{t}{e}_{a}{d}{d}
date_sub {d}{a}{t}{e}_{s}{u}{b}
day {d}{a}{y}
dayname {d}{a}{y}{n}{a}{m}{e}
dayofweek {d}{a}{y}{o}{f}{w}{e}{e}{k}
dayofmonth {d}{a}{y}{o}{f}{m}{o}{n}{t}{h}
dayofyear {d}{a}{y}{o}{f}{y}{e}{a}{r}
Expand Down Expand Up @@ -710,6 +711,8 @@ year_month {y}{e}{a}{r}_{m}{o}{n}{t}{h}
{date_sub} return dateSub
{day} lval.item = string(l.val)
return day
{dayname} lval.item = string(l.val)
return dayname
{dayofweek} lval.item = string(l.val)
return dayofweek
{dayofmonth} lval.item = string(l.val)
Expand Down

0 comments on commit b607c85

Please sign in to comment.