Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4940,6 +4940,40 @@ ImmutableList<RelNode> retrieveCursors() {
}
}

/** Tries to simplify case:
* select t1.a FROM emps t1 JOIN emps t2 ON (SELECT t2.a) _compare opeartor_ val;
* The idea is to transform such a case into equivalent:
* select t1.a FROM emps t1 JOIN emps t2 ON t2.a _compare opeartor_ val;
*/
private @Nullable RexNode simplifyOnWithSelectInConditions(SqlNode expr) {
if (!(expr instanceof SqlBasicCall)) {
return null;
}
// (select t2.a) _compare opeartor_ val
SqlBasicCall call0 = (SqlBasicCall) expr;
if (call0.operandCount() != 2 || !(call0.operand(0) instanceof SqlBasicCall)) {
return null;
}
// left side i.e. (select t2.a)
SqlBasicCall selectCall = call0.operand(0);
if (selectCall.operandCount() != 1 || !(selectCall.getOperands()[0] instanceof SqlSelect)) {
return null;
}
// select t2.a
@Nullable SqlSelect colExpr = (SqlSelect) selectCall.getOperands()[0];
// empty from case, only 1 operand in current case possible
if (colExpr == null || colExpr.getFrom() != null || colExpr.getSelectList().size() != 1) {
return null;
}
// a
SqlNode selectParam = colExpr.getSelectList().get(0);
SqlNode op2 = call0.operand(1);
RexNode exp0 = convertExpression(selectParam);
RexNode exp1 = convertExpression(op2);
RexNode rex0 = rexBuilder.makeCall(call0.getOperator(), exp0, exp1);
return rex0;
}

@Override public RexNode convertExpression(SqlNode expr) {
// If we're in aggregation mode and this is an expression in the
// GROUP BY clause, return a reference to the field.
Expand Down Expand Up @@ -4974,6 +5008,16 @@ ImmutableList<RelNode> retrieveCursors() {
final SqlNode query;
final RelRoot root;
switch (kind) {
case LESS_THAN:
case GREATER_THAN:
case LESS_THAN_OR_EQUAL:
case GREATER_THAN_OR_EQUAL:
case EQUALS:
RexNode res = simplifyOnWithSelectInConditions(expr);
if (res != null) {
return res;
}
break;
case IN:
case NOT_IN:
case SOME:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,102 @@ class EnumerableCorrelateTest {
"empid=200");
}

/** Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-4833">[CALCITE-4833]
* Complex nested correlated subquery failed</a>.
*/
@Test void complexNestedCorrelatedSubquery() {
String sql = "SELECT t1.empid FROM emps t1 LEFT JOIN emps t2 ON (SELECT t2.empid)<=101";

tester(false, new HrSchema())
.query(sql)
.explainContains(""
+ "EnumerableCalc(expr#0..1=[{inputs}], empid=[$t0])\n"
+ " EnumerableNestedLoopJoin(condition=[true], joinType=[left])\n"
+ " EnumerableCalc(expr#0..4=[{inputs}], empid=[$t0])\n"
+ " EnumerableTableScan(table=[[s, emps]])\n"
+ " EnumerableCalc(expr#0..4=[{inputs}], expr#5=[101], expr#6=[<=($t0, $t5)], $f5=[$t6], $condition=[$t6])\n"
+ " EnumerableTableScan(table=[[s, emps]])\n\n")
.returnsUnordered(
"empid=100",
"empid=110",
"empid=150",
"empid=200");

sql = "SELECT t1.empid FROM emps t1 LEFT JOIN emps t2 ON (SELECT t2.empid)<101";

tester(false, new HrSchema())
.query(sql)
.explainContains(""
+ "EnumerableCalc(expr#0..1=[{inputs}], empid=[$t0])\n"
+ " EnumerableNestedLoopJoin(condition=[true], joinType=[left])\n"
+ " EnumerableCalc(expr#0..4=[{inputs}], empid=[$t0])\n"
+ " EnumerableTableScan(table=[[s, emps]])\n"
+ " EnumerableCalc(expr#0..4=[{inputs}], expr#5=[101], expr#6=[<($t0, $t5)], $f5=[$t6], $condition=[$t6])\n"
+ " EnumerableTableScan(table=[[s, emps]])\n\n")
.returnsUnordered(
"empid=100",
"empid=110",
"empid=150",
"empid=200");

sql = "SELECT t1.empid FROM emps t1 LEFT JOIN emps t2 ON (SELECT t2.empid)>150";

tester(false, new HrSchema())
.query(sql)
.explainContains(""
+ "EnumerableCalc(expr#0..1=[{inputs}], empid=[$t0])\n"
+ " EnumerableNestedLoopJoin(condition=[true], joinType=[left])\n"
+ " EnumerableCalc(expr#0..4=[{inputs}], empid=[$t0])\n"
+ " EnumerableTableScan(table=[[s, emps]])\n"
+ " EnumerableCalc(expr#0..4=[{inputs}], expr#5=[150], expr#6=[>($t0, $t5)], $f5=[$t6], $condition=[$t6])\n"
+ " EnumerableTableScan(table=[[s, emps]])\n\n")
.returnsUnordered(
"empid=100",
"empid=110",
"empid=150",
"empid=200");

sql = "SELECT t1.empid FROM emps t1 LEFT JOIN emps t2 ON (SELECT t2.empid)=150";

tester(false, new HrSchema())
.query(sql)
.explainContains(""
+ "EnumerableCalc(expr#0..1=[{inputs}], empid=[$t0])\n" +
" EnumerableNestedLoopJoin(condition=[true], joinType=[left])\n" +
" EnumerableCalc(expr#0..4=[{inputs}], empid=[$t0])\n" +
" EnumerableTableScan(table=[[s, emps]])\n" +
" EnumerableCalc(expr#0..4=[{inputs}], expr#5=[150], expr#6=[=($t0, $t5)], empid=[$t0], $condition=[$t6])\n" +
" EnumerableTableScan(table=[[s, emps]])\n\n")
.returnsUnordered(
"empid=100",
"empid=110",
"empid=150",
"empid=200");

sql = "SELECT t1.empid FROM emps t1 LEFT JOIN emps t2 ON (SELECT t2.empid)=(select 100 + 50)";

tester(false, new HrSchema())
.query(sql)
.explainContains(""
+ "EnumerableCalc(expr#0..2=[{inputs}], empid=[$t0])\n"
+ " EnumerableNestedLoopJoin(condition=[true], joinType=[left])\n"
+ " EnumerableCalc(expr#0..4=[{inputs}], empid=[$t0])\n"
+ " EnumerableTableScan(table=[[s, emps]])\n"
+ " EnumerableCalc(expr#0..1=[{inputs}], expr#2=[CAST($t0):INTEGER], empid=[$t1], $f0=[$t2])\n"
+ " EnumerableHashJoin(condition=[=($0, $1)], joinType=[inner])\n"
+ " EnumerableAggregate(group=[{}], agg#0=[SINGLE_VALUE($0)])\n"
+ " EnumerableCalc(expr#0=[{inputs}], expr#1=[100], expr#2=[50], expr#3=[+($t1, $t2)], EXPR$0=[$t3])\n"
+ " EnumerableValues(tuples=[[{ 0 }]])\n"
+ " EnumerableCalc(expr#0..4=[{inputs}], empid=[$t0])\n"
+ " EnumerableTableScan(table=[[s, emps]])\n\n")
.returnsUnordered(
"empid=100",
"empid=110",
"empid=150",
"empid=200");
}

/** Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-2920">[CALCITE-2920]
* RelBuilder: new method to create an anti-join</a>. */
Expand Down