[Bug] Fix bug that push down logic error on semi join (#3481)

For SQL like:
```
select * from
join1 left semi join join2
on join1.id = join2.id and join2.id > 1;
```

the predicate `join2.id > 1` can not be pushed down to table join1.
This commit is contained in:
Mingyu Chen
2020-05-07 09:30:30 +08:00
committed by GitHub
parent 7399997433
commit ca36dc697f
2 changed files with 60 additions and 3 deletions

View File

@ -956,8 +956,9 @@ public class Analyzer {
/**
* Return all registered conjuncts that are fully bound by
* given list of tuple ids, the eqJoinConjuncts and inclOjConjuncts is excluded.
* Return all registered conjuncts that are fully bound by given list of tuple ids.
* the eqJoinConjuncts and sjClauseByConjunct is excluded.
* This method is used get conjuncts which may be able to pushed down to scan node.
*/
public List<Expr> getConjuncts(List<TupleId> tupleIds) {
List<Expr> result = Lists.newArrayList();
@ -968,8 +969,9 @@ public class Analyzer {
for (Expr e : globalState.conjuncts.values()) {
if (e.isBoundByTupleIds(tupleIds)
&& !e.isAuxExpr()
&& !eqJoinConjunctIds.contains(e.getId())
&& !eqJoinConjunctIds.contains(e.getId()) // to exclude to conjuncts like (A.id = B.id)
&& !globalState.ojClauseByConjunct.containsKey(e.getId())
&& !globalState.sjClauseByConjunct.containsKey(e.getId())
&& canEvalPredicate(tupleIds, e)) {
result.add(e);
}

View File

@ -655,6 +655,61 @@ public class QueryPlanTest {
System.out.println(explainString);
Assert.assertTrue(explainString.contains("PREDICATES: `join1`.`id` > 1"));
Assert.assertTrue(explainString.contains("PREDICATES: `join2`.`id` > 1"));
// test anti join, right table join predicate, only push to right table
sql = "select *\n from join1\n" +
"left anti join join2 on join1.id = join2.id\n" +
"and join2.id > 1;";
explainString = UtFrameUtils.getSQLPlanOrErrorMsg(connectContext, "explain " + sql);
System.out.println(explainString);
Assert.assertTrue(explainString.contains("PREDICATES: `join2`.`id` > 1"));
Assert.assertFalse(explainString.contains("PREDICATES: `join1`.`id` > 1"));
// test semi join, right table join predicate, only push to right table
sql = "select *\n from join1\n" +
"left semi join join2 on join1.id = join2.id\n" +
"and join2.id > 1;";
explainString = UtFrameUtils.getSQLPlanOrErrorMsg(connectContext, "explain " + sql);
System.out.println(explainString);
Assert.assertTrue(explainString.contains("PREDICATES: `join2`.`id` > 1"));
Assert.assertFalse(explainString.contains("PREDICATES: `join1`.`id` > 1"));
// test anti join, left table join predicate, left table couldn't push down
sql = "select *\n from join1\n" +
"left anti join join2 on join1.id = join2.id\n" +
"and join1.id > 1;";
explainString = UtFrameUtils.getSQLPlanOrErrorMsg(connectContext, "explain " + sql);
System.out.println(explainString);
Assert.assertTrue(explainString.contains("other join predicates: `join1`.`id` > 1"));
Assert.assertFalse(explainString.contains("PREDICATES: `join1`.`id` > 1"));
// test semi join, left table join predicate, only push to left table
sql = "select *\n from join1\n" +
"left semi join join2 on join1.id = join2.id\n" +
"and join1.id > 1;";
explainString = UtFrameUtils.getSQLPlanOrErrorMsg(connectContext, "explain " + sql);
System.out.println(explainString);
Assert.assertTrue(explainString.contains("PREDICATES: `join1`.`id` > 1"));
// test anti join, left table where predicate, only push to left table
sql = "select join1.id\n" +
"from join1\n" +
"left anti join join2 on join1.id = join2.id\n" +
"where join1.id > 1;";
explainString = UtFrameUtils.getSQLPlanOrErrorMsg(connectContext, "explain " + sql);
System.out.println(explainString);
Assert.assertTrue(explainString.contains("PREDICATES: `join1`.`id` > 1"));
Assert.assertFalse(explainString.contains("PREDICATES: `join2`.`id` > 1"));
// test semi join, left table where predicate, only push to left table
sql = "select join1.id\n" +
"from join1\n" +
"left semi join join2 on join1.id = join2.id\n" +
"where join1.id > 1;";
explainString = UtFrameUtils.getSQLPlanOrErrorMsg(connectContext, "explain " + sql);
System.out.println(explainString);
Assert.assertTrue(explainString.contains("PREDICATES: `join1`.`id` > 1"));
Assert.assertFalse(explainString.contains("PREDICATES: `join2`.`id` > 1"));
}
@Test