vlsi commented on a change in pull request #2271:
URL: https://github.com/apache/calcite/pull/2271#discussion_r535559413



##########
File path: 
core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
##########
@@ -1506,6 +1508,83 @@ private SqlNode getCastedSqlNode(SqlNode argInput, 
RelDataType varType,
     }
   }
 
+  /** Convertlet that handles Oracle's {@code SUBSTR} function. */
+  private static class OracleSubstrConvertlet implements SqlRexConvertlet {
+    @Override public RexNode convertCall(SqlRexContext cx, SqlCall call) {
+      // Translate
+      //   SUBSTR(value, start, length)
+      // to
+      //   CASE
+      //   WHEN length < 0 THEN ""
+      //   WHEN start + length(value) < 0 THEN ""
+      //   WHEN start = 0 THEN substring(value, 1, length)
+      //   WHEN start < 0 THEN substring(value, start + length(value) + 1, 
length)
+      //   ELSE substring(value, start, length)
+      //   END
+      //
+      // Translate
+      //   SUBSTR(value, start)
+      // to
+      //   CASE
+      //   WHEN start + length(value) < 0 THEN ""
+      //   WHEN start = 0 THEN substring(value, 1)
+      //   WHEN start < 0 THEN substring(value, start + length(value) + 1)
+      //   ELSE substring(value, start)
+      //   END
+
+      final RexBuilder rexBuilder = cx.getRexBuilder();
+      final List<RexNode> exprs =
+          convertOperands(cx, call, SqlOperandTypeChecker.Consistency.NONE);
+      final RexNode value = exprs.get(0);
+      final RexNode start = exprs.get(1);
+      final RexNode zeroLiteral = rexBuilder.makeLiteral(0, start.getType(), 
false);
+      final RexNode oneLiteral = rexBuilder.makeLiteral(1, start.getType(), 
false);
+      final RexNode emptyStrLiteral = rexBuilder.makeLiteral("", 
value.getType(), false);
+
+      final RexNode valueLength =
+          rexBuilder.makeCall(SqlStdOperatorTable.CHAR_LENGTH, value);
+      final RexNode negativeIndexStart = 
rexBuilder.makeCall(SqlStdOperatorTable.PLUS,
+          rexBuilder.makeCall(SqlStdOperatorTable.PLUS, valueLength, start),
+          oneLiteral);
+
+      final RexNode startIndexOutOfBound = 
rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN,
+          rexBuilder.makeCall(SqlStdOperatorTable.PLUS, start, valueLength),
+          zeroLiteral);
+      final RexNode startLessThanZero =
+          rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN, start, 
zeroLiteral);
+      final RexNode startIsZero =
+          rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, start, zeroLiteral);
+
+      final Function<RexNode, RexNode> startToSubstr;
+      switch (call.operandCount()) {
+      case 2:
+        startToSubstr = startRex ->
+            rexBuilder.makeCall(SqlStdOperatorTable.SUBSTRING, value, 
startRex);
+        return rexBuilder.makeCall(SqlStdOperatorTable.CASE,
+            startIndexOutOfBound, emptyStrLiteral,
+            startIsZero, startToSubstr.apply(oneLiteral),
+            startLessThanZero, startToSubstr.apply(negativeIndexStart),
+            startToSubstr.apply(start));
+      case 3:
+        final RexNode length = exprs.get(2);
+        final RexNode lengthLessThanZero =
+            rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN, length, 
zeroLiteral);
+
+        startToSubstr = startRex ->
+            rexBuilder.makeCall(SqlStdOperatorTable.SUBSTRING, value, 
startRex, length);
+
+        return rexBuilder.makeCall(SqlStdOperatorTable.CASE,
+            lengthLessThanZero, emptyStrLiteral,
+            startIndexOutOfBound, emptyStrLiteral,
+            startIsZero, startToSubstr.apply(oneLiteral),
+            startLessThanZero, startToSubstr.apply(negativeIndexStart),
+            startToSubstr.apply(start));
+      default:
+        throw new AssertionError();

Review comment:
       Please add the relevant message to clarify why this branch must not be 
reachable.




----------------------------------------------------------------
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.

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to