Skip to content

[BEAM-8057] Support ZetaSQL DOUBLE +INF, -INF and NAN - #12292

Merged
robinyqiu merged 1 commit into
apache:masterfrom
ZijieSong946:DoubleBugFixed
Jul 22, 2020
Merged

[BEAM-8057] Support ZetaSQL DOUBLE +INF, -INF and NAN#12292
robinyqiu merged 1 commit into
apache:masterfrom
ZijieSong946:DoubleBugFixed

Conversation

@ZijieSong946

Copy link
Copy Markdown
Contributor

This PR supports +inf, -inf and NaN for ZetaSQL DOUBLE type.

  • Original ignored test case ZetaSqlDialectSpecTest.testEQ2 passed.
  • IS_INF() and IS_NAN() are supported for ZetaSQL now.
  • Additional corresponding test cases added.

r: @apilloud @robinyqiu


Thank you for your contribution! Follow this checklist to help us incorporate your contribution quickly and easily:

  • Choose reviewer(s) and mention them in a comment (R: @username).
  • Format the pull request title like [BEAM-XXX] Fixes bug in ApproximateQuantiles, where you replace BEAM-XXX with the appropriate JIRA issue, if applicable. This will automatically link the pull request to the issue.
  • Update CHANGES.md with noteworthy changes.
  • If this contribution is large, please file an Apache Individual Contributor License Agreement.

See the Contributor Guide for more tips on how to make review process smoother.

Post-Commit Tests Status (on master branch)

Lang SDK Dataflow Flink Samza Spark Twister2
Go Build Status --- Build Status --- Build Status ---
Java Build Status Build Status
Build Status
Build Status
Build Status
Build Status
Build Status
Build Status Build Status
Build Status
Build Status
Build Status
Python Build Status
Build Status
Build Status
Build Status
Build Status
Build Status
Build Status
Build Status
Build Status
Build Status
--- Build Status ---
XLang Build Status --- Build Status --- Build Status ---

Pre-Commit Tests Status (on master branch)

--- Java Python Go Website
Non-portable Build Status Build Status
Build Status
Build Status Build Status
Portable --- Build Status --- ---

See .test-infra/jenkins/README for trigger phrase, status and link of all Jenkins jobs.

@robinyqiu robinyqiu left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's great to see this long-standing issue fixed. Thank you for working on this, Zijie. Please also link to your doc from here after you finish that. Left some comments to further simplify the code.

@apilloud apilloud left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

I love this approach! It is very clean and keeps most doubles as normal Calcite literals.

@ZijieSong946

Copy link
Copy Markdown
Contributor Author

LGTM.

I love this approach! It is very clean and keeps most doubles as normal Calcite literals.

Great. Thanks a lot.

@robinyqiu

Copy link
Copy Markdown
Contributor

I am testing this internally, after the tests pass I will merge it.

@ZijieSong946

Copy link
Copy Markdown
Contributor Author

I am testing this internally, after the tests pass I will merge it.

Thanks.

@robinyqiu

robinyqiu commented Jul 17, 2020

Copy link
Copy Markdown
Contributor

Actually this change unveils a data corruption bug (produces wrong result).

It is related to NaN comparison (=, !=, >, >=, <, and <=). For example, if you have a query like

SELECT CAST('NAN' AS FLOAT64) = CAST('NAN' AS FLOAT64)

the expected result is false because according to ZetaSQL definition, NaN compared to any value should return false, but our engine returns true (please add a test to reproduce this).

