-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[CALCITE-1703] Functions on TIMESTAMP column throws ClassCastException #971
base: main
Are you sure you want to change the base?
Conversation
80f0ee4
to
c2056f6
Compare
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. |
c2056f6
to
4f12312
Compare
Fixed check-style errors. |
core/src/test/java/org/apache/calcite/test/ObjectArrayTableTest.java
Outdated
Show resolved
Hide resolved
core/src/test/java/org/apache/calcite/test/ObjectArrayTableTest.java
Outdated
Show resolved
Hide resolved
@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. |
core/src/main/java/org/apache/calcite/rel/type/RelDataTypeFactoryImpl.java
Show resolved
Hide resolved
@ijokarumawak Does this supersede #405? If so, I will close that PR. |
core/src/test/java/org/apache/calcite/test/ObjectArrayTableTest.java
Outdated
Show resolved
Hide resolved
core/src/test/java/org/apache/calcite/test/ObjectArrayTableTest.java
Outdated
Show resolved
Hide resolved
core/src/test/java/org/apache/calcite/test/ObjectArrayTableTest.java
Outdated
Show resolved
Hide resolved
@ijokarumawak Thanks for taking this on! I'll close #405 |
…astException Incorporated review comments - Added the new test to CalciteSuite - Added test case message to clarify assertion objectives Adding more fixes - java.sql.Time is not converted to int correctly - java.sql.Timestamp fraction can not be used with some conditions such as '=' Fixed checkstyle errors. Better assertion messages.
7bd603e
to
db41fa5
Compare
Rebased with the latest master as the PR had a conflict on CalciteSuite. Also squashed commits. |
@vlsi I've implemented timestamp cast and added unit test for that. The issue was the existing code has had the conversion but used |
@vlsi - planning to merge still? |
format(Locale.ROOT, sql, expected, actual)); | ||
resultSet.next(); | ||
assertEquals(format(Locale.ROOT, "cast(java.sql.Timestamp as %s)", castTo), | ||
resultSet.getTimestamp(1), resultSet.getTimestamp(2)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ijokarumawak , this is wrong. "EXPECTED" value must not come from a system under test.
You should either hard-code the expected value (which is preferred) or compute it with a "simple to understand" approach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to use hard-coded expected values.
final ResultSet resultSet = statement.executeQuery( | ||
format(Locale.ROOT, sql, expected, actual)); | ||
resultSet.next(); | ||
assertEquals(format(Locale.ROOT, "cast(java.sql.Timestamp as %s)", castTo), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is great you add castTo
to the message, however it would be really good if you add source value as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added source value.
final String sql = "select %s as EXPECTED, %s as ACTUAL from \"java_sql_date_types\""; | ||
|
||
for (int i = 3; i >= 0; i--) { | ||
final String castTo = format(Locale.ROOT, "TIMESTAMP(%d)", i); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You seem to use format(Locale.ROOT
extensively. It makes the code extremely obscure. Could you just use +
operator?
Alternative option is to use Kotlin's string interpolation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to simple string concatenation using +
.
@Test public void testCastTimestampToTimestamp() throws SQLException { | ||
|
||
withJavaSqlDateTypes(connection -> { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please avoid having to many blank lines
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed blank lines.
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! |
Hi @vlsi I just noticed that CI tests failed at |
@vlsi Could you take another look? |
@michaelmior , the review comments are resolved. However it looks like the change fails the build, and I have not analyzed the reason. |
Thanks! |
@ijokarumawak What JDK version are you using? It passes on CI with JDK 10. |
@michaelmior , it does not. |
80f411d
to
ca27fe9
Compare
49cb002
to
8768a23
Compare
8a5cf83
to
cf7f71b
Compare
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]
: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 castscurrent[1]
to Long blindly.The condition should accept not only
java.sql.Date
but alsojava.sql.Time
andjava.sql.Timestamp
. Since these classes are all sub-class ofjava.util.Date
, usingisAssignableFrom
method will address the issue.Current if statement only supports
java.sql.Date
: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 astestSumOverUnboundedPreceding
does callPhysTypeImple.fieldReference
. I don't know where this difference comes from..