Skip to content

Commit ddeab07

Browse files
authored
special case for unix_timestamp (#2907)
1 parent 33b112f commit ddeab07

File tree

6 files changed

+60
-11
lines changed

6 files changed

+60
-11
lines changed

enginetest/queries/queries.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -799,7 +799,7 @@ var QueryTests = []QueryTest{
799799
{
800800
// Assert that SYSDATE() returns different times on each call in a query (unlike NOW())
801801
// Using the maximum precision for fractional seconds, lets us see a difference.
802-
Query: "select now() = sysdate(), sleep(0.1), now(6) < sysdate(6);",
802+
Query: "select now() = sysdate(), sleep(0.5), now(6) < sysdate(6);",
803803
Expected: []sql.Row{{true, 0, true}},
804804
},
805805
{

enginetest/queries/script_queries.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5128,6 +5128,34 @@ CREATE TABLE tab3 (
51285128
},
51295129
},
51305130
},
5131+
{
5132+
Dialect: "mysql",
5133+
Name: "UNIX_TIMESTAMP function preserves trailing 0s",
5134+
SetUpScript: []string{
5135+
"SET time_zone = '+07:00';",
5136+
},
5137+
Assertions: []ScriptTestAssertion{
5138+
{
5139+
Query: "select unix_timestamp('2001-02-03 12:34:56.10');",
5140+
Expected: []sql.Row{
5141+
{"981178496.10"},
5142+
},
5143+
},
5144+
{
5145+
Query: "select unix_timestamp('2001-02-03 12:34:56.000000');",
5146+
Expected: []sql.Row{
5147+
{"981178496.000000"},
5148+
},
5149+
},
5150+
{
5151+
Query: "select unix_timestamp('2001-02-03 12:34:56.1234567');",
5152+
Expected: []sql.Row{
5153+
{"981178496.123457"},
5154+
},
5155+
},
5156+
},
5157+
},
5158+
51315159
{
51325160
Name: "Querying existing view that references non-existing table",
51335161
SetUpScript: []string{

sql/expression/function/date.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,26 @@ func NewUnixTimestamp(args ...sql.Expression) (sql.Expression, error) {
476476
if err != nil || date == nil {
477477
return &UnixTimestamp{Date: arg}, nil
478478
}
479+
// special case: text types with fractional seconds preserve scale
480+
// e.g. '2000-01-02 12:34:56.000' -> scale 3
481+
if types.IsText(arg.Type()) {
482+
dateStr := date.(string)
483+
idx := strings.Index(dateStr, ".")
484+
if idx != -1 {
485+
dateStr = strings.TrimSpace(dateStr[idx:])
486+
scale := uint8(len(dateStr) - 1)
487+
if scale > 0 {
488+
if scale > 6 {
489+
scale = 6
490+
}
491+
typ, tErr := types.CreateDecimalType(19, scale)
492+
if tErr != nil {
493+
return nil, tErr
494+
}
495+
return &UnixTimestamp{Date: arg, typ: typ}, nil
496+
}
497+
}
498+
}
479499
date, _, err = types.DatetimeMaxPrecision.Convert(date)
480500
if err != nil {
481501
return &UnixTimestamp{Date: arg}, nil

sql/expression/function/time_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package function
1616

1717
import (
1818
"fmt"
19+
"math"
1920
"testing"
2021
"time"
2122

@@ -377,7 +378,7 @@ func TestTime_Microsecond(t *testing.T) {
377378
{"null date", sql.NewRow(nil), nil, false},
378379
{"invalid type", sql.NewRow([]byte{0, 1, 2}), nil, true},
379380
{"date as string", sql.NewRow(stringDate), uint64(0), false},
380-
{"date as time", sql.NewRow(currTime), uint64(currTime.Nanosecond()) / uint64(time.Microsecond), false},
381+
{"date as time", sql.NewRow(currTime), uint64(math.Round(float64(currTime.Nanosecond()) / float64(time.Microsecond))), false},
381382
}
382383

383384
for _, tt := range testCases {

sql/types/datetime.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,10 +198,10 @@ func ConvertToTime(v interface{}, t datetimeType) (time.Time, error) {
198198
return zeroTime, nil
199199
}
200200

201-
// Truncate the date to the precision of this type
201+
// Round the date to the precision of this type
202202
truncationDuration := time.Second
203203
truncationDuration /= time.Duration(precisionConversion[t.precision])
204-
res = res.Truncate(truncationDuration)
204+
res = res.Round(truncationDuration)
205205

206206
switch t.baseType {
207207
case sqltypes.Date:

sql/types/datetime_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ func TestDatetimeCompare(t *testing.T) {
5757
{DatetimeMaxPrecision, "2010-06-03 06:03:11.123456111", "2010-06-03 06:03:11.123456333", 0},
5858
{MustCreateDatetimeType(sqltypes.Datetime, 3), "2010-06-03 06:03:11.123", "2010-06-03 06:03:11", 1},
5959
{MustCreateDatetimeType(sqltypes.Datetime, 3), "2010-06-03 06:03:11", "2010-06-03 06:03:11.123", -1},
60-
{MustCreateDatetimeType(sqltypes.Datetime, 3), "2010-06-03 06:03:11.123456", "2010-06-03 06:03:11.123789", 0},
60+
{MustCreateDatetimeType(sqltypes.Datetime, 3), "2010-06-03 06:03:11.123456", "2010-06-03 06:03:11.123789", -1},
6161
{Timestamp, time.Date(2012, 12, 12, 12, 12, 12, 12, time.UTC),
6262
time.Date(2012, 12, 12, 12, 24, 24, 24, time.UTC), -1},
6363
{Timestamp, time.Date(2012, 12, 12, 12, 12, 12, 12, time.UTC),
@@ -219,9 +219,9 @@ func TestDatetimeConvert(t *testing.T) {
219219
time.Date(2012, 12, 12, 12, 12, 12, 0, time.UTC), false},
220220
{Datetime, "2010-06-03 12:12:12.123456", time.Date(2010, 6, 3, 12, 12, 12, 0, time.UTC), false},
221221
{Datetime, "2010-06-03T12:12:12.123456Z", time.Date(2010, 6, 3, 12, 12, 12, 0, time.UTC), false},
222-
{Datetime, "2010-06-03 12:34:56.7", time.Date(2010, 6, 3, 12, 34, 56, 0, time.UTC), false},
223-
{Datetime, "2010-06-03 12:34:56.78", time.Date(2010, 6, 3, 12, 34, 56, 0, time.UTC), false},
224-
{Datetime, "2010-06-03 12:34:56.789", time.Date(2010, 6, 3, 12, 34, 56, 0, time.UTC), false},
222+
{Datetime, "2010-06-03 12:34:56.7", time.Date(2010, 6, 3, 12, 34, 57, 0, time.UTC), false},
223+
{Datetime, "2010-06-03 12:34:56.78", time.Date(2010, 6, 3, 12, 34, 57, 0, time.UTC), false},
224+
{Datetime, "2010-06-03 12:34:56.789", time.Date(2010, 6, 3, 12, 34, 57, 0, time.UTC), false},
225225

226226
{TimestampMaxPrecision, nil, nil, false},
227227
{TimestampMaxPrecision, time.Date(2012, 12, 12, 12, 12, 12, 12, time.UTC),
@@ -258,9 +258,9 @@ func TestDatetimeConvert(t *testing.T) {
258258
time.Date(2012, 12, 12, 12, 12, 12, 0, time.UTC), false},
259259
{Timestamp, "2010-06-03 12:12:12.123456", time.Date(2010, 6, 3, 12, 12, 12, 0, time.UTC), false},
260260
{Timestamp, "2010-06-03T12:12:12.123456Z", time.Date(2010, 6, 3, 12, 12, 12, 0, time.UTC), false},
261-
{Timestamp, "2010-06-03 12:34:56.7", time.Date(2010, 6, 3, 12, 34, 56, 0, time.UTC), false},
262-
{Timestamp, "2010-06-03 12:34:56.78", time.Date(2010, 6, 3, 12, 34, 56, 0, time.UTC), false},
263-
{Timestamp, "2010-06-03 12:34:56.789", time.Date(2010, 6, 3, 12, 34, 56, 0, time.UTC), false},
261+
{Timestamp, "2010-06-03 12:34:56.7", time.Date(2010, 6, 3, 12, 34, 57, 0, time.UTC), false},
262+
{Timestamp, "2010-06-03 12:34:56.78", time.Date(2010, 6, 3, 12, 34, 57, 0, time.UTC), false},
263+
{Timestamp, "2010-06-03 12:34:56.789", time.Date(2010, 6, 3, 12, 34, 57, 0, time.UTC), false},
264264

265265
{Date, "0000-01-01 00:00:00", time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC), false},
266266
{Date, "0500-01-01 00:00:00", time.Date(500, 1, 1, 0, 0, 0, 0, time.UTC), false},

0 commit comments

Comments
 (0)