Skip to content
This repository was archived by the owner on Jan 28, 2021. It is now read-only.

sql/expression: new date function #654

Merged
merged 2 commits into from
Apr 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ We support and actively test against certain third-party clients to ensure compa
|`CONNECTION_ID()`|Return the current connection ID.|
|`COUNT(expr)`| Returns a count of the number of non-NULL values of expr in the rows retrieved by a SELECT statement.|
|`DAY(date)`|Synonym for DAYOFMONTH().|
|`DATE(date)`|Returns the date part of the given date.|
|`DAYOFMONTH(date)`|Return the day of the month (0-31).|
|`DAYOFWEEK(date)`|Returns the day of the week of the given date.|
|`DAYOFYEAR(date)`|Returns the day of the year of the given date.|
Expand Down
2 changes: 2 additions & 0 deletions SUPPORTED.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,10 @@
- FROM_BASE64

## Time functions
- DATE
- DAY
- WEEKDAY
- DAYOFMONTH
- DAYOFWEEK
- DAYOFYEAR
- HOUR
Expand Down
1 change: 1 addition & 0 deletions sql/expression/function/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ var Defaults = []sql.Function{
sql.FunctionN{Name: "substring", Fn: NewSubstring},
sql.FunctionN{Name: "mid", Fn: NewSubstring},
sql.FunctionN{Name: "substr", Fn: NewSubstring},
sql.Function1{Name: "date", Fn: NewDate},
sql.Function1{Name: "year", Fn: NewYear},
sql.Function1{Name: "month", Fn: NewMonth},
sql.Function1{Name: "day", Fn: NewDay},
Expand Down
36 changes: 36 additions & 0 deletions sql/expression/function/time.go
Original file line number Diff line number Diff line change
Expand Up @@ -573,3 +573,39 @@ func (n *Now) Eval(*sql.Context, sql.Row) (interface{}, error) {
func (n *Now) TransformUp(f sql.TransformExprFunc) (sql.Expression, error) {
return f(n)
}

// Date a function takes the DATE part out from a datetime expression.
type Date struct {
expression.UnaryExpression
}

// NewDate returns a new Date node.
func NewDate(date sql.Expression) sql.Expression {
return &Date{expression.UnaryExpression{Child: date}}
}

func (d *Date) String() string { return fmt.Sprintf("DATE(%s)", d.Child) }

// Type implements the Expression interface.
func (d *Date) Type() sql.Type { return sql.Text }

// Eval implements the Expression interface.
func (d *Date) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
return getDatePart(ctx, d.UnaryExpression, row, func(v interface{}) interface{} {
if v == nil {
return nil
}

return v.(time.Time).Format("2006-01-02")
})
}

// TransformUp implements the sql.Expression interface.
func (d *Date) TransformUp(f sql.TransformExprFunc) (sql.Expression, error) {
child, err := d.Child.TransformUp(f)
if err != nil {
return nil, err
}

return f(NewDate(child))
}
31 changes: 31 additions & 0 deletions sql/expression/function/time_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,3 +354,34 @@ func TestNow(t *testing.T) {
require.NoError(err)
require.Equal(date, result)
}

func TestDate(t *testing.T) {
f := NewDate(expression.NewGetField(0, sql.Text, "foo", false))
ctx := sql.NewEmptyContext()

testCases := []struct {
name string
row sql.Row
expected interface{}
err bool
}{
{"null date", sql.NewRow(nil), nil, false},
{"invalid type", sql.NewRow([]byte{0, 1, 2}), nil, false},
{"date as string", sql.NewRow(stringDate), "2007-01-02", false},
{"date as time", sql.NewRow(time.Now()), time.Now().Format("2006-01-02"), false},
{"date as unix timestamp", sql.NewRow(int64(tsDate)), "2009-11-22", false},
}

for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
require := require.New(t)
val, err := f.Eval(ctx, tt.row)
if tt.err {
require.Error(err)
} else {
require.NoError(err)
require.Equal(tt.expected, val)
}
})
}
}