Skip to content

Commit

Permalink
Merge pull request #2420 from cockroachdb/vivek/set
Browse files Browse the repository at this point in the history
Add important timestamp/date builtins.
  • Loading branch information
vivekmenezes committed Sep 9, 2015
2 parents b7cfd5c + 42447d2 commit 527af89
Show file tree
Hide file tree
Showing 6 changed files with 2,631 additions and 2,451 deletions.
109 changes: 107 additions & 2 deletions sql/parser/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"math/rand"
"reflect"
"strings"
"time"
)

var errEmptyInputString = errors.New("the input string should not be empty")
Expand All @@ -36,8 +37,10 @@ type typeList []reflect.Type
type builtin struct {
types typeList
returnType Datum
impure bool
fn func(DTuple) (Datum, error)
// Set to true when a function returns a different value when called with
// the same parameters. e.g.: random(), now().
impure bool
fn func(DTuple) (Datum, error)
}

func (b builtin) match(types typeList) bool {
Expand Down Expand Up @@ -319,6 +322,99 @@ var builtins = map[string][]builtin{
},
},

// Timestamp/Date functions.

"age": {
builtin{
types: typeList{timestampType},
returnType: DummyInterval,
impure: true,
fn: func(args DTuple) (Datum, error) {
return DInterval{Duration: time.Now().Sub(args[0].(DTimestamp).Time)}, nil
},
},
builtin{
types: typeList{timestampType, timestampType},
returnType: DummyInterval,
fn: func(args DTuple) (Datum, error) {
return DInterval{Duration: args[0].(DTimestamp).Sub(args[1].(DTimestamp).Time)}, nil
},
},
},

"current_date": {
builtin{
types: typeList{},
returnType: DummyDate,
impure: true,
fn: func(args DTuple) (Datum, error) {
return DDate{Time: time.Now().Truncate(24 * time.Hour)}, nil
},
},
},

"current_timestamp": {nowImpl},
"now": {nowImpl},

"extract": {
builtin{
types: typeList{stringType, timestampType},
returnType: DummyInt,
fn: func(args DTuple) (Datum, error) {
// extract timeSpan fromTime.
fromTime := args[1].(DTimestamp)
timeSpan := strings.ToLower(string(args[0].(DString)))
switch timeSpan {
case "year":
return DInt(fromTime.Year()), nil

case "quarter":
return DInt(fromTime.Month()/4 + 1), nil

case "month":
return DInt(fromTime.Month()), nil

case "week":
_, week := fromTime.ISOWeek()
return DInt(week), nil

case "day":
return DInt(fromTime.Day()), nil

case "dayofweek", "dow":
return DInt(fromTime.Weekday()), nil

case "dayofyear", "doy":
return DInt(fromTime.YearDay()), nil

case "hour":
return DInt(fromTime.Hour()), nil

case "minute":
return DInt(fromTime.Minute()), nil

case "second":
return DInt(fromTime.Second()), nil

case "millisecond":
return DInt(fromTime.Nanosecond() / int(time.Millisecond)), nil

case "microsecond":
return DInt(fromTime.Nanosecond() / int(time.Microsecond)), nil

case "nanosecond":
return DInt(fromTime.Nanosecond()), nil

case "epoch":
return DInt(fromTime.Unix()), nil

default:
return DNull, fmt.Errorf("unsupported timespan: %s", timeSpan)
}
},
},
},

// Aggregate functions.

"avg": {
Expand Down Expand Up @@ -433,6 +529,15 @@ var substringImpls = []builtin{
},
}

var nowImpl = builtin{
types: typeList{},
returnType: DummyTimestamp,
impure: true,
fn: func(args DTuple) (Datum, error) {
return DTimestamp{Time: time.Now()}, nil
},
}

func stringBuiltin1(f func(string) (Datum, error), returnType Datum) builtin {
return builtin{
types: typeList{stringType},
Expand Down
6 changes: 5 additions & 1 deletion sql/parser/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -1512,7 +1512,11 @@ func ParseDate(s DString) (DDate, error) {
// ParseTimestamp parses the timestamp.
func ParseTimestamp(s DString) (DTimestamp, error) {
str := string(s)
t, err := time.Parse(timestampFormat, str)
t, err := time.Parse(dateFormat, str)
if err == nil {
return DTimestamp{Time: t}, nil
}
t, err = time.Parse(timestampFormat, str)
if err == nil {
t = t.UTC()
return DTimestamp{Time: t}, nil
Expand Down
1 change: 1 addition & 0 deletions sql/parser/eval_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ func TestEvalExpr(t *testing.T) {
{`'hello'::char(2)`, `'he'`},
{`123::text`, `'123'`},
{`'2010-09-28'::date`, `2010-09-28`},
{`'2010-09-28'::timestamp`, `2010-09-28 00:00:00+00:00`},
{`('2010-09-28 12:00:00.1'::timestamp)::date`, `2010-09-28`},
{`'2010-09-28 12:00:00.1'::timestamp`, `2010-09-28 12:00:00.1+00:00`},
{`'2010-09-28 12:00:00.1+02:00'::timestamp`, `2010-09-28 10:00:00.1+00:00`},
Expand Down
Loading

0 comments on commit 527af89

Please sign in to comment.