Skip to content

[CALCITE-7443] Incorrect simplification for large interval#4845

Open
mihaibudiu wants to merge 1 commit intoapache:mainfrom
mihaibudiu:issue7443
Open

[CALCITE-7443] Incorrect simplification for large interval#4845
mihaibudiu wants to merge 1 commit intoapache:mainfrom
mihaibudiu:issue7443

Conversation

@mihaibudiu
Copy link
Copy Markdown
Contributor

Jira Link

https://issues.apache.org/jira/browse/CALCITE-7443

Changes Proposed

This PR changes all arithmetic on values of type INTERVAL to use checked arithmetic.

Currently, using the default conformance, Calcite's arithmetic obeys the Java rules, i.e., overflow is just wrap-around. There is a conformance flag which allows you to change this behavior; checked arithmetic will throw on overflow (at runtime).

Values such as intervals are encoded into long/integer values, and arithmetic on intervals is compiled into suitably scaled computations in Java. However, I can argue that there is no reason for interval arithmetic to wrap-around; in fact, if it does, it can produce very surprising results, since the encoding of intervals into integers is not part of any spec (it is an implementation detail).

We already had a visitor to convert unchecked arithmetic into checked arithmetic. Previously the visitor was only invoked when the conformance required checked arithmetic. Now the visitor is always invoked, and it performs the following rewrites:

  • any operation that has an operand of type interval and a result of type interval is rewritten to use checked arithmetic
  • other arithmetic operations are rewritten to be checked only if conformance requires it, keeping the previous behavior

Signed-off-by: Mihai Budiu <mbudiu@feldera.com>
// Do not rewrite operator if the type is e.g., DOUBLE or DATE
(this.allArithmetic && SqlTypeName.EXACT_TYPES.contains(resultType))
// But always rewrite if the type is an INTERVAL and any operand is INTERVAL
// This will not rewrite date subtraction, for example
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.

I'm not sure if the comments are finished, because there's no further content after "for example".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, the example is "it will not rewrite date subtraction"

!error

SELECT INTERVAL 3000000 months / .0001;
java.lang.ArithmeticException: Overflow
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.

I'm not sure if this outputs a more complete error message; I'll take a look at the code later.

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.

After reviewing the code, it seems the error message wasn't thrown by Calcite, but rather by the Java API, which makes sense now.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The error message is not informative, it is the innermost exception, which is not very helpful. But this is the best we can do now.

(this.allArithmetic && SqlTypeName.EXACT_TYPES.contains(resultType))
// But always rewrite if the type is an INTERVAL and any operand is INTERVAL
// This will not rewrite date subtraction, for example
|| (resultIsInterval && anyOperandIsInterval);
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.

Why is the condition anyOperandIsInterval needed?🤔

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

To avoid rewriting date subtraction

Copy link
Copy Markdown
Member

@caicancai caicancai left a comment

Choose a reason for hiding this comment

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

After the comments for "for example" were improved, I had no further questions.

@mihaibudiu mihaibudiu added the LGTM-will-merge-soon Overall PR looks OK. Only minor things left. label Mar 25, 2026
Copy link
Copy Markdown
Member

@xiedeyantu xiedeyantu left a comment

Choose a reason for hiding this comment

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

Left two minor comments for reference only.

public class ConvertToChecked extends RelHomogeneousShuttle {
final ConvertRexToChecked converter;

public ConvertToChecked(RexBuilder builder) {
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.

Should we add an
"@deprecated" annotation here to preserve the original method?


# 5 test cases for [CALCITE-7443] Incorrect simplification for large interval
SELECT -(INTERVAL -2147483648 months);
java.lang.ArithmeticException: integer overflow
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.

"java.lang.ArithmeticException: INTERVAL MONTH value out of integer range"
Can the error message be made more informative? For example, when encountering an error in a complex SQL, it might be difficult to quickly pinpoint the exact location. Could we even include the specific number in the error message?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That is a very difficult problem. The Enumerable API has not been designed for ergonomic handling of runtime errors. Normally it would (1) install catch blocks and (2) use source-position information to give more meaningful error messages. This would be out of scope in this PR anyway.

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.

No problem, let's set this aside for now.

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

Labels

LGTM-will-merge-soon Overall PR looks OK. Only minor things left.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants