xiedeyantu commented on code in PR #4400:
URL: https://github.com/apache/calcite/pull/4400#discussion_r2133881000
##########
core/src/test/java/org/apache/calcite/test/RexImplicationCheckerTest.java:
##########
@@ -360,6 +361,135 @@ public class RexImplicationCheckerTest {
hasToString("2014"));
}
+ /** Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-7042">[CALCITE-7042]
+ * Eliminate nested TRIM calls, exploiting the fact that TRIM is
idempotent</a>. */
+ @Test void testSimplifyIdempotentFunctions() {
+ final Fixture f = new Fixture();
+ RexLiteral trimBoth = f.rexBuilder.makeLiteral("BOTH");
+ RexLiteral trimed = f.rexBuilder.makeLiteral("a");
+ RexLiteral trimString = f.rexBuilder.makeLiteral("bb");
+
+ // trim way and string are the same
+ RexCall innerTrimCall =
+ (RexCall) f.rexBuilder.makeCall(SqlStdOperatorTable.TRIM, trimBoth,
trimed, trimString);
+ RexCall outerTrimCall =
+ (RexCall) f.rexBuilder.makeCall(SqlStdOperatorTable.TRIM, trimBoth,
trimed, innerTrimCall);
+ RexCall trimSimplifiedCall =
+ (RexCall) f.simplify.simplifyPreservingType(outerTrimCall,
+ RexUnknownAs.UNKNOWN, true);
+
+ // after simplify trimSimplifiedCall is equal to innerTrimCall
+ assertThat(trimSimplifiedCall.getKind(), is(SqlKind.TRIM));
+ assertThat(((RexLiteral) trimSimplifiedCall.getOperands().get(1))
+ .getValue(),
+ is(((RexLiteral) innerTrimCall.getOperands().get(1)).getValue()));
+ assertThat(((RexLiteral) trimSimplifiedCall.getOperands().get(2))
+ .getValue(),
+ is(((RexLiteral) innerTrimCall.getOperands().get(2)).getValue()));
+
+ // trim string are expression
+ final RelDataType integer =
+ f.rexBuilder.getTypeFactory().createSqlType(SqlTypeName.INTEGER);
+ final RexNode lengthArg = f.rexBuilder.makeLiteral(1, integer, true);
+ RexNode expressionTrim =
+ f.rexBuilder.makeCall(SqlStdOperatorTable.SUBSTRING, trimed,
lengthArg);
+ innerTrimCall =
+ (RexCall) f.rexBuilder.makeCall(SqlStdOperatorTable.TRIM, trimBoth,
+ expressionTrim, trimString);
+ outerTrimCall =
+ (RexCall) f.rexBuilder.makeCall(SqlStdOperatorTable.TRIM, trimBoth,
+ expressionTrim, innerTrimCall);
+ trimSimplifiedCall =
+ (RexCall) f.simplify.simplifyPreservingType(outerTrimCall,
+ RexUnknownAs.UNKNOWN, true);
+ // after simplify trimSimplifiedCall is equal to innerTrimCall
+ assertThat(trimSimplifiedCall.getOperands().get(1),
+ is(innerTrimCall.getOperands().get(1)));
+ assertThat(trimSimplifiedCall.getOperands().get(2),
+ is(innerTrimCall.getOperands().get(2)));
+
+ // Negative test of trim way is not the same
+ RexLiteral trimLeft = f.rexBuilder.makeLiteral("LEADING");
+ innerTrimCall =
+ (RexCall) f.rexBuilder.makeCall(SqlStdOperatorTable.TRIM, trimBoth,
trimed, trimString);
+ RexCall outerLeftTrimCall =
+ (RexCall) f.rexBuilder.makeCall(SqlStdOperatorTable.TRIM, trimLeft,
trimed, innerTrimCall);
+ trimSimplifiedCall =
+ (RexCall) f.simplify.simplifyPreservingType(outerLeftTrimCall,
+ RexUnknownAs.UNKNOWN, true);
+
+ // after simplify trimSimplifiedCall is not equal to innerTrimCall
+ assertThat(trimSimplifiedCall.getKind(), is(SqlKind.TRIM));
+ assertThat(((RexLiteral) trimSimplifiedCall.getOperands().get(1))
+ .getValue(),
+ is(((RexLiteral) innerTrimCall.getOperands().get(1)).getValue()));
+ assertThat(trimSimplifiedCall.getOperands().get(2),
+ is(innerTrimCall));
+
+ // Negative test of trimed string is null
+ RexLiteral trimNull = f.rexBuilder.makeNullLiteral(trimString.getType());
+ innerTrimCall =
+ (RexCall) f.rexBuilder.makeCall(SqlStdOperatorTable.TRIM, trimBoth,
trimNull, trimString);
+ RexCall outerNullTrimCall =
+ (RexCall) f.rexBuilder.makeCall(SqlStdOperatorTable.TRIM, trimLeft,
trimed, innerTrimCall);
+ RexNode trimSimplifiedNullCall =
+ f.simplify.simplifyPreservingType(outerNullTrimCall,
+ RexUnknownAs.UNKNOWN, true);
+ // after simplify trimSimplifiedCall is equal to null
+ assertThat(trimSimplifiedNullCall, hasToString("null:VARCHAR(2)"));
+
+ // Negative test of string is null
+ trimNull = f.rexBuilder.makeNullLiteral(trimString.getType());
+ innerTrimCall =
+ (RexCall) f.rexBuilder.makeCall(SqlStdOperatorTable.TRIM, trimBoth,
trimed, trimNull);
+ outerNullTrimCall =
+ (RexCall) f.rexBuilder.makeCall(SqlStdOperatorTable.TRIM, trimLeft,
trimed, innerTrimCall);
+ trimSimplifiedNullCall =
+ f.simplify.simplifyPreservingType(outerNullTrimCall,
+ RexUnknownAs.UNKNOWN, true);
+ // after simplify trimSimplifiedCall is equal to null
+ assertThat(trimSimplifiedNullCall, hasToString("null:VARCHAR(2)"));
+
+ final RexNode literalTs =
Review Comment:
```suggestion
// simplifyTrim supports recursive simplification
RelDataType varcharType =
f.typeFactory.createSqlType(SqlTypeName.VARCHAR);
// castCall is CAST(CAST(1111):VARCHAR NOT NULL):VARCHAR NOT NULL
final RexNode castCall =
f.cast(varcharType,
f.cast(varcharType, f.literal(1111)));
innerTrimCall =
(RexCall) f.rexBuilder.makeCall(SqlStdOperatorTable.TRIM, trimBoth,
trimed, castCall);
// outerTrimCall is
// TRIM('BOTH', 'a', TRIM('BOTH', 'a', CAST(CAST(1111):VARCHAR NOT
NULL):VARCHAR NOT NULL))
outerTrimCall =
(RexCall) f.rexBuilder.makeCall(SqlStdOperatorTable.TRIM, trimBoth,
trimed, innerTrimCall);
trimSimplifiedCall =
(RexCall) f.simplify.simplifyPreservingType(outerTrimCall,
RexUnknownAs.UNKNOWN, true);
assertThat(trimSimplifiedCall,
hasToString("TRIM('BOTH', 'a', '1111':VARCHAR)"));
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]