[
https://issues.apache.org/jira/browse/CALCITE-5016?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Alessandro Solimando resolved CALCITE-5016.
-------------------------------------------
Resolution: Duplicate
> NPE: "variable $cor0 is not found", "Unable to implement EnumerableCorrelate"
> in nested ARRAY() query
> -----------------------------------------------------------------------------------------------------
>
> Key: CALCITE-5016
> URL: https://issues.apache.org/jira/browse/CALCITE-5016
> Project: Calcite
> Issue Type: Bug
> Components: core
> Affects Versions: 1.30.0
> Reporter: Gavin Ray
> Priority: Major
>
> If you remove the WHERE clause in the inner part, it will run:
> {code:sql}
> -- Remove this where clause to fix the bug
> WHERE
> "users"."house_id" = "houses"."id"
> {code}
> Here is a reproduction:
> {code:java}
> import org.apache.calcite.adapter.jdbc.JdbcSchema;
> import org.apache.calcite.jdbc.CalciteConnection;
> import org.apache.calcite.jdbc.Driver;
> import org.apache.calcite.rel.RelNode;
> import org.apache.calcite.schema.SchemaPlus;
> import org.apache.calcite.sql.SqlNode;
> import org.apache.calcite.sql.parser.SqlParseException;
> import org.apache.calcite.sql.parser.SqlParser;
> import org.apache.calcite.tools.*;
> import org.hsqldb.jdbc.JDBCDataSource;
> import java.sql.*;
> public class HouseUserTodoSchemaTest {
> static String ddl = """
> CREATE TABLE "houses" (
> "id" INTEGER NOT NULL,
> "address" VARCHAR(255) NOT NULL,
> );
> CREATE TABLE "users" (
> "id" INTEGER NOT NULL,
> "name" VARCHAR(255) NOT NULL,
> "house_id" INTEGER NOT NULL
> );
> CREATE TABLE "todos" (
> "id" INTEGER NOT NULL,
> "description" VARCHAR(255) NOT NULL,
> "user_id" INTEGER NOT NULL
> );
> """;
> static String dml = """
> INSERT INTO "houses" VALUES (1, '123 Main St');
> INSERT INTO "houses" VALUES (2, '456 Ocean Ave');
>
> INSERT INTO "users" VALUES (1, 'Alice', 1);
> INSERT INTO "users" VALUES (2, 'Bob', 1);
> INSERT INTO "users" VALUES (3, 'Carol', 2);
>
> INSERT INTO "todos" VALUES (1, 'Buy milk', 1);
> INSERT INTO "todos" VALUES (2, 'Buy eggs', 1);
> INSERT INTO "todos" VALUES (3, 'Buy bread', 2);
> INSERT INTO "todos" VALUES (4, 'Vacuum', 3);
> """;
> static String query = """
> SELECT
> "houses"."id",
> "houses"."address",
> ARRAY(
> SELECT
> "users"."id",
> "users"."name",
> ARRAY(
> SELECT
> "todos"."id",
> "todos"."description"
> FROM
> "todos"
> WHERE
> "todos"."user_id" = "users"."id"
> ) AS "todos"
> FROM
> "users"
> -- Remove this where clause to fix the bug
> WHERE
> "users"."house_id" = "houses"."id"
> ) AS "users"
> FROM
> "houses"
> """;
> public static void main(String[] args) throws SqlParseException,
> ValidationException, RelConversionException, ClassNotFoundException,
> SQLException {
> JDBCDataSource hsqldb = new org.hsqldb.jdbc.JDBCDataSource();
> hsqldb.setDatabase("jdbc:hsqldb:mem:house_user_todo");
> try (Connection connection = hsqldb.getConnection()) {
> try (Statement statement = connection.createStatement()) {
> statement.execute(ddl);
> statement.execute(dml);
> }
> }
> SchemaPlus rootSchema = Frameworks.createRootSchema(false);
> rootSchema.add("house_user_todo", JdbcSchema.create(rootSchema,
> "house_user_todo", hsqldb, null, null));
> FrameworkConfig config = Frameworks.newConfigBuilder()
> .parserConfig(SqlParser.config().withCaseSensitive(false))
> .defaultSchema(rootSchema.getSubSchema("house_user_todo"))
> .build();
> Planner planner = Frameworks.getPlanner(config);
> SqlNode sqlNode = planner.parse(query);
> SqlNode validated = planner.validate(sqlNode);
> RelNode relNode = planner.rel(validated).project();
> Class.forName(Driver.class.getName());
> Connection connection =
> DriverManager.getConnection(Driver.CONNECT_STRING_PREFIX);
> CalciteConnection calciteConnection =
> connection.unwrap(CalciteConnection.class);
> RelRunner runner = calciteConnection.unwrap(RelRunner.class);
> try (PreparedStatement ps = runner.prepareStatement(relNode)) {
> ResultSet rs = ps.executeQuery();
> while (rs.next()) {
> ResultSetMetaData md = rs.getMetaData();
> for (int i = 1; i <= md.getColumnCount(); i++) {
> System.out.print(md.getColumnName(i) + ": ");
> System.out.println(rs.getObject(i));
> }
> System.out.println();
> }
> }
> }
> }
> {code}
> And the stack trace:
> {code:java}
> Exception in thread "main" java.sql.SQLException: Error while preparing plan
> [LogicalProject(id=[$0], address=[$1], users=[$2])
> LogicalCorrelate(correlation=[$cor0], joinType=[inner],
> requiredColumns=[{0}])
> JdbcTableScan(table=[[house_user_todo, houses]])
> Collect(field=[EXPR$0])
> LogicalProject(id=[$0], name=[$1], todos=[$3])
> LogicalCorrelate(correlation=[$cor1], joinType=[inner],
> requiredColumns=[{0}])
> LogicalFilter(condition=[=($2, $cor0.id)])
> JdbcTableScan(table=[[house_user_todo, users]])
> Collect(field=[EXPR$0])
> LogicalProject(id=[$0], description=[$1])
> LogicalFilter(condition=[=($2, $cor1.id)])
> JdbcTableScan(table=[[house_user_todo, todos]])
> ]
> at org.apache.calcite.avatica.Helper.createException(Helper.java:56)
> at org.apache.calcite.avatica.Helper.createException(Helper.java:41)
> at
> org.apache.calcite.jdbc.CalciteConnectionImpl.prepareStatement_(CalciteConnectionImpl.java:239)
> at
> org.apache.calcite.jdbc.CalciteConnectionImpl.access$100(CalciteConnectionImpl.java:101)
> at
> org.apache.calcite.jdbc.CalciteConnectionImpl$2.prepareStatement(CalciteConnectionImpl.java:188)
> at
> com.example.HouseUserTodoSchemaTest.main(HouseUserTodoSchemaTest.java:105)
> Caused by: java.lang.IllegalStateException: Unable to implement
> EnumerableCorrelate(correlation=[$cor0], joinType=[inner],
> requiredColumns=[{0}]): rowcount = 22500.0, cumulative cost = {318610.0 rows,
> 562611.0 cpu, 0.0 io}, id = 252
> Caused by: java.lang.IllegalStateException: Unable to implement
> EnumerableCorrelate(correlation=[$cor0], joinType=[inner],
> requiredColumns=[{0}]): rowcount = 22500.0, cumulative cost = {318610.0 rows,
> 562611.0 cpu, 0.0 io}, id = 252
> JdbcToEnumerableConverter: rowcount = 100.0, cumulative cost = {110.0 rows,
> 111.0 cpu, 0.0 io}, id = 230
> JdbcTableScan(table=[[house_user_todo, houses]]): rowcount = 100.0,
> cumulative cost = {100.0 rows, 101.0 cpu, 0.0 io}, id = 15
> EnumerableCollect(field=[EXPR$0]): rowcount = 225.0, cumulative cost =
> {2959.0 rows, 5625.0 cpu, 0.0 io}, id = 250
> EnumerableCalc(expr#0..3=[{inputs}], proj#0..1=[{exprs}], todos=[$t3]):
> rowcount = 225.0, cumulative cost = {2734.0 rows, 5400.0 cpu, 0.0 io}, id =
> 254
> EnumerableCorrelate(correlation=[$cor1], joinType=[inner],
> requiredColumns=[{0}]): rowcount = 225.0, cumulative cost = {2509.0 rows,
> 3825.0 cpu, 0.0 io}, id = 246
> JdbcToEnumerableConverter: rowcount = 15.0, cumulative cost = {116.5
> rows, 202.5 cpu, 0.0 io}, id = 235
> JdbcFilter(condition=[=($2, $cor0.id)]): rowcount = 15.0,
> cumulative cost = {115.0 rows, 201.0 cpu, 0.0 io}, id = 233
> JdbcTableScan(table=[[house_user_todo, users]]): rowcount =
> 100.0, cumulative cost = {100.0 rows, 101.0 cpu, 0.0 io}, id = 16
> EnumerableCollect(field=[EXPR$0]): rowcount = 15.0, cumulative cost =
> {143.5 rows, 241.5 cpu, 0.0 io}, id = 244
> JdbcToEnumerableConverter: rowcount = 15.0, cumulative cost =
> {128.5 rows, 226.5 cpu, 0.0 io}, id = 242
> JdbcProject(id=[$0], description=[$1]): rowcount = 15.0,
> cumulative cost = {127.0 rows, 225.0 cpu, 0.0 io}, id = 240
> JdbcFilter(condition=[=($2, $cor1.id)]): rowcount = 15.0,
> cumulative cost = {115.0 rows, 201.0 cpu, 0.0 io}, id = 238
> JdbcTableScan(table=[[house_user_todo, todos]]): rowcount =
> 100.0, cumulative cost = {100.0 rows, 101.0 cpu, 0.0 io}, id = 18
> at
> org.apache.calcite.adapter.enumerable.EnumerableRelImplementor.implementRoot(EnumerableRelImplementor.java:114)
> at
> org.apache.calcite.adapter.enumerable.EnumerableInterpretable.toBindable(EnumerableInterpretable.java:114)
> at
> org.apache.calcite.prepare.CalcitePrepareImpl$CalcitePreparingStmt.implement(CalcitePrepareImpl.java:1130)
> at
> org.apache.calcite.prepare.CalcitePrepareImpl$CalcitePreparingStmt.prepare_(CalcitePrepareImpl.java:1032)
> at
> org.apache.calcite.prepare.CalcitePrepareImpl$CalcitePreparingStmt.prepareRel(CalcitePrepareImpl.java:988)
> at
> org.apache.calcite.prepare.CalcitePrepareImpl.prepare2_(CalcitePrepareImpl.java:668)
> at
> org.apache.calcite.prepare.CalcitePrepareImpl.prepare_(CalcitePrepareImpl.java:513)
> at
> org.apache.calcite.prepare.CalcitePrepareImpl.prepareSql(CalcitePrepareImpl.java:483)
> at
> org.apache.calcite.jdbc.CalciteConnectionImpl.parseQuery(CalciteConnectionImpl.java:249)
> at
> org.apache.calcite.jdbc.CalciteConnectionImpl.prepareStatement_(CalciteConnectionImpl.java:229)
> ... 3 more
> Suppressed: java.lang.NullPointerException: variable $cor0 is not found
> at java.base/java.util.Objects.requireNonNull(Objects.java:334)
> at
> org.apache.calcite.rel.rel2sql.SqlImplementor$BaseContext.getAliasContext(SqlImplementor.java:1429)
> at
> org.apache.calcite.rel.rel2sql.SqlImplementor$Context.toSql(SqlImplementor.java:628)
> at
> org.apache.calcite.rel.rel2sql.SqlImplementor$Context.toSql(SqlImplementor.java:1069)
> at
> org.apache.calcite.rel.rel2sql.SqlImplementor$Context.callToSql(SqlImplementor.java:776)
> at
> org.apache.calcite.rel.rel2sql.SqlImplementor$Context.toSql(SqlImplementor.java:750)
> at
> org.apache.calcite.rel.rel2sql.RelToSqlConverter.visit(RelToSqlConverter.java:427)
> at
> java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at
> java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
> at
> java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> at java.base/java.lang.reflect.Method.invoke(Method.java:568)
> at
> org.apache.calcite.util.ReflectUtil$2.invoke(ReflectUtil.java:531)
> at
> org.apache.calcite.rel.rel2sql.RelToSqlConverter.dispatch(RelToSqlConverter.java:139)
> at
> org.apache.calcite.rel.rel2sql.RelToSqlConverter.visitInput(RelToSqlConverter.java:147)
> at
> org.apache.calcite.rel.rel2sql.SqlImplementor.visitInput(SqlImplementor.java:201)
> at
> org.apache.calcite.rel.rel2sql.SqlImplementor.visitInput(SqlImplementor.java:189)
> at
> org.apache.calcite.adapter.jdbc.JdbcToEnumerableConverter.generateSql(JdbcToEnumerableConverter.java:351)
> at
> org.apache.calcite.adapter.jdbc.JdbcToEnumerableConverter.implement(JdbcToEnumerableConverter.java:107)
> at
> org.apache.calcite.adapter.enumerable.EnumerableRelImplementor.visitChild(EnumerableRelImplementor.java:104)
> at
> org.apache.calcite.adapter.enumerable.EnumerableCorrelate.implement(EnumerableCorrelate.java:113)
> at
> org.apache.calcite.adapter.enumerable.EnumerableRelImplementor.visitChild(EnumerableRelImplementor.java:104)
> at
> org.apache.calcite.adapter.enumerable.EnumerableCalc.implement(EnumerableCalc.java:118)
> at
> org.apache.calcite.adapter.enumerable.EnumerableRelImplementor.visitChild(EnumerableRelImplementor.java:104)
> at
> org.apache.calcite.adapter.enumerable.EnumerableCollect.implement(EnumerableCollect.java:81)
> at
> org.apache.calcite.adapter.enumerable.EnumerableRelImplementor.visitChild(EnumerableRelImplementor.java:104)
> at
> org.apache.calcite.adapter.enumerable.EnumerableCorrelate.implement(EnumerableCorrelate.java:139)
> at
> org.apache.calcite.adapter.enumerable.EnumerableRelImplementor.implementRoot(EnumerableRelImplementor.java:111)
> ... 12 more
> {code}
--
This message was sent by Atlassian Jira
(v8.20.1#820001)