From 3c60baa6fc0ff5310c67f6fd7c538033647204c4 Mon Sep 17 00:00:00 2001 From: Noble Mittal <62551163+beingnoble03@users.noreply.github.com> Date: Mon, 5 Feb 2024 14:27:29 +0530 Subject: [PATCH] evalEngine: Implement TIME_TO_SEC (#15094) Signed-off-by: Noble Mittal --- go/mysql/datetime/datetime.go | 4 ++ go/vt/vtgate/evalengine/cached_size.go | 12 ++++++ go/vt/vtgate/evalengine/compiler_asm.go | 13 ++++++ go/vt/vtgate/evalengine/fn_time.go | 42 ++++++++++++++++++++ go/vt/vtgate/evalengine/testcases/cases.go | 25 ++++++++++++ go/vt/vtgate/evalengine/translate_builtin.go | 5 +++ 6 files changed, 101 insertions(+) diff --git a/go/mysql/datetime/datetime.go b/go/mysql/datetime/datetime.go index 2db325b5d80..c27593ee0a6 100644 --- a/go/mysql/datetime/datetime.go +++ b/go/mysql/datetime/datetime.go @@ -448,6 +448,10 @@ func (t Time) toDuration() time.Duration { return dur } +func (t Time) ToSeconds() int64 { + return int64(t.ToDuration().Seconds()) +} + func (d Date) ToStdTime(loc *time.Location) (out time.Time) { return time.Date(d.Year(), time.Month(d.Month()), d.Day(), 0, 0, 0, 0, loc) } diff --git a/go/vt/vtgate/evalengine/cached_size.go b/go/vt/vtgate/evalengine/cached_size.go index 8c22ff4ecd9..66fcc72a9c0 100644 --- a/go/vt/vtgate/evalengine/cached_size.go +++ b/go/vt/vtgate/evalengine/cached_size.go @@ -1567,6 +1567,18 @@ func (cached *builtinTime) CachedSize(alloc bool) int64 { size += cached.CallExpr.CachedSize(false) return size } +func (cached *builtinTimeToSec) CachedSize(alloc bool) int64 { + if cached == nil { + return int64(0) + } + size := int64(0) + if alloc { + size += int64(48) + } + // field CallExpr vitess.io/vitess/go/vt/vtgate/evalengine.CallExpr + size += cached.CallExpr.CachedSize(false) + return size +} func (cached *builtinToBase64) CachedSize(alloc bool) int64 { if cached == nil { return int64(0) diff --git a/go/vt/vtgate/evalengine/compiler_asm.go b/go/vt/vtgate/evalengine/compiler_asm.go index de856bb4333..868ec6322b9 100644 --- a/go/vt/vtgate/evalengine/compiler_asm.go +++ b/go/vt/vtgate/evalengine/compiler_asm.go @@ -3818,6 +3818,19 @@ func (asm *assembler) Fn_FROM_DAYS() { }, "FN FROM_DAYS INT64(SP-1)") } +func (asm *assembler) Fn_TIME_TO_SEC() { + asm.emit(func(env *ExpressionEnv) int { + if env.vm.stack[env.vm.sp-1] == nil { + return 1 + } + d := env.vm.stack[env.vm.sp-1].(*evalTemporal) + + sec := d.dt.Time.ToSeconds() + env.vm.stack[env.vm.sp-1] = env.vm.arena.newEvalInt64(sec) + return 1 + }, "FN TIME_TO_SEC TIME(SP-1)") +} + func (asm *assembler) Fn_QUARTER() { asm.emit(func(env *ExpressionEnv) int { if env.vm.stack[env.vm.sp-1] == nil { diff --git a/go/vt/vtgate/evalengine/fn_time.go b/go/vt/vtgate/evalengine/fn_time.go index 82e38bff9d9..ecb1fedc135 100644 --- a/go/vt/vtgate/evalengine/fn_time.go +++ b/go/vt/vtgate/evalengine/fn_time.go @@ -119,6 +119,10 @@ type ( CallExpr } + builtinTimeToSec struct { + CallExpr + } + builtinQuarter struct { CallExpr } @@ -183,6 +187,7 @@ var _ IR = (*builtinMonthName)(nil) var _ IR = (*builtinLastDay)(nil) var _ IR = (*builtinToDays)(nil) var _ IR = (*builtinFromDays)(nil) +var _ IR = (*builtinTimeToSec)(nil) var _ IR = (*builtinQuarter)(nil) var _ IR = (*builtinSecond)(nil) var _ IR = (*builtinTime)(nil) @@ -1327,6 +1332,43 @@ func (call *builtinFromDays) compile(c *compiler) (ctype, error) { return ctype{Type: sqltypes.Date, Flag: arg.Flag | flagNullable}, nil } +func (b *builtinTimeToSec) eval(env *ExpressionEnv) (eval, error) { + arg, err := b.arg1(env) + if arg == nil { + return nil, nil + } + if err != nil { + return nil, err + } + + d := evalToTime(arg, -1) + if d == nil { + return nil, nil + } + + sec := d.dt.Time.ToSeconds() + return newEvalInt64(sec), nil +} + +func (call *builtinTimeToSec) compile(c *compiler) (ctype, error) { + arg, err := call.Arguments[0].compile(c) + if err != nil { + return ctype{}, err + } + + skip := c.compileNullCheck1(arg) + + switch arg.Type { + case sqltypes.Date, sqltypes.Datetime, sqltypes.Time: + default: + c.asm.Convert_xT(1, -1) + } + + c.asm.Fn_TIME_TO_SEC() + c.asm.jumpDestination(skip) + return ctype{Type: sqltypes.Int64, Col: collationNumeric, Flag: arg.Flag | flagNullable}, nil +} + func (b *builtinQuarter) eval(env *ExpressionEnv) (eval, error) { date, err := b.arg1(env) if err != nil { diff --git a/go/vt/vtgate/evalengine/testcases/cases.go b/go/vt/vtgate/evalengine/testcases/cases.go index f9036c1afca..b9ae41722eb 100644 --- a/go/vt/vtgate/evalengine/testcases/cases.go +++ b/go/vt/vtgate/evalengine/testcases/cases.go @@ -133,6 +133,7 @@ var Cases = []TestCase{ {Run: FnLastDay}, {Run: FnToDays}, {Run: FnFromDays}, + {Run: FnTimeToSec}, {Run: FnQuarter}, {Run: FnSecond}, {Run: FnTime}, @@ -1816,6 +1817,30 @@ func FnFromDays(yield Query) { } } +func FnTimeToSec(yield Query) { + for _, d := range inputConversions { + yield(fmt.Sprintf("TIME_TO_SEC(%s)", d), nil) + } + + time := []string{ + `0`, + `'00:00:00'`, + `'22:23:00'`, + `'00:39:38'`, + `TIME'00:39:38'`, + `TIME'102:39:38'`, + `TIME'838:59:59'`, + `TIME'-838:59:59'`, + `'000220`, + `'2003-09-03 00:39:38'`, + `'2003-09-03'`, + } + + for _, t := range time { + yield(fmt.Sprintf("TIME_TO_SEC(%s)", t), nil) + } +} + func FnQuarter(yield Query) { for _, d := range inputConversions { yield(fmt.Sprintf("QUARTER(%s)", d), nil) diff --git a/go/vt/vtgate/evalengine/translate_builtin.go b/go/vt/vtgate/evalengine/translate_builtin.go index b44c17f6f9b..8f3bd49b8c7 100644 --- a/go/vt/vtgate/evalengine/translate_builtin.go +++ b/go/vt/vtgate/evalengine/translate_builtin.go @@ -429,6 +429,11 @@ func (ast *astCompiler) translateFuncExpr(fn *sqlparser.FuncExpr) (IR, error) { return nil, argError(method) } return &builtinFromDays{CallExpr: call}, nil + case "time_to_sec": + if len(args) != 1 { + return nil, argError(method) + } + return &builtinTimeToSec{CallExpr: call}, nil case "quarter": if len(args) != 1 { return nil, argError(method)