Skip to content

Commit d1ff450

Browse files
authored
SQL: Fix casting from date to numeric type to use millis (elastic#37869)
Previously casting from a DATE[TIME] type to a numeric (DOUBLE, LONG, INT, etc. used seconds instead of the epoch millis. Fixes: elastic#37655
1 parent eb7bf16 commit d1ff450

File tree

3 files changed

+77
-36
lines changed

3 files changed

+77
-36
lines changed

x-pack/plugin/sql/qa/src/main/resources/datetime.csv-spec

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -131,32 +131,32 @@ SELECT CONVERT(birth_date, DOUBLE) AS date FROM test_emp GROUP BY date ORDER BY
131131
date:d
132132
---------------
133133
null
134-
-5.631552E8
135-
-5.586624E8
136-
-5.56416E8
137-
-5.539104E8
138-
-5.517504E8
139-
-5.492448E8
140-
-5.406912E8
141-
-5.371488E8
142-
-5.359392E8
134+
-5.631552E11
135+
-5.586624E11
136+
-5.56416E11
137+
-5.539104E11
138+
-5.517504E11
139+
-5.492448E11
140+
-5.406912E11
141+
-5.371488E11
142+
-5.359392E11
143143
;
144144

145145
castedDateTimeWithGroupBy2
146-
SELECT CAST(hire_date AS INTEGER) AS date FROM test_emp GROUP BY date ORDER BY date LIMIT 10;
146+
SELECT CAST(hire_date AS LONG) AS date FROM test_emp GROUP BY date ORDER BY date LIMIT 10;
147147

148-
date:i
148+
date:l
149149
---------------
150-
477532800
151-
478051200
152-
484790400
153-
489715200
154-
495763200
155-
498096000
156-
498614400
157-
501206400
158-
501292800
159-
501379200
150+
477532800000
151+
478051200000
152+
484790400000
153+
489715200000
154+
495763200000
155+
498096000000
156+
498614400000
157+
501206400000
158+
501292800000
159+
501379200000
160160
;
161161

162162
dateTimeAggByIsoDayOfWeekWithFilter

x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DataTypeConversion.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ private static Function<Object, Object> fromBool(Function<Boolean, Object> conve
557557
}
558558

559559
private static Function<Object, Object> fromDateTime(Function<Long, Object> converter) {
560-
return l -> converter.apply(((ZonedDateTime) l).toEpochSecond());
560+
return l -> converter.apply(((ZonedDateTime) l).toInstant().toEpochMilli());
561561
}
562562

563563
private static Function<Object, Object> toDateTime(Conversion conversion) {

x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/type/DataTypeConversionTests.java

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,14 @@ public void testConversionToLong() {
9999
{
100100
Conversion conversion = conversionFor(DATE, to);
101101
assertNull(conversion.convert(null));
102-
assertEquals(123379200L, conversion.convert(DateUtils.asDateOnly(123456789101L)));
103-
assertEquals(-123465600L, conversion.convert(DateUtils.asDateOnly(-123456789101L)));
102+
assertEquals(123379200000L, conversion.convert(DateUtils.asDateOnly(123456789101L)));
103+
assertEquals(-123465600000L, conversion.convert(DateUtils.asDateOnly(-123456789101L)));
104104
}
105105
{
106106
Conversion conversion = conversionFor(DATETIME, to);
107107
assertNull(conversion.convert(null));
108-
assertEquals(123456789L, conversion.convert(asDateTime(123456789101L)));
109-
assertEquals(-123456790L, conversion.convert(asDateTime(-123456789101L)));
108+
assertEquals(123456789101L, conversion.convert(asDateTime(123456789101L)));
109+
assertEquals(-123456789101L, conversion.convert(asDateTime(-123456789101L)));
110110
}
111111
{
112112
Conversion conversion = conversionFor(KEYWORD, to);
@@ -238,14 +238,14 @@ public void testConversionToDouble() {
238238
{
239239
Conversion conversion = conversionFor(DATE, to);
240240
assertNull(conversion.convert(null));
241-
assertEquals(1.233792E8, (double) conversion.convert(DateUtils.asDateOnly(123456789101L)), 0);
242-
assertEquals(-1.234656E8, (double) conversion.convert(DateUtils.asDateOnly(-123456789101L)), 0);
241+
assertEquals(1.233792E11, (double) conversion.convert(DateUtils.asDateOnly(123456789101L)), 0);
242+
assertEquals(-1.234656E11, (double) conversion.convert(DateUtils.asDateOnly(-123456789101L)), 0);
243243
}
244244
{
245245
Conversion conversion = conversionFor(DATETIME, to);
246246
assertNull(conversion.convert(null));
247-
assertEquals(1.23456789E8, (double) conversion.convert(asDateTime(123456789101L)), 0);
248-
assertEquals(-1.2345679E8, (double) conversion.convert(asDateTime(-123456789101L)), 0);
247+
assertEquals(1.23456789101E11, (double) conversion.convert(asDateTime(123456789101L)), 0);
248+
assertEquals(-1.23456789101E11, (double) conversion.convert(asDateTime(-123456789101L)), 0);
249249
}
250250
{
251251
Conversion conversion = conversionFor(KEYWORD, to);
@@ -340,39 +340,80 @@ public void testConversionToInt() {
340340
{
341341
Conversion conversion = conversionFor(DATE, to);
342342
assertNull(conversion.convert(null));
343-
assertEquals(123379200, conversion.convert(DateUtils.asDateOnly(123456789101L)));
344-
assertEquals(-123465600, conversion.convert(DateUtils.asDateOnly(-123456789101L)));
343+
assertEquals(0, conversion.convert(DateUtils.asDateOnly(12345678L)));
344+
assertEquals(86400000, conversion.convert(DateUtils.asDateOnly(123456789L)));
345+
assertEquals(172800000, conversion.convert(DateUtils.asDateOnly(223456789L)));
346+
assertEquals(-172800000, conversion.convert(DateUtils.asDateOnly(-123456789L)));
347+
Exception e = expectThrows(SqlIllegalArgumentException.class, () -> conversion.convert(DateUtils.asDateOnly(Long.MAX_VALUE)));
348+
assertEquals("[9223372036828800000] out of [integer] range", e.getMessage());
345349
}
346350
{
347351
Conversion conversion = conversionFor(DATETIME, to);
348352
assertNull(conversion.convert(null));
349-
assertEquals(123456789, conversion.convert(asDateTime(123456789101L)));
350-
assertEquals(-123456790, conversion.convert(asDateTime(-123456789101L)));
353+
assertEquals(12345678, conversion.convert(DateUtils.asDateTime(12345678L)));
354+
assertEquals(223456789, conversion.convert(DateUtils.asDateTime(223456789L)));
355+
assertEquals(-123456789, conversion.convert(DateUtils.asDateTime(-123456789L)));
356+
Exception e = expectThrows(SqlIllegalArgumentException.class, () -> conversion.convert(DateUtils.asDateTime(Long.MAX_VALUE)));
357+
assertEquals("[" + Long.MAX_VALUE + "] out of [integer] range", e.getMessage());
351358
}
352359
}
353360

354361
public void testConversionToShort() {
362+
DataType to = SHORT;
355363
{
356-
Conversion conversion = conversionFor(DOUBLE, SHORT);
364+
Conversion conversion = conversionFor(DOUBLE, to);
357365
assertNull(conversion.convert(null));
358366
assertEquals((short) 10, conversion.convert(10.0));
359367
assertEquals((short) 10, conversion.convert(10.1));
360368
assertEquals((short) 11, conversion.convert(10.6));
361369
Exception e = expectThrows(SqlIllegalArgumentException.class, () -> conversion.convert(Integer.MAX_VALUE));
362370
assertEquals("[" + Integer.MAX_VALUE + "] out of [short] range", e.getMessage());
363371
}
372+
{
373+
Conversion conversion = conversionFor(DATE, to);
374+
assertNull(conversion.convert(null));
375+
assertEquals((short) 0, conversion.convert(DateUtils.asDateOnly(12345678L)));
376+
Exception e = expectThrows(SqlIllegalArgumentException.class, () -> conversion.convert(DateUtils.asDateOnly(123456789L)));
377+
assertEquals("[86400000] out of [short] range", e.getMessage());
378+
}
379+
{
380+
Conversion conversion = conversionFor(DATETIME, to);
381+
assertNull(conversion.convert(null));
382+
assertEquals((short) 12345, conversion.convert(DateUtils.asDateTime(12345L)));
383+
assertEquals((short) -12345, conversion.convert(DateUtils.asDateTime(-12345L)));
384+
Exception e = expectThrows(SqlIllegalArgumentException.class,
385+
() -> conversion.convert(DateUtils.asDateTime(Integer.MAX_VALUE)));
386+
assertEquals("[" + Integer.MAX_VALUE + "] out of [short] range", e.getMessage());
387+
}
364388
}
365389

366390
public void testConversionToByte() {
391+
DataType to = BYTE;
367392
{
368-
Conversion conversion = conversionFor(DOUBLE, BYTE);
393+
Conversion conversion = conversionFor(DOUBLE, to);
369394
assertNull(conversion.convert(null));
370395
assertEquals((byte) 10, conversion.convert(10.0));
371396
assertEquals((byte) 10, conversion.convert(10.1));
372397
assertEquals((byte) 11, conversion.convert(10.6));
373398
Exception e = expectThrows(SqlIllegalArgumentException.class, () -> conversion.convert(Short.MAX_VALUE));
374399
assertEquals("[" + Short.MAX_VALUE + "] out of [byte] range", e.getMessage());
375400
}
401+
{
402+
Conversion conversion = conversionFor(DATE, to);
403+
assertNull(conversion.convert(null));
404+
assertEquals((byte) 0, conversion.convert(DateUtils.asDateOnly(12345678L)));
405+
Exception e = expectThrows(SqlIllegalArgumentException.class, () -> conversion.convert(DateUtils.asDateOnly(123456789L)));
406+
assertEquals("[86400000] out of [byte] range", e.getMessage());
407+
}
408+
{
409+
Conversion conversion = conversionFor(DATETIME, to);
410+
assertNull(conversion.convert(null));
411+
assertEquals((byte) 123, conversion.convert(DateUtils.asDateTime(123L)));
412+
assertEquals((byte) -123, conversion.convert(DateUtils.asDateTime(-123L)));
413+
Exception e = expectThrows(SqlIllegalArgumentException.class,
414+
() -> conversion.convert(DateUtils.asDateTime(Integer.MAX_VALUE)));
415+
assertEquals("[" + Integer.MAX_VALUE + "] out of [byte] range", e.getMessage());
416+
}
376417
}
377418

378419
public void testConversionToNull() {

0 commit comments

Comments
 (0)