This is an automated email from the ASF dual-hosted git repository.
htowaileb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/asterixdb.git
The following commit(s) were added to refs/heads/master by this push:
new d884873d85 [ASTERIXDB-3240][COMP] Convert Outer joins to joins when
possible
d884873d85 is described below
commit d884873d85a42a383a013095a29688fe34f49bbe
Author: murali4104 <[email protected]>
AuthorDate: Wed Aug 9 15:30:12 2023 -0700
[ASTERIXDB-3240][COMP] Convert Outer joins to joins when possible
Change-Id: Ic102b958f564439a7075430e0c7286396f37d9ef
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/17713
Integration-Tests: Jenkins <[email protected]>
Tested-by: Jenkins <[email protected]>
Reviewed-by: Vijay Sarathy <[email protected]>
---
.../optimizer/rules/cbo/EnumerateJoinsRule.java | 108 +++++++++++++--------
1 file changed, 67 insertions(+), 41 deletions(-)
diff --git
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/EnumerateJoinsRule.java
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/EnumerateJoinsRule.java
index 52b4a4cf51..f1645275e7 100644
---
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/EnumerateJoinsRule.java
+++
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/EnumerateJoinsRule.java
@@ -56,6 +56,7 @@ import
org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogi
import
org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
import
org.apache.hyracks.algebricks.core.algebra.operators.logical.DataSourceScanOperator;
import
org.apache.hyracks.algebricks.core.algebra.operators.logical.EmptyTupleSourceOperator;
+import
org.apache.hyracks.algebricks.core.algebra.operators.logical.InnerJoinOperator;
import
org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
import
org.apache.hyracks.algebricks.core.algebra.operators.logical.visitors.VariableUtilities;
import org.apache.hyracks.algebricks.core.algebra.plan.ALogicalPlanImpl;
@@ -142,7 +143,7 @@ public class EnumerateJoinsRule implements
IAlgebraicRewriteRule {
return false;
}
- //convertOuterJoinstoJoinsIfPossible(outerJoinsDependencyList);
+ convertOuterJoinstoJoinsIfPossible(outerJoinsDependencyList);
printPlan(pp, (AbstractLogicalOperator) op, "Original Whole plan2");
int numberOfFromTerms = leafInputs.size();
@@ -420,38 +421,41 @@ public class EnumerateJoinsRule implements
IAlgebraicRewriteRule {
return false;
}
- /* will implement this soon
// dependencylist is first, second, op
// If we have R outer join S, first is the null extending table as in R,
null
// In this case, if S is to joined, then R must be present. So S depends
on R.
// If we have a case of (first, second, LOJ_operator) = (R_leaf_input_id,
S_leaf_input_id, LOJop),
// and another (S_leaf_input_id, ..., joinOp),
// OR (..., S_leaf_input_id, joinOp) then the LOJ can be converted to a
join!!
- private void convertOuterJoinstoJoinsIfPossible(List<Quadruple<Integer,
Integer, JoinOperator, Integer>> outerJoinsDependencyList) {
- List<Integer> getRidOff = new ArrayList<>();
- int i;
- //for (Triple<Integer, Integer, ILogicalOperator> tr1 :
outerJoinsDependencyList) {
- for (i = 0; i < outerJoinsDependencyList.size(); i++) {
- Quadruple<Integer, Integer, JoinOperator, Integer> tr1 =
outerJoinsDependencyList.get(i);
- if (tr1.getThird().getOuterJoin()) {
- for (Quadruple<Integer, Integer, JoinOperator, Integer> tr2 :
outerJoinsDependencyList) {
- if (tr2.getThird().getOuterJoin()) {
- if ((tr1.getSecond().equals(tr2.getFirst())) ||
(tr1.getSecond().equals(tr2.getSecond()))) {
- getRidOff.add(i);
+ private void convertOuterJoinstoJoinsIfPossible(
+ List<Quadruple<Integer, Integer, JoinOperator, Integer>>
outerJoinsDependencyList) {
+ int i, j;
+ boolean changes = true;
+ while (changes) {
+ changes = false;
+ for (i = 0; i < outerJoinsDependencyList.size(); i++) {
+ Quadruple<Integer, Integer, JoinOperator, Integer> tr1 =
outerJoinsDependencyList.get(i);
+ if (tr1.getThird().getOuterJoin()) {
+ for (j = 0; j < outerJoinsDependencyList.size(); j++) {
+ Quadruple<Integer, Integer, JoinOperator, Integer> tr2
= outerJoinsDependencyList.get(j);
+ if ((i != j) && !(tr2.getThird().getOuterJoin())) {
+ if ((tr1.getSecond().equals(tr2.getFirst())) ||
(tr1.getSecond().equals(tr2.getSecond()))) {
+
outerJoinsDependencyList.get(i).getThird().setOuterJoin(false);
+ changes = true;
+ }
}
}
}
}
}
-
- for (i = getRidOff.size() - 1; i >= 0; i--) {
- int j = getRidOff.get(i);
- JoinOperator joinOp = outerJoinsDependencyList.get(j).getThird();
- joinOp.setOuterJoin(false);
- outerJoinsDependencyList.remove(j);
+
+ // now remove all joins from the list, as we do not need them anymore!
We only need the outer joins
+ for (i = outerJoinsDependencyList.size() - 1; i >= 0; i--) {
+ if (!outerJoinsDependencyList.get(i).getThird().getOuterJoin()) {
+ outerJoinsDependencyList.remove(i);
+ }
}
}
- */
// Each outer join will create one set of dependencies. The right side
depends on the left side.
private boolean buildDependencyList(ILogicalOperator op, JoinOperator jO,
@@ -480,7 +484,7 @@ public class EnumerateJoinsRule implements
IAlgebraicRewriteRule {
}
}
if (leftSideExprBits != 0 && rightSideExprBits != 0) {// avoid
expressions like true
- outerJoinsDependencyList.add(new
Quadruple(leftSideExprBits, rightSideBits, jO, 1));
+ outerJoinsDependencyList.add(new
Quadruple(leftSideExprBits, rightSideBits, jO, 0));
}
}
} else {
@@ -499,7 +503,7 @@ public class EnumerateJoinsRule implements
IAlgebraicRewriteRule {
}
}
if (leftSideExprBits != 0 && rightSideExprBits != 0) {// avoid
expressions like true
- outerJoinsDependencyList.add(new Quadruple(leftSideExprBits,
rightSideBits, jO, 1));
+ outerJoinsDependencyList.add(new Quadruple(leftSideExprBits,
rightSideBits, jO, 0));
}
}
return true;
@@ -547,11 +551,14 @@ public class EnumerateJoinsRule implements
IAlgebraicRewriteRule {
lastLeafInputNumber = leafInputNumber; // we are interested in
the 2nd input only
k = 0;
// now we know the leafInput numbers that occurred on the
right side of this join.
- if ((op.getOperatorTag() == LogicalOperatorTag.LEFTOUTERJOIN)
&& (i == 1)) {
+ //if ((op.getOperatorTag() ==
LogicalOperatorTag.LEFTOUTERJOIN) && (i == 1)) {
+ if ((joinClause(op)) && (i == 1)) {
for (int j = firstLeafInputNumber; j <=
lastLeafInputNumber; j++) {
k |= 1 << (j - 1);
}
- if (firstLeafInputNumber < lastLeafInputNumber) { // if
more is than one leafInput, only then buildSets make sense.
+ // buildSets are only for outerjoins.
+ if ((op.getOperatorTag() ==
LogicalOperatorTag.LEFTOUTERJOIN)
+ && (firstLeafInputNumber < lastLeafInputNumber)) {
// if more is than one leafInput, only then buildSets make sense.
buildSets.add(new Triple<>(k, lastLeafInputNumber -
firstLeafInputNumber + 1, true)); // convert the second to boolean later
}
boolean ret = buildDependencyList(op, jO,
outerJoinsDependencyList, k);
@@ -723,21 +730,41 @@ public class EnumerateJoinsRule implements
IAlgebraicRewriteRule {
}
private void getJoinNode(PlanNode plan, List<JoinOperator> allJoinOps)
throws AlgebricksException {
- //AbstractBinaryJoinOperator joinOp;
- Boolean outerJoin;
- LogicalOperatorTag tag;
- if (plan.outerJoin) {
- outerJoin = true;
- } else {
- outerJoin = false;
- }
- int i = -1;
- for (JoinOperator ajOp : allJoinOps) {
- i++;
- if (ajOp.getOuterJoin() == outerJoin && unUsedJoinOps[i]) {
- unUsedJoinOps[i] = false;
- newJoinOps.add(ajOp.getAbstractJoinOp());
- break;
+ AbstractBinaryJoinOperator abjOp;
+ int i;
+
+ if (plan.outerJoin) { // find an unused outer join op.
+ for (i = 0; i < allJoinOps.size(); i++) {
+ abjOp = allJoinOps.get(i).getAbstractJoinOp();
+ if (unUsedJoinOps[i] && abjOp.getJoinKind() ==
AbstractBinaryJoinOperator.JoinKind.LEFT_OUTER) {
+ unUsedJoinOps[i] = false;
+ newJoinOps.add(abjOp);
+ return;
+ }
+ }
+ } else {// now look for an unused join node.
+ // This may not always be possible as an outer join may have been
converted to a join node.
+ // In this case, there won't be as many join nodes. But we are
guaranteed to find at least one join node
+ // but it may already have been used. We just need to make a copy
of it!
+ for (i = 0; i < allJoinOps.size(); i++) {
+ abjOp = allJoinOps.get(i).getAbstractJoinOp();
+ if (unUsedJoinOps[i] && abjOp.getJoinKind() ==
AbstractBinaryJoinOperator.JoinKind.INNER) {
+ unUsedJoinOps[i] = false;
+ newJoinOps.add(abjOp);
+ return;
+ }
+ }
+ // This means we have not found an unused join node. Find a used
join node and make a copy.
+ for (i = 0; i < allJoinOps.size(); i++) {
+ abjOp = allJoinOps.get(i).getAbstractJoinOp();
+ if (abjOp.getJoinKind() ==
AbstractBinaryJoinOperator.JoinKind.INNER) {
+ //InnerJoinOperator inJOp = new
InnerJoinOperator((Mutable<ILogicalExpression>) plan.getJoinExpr());
+ InnerJoinOperator inJOp =
+ new InnerJoinOperator(new
MutableObject<ILogicalExpression>(plan.getJoinExpr()),
+ new MutableObject<>(null), new
MutableObject<>(null));
+ newJoinOps.add(inJOp);
+ return;
+ }
}
}
}
@@ -853,7 +880,6 @@ public class EnumerateJoinsRule implements
IAlgebraicRewriteRule {
// our plan, so the rest of the code will be happy. Strange that this
assign appears in the join graph.
private ILogicalOperator addRemainingAssignsAtTheTop(ILogicalOperator op,
List<AssignOperator> assignOps) {
-
ILogicalOperator root = op;
for (AssignOperator aOp : assignOps) {
aOp.getInputs().get(0).setValue(root);
@@ -916,4 +942,4 @@ public class EnumerateJoinsRule implements
IAlgebraicRewriteRule {
}
return true;
}
-}
\ No newline at end of file
+}