[CALCITE-6361] Uncollect.deriveUncollectRowType throws AssertionFailures
   * if the input data is not a collection

Signed-off-by: Mihai Budiu <mbudiu@feldera.com>
diff --git a/core/src/main/java/org/apache/calcite/rel/core/Uncollect.java b/core/src/main/java/org/apache/calcite/rel/core/Uncollect.java
index 6a4c15e..e19faca 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/Uncollect.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/Uncollect.java
@@ -35,6 +35,8 @@
 import java.util.Collections;
 import java.util.List;
 
+import static org.apache.calcite.util.Static.RESOURCE;
+
 /**
  * Relational expression that unnests its input's columns into a relation.
  *
@@ -168,7 +170,9 @@
         builder.add(SqlUnnestOperator.MAP_VALUE_COLUMN_NAME, mapType.getValueType());
       } else {
         RelDataType ret = field.getType().getComponentType();
-        assert null != ret;
+        if (null == ret) {
+          throw RESOURCE.unnestArgument().ex();
+        }
 
         if (requireAlias) {
           builder.add(itemAliases.get(i), ret);
diff --git a/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java b/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
index 86e6779..6b531c0 100644
--- a/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
+++ b/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
@@ -941,6 +941,9 @@
   @BaseMessage("Invalid character for cast: {0}")
   ExInst<CalciteException> invalidCharacterForCast(String s);
 
+  @BaseMessage("UNNEST argument must be a collection")
+  ExInst<CalciteException> unnestArgument();
+
   @BaseMessage("More than one value in list: {0}")
   ExInst<CalciteException> moreThanOneValueInList(String list);
 
diff --git a/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java b/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
index 2b79213..e9b9eff 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
@@ -225,6 +225,7 @@
 import static org.apache.calcite.sql.SqlUtil.containsDefault;
 import static org.apache.calcite.sql.SqlUtil.containsIn;
 import static org.apache.calcite.sql.SqlUtil.stripAs;
+import static org.apache.calcite.util.Static.RESOURCE;
 
 import static java.util.Objects.requireNonNull;
 
@@ -2499,21 +2500,27 @@
     RelNode child =
         (null != bb.root) ? bb.root : LogicalValues.createOneRow(cluster);
     RelNode uncollect;
-    if (validator().config().conformance().allowAliasUnnestItems()) {
-      uncollect = relBuilder
-          .push(child)
-          .project(exprs)
-          .uncollect(requireNonNull(fieldNames, "fieldNames"), operator.withOrdinality)
-          .build();
-    } else {
-      // REVIEW danny 2020-04-26: should we unify the normal field aliases and
-      // the item aliases?
-      uncollect = relBuilder
-          .push(child)
-          .project(exprs)
-          .uncollect(Collections.emptyList(), operator.withOrdinality)
-          .let(r -> fieldNames == null ? r : r.rename(fieldNames))
-          .build();
+    try {
+      if (validator().config().conformance().allowAliasUnnestItems()) {
+        uncollect = relBuilder
+            .push(child)
+            .project(exprs)
+            .uncollect(requireNonNull(fieldNames, "fieldNames"), operator.withOrdinality)
+            .build();
+      } else {
+        // REVIEW danny 2020-04-26: should we unify the normal field aliases and
+        // the item aliases?
+        uncollect = relBuilder
+            .push(child)
+            .project(exprs)
+            .uncollect(Collections.emptyList(), operator.withOrdinality)
+            .let(r -> fieldNames == null ? r : r.rename(fieldNames))
+            .build();
+      }
+    } catch (Exception ex) {
+      SqlParserPos pos = call.getParserPosition();
+      throw RESOURCE.validatorContext(
+          pos.getLineNum(), pos.getColumnNum(), pos.getEndLineNum(), pos.getEndColumnNum()).ex(ex);
     }
     bb.setRoot(uncollect, true);
   }
diff --git a/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties b/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
index 684e6c7..ab88f0a 100644
--- a/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
+++ b/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
@@ -307,6 +307,7 @@
 InvalidTypesForComparison=Invalid types for comparison: {0} {1} {2}
 CannotConvert=Cannot convert {0} to {1}
 InvalidCharacterForCast=Invalid character for cast: {0}
+UnnestArgument=UNNEST argument must be a collection
 MoreThanOneValueInList=More than one value in list: {0}
 FailedToAccessField=Failed to access field ''{0}'', index {1,number,#} of object of type {2}
 IllegalJsonPathSpec=Illegal jsonpath spec ''{0}'', format of the spec should be: ''<lax|strict> $'{'expr'}'''
diff --git a/server/src/test/java/org/apache/calcite/test/ServerTest.java b/server/src/test/java/org/apache/calcite/test/ServerTest.java
index d48b194..881391c 100644
--- a/server/src/test/java/org/apache/calcite/test/ServerTest.java
+++ b/server/src/test/java/org/apache/calcite/test/ServerTest.java
@@ -198,6 +198,27 @@
     }
   }
 
+  /** Test case for
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-6361">[CALCITE-6361]
+   * Uncollect.deriveUncollectRowType throws AssertionFailures
+   * if the input data is not a collection</a>. */
+  @Test void testUnnest() throws SQLException {
+    try (Connection c = connect();
+         Statement s = c.createStatement()) {
+      boolean b = s.execute("CREATE TYPE simple AS (s INT, t BOOLEAN)");
+      assertThat(b, is(false));
+      b = s.execute("CREATE TYPE vec AS (fields SIMPLE ARRAY)");
+      assertThat(b, is(false));
+      b = s.execute(" CREATE TABLE T(col vec)");
+      assertThat(b, is(false));
+      SQLException e =
+          assertThrows(
+              SQLException.class,
+              () -> s.executeQuery("SELECT A.* FROM (T CROSS JOIN UNNEST(T.col) A)"));
+      assertThat(e.getMessage(), containsString("UNNEST argument must be a collection"));
+    }
+  }
+
   @Test void testCreateType() throws Exception {
     try (Connection c = connect();
          Statement s = c.createStatement()) {