This is an automated email from the ASF dual-hosted git repository.

amaliujia pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/master by this push:
     new 9b27206  CALCITE-4434 fix cannot implement 'CASE row WHEN row...'
9b27206 is described below

commit 9b272069091c649935c36a6bf26204b64b18ef44
Author: zhen wang <[email protected]>
AuthorDate: Wed Dec 16 17:25:52 2020 +0800

    CALCITE-4434 fix cannot implement 'CASE row WHEN row...'
---
 .../calcite/sql2rel/StandardConvertletTable.java   | 24 ++++++++++++
 core/src/test/resources/sql/struct.iq              | 44 ++++++++++++++++++++++
 2 files changed, 68 insertions(+)

diff --git 
a/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java 
b/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
index aec9007..f6987a3 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
@@ -30,6 +30,7 @@ import org.apache.calcite.rex.RexLiteral;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.rex.RexRangeRef;
 import org.apache.calcite.rex.RexUtil;
+import org.apache.calcite.runtime.FlatLists;
 import org.apache.calcite.runtime.SqlFunctions;
 import org.apache.calcite.sql.SqlAggFunction;
 import org.apache.calcite.sql.SqlBasicCall;
@@ -900,6 +901,29 @@ public class StandardConvertletTable extends 
ReflectiveConvertletTable {
             : operandTypeChecker.getConsistency();
     final List<RexNode> exprs = convertOperands(cx, call, consistency);
     RelDataType type = rexBuilder.deriveReturnType(op, exprs);
+
+    //generate relation for `=(Row1,Row2)`
+    if (op.kind == SqlKind.EQUALS) {
+      RexNode expr0 = RexUtil.removeCast(exprs.get(0));
+      RexNode expr1 = RexUtil.removeCast(exprs.get(1));
+      SqlKind expr0Kind = expr0.getKind();
+      SqlKind expr1Kind = expr1.getKind();
+      if (expr0Kind == SqlKind.ROW && expr1Kind == SqlKind.ROW) {
+        RexCall call0 = (RexCall) expr0;
+        RexCall call1 = (RexCall) expr1;
+        int cmpCount = call0.getOperands().size();
+        ImmutableList.Builder<RexNode> compareBuilder = 
ImmutableList.builder();
+        for (int i = 0; i < cmpCount; i += 1) {
+          RexNode cmp = rexBuilder.makeCall(type, op,
+              FlatLists.of(
+                  call0.getOperands().get(i),
+                  call1.getOperands().get(i))
+          );
+          compareBuilder.add(cmp);
+        }
+        return rexBuilder.makeCall(type, SqlStdOperatorTable.AND, 
compareBuilder.build());
+      }
+    }
     return rexBuilder.makeCall(type, op, RexUtil.flatten(exprs, op));
   }
 
diff --git a/core/src/test/resources/sql/struct.iq 
b/core/src/test/resources/sql/struct.iq
index 651b388..eaa429e 100644
--- a/core/src/test/resources/sql/struct.iq
+++ b/core/src/test/resources/sql/struct.iq
@@ -83,4 +83,48 @@ where t.struct = ROW(2, ROW(3,4));
 
 !ok
 
+!use scott
+
+# [CALCITE-4434] Cannot implement 'CASE row WHEN row ...'
+SELECT deptno, job,
+  CASE (deptno, job)
+  WHEN (20, 'CLERK') THEN 1
+  WHEN (30, 'SALESMAN') THEN 2
+  ELSE 3
+  END AS x
+FROM "scott".emp
+WHERE empno < 7600;
++--------+----------+---+
+| DEPTNO | JOB      | X |
++--------+----------+---+
+|     20 | CLERK    | 1 |
+|     20 | MANAGER  | 3 |
+|     30 | SALESMAN | 2 |
+|     30 | SALESMAN | 2 |
++--------+----------+---+
+(4 rows)
+
+!ok
+
+# Equivalent to previous
+SELECT deptno, job,
+  CASE
+  WHEN deptno = 20 AND job = 'CLERK' THEN 1
+  WHEN deptno = 30 AND job = 'SALESMAN' THEN 2
+  ELSE 3
+  END AS x
+FROM "scott".emp
+WHERE empno < 7600;
++--------+----------+---+
+| DEPTNO | JOB      | X |
++--------+----------+---+
+|     20 | CLERK    | 1 |
+|     20 | MANAGER  | 3 |
+|     30 | SALESMAN | 2 |
+|     30 | SALESMAN | 2 |
++--------+----------+---+
+(4 rows)
+
+!ok
+
 # End struct.iq

Reply via email to