diff --git a/enginetest/queries/queries.go b/enginetest/queries/queries.go index 59c09b1f79..0dfb832220 100644 --- a/enginetest/queries/queries.go +++ b/enginetest/queries/queries.go @@ -4246,53 +4246,45 @@ SELECT * FROM cte WHERE d = 2;`, Expected: []sql.Row{{time.Date(2020, time.January, 1, 12, 34, 56, 0, time.UTC)}}, }, { - // TODO: implement precision for datetime casting - Skip: true, Query: "select cast('2020-01-01 12:34:56.123456abc' as datetime(1));", ExpectedWarning: 1292, ExpectedWarningsCount: 1, Expected: []sql.Row{{time.Date(2020, time.January, 1, 12, 34, 56, 100000000, time.UTC)}}, }, { - // TODO: implement precision for datetime casting - Skip: true, Query: "select cast('2020-01-01 12:34:56.123456abc' as datetime(2));", ExpectedWarning: 1292, ExpectedWarningsCount: 1, Expected: []sql.Row{{time.Date(2020, time.January, 1, 12, 34, 56, 120000000, time.UTC)}}, }, { - // TODO: implement precision for datetime casting - Skip: true, Query: "select cast('2020-01-01 12:34:56.123456abc' as datetime(3));", ExpectedWarning: 1292, ExpectedWarningsCount: 1, Expected: []sql.Row{{time.Date(2020, time.January, 1, 12, 34, 56, 123000000, time.UTC)}}, }, { - // TODO: implement precision for datetime casting - Skip: true, Query: "select cast('2020-01-01 12:34:56.123456abc' as datetime(4));", ExpectedWarning: 1292, ExpectedWarningsCount: 1, Expected: []sql.Row{{time.Date(2020, time.January, 1, 12, 34, 56, 123500000, time.UTC)}}, }, { - // TODO: implement precision for datetime casting - Skip: true, Query: "select cast('2020-01-01 12:34:56.123456abc' as datetime(5));", ExpectedWarning: 1292, ExpectedWarningsCount: 1, Expected: []sql.Row{{time.Date(2020, time.January, 1, 12, 34, 56, 123460000, time.UTC)}}, }, { - // TODO: implement precision for datetime casting - Skip: true, Query: "select cast('2020-01-01 12:34:56.123456abc' as datetime(6));", ExpectedWarning: 1292, ExpectedWarningsCount: 1, Expected: []sql.Row{{time.Date(2020, time.January, 1, 12, 34, 56, 123456000, time.UTC)}}, }, + { + Query: "select cast('2020-01-01 12:34:56.123456' as datetime(6)) > cast('2020-01-01 12:34:56' as datetime)", + Expected: []sql.Row{{true}}, + }, { Query: `SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM othertable) othertable_one) othertable_two) othertable_three WHERE s2 = 'first'`, Expected: []sql.Row{ diff --git a/sql/expression/comparison.go b/sql/expression/comparison.go index 97e5f4ba6e..e7cb0b8e15 100644 --- a/sql/expression/comparison.go +++ b/sql/expression/comparison.go @@ -226,7 +226,6 @@ func (c *comparison) castLeftAndRight(ctx *sql.Context, left, right interface{}) if err != nil { return nil, nil, nil, err } - return l, r, types.DatetimeMaxPrecision, nil } @@ -302,12 +301,16 @@ func (c *comparison) castLeftAndRight(ctx *sql.Context, left, right interface{}) } func convertLeftAndRight(ctx *sql.Context, left, right interface{}, convertTo string) (interface{}, interface{}, error) { - l, err := convertValue(ctx, left, convertTo, nil, 0, 0) + typeLength := 0 + if convertTo == ConvertToDatetime { + typeLength = types.MaxDatetimePrecision + } + l, err := convertValue(ctx, left, convertTo, nil, typeLength, 0) if err != nil { return nil, nil, err } - r, err := convertValue(ctx, right, convertTo, nil, 0, 0) + r, err := convertValue(ctx, right, convertTo, nil, typeLength, 0) if err != nil { return nil, nil, err } diff --git a/sql/expression/convert.go b/sql/expression/convert.go index 7cfa69ee25..9d5d7af6bd 100644 --- a/sql/expression/convert.go +++ b/sql/expression/convert.go @@ -341,7 +341,7 @@ func convertValue(ctx *sql.Context, val interface{}, castTo string, originType s if !(isTime || isString || isBinary) { return nil, nil } - d, _, err := types.DatetimeDefaultPrecision.Convert(ctx, val) + d, _, err := types.MustCreateDatetimeType(sqltypes.Datetime, typeLength).Convert(ctx, val) if err != nil { if !sql.ErrTruncatedIncorrect.Is(err) { return nil, err diff --git a/sql/types/datetime.go b/sql/types/datetime.go index 60d87b6ad6..387956f0fb 100644 --- a/sql/types/datetime.go +++ b/sql/types/datetime.go @@ -36,6 +36,8 @@ const ZeroTimestampDatetimeStr = "0000-00-00 00:00:00" const MinDatetimeStringLength = 8 // length of "2000-1-1" +const MaxDatetimePrecision = 6 + var ( // ErrConvertingToTime is thrown when a value cannot be converted to a Time ErrConvertingToTime = errors.NewKind("Incorrect datetime value: '%v'") @@ -102,16 +104,14 @@ var ( Date = MustCreateDatetimeType(sqltypes.Date, 0) // Datetime is a date and a time with default precision (no fractional seconds). Datetime = MustCreateDatetimeType(sqltypes.Datetime, 0) - // DatetimeDefaultPrecision is a date and a time without a specified precision - DatetimeDefaultPrecision = MustCreateDatetimeType(sqltypes.Datetime, 0) // DatetimeMaxPrecision is a date and a time with maximum precision - DatetimeMaxPrecision = MustCreateDatetimeType(sqltypes.Datetime, 6) + DatetimeMaxPrecision = MustCreateDatetimeType(sqltypes.Datetime, MaxDatetimePrecision) // Timestamp is a UNIX timestamp with default precision (no fractional seconds). Timestamp = MustCreateDatetimeType(sqltypes.Timestamp, 0) // TimestampMaxPrecision is a UNIX timestamp with maximum precision - TimestampMaxPrecision = MustCreateDatetimeType(sqltypes.Timestamp, 6) + TimestampMaxPrecision = MustCreateDatetimeType(sqltypes.Timestamp, MaxDatetimePrecision) // DatetimeMaxRange is a date and a time with maximum precision and maximum range. - DatetimeMaxRange = MustCreateDatetimeType(sqltypes.Datetime, 6) + DatetimeMaxRange = MustCreateDatetimeType(sqltypes.Datetime, MaxDatetimePrecision) datetimeValueType = reflect.TypeOf(time.Time{}) ) @@ -128,7 +128,7 @@ var _ sql.CollationCoercible = datetimeType{} func CreateDatetimeType(baseType query.Type, precision int) (sql.DatetimeType, error) { switch baseType { case sqltypes.Date, sqltypes.Datetime, sqltypes.Timestamp: - if precision < 0 || precision > 6 { + if precision < 0 || precision > MaxDatetimePrecision { return nil, fmt.Errorf("precision must be between 0 and 6, got %d", precision) } return datetimeType{ @@ -221,7 +221,7 @@ func ConvertToTime(ctx context.Context, v interface{}, t datetimeType) (time.Tim } // Round the date to the precision of this type - if t.precision < 6 { + if t.precision < MaxDatetimePrecision { truncationDuration := time.Second / time.Duration(precisionConversion[t.precision]) res = res.Round(truncationDuration) } else {