I dug into this a bit and found it is because Calcite internally does simplification to comparison operations (https://github.com/apache/calcite/blob/3fb68f6c22a7bcbc4cb1fff114bc911b1e31c4de/core/src/main/java/org/apache/calcite/rex/RexSimplify.java#L336-L351). So the above expression will be simplified to (you can print the sql query in BeamZetaSqlCalcRel to verify yourself)

NULL OR CAST('NAN' AS FLOAT64) IS NOT NULL

The simplification is triggered because the 2 operands of = are "equal" (they are both a RexCall to a function named double_nan with no input).

One way I can think of to fix this, without affecting other code path, is that we can generate a random double and convert it to BigDecimal and make it a input to double_nan. This input parameter is never used, its sole purpose is to make Calcite treat two calls to double_nan different.

@apilloud

Copy link
Copy Markdown
Member

Instead of adding an argument with a random number, make isDeterministic() false: https://github.com/apache/calcite/blob/551e3f5a182a48e20586e40c378224bb63e4bfb3/core/src/main/java/org/apache/calcite/sql/SqlOperator.java#L940

@apilloud

apilloud commented Jul 17, 2020

Copy link
Copy Markdown
Member

(There are a few other config parameters in that file, one should stop the optimizer from affecting NaN if isDeterministic doesn't. Looks like isDynamicFunction is used by RAND and CURRENT_TIME.)

@robinyqiu

Copy link
Copy Markdown
Contributor

Yeah that is definitely a better approach. However checking of isDeterministic() in RexSimplify (https://github.com/apache/calcite/blob/551e3f5a182a48e20586e40c378224bb63e4bfb3/core/src/main/java/org/apache/calcite/rex/RexSimplify.java#L334) is only enabled in Calcite 1.23.0 (See https://issues.apache.org/jira/browse/CALCITE-3809).

So how about we use the old approach for now, and create a JIRA for updating to the new approach after we update to 1.23? (The JIRA should be marked blocked by: https://issues.apache.org/jira/browse/BEAM-9379 (we should change 1.22 to 1.23)

@robinyqiu

robinyqiu commented Jul 17, 2020

Copy link
Copy Markdown
Contributor

Oh the last comment was replying to your first comment. If other config parameters can do the work we should definitely do that. @ZijieSong946 Could you investigate this a bit next week?

@ZijieSong946

Copy link
Copy Markdown
Contributor Author

(There are a few other config parameters in that file, one should stop the optimizer from affecting NaN if isDeterministic doesn't. Looks like isDynamicFunction is used by RAND and CURRENT_TIME.)

Acknowledged.

@ZijieSong946

Copy link
Copy Markdown
Contributor Author

Oh the last comment was replying to your first comment. If other config parameters can do the work we should definitely do that. @ZijieSong946 Could you investigate this a bit next week?

Got it. I would figure out a possible solution to handle that issue.

@ZijieSong946

Copy link
Copy Markdown
Contributor Author

I dug into this problem and figured out that we should avoid hitting into the operation simplification branch here (https://github.com/apache/calcite/blob/3530daaa8cad43aad6845b6c79e4bc1ca0e72f5f/core/src/main/java/org/apache/calcite/rex/RexSimplify.java#L325).
For the current Calcite version we use (1.20), there is no check for isDeterministic(), it is added on Mar.6. (apache/calcite#1818)
So, we have to make equals() to be false. As for RexLiteral.equals(), it checks if the type and the value equals. (https://github.com/apache/calcite/blob/3530daaa8cad43aad6845b6c79e4bc1ca0e72f5f/core/src/main/java/org/apache/calcite/rex/RexLiteral.java#L1084-L1088)
I decided to add a random parameter to the Nan wrapper function for make two Nan different in value to avoid operation simplification in Calcite.
@robinyqiu @apilloud

@robinyqiu

Copy link
Copy Markdown
Contributor

Thank you Zijie for the investigation. The temporary solution LGTM. I assigned the JIRA to myself because as discussed in meeting I will be updating the vendored Calcite version.

This PR failed building because I made some changes to some functions your code depends on. You will need to rebase against master and fix it.

@ZijieSong946

Copy link
Copy Markdown
Contributor Author

Thank you Zijie for the investigation. The temporary solution LGTM. I assigned the JIRA to myself because as discussed in meeting I will be updating the vendored Calcite version.

This PR failed building because I made some changes to some functions your code depends on. You will need to rebase against master and fix it.

Rebased.

@robinyqiu

Copy link
Copy Markdown
Contributor

Thank you! I will merge it now (tested internally).

@robinyqiu
robinyqiu merged commit 1e569fa into apache:master Jul 22, 2020
@ZijieSong946

ZijieSong946 commented Aug 17, 2020

Copy link
Copy Markdown
Contributor Author

The detailed designs for overcoming the inconsistency between Calcite and ZetaSQL DOUBLE +inf/-inf/NaN literal representation:
https://docs.google.com/document/d/1veKaDTMttU2q2Izss--Y5Cagg2JUSEA1dS3NVxYjnYg/edit?usp=sharing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants