diff --git a/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java b/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java index 0404fa7bc51c..586680778ada 100644 --- a/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java +++ b/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java @@ -546,17 +546,34 @@ public Result visit(Correlate e) { null); return result(join, leftResult, rightResult); } - /** Visits a Filter; called by {@link #dispatch} via reflection. */ public Result visit(Filter e) { final RelNode input = e.getInput(); + final Set definedHere = e.getVariablesSet(); + if (input instanceof Aggregate) { final Aggregate aggregate = (Aggregate) input; final boolean ignoreClauses = aggregate.getInput() instanceof Project; - final Result x = + Result x = visitInput(e, 0, isAnon(), ignoreClauses, ImmutableSet.of(Clause.HAVING)); + final boolean pushed = !definedHere.isEmpty() + && e.getInput().getInputs().size() <= 1; + if (pushed) { + String alias = x.neededAlias; + if (alias != null) { + x = x.resetAliasForCorrelation(alias, e.getInput().getRowType()); + } else { + alias = unqualifiedName(x.node); + if (alias == null) { + alias = "t"; + } + x = x.resetAliasForCorrelation + (alias, e.getInput().getRowType()); + } + } parseCorrelTable(e, x); + final Builder builder = x.builder(e); x.asSelect().setHaving( SqlUtil.andExpressions(x.asSelect().getHaving(), @@ -564,8 +581,20 @@ public Result visit(Filter e) { return builder.result(); } else { Result x = visitInput(e, 0, Clause.WHERE); - if (!e.getVariablesSet().isEmpty()) { - x = x.resetAlias(); + final boolean pushed = !definedHere.isEmpty() + && e.getInput().getInputs().size() <= 1; + if (pushed) { + String alias = x.neededAlias; + if (alias != null) { + x = x.resetAliasForCorrelation(alias, e.getInput().getRowType()); + } else { + alias = unqualifiedName(x.node); + if (alias == null) { + alias = "t"; + } + x = x.resetAliasForCorrelation + (alias, e.getInput().getRowType()); + } } parseCorrelTable(e, x); final Builder builder = x.builder(e); diff --git a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java index 4e2825bb3b62..52a45703fe6c 100644 --- a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java +++ b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java @@ -6527,7 +6527,7 @@ private void checkLiteral2(String expression, String expected) { + "from \"sales_fact_1997\"b " + "where b.\"product_id\" = a.\"product_id\")"; String expected = "SELECT \"product_name\"\n" - + "FROM \"foodmart\".\"product\"\n" + + "FROM \"foodmart\".\"product\" AS \"product\"\n" + "WHERE EXISTS (SELECT COUNT(*)\n" + "FROM \"foodmart\".\"sales_fact_1997\"\n" + "WHERE \"product_id\" = \"product\".\"product_id\")"; @@ -6540,7 +6540,7 @@ private void checkLiteral2(String expression, String expected) { + "from \"sales_fact_1997\"b " + "where b.\"product_id\" = a.\"product_id\")"; String expected = "SELECT \"product_name\"\n" - + "FROM \"foodmart\".\"product\"\n" + + "FROM \"foodmart\".\"product\" AS \"product\"\n" + "WHERE NOT EXISTS (SELECT COUNT(*)\n" + "FROM \"foodmart\".\"sales_fact_1997\"\n" + "WHERE \"product_id\" = \"product\".\"product_id\")"; @@ -6553,7 +6553,7 @@ private void checkLiteral2(String expression, String expected) { + "from \"sales_fact_1997\"b " + "where b.\"product_id\" = a.\"product_id\")"; String expected = "SELECT \"product_name\"\n" - + "FROM \"foodmart\".\"product\"\n" + + "FROM \"foodmart\".\"product\" AS \"product\"\n" + "WHERE \"product_id\" IN (SELECT \"product_id\"\n" + "FROM \"foodmart\".\"sales_fact_1997\"\n" + "WHERE \"product_id\" = \"product\".\"product_id\")"; @@ -6575,7 +6575,7 @@ private void checkLiteral2(String expression, String expected) { + "from \"sales_fact_1997\"b " + "where b.\"product_id\" = a.\"product_id\")"; String expected = "SELECT \"product_name\"\n" - + "FROM \"foodmart\".\"product\"\n" + + "FROM \"foodmart\".\"product\" AS \"product\"\n" + "WHERE \"product_id\" NOT IN (SELECT \"product_id\"\n" + "FROM \"foodmart\".\"sales_fact_1997\"\n" + "WHERE \"product_id\" = \"product\".\"product_id\")"; @@ -6593,7 +6593,7 @@ private void checkLiteral2(String expression, String expected) { + "where t2.\"product_id\" = t1.\"product_id\" " + "and t1.\"product_id\" = 2 and t2.\"product_id\" = 1)"; String expected = "SELECT \"product_name\"\n" - + "FROM \"foodmart\".\"product\"\n" + + "FROM \"foodmart\".\"product\" AS \"product\"\n" + "WHERE \"product_id\" NOT IN (SELECT \"product_id\"\n" + "FROM \"foodmart\".\"product\" AS \"product0\"\n" + "WHERE \"product_id\" = \"product\".\"product_id\" " @@ -8892,7 +8892,7 @@ private void checkLiteral2(String expression, String expected) { + "GROUP BY \"t1\".\"department_id\"\n" + "HAVING \"t1\".\"department_id\" = MIN(\"t1\".\"department_id\")) \"t4\" ON \"employee\".\"department_id\" = \"t4\".\"department_id0\""; final String expectedNoExpand = "SELECT \"department_id\"\n" - + "FROM \"foodmart\".\"employee\"\n" + + "FROM \"foodmart\".\"employee\" AS \"employee\"\n" + "WHERE \"department_id\" = (SELECT MIN(\"employee\".\"department_id\")\n" + "FROM \"foodmart\".\"department\"\n" + "WHERE 1 = 2)"; @@ -12324,4 +12324,29 @@ public Sql schema(CalciteAssert.SchemaSpec schemaSpec) { sql(query).withLibrary(SqlLibrary.HIVE).withHive().ok(expectedHive); sql(query).withLibrary(SqlLibrary.SPARK).withSpark().ok(expectedSpark); } + + /** Test case for + * [CALCITE-7505] + * RelToSqlConverter fails to alias outer relation for correlated sub-queries in Filter. */ + @Test void testExistsSubQueryAliasConflict() { + final String sql = + "select deptno, sum(sal) as total\n" + + "from emp t\n" + + "where exists (\n" + + " select * from dept t0\n" + + " where deptno = t.deptno\n" + + ")\n" + + "group by deptno"; + + + sql(sql) + .schema(CalciteAssert.SchemaSpec.JDBC_SCOTT) + .ok( + "SELECT \"DEPTNO\", SUM(\"SAL\") AS \"TOTAL\"\n" + + "FROM \"SCOTT\".\"EMP\" AS \"EMP\"\n" + + "WHERE EXISTS (SELECT *\n" + + "FROM \"SCOTT\".\"DEPT\"\n" + + "WHERE \"DEPTNO\" = \"EMP\".\"DEPTNO\")\n" + + "GROUP BY \"DEPTNO\""); + } }