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

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


The following commit(s) were added to refs/heads/main by this push:
     new 43c8848290 [CALCITE-6400] MAP_ENTRIES function should throw if a key 
value is null
43c8848290 is described below

commit 43c88482904bc3614f4e21eb1804b4f0af76997b
Author: caicancai <[email protected]>
AuthorDate: Sat May 4 23:11:49 2024 +0800

    [CALCITE-6400] MAP_ENTRIES function should throw if a key value is null
---
 .../org/apache/calcite/runtime/SqlFunctions.java   |  3 +++
 .../org/apache/calcite/test/SqlOperatorTest.java   | 25 +++++++++++-----------
 2 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java 
b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
index 37c70e7fe0..160b99a4da 100644
--- a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
+++ b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
@@ -5504,6 +5504,9 @@ public class SqlFunctions {
   public static List mapEntries(Map<Object, Object> map) {
     final List result = new ArrayList(map.size());
     for (Map.Entry<Object, Object> entry : map.entrySet()) {
+      if (entry.getKey() == null) {
+        throw new IllegalArgumentException("Cannot use null as map key");
+      }
       result.add(Arrays.asList(entry.getKey(), entry.getValue()));
     }
     return result;
diff --git a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java 
b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
index 3402b92429..6e303053ed 100644
--- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
+++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
@@ -7775,23 +7775,16 @@ public class SqlOperatorTest {
     final SqlOperatorFixture f = f0.withLibrary(SqlLibrary.SPARK);
     f.checkScalar("map_entries(map['foo', 1, 'bar', 2])", "[{foo, 1}, {bar, 
2}]",
         "RecordType(CHAR(3) NOT NULL f0, INTEGER NOT NULL f1) NOT NULL ARRAY 
NOT NULL");
-    f.checkScalar("map_entries(map['foo', 1, null, 2])", "[{foo, 1}, {null, 
2}]",
-        "RecordType(CHAR(3) f0, INTEGER NOT NULL f1) NOT NULL ARRAY NOT NULL");
+
     // elements cast
     // key cast
     f.checkScalar("map_entries(map[cast(1 as tinyint), 1, 2, 2])", "[{1, 1}, 
{2, 2}]",
         "RecordType(INTEGER NOT NULL f0, INTEGER NOT NULL f1) NOT NULL ARRAY 
NOT NULL");
-    f.checkScalar("map_entries(map[cast(1 as bigint), 1, null, 2])", "[{1, 1}, 
{null, 2}]",
-        "RecordType(BIGINT f0, INTEGER NOT NULL f1) NOT NULL ARRAY NOT NULL");
-    f.checkScalar("map_entries(map[cast(1 as decimal), 1, null, 2])", "[{1, 
1}, {null, 2}]",
-        "RecordType(DECIMAL(19, 0) f0, INTEGER NOT NULL f1) NOT NULL ARRAY NOT 
NULL");
+
     // value cast
     f.checkScalar("map_entries(map[1, cast(1 as tinyint), 2, 2])", "[{1, 1}, 
{2, 2}]",
         "RecordType(INTEGER NOT NULL f0, INTEGER NOT NULL f1) NOT NULL ARRAY 
NOT NULL");
-    f.checkScalar("map_entries(map[1, cast(1 as bigint), null, 2])", "[{1, 1}, 
{null, 2}]",
-        "RecordType(INTEGER f0, BIGINT NOT NULL f1) NOT NULL ARRAY NOT NULL");
-    f.checkScalar("map_entries(map[1, cast(1 as decimal), null, 2])", "[{1, 
1}, {null, 2}]",
-        "RecordType(INTEGER f0, DECIMAL(19, 0) NOT NULL f1) NOT NULL ARRAY NOT 
NULL");
+
 
     // 2. check with map function, map(k, v ...)
     final SqlOperatorFixture f1 = fixture()
@@ -7801,8 +7794,16 @@ public class SqlOperatorTest {
         "RecordType(UNKNOWN NOT NULL f0, UNKNOWN NOT NULL f1) NOT NULL ARRAY 
NOT NULL");
     f1.checkScalar("map_entries(map('foo', 1, 'bar', 2))", "[{foo, 1}, {bar, 
2}]",
         "RecordType(CHAR(3) NOT NULL f0, INTEGER NOT NULL f1) NOT NULL ARRAY 
NOT NULL");
-    f1.checkScalar("map_entries(map('foo', 1, null, 2))", "[{foo, 1}, {null, 
2}]",
-        "RecordType(CHAR(3) f0, INTEGER NOT NULL f1) NOT NULL ARRAY NOT NULL");
+
+    // 3. check key is not allowed to be null
+    f.checkFails("map_entries(map[cast(1 as decimal), 1, null, 2])",
+        "Cannot use null as map key", true);
+    f.checkFails("map_entries(map[1, cast(1 as bigint), null, 2])",
+        "Cannot use null as map key", true);
+    f.checkFails("map_entries(map[1, cast(1 as decimal), null, 2])",
+        "Cannot use null as map key", true);
+    f.checkFails("map_entries(map['foo', 1, null, 2])",
+        "Cannot use null as map key", true);
   }
 
   /** Tests {@code MAP_KEYS} function from Spark. */

Reply via email to