Skip to content

Commit 8d4a7bc

Browse files
authored
more precision fixes for unix_timestamp (#2918)
1 parent fead863 commit 8d4a7bc

File tree

4 files changed

+37
-14
lines changed

4 files changed

+37
-14
lines changed

enginetest/queries/script_queries.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3068,7 +3068,7 @@ CREATE TABLE tab3 (
30683068
{
30693069
Query: "SELECT unix_timestamp(timestamp_col), unix_timestamp(datetime_col) from datetime_table",
30703070
Expected: []sql.Row{
3071-
{"86400.000000", "57600.000000"},
3071+
{"86400", "57600"},
30723072
},
30733073
},
30743074
},
@@ -5133,6 +5133,11 @@ CREATE TABLE tab3 (
51335133
Name: "UNIX_TIMESTAMP function preserves trailing 0s",
51345134
SetUpScript: []string{
51355135
"SET time_zone = '+07:00';",
5136+
"create table dt (dt0 datetime(0), dt1 datetime(1), dt2 datetime(2), dt3 datetime(3), dt4 datetime(4), dt5 datetime(5), dt6 datetime(6));",
5137+
"insert into dt values ('2020-01-02 12:34:56.123456', '2020-01-02 12:34:56.123456', '2020-01-02 12:34:56.123456', '2020-01-02 12:34:56.123456', '2020-01-02 12:34:56.123456', '2020-01-02 12:34:56.123456', '2020-01-02 12:34:56.123456')",
5138+
// TODO: time length not supported, so by default we have max precision
5139+
"create table t (d date, tt time);",
5140+
"insert into t values ('2020-01-02 12:34:56.123456', '12:34:56.123456');",
51365141
},
51375142
Assertions: []ScriptTestAssertion{
51385143
{
@@ -5153,6 +5158,18 @@ CREATE TABLE tab3 (
51535158
{"981178496.123457"},
51545159
},
51555160
},
5161+
{
5162+
Query: "select unix_timestamp(dt0), unix_timestamp(dt1), unix_timestamp(dt2), unix_timestamp(dt3), unix_timestamp(dt4), unix_timestamp(dt5), unix_timestamp(dt6) from dt;",
5163+
Expected: []sql.Row{
5164+
{"1577943296", "1577943296.1", "1577943296.12", "1577943296.123", "1577943296.1235", "1577943296.12346", "1577943296.123456"},
5165+
},
5166+
},
5167+
{
5168+
Query: "select unix_timestamp(d), unix_timestamp(tt) from t;",
5169+
Expected: []sql.Row{
5170+
{"1577898000", "1743140096.123456"},
5171+
},
5172+
},
51565173
},
51575174
},
51585175

sql/expression/convert.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"strings"
2222
"time"
2323

24+
"github.com/dolthub/vitess/go/sqltypes"
2425
"github.com/sirupsen/logrus"
2526
"gopkg.in/src-d/go-errors.v1"
2627

@@ -155,7 +156,7 @@ func (c *Convert) Type() sql.Type {
155156
case ConvertToDate:
156157
return types.Date
157158
case ConvertToDatetime:
158-
return types.DatetimeMaxPrecision
159+
return types.MustCreateDatetimeType(sqltypes.Datetime, c.typeLength)
159160
case ConvertToDecimal:
160161
if c.cachedDecimalType == nil {
161162
c.cachedDecimalType = createConvertedDecimalType(c.typeLength, c.typeScale, true)

sql/expression/function/date.go

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -405,19 +405,18 @@ var _ sql.CollationCoercible = (*UnixTimestamp)(nil)
405405

406406
const MaxUnixTimeMicroSecs = 32536771199999999
407407

408-
// noEval returns true if the expression contains an expression that cannot be evaluated without sql.Context or sql.Row.
409-
func noEval(expr sql.Expression) bool {
410-
var hasBadExpr bool
408+
// canEval returns if the expression contains an expression that cannot be evaluated without sql.Context or sql.Row.
409+
func canEval(expr sql.Expression) bool {
410+
evaluable := true
411411
transform.InspectExpr(expr, func(e sql.Expression) bool {
412412
switch e.(type) {
413-
case *expression.GetField:
414-
hasBadExpr = true
415-
case *ConvertTz:
416-
hasBadExpr = true
413+
case *expression.GetField, *ConvertTz:
414+
evaluable = false
415+
return true
417416
}
418-
return hasBadExpr
417+
return false
419418
})
420-
return hasBadExpr
419+
return evaluable
421420
}
422421

423422
func getNowExpr(expr sql.Expression) *Now {
@@ -436,7 +435,7 @@ func evalNowType(now *Now) sql.Type {
436435
if now.prec == nil {
437436
return types.Int64
438437
}
439-
if noEval(now.prec) {
438+
if !canEval(now.prec) {
440439
return types.MustCreateDecimalType(19, 6)
441440
}
442441
prec, pErr := now.prec.Eval(nil, nil)
@@ -463,7 +462,10 @@ func NewUnixTimestamp(args ...sql.Expression) (sql.Expression, error) {
463462
}
464463

465464
arg := args[0]
466-
if noEval(arg) {
465+
if dtType, isDtType := arg.Type().(sql.DatetimeType); isDtType {
466+
return &UnixTimestamp{Date: arg, typ: types.MustCreateDecimalType(19, uint8(dtType.Precision()))}, nil
467+
}
468+
if !canEval(arg) {
467469
return &UnixTimestamp{Date: arg, typ: types.MustCreateDecimalType(19, 6)}, nil
468470
}
469471
if now := getNowExpr(arg); now != nil {

sql/types/datetime.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,10 @@ func (t datetimeType) MustConvert(v interface{}) interface{} {
350350

351351
// Equals implements the Type interface.
352352
func (t datetimeType) Equals(otherType sql.Type) bool {
353-
return t.baseType == otherType.Type()
353+
if dtType, isDtType := otherType.(sql.DatetimeType); isDtType {
354+
return t.baseType == dtType.Type() && t.precision == dtType.Precision()
355+
}
356+
return false
354357
}
355358

356359
// MaxTextResponseByteLength implements the Type interface

0 commit comments

Comments
 (0)