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. */