Skip to content

Commit

Permalink
evalengine: Implement FROM_DAYS (#15058)
Browse files Browse the repository at this point in the history
Signed-off-by: Noble Mittal <[email protected]>
  • Loading branch information
beingnoble03 authored Jan 29, 2024
1 parent f106164 commit 4c23faa
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 0 deletions.
8 changes: 8 additions & 0 deletions go/mysql/datetime/mydate.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,11 @@ func mysqlDateFromDayNumber(daynr int) (uint16, uint8, uint8) {

panic("unreachable: yday is too large?")
}

// DateFromDayNumber converts an absolute day number into a Date.
// Returns zero date if day number exceeds 3652499 or is less than 366.
func DateFromDayNumber(daynr int) Date {
var d Date
d.year, d.month, d.day = mysqlDateFromDayNumber(daynr)
return d
}
12 changes: 12 additions & 0 deletions go/vt/vtgate/evalengine/cached_size.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions go/vt/vtgate/evalengine/compiler_asm.go
Original file line number Diff line number Diff line change
Expand Up @@ -3795,6 +3795,20 @@ func (asm *assembler) Fn_LAST_DAY() {
}, "FN LAST_DAY DATETIME(SP-1)")
}

func (asm *assembler) Fn_FROM_DAYS() {
asm.emit(func(env *ExpressionEnv) int {
arg := env.vm.stack[env.vm.sp-1].(*evalInt64)
d := datetime.DateFromDayNumber(int(arg.i))
if d.Year() > 9999 {
env.vm.stack[env.vm.sp-1] = nil
return 1
}

env.vm.stack[env.vm.sp-1] = env.vm.arena.newEvalDate(d)
return 1
}, "FN FROM_DAYS INT64(SP-1)")
}

func (asm *assembler) Fn_QUARTER() {
asm.emit(func(env *ExpressionEnv) int {
if env.vm.stack[env.vm.sp-1] == nil {
Expand Down
41 changes: 41 additions & 0 deletions go/vt/vtgate/evalengine/fn_time.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ type (
CallExpr
}

builtinFromDays struct {
CallExpr
}

builtinQuarter struct {
CallExpr
}
Expand Down Expand Up @@ -173,6 +177,7 @@ var _ IR = (*builtinMinute)(nil)
var _ IR = (*builtinMonth)(nil)
var _ IR = (*builtinMonthName)(nil)
var _ IR = (*builtinLastDay)(nil)
var _ IR = (*builtinFromDays)(nil)
var _ IR = (*builtinQuarter)(nil)
var _ IR = (*builtinSecond)(nil)
var _ IR = (*builtinTime)(nil)
Expand Down Expand Up @@ -1249,6 +1254,42 @@ func (call *builtinLastDay) compile(c *compiler) (ctype, error) {
return ctype{Type: sqltypes.Date, Flag: arg.Flag | flagNullable}, nil
}

func (b *builtinFromDays) eval(env *ExpressionEnv) (eval, error) {
arg, err := b.arg1(env)
if arg == nil {
return nil, nil
}
if err != nil {
return nil, err
}

d := datetime.DateFromDayNumber(int(evalToInt64(arg).i))

// mysql returns NULL if year is greater than 9999
if d.Year() > 9999 {
return nil, nil
}
return newEvalDate(d, true), nil
}

func (call *builtinFromDays) 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.Int64:
default:
c.asm.Convert_xi(1)
}

c.asm.Fn_FROM_DAYS()
c.asm.jumpDestination(skip)
return ctype{Type: sqltypes.Date, Flag: arg.Flag | flagNullable}, nil
}

func (b *builtinQuarter) eval(env *ExpressionEnv) (eval, error) {
date, err := b.arg1(env)
if err != nil {
Expand Down
23 changes: 23 additions & 0 deletions go/vt/vtgate/evalengine/testcases/cases.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ var Cases = []TestCase{
{Run: FnMonth},
{Run: FnMonthName},
{Run: FnLastDay},
{Run: FnFromDays},
{Run: FnQuarter},
{Run: FnSecond},
{Run: FnTime},
Expand Down Expand Up @@ -1766,6 +1767,28 @@ func FnLastDay(yield Query) {
}
}

func FnFromDays(yield Query) {
for _, d := range inputConversions {
yield(fmt.Sprintf("FROM_DAYS(%s)", d), nil)
}

days := []string{
"0",
"1",
"366",
"365242",
"3652424",
"3652425",
"3652500",
"3652499",
"730669",
}

for _, d := range days {
yield(fmt.Sprintf("FROM_DAYS(%s)", d), nil)
}
}

func FnQuarter(yield Query) {
for _, d := range inputConversions {
yield(fmt.Sprintf("QUARTER(%s)", d), nil)
Expand Down
5 changes: 5 additions & 0 deletions go/vt/vtgate/evalengine/translate_builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,11 @@ func (ast *astCompiler) translateFuncExpr(fn *sqlparser.FuncExpr) (IR, error) {
return nil, argError(method)
}
return &builtinLastDay{CallExpr: call}, nil
case "from_days":
if len(args) != 1 {
return nil, argError(method)
}
return &builtinFromDays{CallExpr: call}, nil
case "quarter":
if len(args) != 1 {
return nil, argError(method)
Expand Down

0 comments on commit 4c23faa

Please sign in to comment.