-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
evalengine: Implement SEC_TO_TIME
#15755
Changes from 5 commits
99a072d
beb06f2
93bdb29
86930d4
d62a741
442c248
b9e929d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -719,6 +719,52 @@ func NewTimeFromStd(t time.Time) Time { | |
} | ||
} | ||
|
||
func NewTimeFromSecondsDecimal(seconds decimal.Decimal) Time { | ||
var neg bool | ||
if seconds.Cmp(decimal.NewFromInt(0)) < 0 { | ||
neg = true | ||
seconds = seconds.Mul(decimal.NewFromInt(-1)) | ||
} | ||
beingnoble03 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
sec, frac := seconds.QuoRem(decimal.New(1, 0), 0) | ||
ns := frac.Mul(decimal.New(1, 9)) | ||
|
||
h := sec.Div(decimal.NewFromInt(3600), 0) | ||
_, sec = sec.QuoRem(decimal.NewFromInt(3600), 0) | ||
min := sec.Div(decimal.NewFromInt(60), 0) | ||
_, sec = sec.QuoRem(decimal.NewFromInt(60), 0) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are you doing a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, we can move the var (
decSecondsInHour = decimal.NewFromInt(3600)
decMinutesInHour = decimal.NewFromInt(60)
decMaxHours = decimal.NewFromInt(MaxHours)
) This way we get to reuse the decimal parsing and allocation between calls. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. got it, done. Thanks @vmg! |
||
|
||
if h.Cmp(decimal.NewFromInt(839)) >= 0 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shall we extract 838 or 839 into a constant? It's also used in We can also use it in the next line then. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done. |
||
h := uint16(838) | ||
if neg { | ||
h |= negMask | ||
} | ||
|
||
return Time{ | ||
hour: h, | ||
minute: 59, | ||
second: 59, | ||
nanosecond: 0, | ||
} | ||
} | ||
|
||
hour, _ := h.Int64() | ||
if neg { | ||
hour |= int64(negMask) | ||
} | ||
|
||
m, _ := min.Int64() | ||
s, _ := sec.Int64() | ||
nsec, _ := ns.Int64() | ||
|
||
return Time{ | ||
hour: uint16(hour), | ||
minute: uint8(m), | ||
second: uint8(s), | ||
nanosecond: uint32(nsec), | ||
} | ||
} | ||
|
||
func NewDateTimeFromStd(t time.Time) DateTime { | ||
return DateTime{ | ||
Date: NewDateFromStd(t), | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -125,6 +125,10 @@ type ( | |
CallExpr | ||
} | ||
|
||
builtinSecToTime struct { | ||
CallExpr | ||
} | ||
|
||
builtinTimeToSec struct { | ||
CallExpr | ||
} | ||
|
@@ -197,6 +201,7 @@ var _ IR = (*builtinMonthName)(nil) | |
var _ IR = (*builtinLastDay)(nil) | ||
var _ IR = (*builtinToDays)(nil) | ||
var _ IR = (*builtinFromDays)(nil) | ||
var _ IR = (*builtinSecToTime)(nil) | ||
var _ IR = (*builtinTimeToSec)(nil) | ||
var _ IR = (*builtinToSeconds)(nil) | ||
var _ IR = (*builtinQuarter)(nil) | ||
|
@@ -1371,6 +1376,70 @@ func (call *builtinFromDays) compile(c *compiler) (ctype, error) { | |
return ctype{Type: sqltypes.Date, Flag: arg.Flag | flagNullable}, nil | ||
} | ||
|
||
func (b *builtinSecToTime) eval(env *ExpressionEnv) (eval, error) { | ||
arg, err := b.arg1(env) | ||
if arg == nil { | ||
return nil, nil | ||
} | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var e *evalDecimal | ||
prec := datetime.DefaultPrecision | ||
|
||
switch { | ||
case sqltypes.IsDecimal(arg.SQLType()): | ||
e = arg.(*evalDecimal) | ||
case sqltypes.IsIntegral(arg.SQLType()): | ||
e = evalToDecimal(arg, 0, 0) | ||
case sqltypes.IsTextOrBinary(arg.SQLType()): | ||
b := arg.(*evalBytes) | ||
if b.isHexOrBitLiteral() { | ||
e = evalToDecimal(arg, 0, 0) | ||
} else { | ||
e = evalToDecimal(arg, 0, datetime.DefaultPrecision) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this the right precision? Or should it be inferred from the input string in this case? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this should be the correct precision for this case, as mysql seems to set 6 as precision for |
||
} | ||
case sqltypes.IsDateOrTime(arg.SQLType()): | ||
d := arg.(*evalTemporal) | ||
e = evalToDecimal(d, 0, int32(d.prec)) | ||
prec = int(d.prec) | ||
default: | ||
e = evalToDecimal(arg, 0, datetime.DefaultPrecision) | ||
} | ||
|
||
prec = min(int(evalDecimalPrecision(e)), prec) | ||
return newEvalTime(datetime.NewTimeFromSecondsDecimal(e.dec), prec), nil | ||
} | ||
|
||
func (call *builtinSecToTime) compile(c *compiler) (ctype, error) { | ||
arg, err := call.Arguments[0].compile(c) | ||
if err != nil { | ||
return ctype{}, err | ||
} | ||
|
||
skip := c.compileNullCheck1(arg) | ||
|
||
switch { | ||
case sqltypes.IsDecimal(arg.Type): | ||
c.asm.Fn_SEC_TO_TIME_d() | ||
case sqltypes.IsIntegral(arg.Type): | ||
c.asm.Convert_xd(1, 0, 0) | ||
c.asm.Fn_SEC_TO_TIME_d() | ||
case sqltypes.IsTextOrBinary(arg.Type) && arg.isHexOrBitLiteral(): | ||
c.asm.Convert_xd(1, 0, 0) | ||
c.asm.Fn_SEC_TO_TIME_d() | ||
case sqltypes.IsDateOrTime(arg.Type): | ||
c.asm.Fn_SEC_TO_TIME_D() | ||
default: | ||
c.asm.Convert_xd(1, 0, datetime.DefaultPrecision) | ||
c.asm.Fn_SEC_TO_TIME_d() | ||
} | ||
|
||
c.asm.jumpDestination(skip) | ||
return ctype{Type: sqltypes.Time, Flag: arg.Flag}, nil | ||
} | ||
|
||
func (b *builtinTimeToSec) eval(env *ExpressionEnv) (eval, error) { | ||
arg, err := b.arg1(env) | ||
if arg == nil { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need the
Decimal
postfix on the function name here?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we usually use
float64
orint64
for representingseconds
, so i thought it would be better to addDecimal
prefix in the func name. altho i think it's already visible from the function signature, so removing it.