This is an automated email from the ASF dual-hosted git repository.
jhyde 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 c330aa30fd [CALCITE-5407] MongoDB adapter throws NullPointerException
when converting an array
c330aa30fd is described below
commit c330aa30fde760eba9086a4b7b1e88b87a5f478b
Author: Tim Nieradzik <[email protected]>
AuthorDate: Wed Nov 30 11:50:31 2022 +0300
[CALCITE-5407] MongoDB adapter throws NullPointerException when converting
an array
The following conversion does not work as expected:
```
cast(_MAP['arr'] as VARCHAR ARRAY)
```
This throws the following exception:
```
Caused by: java.lang.NullPointerException: componentType of ITEM($0, 'arr')
at java.base/java.util.Objects.requireNonNull(Objects.java:347)
at
org.apache.calcite.sql2rel.StandardConvertletTable.convertCast(StandardConvertletTable.java:603)
at
org.apache.calcite.sql2rel.SqlNodeToRexConverterImpl.convertCall(SqlNodeToRexConverterImpl.java:59)
at
org.apache.calcite.sql2rel.SqlToRelConverter$Blackboard.visit(SqlToRelConverter.java:5547)
at
org.apache.calcite.sql2rel.SqlToRelConverter$Blackboard.visit(SqlToRelConverter.java:4711)
at org.apache.calcite.sql.SqlCall.accept(SqlCall.java:161)
at
org.apache.calcite.sql2rel.SqlToRelConverter$Blackboard.convertExpression(SqlToRelConverter.java:5360)
at
org.apache.calcite.sql2rel.SqlToRelConverter.convertSelectList(SqlToRelConverter.java:4524)
at
org.apache.calcite.sql2rel.SqlToRelConverter.convertSelectImpl(SqlToRelConverter.java:756)
at
org.apache.calcite.sql2rel.SqlToRelConverter.convertSelect(SqlToRelConverter.java:677)
at
org.apache.calcite.sql2rel.SqlToRelConverter.convertQueryRecursive(SqlToRelConverter.java:3741)
at
org.apache.calcite.sql2rel.SqlToRelConverter.convertQuery(SqlToRelConverter.java:597)
at org.apache.calcite.prepare.Prepare.prepareSql(Prepare.java:257)
at org.apache.calcite.prepare.Prepare.prepareSql(Prepare.java:220)
at
org.apache.calcite.prepare.CalcitePrepareImpl.prepare2_(CalcitePrepareImpl.java:651)
at
org.apache.calcite.prepare.CalcitePrepareImpl.prepare_(CalcitePrepareImpl.java:517)
at
org.apache.calcite.prepare.CalcitePrepareImpl.prepareSql(CalcitePrepareImpl.java:487)
at
org.apache.calcite.jdbc.CalciteConnectionImpl.parseQuery(CalciteConnectionImpl.java:236)
at
org.apache.calcite.jdbc.CalciteMetaImpl.prepareAndExecute(CalciteMetaImpl.java:623)
at
org.apache.calcite.avatica.AvaticaConnection.prepareAndExecuteInternal(AvaticaConnection.java:677)
at
org.apache.calcite.avatica.AvaticaStatement.executeInternal(AvaticaStatement.java:156)
... 67 more
```
---
.../calcite/sql2rel/StandardConvertletTable.java | 12 +++++++----
.../calcite/adapter/mongodb/MongoAdapterTest.java | 25 ++++++++++++++++++++++
2 files changed, 33 insertions(+), 4 deletions(-)
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 c6c2dfa098..cdf840c2d5 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
@@ -603,10 +603,14 @@ public class StandardConvertletTable extends
ReflectiveConvertletTable {
return cx.convertExpression(left);
}
if (null != dataType.getCollectionsTypeName()) {
- final RelDataType argComponentType =
- requireNonNull(
- arg.getType().getComponentType(),
- () -> "componentType of " + arg);
+ RelDataType argComponentType = arg.getType().getComponentType();
+
+ // arg.getType() may be ANY
+ if (argComponentType == null) {
+ argComponentType =
dataType.getComponentTypeSpec().deriveType(cx.getValidator());
+ }
+
+ requireNonNull(argComponentType, () -> "componentType of " + arg);
RelDataType typeFinal = type;
final RelDataType componentType = requireNonNull(
diff --git
a/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoAdapterTest.java
b/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoAdapterTest.java
index a9aa191fa6..d2e589985b 100644
---
a/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoAdapterTest.java
+++
b/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoAdapterTest.java
@@ -32,6 +32,7 @@ import com.mongodb.client.MongoDatabase;
import net.hydromatic.foodmart.data.json.FoodmartJson;
+import org.bson.BsonArray;
import org.bson.BsonDateTime;
import org.bson.BsonDocument;
import org.bson.BsonInt32;
@@ -107,6 +108,7 @@ public class MongoAdapterTest implements SchemaFactory {
doc.put("date", new BsonDateTime(instant.toEpochMilli()));
doc.put("value", new BsonInt32(1231));
doc.put("ownerId", new BsonString("531e7789e4b0853ddb861313"));
+ doc.put("arr", new BsonArray(Arrays.asList(new BsonString("a"), new
BsonString("b"))));
datatypes.insertOne(doc);
schema = new MongoSchema(database);
@@ -731,6 +733,29 @@ public class MongoAdapterTest implements SchemaFactory {
.returnsUnordered("EXPR$0=2012-09-05 00:00:00");
}
+ /** Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-5407">[CALCITE-5407]
+ * Error casting MongoDB array to VARCHAR ARRAY</a>. */
+ @Test void testArrayConversion() {
+ assertModel("{\n"
+ + " version: '1.0',\n"
+ + " defaultSchema: 'test',\n"
+ + " schemas: [\n"
+ + " {\n"
+ + " type: 'custom',\n"
+ + " name: 'test',\n"
+ + " factory:
'org.apache.calcite.adapter.mongodb.MongoSchemaFactory',\n"
+ + " operand: {\n"
+ + " host: 'localhost',\n"
+ + " database: 'test'\n"
+ + " }\n"
+ + " }\n"
+ + " ]\n"
+ + "}")
+ .query("select cast(_MAP['arr'] as VARCHAR ARRAY) from \"datatypes\"")
+ .returnsUnordered("EXPR$0=[a, b]");
+ }
+
/** Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-665">[CALCITE-665]
* ClassCastException in MongoDB adapter</a>. */