Skip to content

Commit 70b084e

Browse files
authored
Merge pull request #3278 from dolthub/angela/datetime
Respect precision when casting to datetime
2 parents f7aa133 + 62efe69 commit 70b084e

File tree

4 files changed

+18
-23
lines changed

4 files changed

+18
-23
lines changed

enginetest/queries/queries.go

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4246,53 +4246,45 @@ SELECT * FROM cte WHERE d = 2;`,
42464246
Expected: []sql.Row{{time.Date(2020, time.January, 1, 12, 34, 56, 0, time.UTC)}},
42474247
},
42484248
{
4249-
// TODO: implement precision for datetime casting
4250-
Skip: true,
42514249
Query: "select cast('2020-01-01 12:34:56.123456abc' as datetime(1));",
42524250
ExpectedWarning: 1292,
42534251
ExpectedWarningsCount: 1,
42544252
Expected: []sql.Row{{time.Date(2020, time.January, 1, 12, 34, 56, 100000000, time.UTC)}},
42554253
},
42564254
{
4257-
// TODO: implement precision for datetime casting
4258-
Skip: true,
42594255
Query: "select cast('2020-01-01 12:34:56.123456abc' as datetime(2));",
42604256
ExpectedWarning: 1292,
42614257
ExpectedWarningsCount: 1,
42624258
Expected: []sql.Row{{time.Date(2020, time.January, 1, 12, 34, 56, 120000000, time.UTC)}},
42634259
},
42644260
{
4265-
// TODO: implement precision for datetime casting
4266-
Skip: true,
42674261
Query: "select cast('2020-01-01 12:34:56.123456abc' as datetime(3));",
42684262
ExpectedWarning: 1292,
42694263
ExpectedWarningsCount: 1,
42704264
Expected: []sql.Row{{time.Date(2020, time.January, 1, 12, 34, 56, 123000000, time.UTC)}},
42714265
},
42724266
{
4273-
// TODO: implement precision for datetime casting
4274-
Skip: true,
42754267
Query: "select cast('2020-01-01 12:34:56.123456abc' as datetime(4));",
42764268
ExpectedWarning: 1292,
42774269
ExpectedWarningsCount: 1,
42784270
Expected: []sql.Row{{time.Date(2020, time.January, 1, 12, 34, 56, 123500000, time.UTC)}},
42794271
},
42804272
{
4281-
// TODO: implement precision for datetime casting
4282-
Skip: true,
42834273
Query: "select cast('2020-01-01 12:34:56.123456abc' as datetime(5));",
42844274
ExpectedWarning: 1292,
42854275
ExpectedWarningsCount: 1,
42864276
Expected: []sql.Row{{time.Date(2020, time.January, 1, 12, 34, 56, 123460000, time.UTC)}},
42874277
},
42884278
{
4289-
// TODO: implement precision for datetime casting
4290-
Skip: true,
42914279
Query: "select cast('2020-01-01 12:34:56.123456abc' as datetime(6));",
42924280
ExpectedWarning: 1292,
42934281
ExpectedWarningsCount: 1,
42944282
Expected: []sql.Row{{time.Date(2020, time.January, 1, 12, 34, 56, 123456000, time.UTC)}},
42954283
},
4284+
{
4285+
Query: "select cast('2020-01-01 12:34:56.123456' as datetime(6)) > cast('2020-01-01 12:34:56' as datetime)",
4286+
Expected: []sql.Row{{true}},
4287+
},
42964288
{
42974289
Query: `SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM othertable) othertable_one) othertable_two) othertable_three WHERE s2 = 'first'`,
42984290
Expected: []sql.Row{

sql/expression/comparison.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,6 @@ func (c *comparison) castLeftAndRight(ctx *sql.Context, left, right interface{})
226226
if err != nil {
227227
return nil, nil, nil, err
228228
}
229-
230229
return l, r, types.DatetimeMaxPrecision, nil
231230
}
232231

@@ -302,12 +301,16 @@ func (c *comparison) castLeftAndRight(ctx *sql.Context, left, right interface{})
302301
}
303302

304303
func convertLeftAndRight(ctx *sql.Context, left, right interface{}, convertTo string) (interface{}, interface{}, error) {
305-
l, err := convertValue(ctx, left, convertTo, nil, 0, 0)
304+
typeLength := 0
305+
if convertTo == ConvertToDatetime {
306+
typeLength = types.MaxDatetimePrecision
307+
}
308+
l, err := convertValue(ctx, left, convertTo, nil, typeLength, 0)
306309
if err != nil {
307310
return nil, nil, err
308311
}
309312

310-
r, err := convertValue(ctx, right, convertTo, nil, 0, 0)
313+
r, err := convertValue(ctx, right, convertTo, nil, typeLength, 0)
311314
if err != nil {
312315
return nil, nil, err
313316
}

sql/expression/convert.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ func convertValue(ctx *sql.Context, val interface{}, castTo string, originType s
341341
if !(isTime || isString || isBinary) {
342342
return nil, nil
343343
}
344-
d, _, err := types.DatetimeDefaultPrecision.Convert(ctx, val)
344+
d, _, err := types.MustCreateDatetimeType(sqltypes.Datetime, typeLength).Convert(ctx, val)
345345
if err != nil {
346346
if !sql.ErrTruncatedIncorrect.Is(err) {
347347
return nil, err

sql/types/datetime.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ const ZeroTimestampDatetimeStr = "0000-00-00 00:00:00"
3636

3737
const MinDatetimeStringLength = 8 // length of "2000-1-1"
3838

39+
const MaxDatetimePrecision = 6
40+
3941
var (
4042
// ErrConvertingToTime is thrown when a value cannot be converted to a Time
4143
ErrConvertingToTime = errors.NewKind("Incorrect datetime value: '%v'")
@@ -102,16 +104,14 @@ var (
102104
Date = MustCreateDatetimeType(sqltypes.Date, 0)
103105
// Datetime is a date and a time with default precision (no fractional seconds).
104106
Datetime = MustCreateDatetimeType(sqltypes.Datetime, 0)
105-
// DatetimeDefaultPrecision is a date and a time without a specified precision
106-
DatetimeDefaultPrecision = MustCreateDatetimeType(sqltypes.Datetime, 0)
107107
// DatetimeMaxPrecision is a date and a time with maximum precision
108-
DatetimeMaxPrecision = MustCreateDatetimeType(sqltypes.Datetime, 6)
108+
DatetimeMaxPrecision = MustCreateDatetimeType(sqltypes.Datetime, MaxDatetimePrecision)
109109
// Timestamp is a UNIX timestamp with default precision (no fractional seconds).
110110
Timestamp = MustCreateDatetimeType(sqltypes.Timestamp, 0)
111111
// TimestampMaxPrecision is a UNIX timestamp with maximum precision
112-
TimestampMaxPrecision = MustCreateDatetimeType(sqltypes.Timestamp, 6)
112+
TimestampMaxPrecision = MustCreateDatetimeType(sqltypes.Timestamp, MaxDatetimePrecision)
113113
// DatetimeMaxRange is a date and a time with maximum precision and maximum range.
114-
DatetimeMaxRange = MustCreateDatetimeType(sqltypes.Datetime, 6)
114+
DatetimeMaxRange = MustCreateDatetimeType(sqltypes.Datetime, MaxDatetimePrecision)
115115

116116
datetimeValueType = reflect.TypeOf(time.Time{})
117117
)
@@ -128,7 +128,7 @@ var _ sql.CollationCoercible = datetimeType{}
128128
func CreateDatetimeType(baseType query.Type, precision int) (sql.DatetimeType, error) {
129129
switch baseType {
130130
case sqltypes.Date, sqltypes.Datetime, sqltypes.Timestamp:
131-
if precision < 0 || precision > 6 {
131+
if precision < 0 || precision > MaxDatetimePrecision {
132132
return nil, fmt.Errorf("precision must be between 0 and 6, got %d", precision)
133133
}
134134
return datetimeType{
@@ -221,7 +221,7 @@ func ConvertToTime(ctx context.Context, v interface{}, t datetimeType) (time.Tim
221221
}
222222

223223
// Round the date to the precision of this type
224-
if t.precision < 6 {
224+
if t.precision < MaxDatetimePrecision {
225225
truncationDuration := time.Second / time.Duration(precisionConversion[t.precision])
226226
res = res.Round(truncationDuration)
227227
} else {

0 commit comments

Comments
 (0)