-
Notifications
You must be signed in to change notification settings - Fork 96
fix(isthmus)!: mirror negative and normalize zero decimal and floating-point RANGE offsets #1309
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
Changes from all commits
c93cd78
b83ff76
e4d5d76
5be4125
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -250,6 +250,41 @@ void zeroOffsetBecomesCurrentRowEvenAgainstAnUnsupportedOrderingType() { | |
| assertEquals(WindowBound.CURRENT_ROW, converted); | ||
| } | ||
|
|
||
| @Test | ||
| void zeroDecimalOffsetBecomesCurrentRow() { | ||
| // The integral zero check above has a decimal counterpart: a zero-valued DecimalLiteral | ||
| // needs no representation in the ordering expression's type either. | ||
| RexNode offset = c(BigDecimal.ZERO, SqlTypeName.DECIMAL, 19, 1); | ||
| RexWindowBound bound = RexWindowBounds.preceding(offset); | ||
|
|
||
| WindowBound converted = | ||
| WindowBoundConverter.toWindowBound(bound, false, Optional.empty(), rexExpressionConverter); | ||
|
|
||
| assertEquals(WindowBound.CURRENT_ROW, converted); | ||
| } | ||
|
|
||
| @Test | ||
| void zeroDoubleOffsetBecomesCurrentRow() { | ||
| RexNode offset = c(0.0, SqlTypeName.DOUBLE); | ||
| RexWindowBound bound = RexWindowBounds.preceding(offset); | ||
|
|
||
| WindowBound converted = | ||
| WindowBoundConverter.toWindowBound(bound, false, Optional.empty(), rexExpressionConverter); | ||
|
|
||
| assertEquals(WindowBound.CURRENT_ROW, converted); | ||
| } | ||
|
|
||
| @Test | ||
| void zeroRealOffsetBecomesCurrentRow() { | ||
| RexNode offset = c(0.0f, SqlTypeName.REAL); | ||
| RexWindowBound bound = RexWindowBounds.preceding(offset); | ||
|
|
||
| WindowBound converted = | ||
| WindowBoundConverter.toWindowBound(bound, false, Optional.empty(), rexExpressionConverter); | ||
|
|
||
| assertEquals(WindowBound.CURRENT_ROW, converted); | ||
| } | ||
|
|
||
| @Test | ||
| void negativePrecedingOffsetIsFlippedToFollowingWithItsMagnitude() { | ||
| // The spec carries a bound's direction in the Preceding/Following choice, not in the sign of | ||
|
|
@@ -307,4 +342,95 @@ void negativeOffsetOverflowingLongIsRejectedRatherThanThrowingArithmeticExceptio | |
| WindowBoundConverter.toWindowBound( | ||
| bound, false, Optional.of(orderingType), rexExpressionConverter)); | ||
| } | ||
|
|
||
| @Test | ||
| void negativeDecimalPrecedingOffsetIsFlippedToFollowingWithItsMagnitude() { | ||
| // The integral mirror above has a decimal counterpart: RANGE BETWEEN -5.5 PRECEDING is | ||
| // equivalent to FOLLOWING 5.5. | ||
| RexNode offset = c(new BigDecimal("-5.5"), SqlTypeName.DECIMAL, 19, 1); | ||
| RexWindowBound bound = RexWindowBounds.preceding(offset); | ||
|
|
||
| WindowBound converted = | ||
| WindowBoundConverter.toWindowBound(bound, false, Optional.empty(), rexExpressionConverter); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All six new tests pass A positive-FP case is the other gap: nothing fails today if
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
|
|
||
| assertEquals( | ||
| WindowBound.Following.of(ExpressionCreator.decimal(false, new BigDecimal("5.5"), 19, 1)), | ||
| converted); | ||
| } | ||
|
|
||
| @Test | ||
| void negativeDecimalFollowingOffsetIsFlippedToPrecedingWithItsMagnitude() { | ||
| RexNode offset = c(new BigDecimal("-5.5"), SqlTypeName.DECIMAL, 19, 1); | ||
| RexWindowBound bound = RexWindowBounds.following(offset); | ||
|
|
||
| WindowBound converted = | ||
| WindowBoundConverter.toWindowBound(bound, false, Optional.empty(), rexExpressionConverter); | ||
|
|
||
| assertEquals( | ||
| WindowBound.Preceding.of(ExpressionCreator.decimal(false, new BigDecimal("5.5"), 19, 1)), | ||
| converted); | ||
| } | ||
|
|
||
| @Test | ||
| void negativeDecimalPrecedingOffsetIsNotRetypedAgainstTheOrderingType() { | ||
| // Unlike the integral mirror, a decimal offset's magnitude is not retyped against the | ||
| // ordering column: normalizeIntegralOffset only consults integralValue, so the mirrored | ||
| // decimal literal keeps its own precision and scale regardless of orderingType. | ||
| RexNode offset = c(new BigDecimal("-5.5"), SqlTypeName.DECIMAL, 19, 1); | ||
| RexWindowBound bound = RexWindowBounds.preceding(offset); | ||
| RelDataType orderingType = t(SqlTypeName.DECIMAL, 5, 2); | ||
|
|
||
| WindowBound converted = | ||
| WindowBoundConverter.toWindowBound( | ||
| bound, false, Optional.of(orderingType), rexExpressionConverter); | ||
|
|
||
| assertEquals( | ||
| WindowBound.Following.of(ExpressionCreator.decimal(false, new BigDecimal("5.5"), 19, 1)), | ||
| converted); | ||
| } | ||
|
|
||
| @Test | ||
| void precedingWithPositiveDoubleOffsetIsUnchanged() { | ||
| // A positive FP offset must not be mistaken for negative or zero by isZero/negation. | ||
| RexNode offset = c(5.5, SqlTypeName.DOUBLE); | ||
| RexWindowBound bound = RexWindowBounds.preceding(offset); | ||
|
|
||
| WindowBound converted = | ||
| WindowBoundConverter.toWindowBound(bound, false, Optional.empty(), rexExpressionConverter); | ||
|
|
||
| assertEquals(WindowBound.Preceding.of(ExpressionCreator.fp64(false, 5.5)), converted); | ||
| } | ||
|
|
||
| @Test | ||
| void precedingWithPositiveRealOffsetIsUnchanged() { | ||
| RexNode offset = c(5.5f, SqlTypeName.REAL); | ||
| RexWindowBound bound = RexWindowBounds.preceding(offset); | ||
|
|
||
| WindowBound converted = | ||
| WindowBoundConverter.toWindowBound(bound, false, Optional.empty(), rexExpressionConverter); | ||
|
|
||
| assertEquals(WindowBound.Preceding.of(ExpressionCreator.fp32(false, 5.5f)), converted); | ||
| } | ||
|
|
||
| @Test | ||
| void negativeDoublePrecedingOffsetIsFlippedToFollowingWithItsMagnitude() { | ||
| RexNode offset = c(-5.5, SqlTypeName.DOUBLE); | ||
| RexWindowBound bound = RexWindowBounds.preceding(offset); | ||
|
|
||
| WindowBound converted = | ||
| WindowBoundConverter.toWindowBound(bound, false, Optional.empty(), rexExpressionConverter); | ||
|
|
||
| assertEquals(WindowBound.Following.of(ExpressionCreator.fp64(false, 5.5)), converted); | ||
| } | ||
|
|
||
| @Test | ||
| void negativeRealPrecedingOffsetIsFlippedToFollowingWithItsMagnitude() { | ||
| RexNode offset = c(-5.5f, SqlTypeName.REAL); | ||
| RexWindowBound bound = RexWindowBounds.preceding(offset); | ||
|
|
||
| WindowBound converted = | ||
| WindowBoundConverter.toWindowBound(bound, false, Optional.empty(), rexExpressionConverter); | ||
|
|
||
| assertEquals(WindowBound.Following.of(ExpressionCreator.fp32(false, 5.5f)), converted); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.