diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/whitelist/InternalSqlScriptUtils.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/whitelist/InternalSqlScriptUtils.java index f56181bae13..ad64b365af4 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/whitelist/InternalSqlScriptUtils.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/whitelist/InternalSqlScriptUtils.java @@ -348,7 +348,7 @@ public final class InternalSqlScriptUtils { public static ZonedDateTime asDateTime(Object dateTime) { return (ZonedDateTime) asDateTime(dateTime, false); } - + private static Object asDateTime(Object dateTime, boolean lenient) { if (dateTime == null) { return null; @@ -363,7 +363,10 @@ public final class InternalSqlScriptUtils { if (dateTime instanceof Number) { return DateUtils.asDateTime(((Number) dateTime).longValue()); } - + + if (dateTime instanceof String) { + return DateUtils.asDateTime(dateTime.toString()); + } throw new SqlIllegalArgumentException("Invalid date encountered [{}]", dateTime); } return dateTime; diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/script/ScriptWeaver.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/script/ScriptWeaver.java index 5b758789202..5e9199210eb 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/script/ScriptWeaver.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/script/ScriptWeaver.java @@ -17,6 +17,9 @@ import org.elasticsearch.xpack.sql.expression.function.scalar.ScalarFunctionAttr import org.elasticsearch.xpack.sql.expression.literal.IntervalDayTime; import org.elasticsearch.xpack.sql.expression.literal.IntervalYearMonth; import org.elasticsearch.xpack.sql.type.DataType; +import org.elasticsearch.xpack.sql.util.DateUtils; + +import java.time.ZonedDateTime; import static org.elasticsearch.xpack.sql.expression.gen.script.ParamsBuilder.paramsBuilder; @@ -52,7 +55,18 @@ public interface ScriptWeaver { default ScriptTemplate scriptWithFoldable(Expression foldable) { Object fold = foldable.fold(); + + // + // Custom type handling + // + // wrap intervals with dedicated methods for serialization + if (fold instanceof ZonedDateTime) { + ZonedDateTime zdt = (ZonedDateTime) fold; + return new ScriptTemplate(processScript("{sql}.asDateTime({})"), + paramsBuilder().variable(DateUtils.toString(zdt)).build(), dataType()); + } + if (fold instanceof IntervalYearMonth) { IntervalYearMonth iym = (IntervalYearMonth) fold; return new ScriptTemplate(processScript("{sql}.intervalYearMonth({},{})"), diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/planner/QueryTranslatorTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/planner/QueryTranslatorTests.java index aa23603e906..e47f93cab89 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/planner/QueryTranslatorTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/planner/QueryTranslatorTests.java @@ -59,6 +59,7 @@ import java.util.stream.Stream; import static org.elasticsearch.xpack.sql.expression.function.scalar.math.MathProcessor.MathOperation.E; import static org.elasticsearch.xpack.sql.expression.function.scalar.math.MathProcessor.MathOperation.PI; +import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.Matchers.endsWith; import static org.hamcrest.Matchers.startsWith; @@ -728,4 +729,17 @@ public class QueryTranslatorTests extends ESTestCase { EsQueryExec eqe = (EsQueryExec) p; assertFalse("Should NOT be tracking hits", eqe.queryContainer().shouldTrackHits()); } + + public void testZonedDateTimeInScripts() throws Exception { + PhysicalPlan p = optimizeAndPlan( + "SELECT date FROM test WHERE date + INTERVAL 1 YEAR > CAST('2019-03-11T12:34:56.000Z' AS DATETIME)"); + assertEquals(EsQueryExec.class, p.getClass()); + EsQueryExec eqe = (EsQueryExec) p; + assertThat(eqe.queryContainer().toString().replaceAll("\\s+", ""), containsString( + "\"script\":{\"script\":{\"source\":\"InternalSqlScriptUtils.nullSafeFilter(" + + "InternalSqlScriptUtils.gt(InternalSqlScriptUtils.add(InternalSqlScriptUtils.docValue(doc,params.v0)," + + "InternalSqlScriptUtils.intervalYearMonth(params.v1,params.v2)),InternalSqlScriptUtils.asDateTime(params.v3)))\"," + + "\"lang\":\"painless\"," + + "\"params\":{\"v0\":\"date\",\"v1\":\"P1Y\",\"v2\":\"INTERVAL_YEAR\",\"v3\":\"2019-03-11T12:34:56.000Z\"}},")); + } }