There are some gaps in timestamp literal handling in the multi-stage query engine - particularly, when converting from Calcite's internal representation to a long value representing milliseconds since epoch (which is what Pinot uses internally).
The existing logic only handles the case where the representation is an instance of java.util.Calendar. However, the internal representation used by Calcite for timestamp types is org.apache.calcite.util.TimestampString (see here). External callers usually convert this to Calendar or Long (see here), but this doesn't always appear to be the case.
One example is range sets in a Sarg (search argument) - this issue was detected by a query with a filter predicate like WHERE ts BETWEEN '2016-01-01 00:00:00' AND '2016-01-01 10:00:00' where the class cast exception class org.apache.calcite.util.TimestampString cannot be cast to class java.util.Calendar was thrown when converting the bounds of a range here during conversion of SEARCH to an OR of ranges. This wasn't a major issue until recently because search nodes were usually reduced before the final query plan was generated (which changed in https://github.com/apache/pinot/pull/14448).
Simply replacing the Calendar based cast logic to TimestampString based cast logic is also incorrect and a query with a filter predicate like WHERE ts >= CAST(1454284798000 AS TIMESTAMP) will fail with a class cast exception class java.util.GregorianCalendar cannot be cast to class org.apache.calcite.util.TimestampString.
This patch fixes the timestamp literal handling logic to cover all the cases. A couple of query compilation tests based on the above two filter predicates have also been added.
java.util.Calendar
. However, the internal representation used by Calcite for timestamp types isorg.apache.calcite.util.TimestampString
(see here). External callers usually convert this toCalendar
orLong
(see here), but this doesn't always appear to be the case.Sarg
(search argument) - this issue was detected by a query with a filter predicate likeWHERE ts BETWEEN '2016-01-01 00:00:00' AND '2016-01-01 10:00:00'
where the class cast exceptionclass org.apache.calcite.util.TimestampString cannot be cast to class java.util.Calendar
was thrown when converting the bounds of a range here during conversion ofSEARCH
to anOR
of ranges. This wasn't a major issue until recently because search nodes were usually reduced before the final query plan was generated (which changed in https://github.com/apache/pinot/pull/14448).Calendar
based cast logic toTimestampString
based cast logic is also incorrect and a query with a filter predicate likeWHERE ts >= CAST(1454284798000 AS TIMESTAMP)
will fail with a class cast exceptionclass java.util.GregorianCalendar cannot be cast to class org.apache.calcite.util.TimestampString
.