You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2021/01/05 20:22:26 UTC

[calcite] branch master updated: [CALCITE-4434] Cannot implement 'CASE row WHEN row ...'

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

jhyde 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 1dd27f7  [CALCITE-4434] Cannot implement 'CASE row WHEN row ...'
1dd27f7 is described below

commit 1dd27f7ee6eaabd44ecda148bff7db9926dbf201
Author: zhen wang <zi...@gmail.com>
AuthorDate: Thu Dec 31 13:36:31 2020 +0800

    [CALCITE-4434] Cannot implement 'CASE row WHEN row ...'
    
    Fix by expanding
      ROW (x0, x1, ...) = ROW (y0, y1, ...)
    inside a CASE expression to
      x0 = y0 AND x1 = y1 AND ...
    
    Close apache/calcite#2309
---
 .../calcite/sql2rel/StandardConvertletTable.java   | 15 ++++++++
 core/src/test/resources/sql/struct.iq              | 44 ++++++++++++++++++++++
 2 files changed, 59 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..640b37f 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
@@ -900,6 +900,21 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
             : operandTypeChecker.getConsistency();
     final List<RexNode> exprs = convertOperands(cx, call, consistency);
     RelDataType type = rexBuilder.deriveReturnType(op, exprs);
+
+    // Expand 'ROW (x0, x1, ...) = ROW (y0, y1, ...)'
+    // to 'x0 = y0 AND x1 = y1 AND ...'
+    if (op.kind == SqlKind.EQUALS) {
+      final RexNode expr0 = RexUtil.removeCast(exprs.get(0));
+      final RexNode expr1 = RexUtil.removeCast(exprs.get(1));
+      if (expr0.getKind() == SqlKind.ROW && expr1.getKind() == SqlKind.ROW) {
+        final RexCall call0 = (RexCall) expr0;
+        final RexCall call1 = (RexCall) expr1;
+        final List<RexNode> eqList = new ArrayList<>();
+        Pair.forEach(call0.getOperands(), call1.getOperands(), (x, y) ->
+            eqList.add(rexBuilder.makeCall(op, x, y)));
+        return RexUtil.composeConjunction(rexBuilder, eqList);
+      }
+    }
     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