Gavin Ray created CALCITE-5016:
----------------------------------

             Summary: 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


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)

Reply via email to