[CALCITE-6353] Optimization CoreRules.PROJECT_REDUCE_EXPRESSIONS crashes while optimizing ARRAY_CONCAT expression

Signed-off-by: Mihai Budiu <mbudiu@feldera.com>
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
index 6bf8f18..37fdd4a 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
@@ -3349,7 +3349,7 @@
     }
   }
 
-  /** Implementor for a array concat. */
+  /** Implementor for array concat. */
   private static class ArrayConcatImplementor extends AbstractRexCallImplementor {
     ArrayConcatImplementor() {
       super("array_concat", NullPolicy.STRICT, false);
@@ -3364,10 +3364,11 @@
       for (Expression expression : argValueList) {
         blockBuilder.add(
             Expressions.ifThenElse(
-                Expressions.or(
+                Expressions.orElse(
                     Expressions.equal(nullValue, list),
                     Expressions.equal(nullValue, expression)),
-                Expressions.assign(list, nullValue),
+                Expressions.statement(
+                    Expressions.assign(list, nullValue)),
                 Expressions.statement(
                     Expressions.call(list,
                         BuiltInMethod.COLLECTION_ADDALL.method, expression))));
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java b/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
index 9b19c97..1cec66b 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
@@ -1033,6 +1033,13 @@
         if (operand instanceof RexLiteral) {
           return;
         }
+        if (operand instanceof RexCall) {
+          RexCall opCall = (RexCall) operand;
+          if (opCall.getKind() == SqlKind.ARRAY_VALUE_CONSTRUCTOR) {
+            // We can't simplify casts of arrays even if arrays are constant.
+            return;
+          }
+        }
       }
       constExprs.add(exp);
 
diff --git a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
index 51a13e0..bfe1f4b 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -2022,6 +2022,20 @@
         .check();
   }
 
+  /** Test case for
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-6353">[CALCITE-6353]
+   * Optimization CoreRules.PROJECT_REDUCE_EXPRESSIONS crashes
+   * while optimizing ARRAY_CONCAT expression</a>. */
+  @Test void testArrayConcat() {
+    final String sql = "select array_concat(ARRAY [1, 2], ARRAY [3, 4])";
+    sql(sql).withFactory(
+        t -> t.withOperatorTable(
+            opTab -> SqlLibraryOperatorTableFactory.INSTANCE.getOperatorTable(
+                SqlLibrary.STANDARD, SqlLibrary.BIG_QUERY)))
+        .withRule(CoreRules.PROJECT_REDUCE_EXPRESSIONS)
+        .check();
+  }
+
   @Test void testDistinctCountGroupingSets2() {
     final String sql = "select deptno, job, count(distinct ename), sum(sal)\n"
         + "from sales.emp group by rollup(deptno,job)";
diff --git a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
index bc940b8..7302939 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -1286,6 +1286,23 @@
 ]]>
     </Resource>
   </TestCase>
+  <TestCase name="testArrayConcat">
+    <Resource name="sql">
+      <![CDATA[select array_concat(ARRAY [1, 2], ARRAY [3, 4])]]>
+    </Resource>
+    <Resource name="planBefore">
+      <![CDATA[
+LogicalProject(EXPR$0=[ARRAY_CONCAT(ARRAY(1, 2), ARRAY(3, 4))])
+  LogicalValues(tuples=[[{ 0 }]])
+]]>
+    </Resource>
+    <Resource name="planAfter">
+      <![CDATA[
+LogicalProject(EXPR$0=[CAST(ARRAY(1, 2, 3, 4)):INTEGER NOT NULL ARRAY NOT NULL])
+  LogicalValues(tuples=[[{ 0 }]])
+]]>
+    </Resource>
+  </TestCase>
   <TestCase name="testArrayToString">
     <Resource name="sql">
       <![CDATA[select array_to_string(array['1','2','3','4',NULL,'6'], ',', NULL)]]>