calcite icon indicating copy to clipboard operation
calcite copied to clipboard

[CALCITE-1703] Functions on TIMESTAMP column throws ClassCastException

Open ijokarumawak opened this issue 6 years ago • 16 comments

Currently, TIMESTAMP or TIME column is used at any function, ClassCastException is thrown. For example, if a TIMESTAMP column date_added is used like this, select name, EXTRACT(YEAR FROM date_added) as year_added from FLOWFILE, Calcite generates the following code. And a ClassCastException is thrown at (Long) current[1]:

            public Object current() {
              final Object[] current = (Object[]) inputEnumerator.current();
              return new Object[] {
                  current[0],
                  (java.sql.Timestamp) current[1] == null ? (Long) null : Long.valueOf(org.apache.calcite.avatica.util.DateTimeUtils.unixDateExtract(org.apache.calcite.avatica.util.TimeUnitRange.YEAR, (Long) current[1] / 86400000L))};
            }

That happens because of the wrong if condition at PhysTypeImple.fieldReference method where it ignores the fieldType that is used as a fromType to convert the value to Long. Since fromType is null, the generated code casts current[1] to Long blindly.

The condition should accept not only java.sql.Date but also java.sql.Time and java.sql.Timestamp. Since these classes are all sub-class of java.util.Date, using isAssignableFrom method will address the issue.

Current if statement only supports java.sql.Date: image

DISCLAIMER: This is my first PR to Apache Calcite project. Kindly give me some advice on unit testing.

I wanted to add an unit test to reproduce the issue and prove this fix it. But I couldn't figure out where is the right place for such test.

There is an existing case testExtractYearFromTimestamp but this test doesn't call PhysTypeImple.fieldReference. Some other test cases in the same JdbcTest such as testSumOverUnboundedPreceding does call PhysTypeImple.fieldReference. I don't know where this difference comes from..

ijokarumawak avatar Dec 13 '18 08:12 ijokarumawak

I found that the particular code branch that can throw ClassCastException is generated when a timestamp column in an Object array row type is referenced. Referencing timestamp field at a Java class (POJO) doesn't seem having this issue.

ijokarumawak avatar Dec 14 '18 11:12 ijokarumawak

Fixed check-style errors.

ijokarumawak avatar Dec 19 '18 01:12 ijokarumawak

@vlsi Thanks for reviewing! I've added more commits to address your comments. As I was working on that, I've found few more issues to fix. The added test cases illustrate what had not been working as expected.

ijokarumawak avatar Dec 26 '18 07:12 ijokarumawak

@ijokarumawak Does this supersede #405? If so, I will close that PR.

F21 avatar Jan 03 '19 03:01 F21

@F21 Yes, I believe this PR covers what #405 tries to fix.

ijokarumawak avatar Jan 07 '19 06:01 ijokarumawak

@ijokarumawak Thanks for taking this on! I'll close #405

F21 avatar Jan 07 '19 06:01 F21

Rebased with the latest master as the PR had a conflict on CalciteSuite. Also squashed commits.

ijokarumawak avatar Jan 08 '19 01:01 ijokarumawak

@vlsi I've implemented timestamp cast and added unit test for that. The issue was the existing code has had the conversion but used scale instead of precision. Please see the added commit for what I changed. Hopefully this PR is now ready to be merged. Thanks!

ijokarumawak avatar Jan 10 '19 10:01 ijokarumawak

@vlsi - planning to merge still?

risdenk avatar Feb 27 '19 19:02 risdenk

Hi @vlsi, sorry for the delay. I've added another commit to address review feedback. Please let me know if there's anything more. Thanks for reviewing!

ijokarumawak avatar Apr 09 '19 02:04 ijokarumawak

Hi @vlsi I just noticed that CI tests failed at DateRangeRulesTest. But the only thing I changed at the last commit is ObjectArrayTableTest test class. Do you know why DateRangeRulesTest failed on travis and appveyor?? The test had been successful before, and is successful if I run it locally..

ijokarumawak avatar Apr 19 '19 07:04 ijokarumawak

@vlsi Could you take another look?

michaelmior avatar Jun 05 '19 11:06 michaelmior

@michaelmior , the review comments are resolved.

However it looks like the change fails the build, and I have not analyzed the reason.

vlsi avatar Jun 05 '19 12:06 vlsi

Thanks!

michaelmior avatar Jun 05 '19 12:06 michaelmior

@ijokarumawak What JDK version are you using? It passes on CI with JDK 10.

michaelmior avatar Jun 05 '19 12:06 michaelmior

@michaelmior , it does not. I think the reason one of Travis job passes is it runs with SLOW_TESTS=Y, so only a subset of tests is executed.

vlsi avatar Jun 05 '19 12:06 vlsi