Skip to content

Commit b2e5ce7

Browse files
authored
evalengine: Implement TO_SECONDS (#15590)
Signed-off-by: Noble Mittal <noblemittal@outlook.com>
1 parent add3887 commit b2e5ce7

File tree

7 files changed

+119
-1
lines changed

7 files changed

+119
-1
lines changed

go/mysql/datetime/datetime.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,11 @@ func (dt DateTime) toDuration() time.Duration {
599599
return dur
600600
}
601601

602+
func (dt DateTime) ToSeconds() int64 {
603+
numDays := MysqlDayNumber(dt.Date.Year(), dt.Date.Month(), dt.Date.Day())
604+
return int64(numDays*24*3600) + dt.Time.ToSeconds()
605+
}
606+
602607
func (dt *DateTime) addInterval(itv *Interval) bool {
603608
switch {
604609
case itv.unit.HasTimeParts():

go/mysql/datetime/datetime_test.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -552,10 +552,21 @@ func TestToSeconds(t *testing.T) {
552552
assert.Equal(t, 45020, int(res))
553553

554554
// Neg Time Case
555-
tt.hour = 1<<15 | tt.hour
555+
tt.hour |= 1 << 15
556556
res = tt.ToSeconds()
557557

558558
assert.Equal(t, -45020, int(res))
559+
560+
dt := NewDateTimeFromStd(testGoTime)
561+
562+
res = dt.ToSeconds()
563+
assert.Equal(t, 63877465820, int(res))
564+
565+
// Neg Time Case
566+
dt.Time.hour |= 1 << 15
567+
res = dt.ToSeconds()
568+
569+
assert.Equal(t, 63877375780, int(res))
559570
}
560571

561572
func TestToStdTime(t *testing.T) {

go/vt/vtgate/evalengine/cached_size.go

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

go/vt/vtgate/evalengine/compiler_asm.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3927,6 +3927,17 @@ func (asm *assembler) Fn_TIME_TO_SEC() {
39273927
}, "FN TIME_TO_SEC TIME(SP-1)")
39283928
}
39293929

3930+
func (asm *assembler) Fn_TO_SECONDS() {
3931+
asm.emit(func(env *ExpressionEnv) int {
3932+
if env.vm.stack[env.vm.sp-1] == nil {
3933+
return 1
3934+
}
3935+
arg := env.vm.stack[env.vm.sp-1].(*evalTemporal)
3936+
env.vm.stack[env.vm.sp-1] = env.vm.arena.newEvalInt64(arg.dt.ToSeconds())
3937+
return 1
3938+
}, "FN TO_SECONDS DATETIME(SP-1)")
3939+
}
3940+
39303941
func (asm *assembler) Fn_QUARTER() {
39313942
asm.emit(func(env *ExpressionEnv) int {
39323943
if env.vm.stack[env.vm.sp-1] == nil {

go/vt/vtgate/evalengine/fn_time.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ type (
123123
CallExpr
124124
}
125125

126+
builtinToSeconds struct {
127+
CallExpr
128+
}
129+
126130
builtinQuarter struct {
127131
CallExpr
128132
}
@@ -188,6 +192,7 @@ var _ IR = (*builtinLastDay)(nil)
188192
var _ IR = (*builtinToDays)(nil)
189193
var _ IR = (*builtinFromDays)(nil)
190194
var _ IR = (*builtinTimeToSec)(nil)
195+
var _ IR = (*builtinToSeconds)(nil)
191196
var _ IR = (*builtinQuarter)(nil)
192197
var _ IR = (*builtinSecond)(nil)
193198
var _ IR = (*builtinTime)(nil)
@@ -1373,6 +1378,40 @@ func (call *builtinTimeToSec) compile(c *compiler) (ctype, error) {
13731378
return ctype{Type: sqltypes.Int64, Col: collationNumeric, Flag: arg.Flag | flagNullable}, nil
13741379
}
13751380

1381+
func (b *builtinToSeconds) eval(env *ExpressionEnv) (eval, error) {
1382+
date, err := b.arg1(env)
1383+
if err != nil {
1384+
return nil, err
1385+
}
1386+
if date == nil {
1387+
return nil, nil
1388+
}
1389+
dt := evalToDateTime(date, -1, env.now, false)
1390+
if dt == nil {
1391+
return nil, nil
1392+
}
1393+
1394+
return newEvalInt64(dt.dt.ToSeconds()), nil
1395+
}
1396+
1397+
func (call *builtinToSeconds) compile(c *compiler) (ctype, error) {
1398+
arg, err := call.Arguments[0].compile(c)
1399+
if err != nil {
1400+
return ctype{}, err
1401+
}
1402+
1403+
skip := c.compileNullCheck1(arg)
1404+
1405+
switch arg.Type {
1406+
case sqltypes.Date, sqltypes.Datetime:
1407+
default:
1408+
c.asm.Convert_xDT(1, -1, false)
1409+
}
1410+
c.asm.Fn_TO_SECONDS()
1411+
c.asm.jumpDestination(skip)
1412+
return ctype{Type: sqltypes.Int64, Col: collationNumeric, Flag: arg.Flag | flagNullable}, nil
1413+
}
1414+
13761415
func (b *builtinQuarter) eval(env *ExpressionEnv) (eval, error) {
13771416
date, err := b.arg1(env)
13781417
if err != nil {

go/vt/vtgate/evalengine/testcases/cases.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ var Cases = []TestCase{
142142
{Run: FnToDays},
143143
{Run: FnFromDays},
144144
{Run: FnTimeToSec},
145+
{Run: FnToSeconds},
145146
{Run: FnQuarter},
146147
{Run: FnSecond},
147148
{Run: FnTime},
@@ -1997,6 +1998,40 @@ func FnTimeToSec(yield Query) {
19971998
}
19981999
}
19992000

2001+
func FnToSeconds(yield Query) {
2002+
for _, t := range inputConversions {
2003+
yield(fmt.Sprintf("TO_SECONDS(%s)", t), nil)
2004+
}
2005+
2006+
timeInputs := []string{
2007+
`DATE'0000-00-00'`,
2008+
`0`,
2009+
`'0000-00-00'`,
2010+
`'00:00:00'`,
2011+
`DATE'2023-09-03 00:00:00'`,
2012+
`DATE'0000-00-00 00:00:00'`,
2013+
`950501`,
2014+
`'2007-10-07'`,
2015+
`'0000-01-01'`,
2016+
`TIME'00:00:00'`,
2017+
`TIME'120:01:12'`,
2018+
}
2019+
2020+
for _, t := range timeInputs {
2021+
yield(fmt.Sprintf("TO_SECONDS(%s)", t), nil)
2022+
}
2023+
2024+
mysqlDocSamples := []string{
2025+
`TO_SECONDS(950501)`,
2026+
`TO_SECONDS('2009-11-29')`,
2027+
`TO_SECONDS('2009-11-29 13:43:32')`,
2028+
}
2029+
2030+
for _, q := range mysqlDocSamples {
2031+
yield(q, nil)
2032+
}
2033+
}
2034+
20002035
func FnQuarter(yield Query) {
20012036
for _, d := range inputConversions {
20022037
yield(fmt.Sprintf("QUARTER(%s)", d), nil)

go/vt/vtgate/evalengine/translate_builtin.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,11 @@ func (ast *astCompiler) translateFuncExpr(fn *sqlparser.FuncExpr) (IR, error) {
457457
return nil, argError(method)
458458
}
459459
return &builtinTimeToSec{CallExpr: call}, nil
460+
case "to_seconds":
461+
if len(args) != 1 {
462+
return nil, argError(method)
463+
}
464+
return &builtinToSeconds{CallExpr: call}, nil
460465
case "quarter":
461466
if len(args) != 1 {
462467
return nil, argError(method)

0 commit comments

Comments
 (0)