From a609bb6a29dfdcae0648474d9881bf46d225a1da Mon Sep 17 00:00:00 2001 From: James Cor Date: Mon, 24 Mar 2025 12:01:36 -0700 Subject: [PATCH 1/9] special case for unix timestamp --- enginetest/queries/queries.go | 14 ++++++++++++++ sql/expression/function/date.go | 16 ++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/enginetest/queries/queries.go b/enginetest/queries/queries.go index 79d1192e2e..dfb6223520 100644 --- a/enginetest/queries/queries.go +++ b/enginetest/queries/queries.go @@ -10218,6 +10218,20 @@ from typestable`, {" └─ name: "}, }, }, + + // check that string timestamps preserve trailing 0s + { + Query: "select unix_timestamp('2001-02-03 12:34:56.10');", + Expected: []sql.Row{ + {"981228896.10"}, + }, + }, + { + Query: "select unix_timestamp('2001-02-03 12:34:56.000000');", + Expected: []sql.Row{ + {"981228896.000000"}, + }, + }, } var KeylessQueries = []QueryTest{ diff --git a/sql/expression/function/date.go b/sql/expression/function/date.go index 1d12893b05..d78cfcaf0f 100644 --- a/sql/expression/function/date.go +++ b/sql/expression/function/date.go @@ -476,6 +476,22 @@ func NewUnixTimestamp(args ...sql.Expression) (sql.Expression, error) { if err != nil || date == nil { return &UnixTimestamp{Date: arg}, nil } + // special case: text types with fractional seconds preserve scale + if types.IsText(arg.Type()) { + dateStr := date.(string) + idx := strings.Index(dateStr, ".") + if idx != -1 { + dateStr = strings.TrimSpace(dateStr[idx:]) + scale := uint8(len(dateStr) - 1) + if scale > 0 { + typ, tErr := types.CreateDecimalType(19, scale) + if tErr != nil { + return nil, tErr + } + return &UnixTimestamp{Date: arg, typ: typ}, nil + } + } + } date, _, err = types.DatetimeMaxPrecision.Convert(date) if err != nil { return &UnixTimestamp{Date: arg}, nil From 7788e7ee0625d84fd59ebf0fd193779791389e10 Mon Sep 17 00:00:00 2001 From: James Cor Date: Mon, 24 Mar 2025 12:07:13 -0700 Subject: [PATCH 2/9] more fixes --- enginetest/queries/queries.go | 6 ++++++ sql/expression/function/date.go | 3 +++ sql/types/datetime.go | 4 ++-- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/enginetest/queries/queries.go b/enginetest/queries/queries.go index dfb6223520..3277ed3926 100644 --- a/enginetest/queries/queries.go +++ b/enginetest/queries/queries.go @@ -10232,6 +10232,12 @@ from typestable`, {"981228896.000000"}, }, }, + { + Query: "select unix_timestamp('2001-02-03 12:34:56.1234567');", + Expected: []sql.Row{ + {"981228896.123457"}, + }, + }, } var KeylessQueries = []QueryTest{ diff --git a/sql/expression/function/date.go b/sql/expression/function/date.go index d78cfcaf0f..73b6751fc6 100644 --- a/sql/expression/function/date.go +++ b/sql/expression/function/date.go @@ -484,6 +484,9 @@ func NewUnixTimestamp(args ...sql.Expression) (sql.Expression, error) { dateStr = strings.TrimSpace(dateStr[idx:]) scale := uint8(len(dateStr) - 1) if scale > 0 { + if scale > 6 { + scale = 6 + } typ, tErr := types.CreateDecimalType(19, scale) if tErr != nil { return nil, tErr diff --git a/sql/types/datetime.go b/sql/types/datetime.go index 68f8f7db41..01813d87b8 100644 --- a/sql/types/datetime.go +++ b/sql/types/datetime.go @@ -198,10 +198,10 @@ func ConvertToTime(v interface{}, t datetimeType) (time.Time, error) { return zeroTime, nil } - // Truncate the date to the precision of this type + // Round the date to the precision of this type truncationDuration := time.Second truncationDuration /= time.Duration(precisionConversion[t.precision]) - res = res.Truncate(truncationDuration) + res = res.Round(truncationDuration) switch t.baseType { case sqltypes.Date: From 828e8dc1abda0a0ec0dd902a6ca612a0b605b95e Mon Sep 17 00:00:00 2001 From: James Cor Date: Mon, 24 Mar 2025 12:08:43 -0700 Subject: [PATCH 3/9] better comment --- sql/expression/function/date.go | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/expression/function/date.go b/sql/expression/function/date.go index 73b6751fc6..e2568b54f2 100644 --- a/sql/expression/function/date.go +++ b/sql/expression/function/date.go @@ -477,6 +477,7 @@ func NewUnixTimestamp(args ...sql.Expression) (sql.Expression, error) { return &UnixTimestamp{Date: arg}, nil } // special case: text types with fractional seconds preserve scale + // e.g. '2000-01-02 12:34:56.000' -> scale 3 if types.IsText(arg.Type()) { dateStr := date.(string) idx := strings.Index(dateStr, ".") From b3f90cab7ea9d3fdeb6485fbef7a817b6a07a5d9 Mon Sep 17 00:00:00 2001 From: jycor Date: Mon, 24 Mar 2025 19:08:44 +0000 Subject: [PATCH 4/9] [ga-format-pr] Run ./format_repo.sh to fix formatting --- enginetest/queries/queries.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/enginetest/queries/queries.go b/enginetest/queries/queries.go index 3277ed3926..30ec6be6cb 100644 --- a/enginetest/queries/queries.go +++ b/enginetest/queries/queries.go @@ -10221,19 +10221,19 @@ from typestable`, // check that string timestamps preserve trailing 0s { - Query: "select unix_timestamp('2001-02-03 12:34:56.10');", + Query: "select unix_timestamp('2001-02-03 12:34:56.10');", Expected: []sql.Row{ {"981228896.10"}, }, }, { - Query: "select unix_timestamp('2001-02-03 12:34:56.000000');", + Query: "select unix_timestamp('2001-02-03 12:34:56.000000');", Expected: []sql.Row{ {"981228896.000000"}, }, }, { - Query: "select unix_timestamp('2001-02-03 12:34:56.1234567');", + Query: "select unix_timestamp('2001-02-03 12:34:56.1234567');", Expected: []sql.Row{ {"981228896.123457"}, }, From cc3e577fdece5517942e2b86711d7f79dab14346 Mon Sep 17 00:00:00 2001 From: James Cor Date: Mon, 24 Mar 2025 12:35:59 -0700 Subject: [PATCH 5/9] fix tests --- enginetest/queries/queries.go | 2 +- sql/types/datetime_test.go | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/enginetest/queries/queries.go b/enginetest/queries/queries.go index 30ec6be6cb..71648bbf11 100644 --- a/enginetest/queries/queries.go +++ b/enginetest/queries/queries.go @@ -799,7 +799,7 @@ var QueryTests = []QueryTest{ { // Assert that SYSDATE() returns different times on each call in a query (unlike NOW()) // Using the maximum precision for fractional seconds, lets us see a difference. - Query: "select now() = sysdate(), sleep(0.1), now(6) < sysdate(6);", + Query: "select now() = sysdate(), sleep(0.5), now(6) < sysdate(6);", Expected: []sql.Row{{true, 0, true}}, }, { diff --git a/sql/types/datetime_test.go b/sql/types/datetime_test.go index 5847df728e..df61f35f49 100644 --- a/sql/types/datetime_test.go +++ b/sql/types/datetime_test.go @@ -57,7 +57,7 @@ func TestDatetimeCompare(t *testing.T) { {DatetimeMaxPrecision, "2010-06-03 06:03:11.123456111", "2010-06-03 06:03:11.123456333", 0}, {MustCreateDatetimeType(sqltypes.Datetime, 3), "2010-06-03 06:03:11.123", "2010-06-03 06:03:11", 1}, {MustCreateDatetimeType(sqltypes.Datetime, 3), "2010-06-03 06:03:11", "2010-06-03 06:03:11.123", -1}, - {MustCreateDatetimeType(sqltypes.Datetime, 3), "2010-06-03 06:03:11.123456", "2010-06-03 06:03:11.123789", 0}, + {MustCreateDatetimeType(sqltypes.Datetime, 3), "2010-06-03 06:03:11.123456", "2010-06-03 06:03:11.123789", -1}, {Timestamp, time.Date(2012, 12, 12, 12, 12, 12, 12, time.UTC), time.Date(2012, 12, 12, 12, 24, 24, 24, time.UTC), -1}, {Timestamp, time.Date(2012, 12, 12, 12, 12, 12, 12, time.UTC), @@ -219,9 +219,9 @@ func TestDatetimeConvert(t *testing.T) { time.Date(2012, 12, 12, 12, 12, 12, 0, time.UTC), false}, {Datetime, "2010-06-03 12:12:12.123456", time.Date(2010, 6, 3, 12, 12, 12, 0, time.UTC), false}, {Datetime, "2010-06-03T12:12:12.123456Z", time.Date(2010, 6, 3, 12, 12, 12, 0, time.UTC), false}, - {Datetime, "2010-06-03 12:34:56.7", time.Date(2010, 6, 3, 12, 34, 56, 0, time.UTC), false}, - {Datetime, "2010-06-03 12:34:56.78", time.Date(2010, 6, 3, 12, 34, 56, 0, time.UTC), false}, - {Datetime, "2010-06-03 12:34:56.789", time.Date(2010, 6, 3, 12, 34, 56, 0, time.UTC), false}, + {Datetime, "2010-06-03 12:34:56.7", time.Date(2010, 6, 3, 12, 34, 57, 0, time.UTC), false}, + {Datetime, "2010-06-03 12:34:56.78", time.Date(2010, 6, 3, 12, 34, 57, 0, time.UTC), false}, + {Datetime, "2010-06-03 12:34:56.789", time.Date(2010, 6, 3, 12, 34, 57, 0, time.UTC), false}, {TimestampMaxPrecision, nil, nil, false}, {TimestampMaxPrecision, time.Date(2012, 12, 12, 12, 12, 12, 12, time.UTC), @@ -258,9 +258,9 @@ func TestDatetimeConvert(t *testing.T) { time.Date(2012, 12, 12, 12, 12, 12, 0, time.UTC), false}, {Timestamp, "2010-06-03 12:12:12.123456", time.Date(2010, 6, 3, 12, 12, 12, 0, time.UTC), false}, {Timestamp, "2010-06-03T12:12:12.123456Z", time.Date(2010, 6, 3, 12, 12, 12, 0, time.UTC), false}, - {Timestamp, "2010-06-03 12:34:56.7", time.Date(2010, 6, 3, 12, 34, 56, 0, time.UTC), false}, - {Timestamp, "2010-06-03 12:34:56.78", time.Date(2010, 6, 3, 12, 34, 56, 0, time.UTC), false}, - {Timestamp, "2010-06-03 12:34:56.789", time.Date(2010, 6, 3, 12, 34, 56, 0, time.UTC), false}, + {Timestamp, "2010-06-03 12:34:56.7", time.Date(2010, 6, 3, 12, 34, 57, 0, time.UTC), false}, + {Timestamp, "2010-06-03 12:34:56.78", time.Date(2010, 6, 3, 12, 34, 57, 0, time.UTC), false}, + {Timestamp, "2010-06-03 12:34:56.789", time.Date(2010, 6, 3, 12, 34, 57, 0, time.UTC), false}, {Date, "0000-01-01 00:00:00", time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC), false}, {Date, "0500-01-01 00:00:00", time.Date(500, 1, 1, 0, 0, 0, 0, time.UTC), false}, From 6cfcdd3af29c00dc8609efd30c68e03caea573a2 Mon Sep 17 00:00:00 2001 From: James Cor Date: Mon, 24 Mar 2025 13:01:03 -0700 Subject: [PATCH 6/9] fix more tests --- enginetest/queries/queries.go | 20 -------------------- enginetest/queries/script_queries.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/enginetest/queries/queries.go b/enginetest/queries/queries.go index 71648bbf11..421b28263f 100644 --- a/enginetest/queries/queries.go +++ b/enginetest/queries/queries.go @@ -10218,26 +10218,6 @@ from typestable`, {" └─ name: "}, }, }, - - // check that string timestamps preserve trailing 0s - { - Query: "select unix_timestamp('2001-02-03 12:34:56.10');", - Expected: []sql.Row{ - {"981228896.10"}, - }, - }, - { - Query: "select unix_timestamp('2001-02-03 12:34:56.000000');", - Expected: []sql.Row{ - {"981228896.000000"}, - }, - }, - { - Query: "select unix_timestamp('2001-02-03 12:34:56.1234567');", - Expected: []sql.Row{ - {"981228896.123457"}, - }, - }, } var KeylessQueries = []QueryTest{ diff --git a/enginetest/queries/script_queries.go b/enginetest/queries/script_queries.go index 991b04df7b..a5279d73bf 100644 --- a/enginetest/queries/script_queries.go +++ b/enginetest/queries/script_queries.go @@ -5128,6 +5128,34 @@ CREATE TABLE tab3 ( }, }, }, + { + Dialect: "mysql", + Name: "UNIX_TIMESTAMP function preserves trailing 0s", + SetUpScript: []string{ + "SET time_zone = '+07:00';", + }, + Assertions: []ScriptTestAssertion{ + { + Query: "select unix_timestamp('2001-02-03 12:34:56.10');", + Expected: []sql.Row{ + {"981178496.10"}, + }, + }, + { + Query: "select unix_timestamp('2001-02-03 12:34:56.000000');", + Expected: []sql.Row{ + {"981178496.000000"}, + }, + }, + { + Query: "select unix_timestamp('2001-02-03 12:34:56.1234567');", + Expected: []sql.Row{ + {"981178496.123457"}, + }, + }, + }, + }, + { Name: "Querying existing view that references non-existing table", SetUpScript: []string{ From 145c7acd9d09d20a98ba980b440e93023eb7e2d5 Mon Sep 17 00:00:00 2001 From: jycor Date: Mon, 24 Mar 2025 20:02:27 +0000 Subject: [PATCH 7/9] [ga-format-pr] Run ./format_repo.sh to fix formatting --- enginetest/queries/script_queries.go | 36 ++++++++++++++-------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/enginetest/queries/script_queries.go b/enginetest/queries/script_queries.go index a5279d73bf..1956b88f35 100644 --- a/enginetest/queries/script_queries.go +++ b/enginetest/queries/script_queries.go @@ -5135,24 +5135,24 @@ CREATE TABLE tab3 ( "SET time_zone = '+07:00';", }, Assertions: []ScriptTestAssertion{ - { - Query: "select unix_timestamp('2001-02-03 12:34:56.10');", - Expected: []sql.Row{ - {"981178496.10"}, - }, - }, - { - Query: "select unix_timestamp('2001-02-03 12:34:56.000000');", - Expected: []sql.Row{ - {"981178496.000000"}, - }, - }, - { - Query: "select unix_timestamp('2001-02-03 12:34:56.1234567');", - Expected: []sql.Row{ - {"981178496.123457"}, - }, - }, + { + Query: "select unix_timestamp('2001-02-03 12:34:56.10');", + Expected: []sql.Row{ + {"981178496.10"}, + }, + }, + { + Query: "select unix_timestamp('2001-02-03 12:34:56.000000');", + Expected: []sql.Row{ + {"981178496.000000"}, + }, + }, + { + Query: "select unix_timestamp('2001-02-03 12:34:56.1234567');", + Expected: []sql.Row{ + {"981178496.123457"}, + }, + }, }, }, From 270ff2a0c99934ad119731e86ffae000f3dfe9b7 Mon Sep 17 00:00:00 2001 From: James Cor Date: Mon, 24 Mar 2025 13:16:55 -0700 Subject: [PATCH 8/9] fix microsecond --- sql/expression/function/time_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sql/expression/function/time_test.go b/sql/expression/function/time_test.go index e96241c204..0a8b8e5893 100644 --- a/sql/expression/function/time_test.go +++ b/sql/expression/function/time_test.go @@ -16,7 +16,8 @@ package function import ( "fmt" - "testing" + "math" +"testing" "time" "github.com/stretchr/testify/assert" @@ -377,7 +378,7 @@ func TestTime_Microsecond(t *testing.T) { {"null date", sql.NewRow(nil), nil, false}, {"invalid type", sql.NewRow([]byte{0, 1, 2}), nil, true}, {"date as string", sql.NewRow(stringDate), uint64(0), false}, - {"date as time", sql.NewRow(currTime), uint64(currTime.Nanosecond()) / uint64(time.Microsecond), false}, + {"date as time", sql.NewRow(currTime), uint64(math.Round(float64(currTime.Nanosecond()) / float64(time.Microsecond))), false}, } for _, tt := range testCases { From 3ab6cd6694fb0413958f8a65ca557a6efe4aa7de Mon Sep 17 00:00:00 2001 From: jycor Date: Mon, 24 Mar 2025 20:19:33 +0000 Subject: [PATCH 9/9] [ga-format-pr] Run ./format_repo.sh to fix formatting --- sql/expression/function/time_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/expression/function/time_test.go b/sql/expression/function/time_test.go index 0a8b8e5893..985907b1d0 100644 --- a/sql/expression/function/time_test.go +++ b/sql/expression/function/time_test.go @@ -17,7 +17,7 @@ package function import ( "fmt" "math" -"testing" + "testing" "time" "github.com/stretchr/testify/assert"