ChooseJoinAlgorithm implements OptimizerRule { @Override public PlanNode execute( QueryContext context, PlanNode plan, LinkedList<OptimizerRule> ruleStack ) { for (PlanNode joinNode : plan.findAllAtOrBelow(Type.JOIN)) { JoinCondition condition = joinNode.getProperty(Property.JOIN_CONDITION, JoinCondition.class); if (useOnlyNested) { joinNode.setProperty(Property.JOIN_ALGORITHM, JoinAlgorithm.NESTED_LOOP); break; } if (condition instanceof DescendantNodeJoinCondition) { joinNode.setProperty(Property.JOIN_ALGORITHM, JoinAlgorithm.NESTED_LOOP); } else { joinNode.setProperty(Property.JOIN_ALGORITHM, JoinAlgorithm.MERGE); assert joinNode.getChildCount() == 2; Set<SelectorName> leftSelectors = joinNode.getFirstChild().getSelectors(); Set<SelectorName> rightSelectors = joinNode.getLastChild().getSelectors(); List<Object> leftSortBy = new LinkedList<Object>(); List<Object> rightSortBy = new LinkedList<Object>(); createOrderBysForJoinCondition(condition, leftSelectors, leftSortBy, rightSelectors, rightSortBy); PlanNode leftSort = new PlanNode(Type.SORT, leftSelectors); leftSort.setProperty(Property.SORT_ORDER_BY, leftSortBy); joinNode.getFirstChild().insertAsParent(leftSort); if (joinNode.getFirstChild().findAllAtOrBelow(Type.DUP_REMOVE).isEmpty()) { PlanNode leftDupRemoval = new PlanNode(Type.DUP_REMOVE, leftSelectors); joinNode.getFirstChild().insertAsParent(leftDupRemoval); } PlanNode rightSort = new PlanNode(Type.SORT, rightSelectors); rightSort.setProperty(Property.SORT_ORDER_BY, rightSortBy); joinNode.getLastChild().insertAsParent(rightSort); if (joinNode.getLastChild().findAllAtOrBelow(Type.DUP_REMOVE).isEmpty()) { PlanNode rightDupRemoval = new PlanNode(Type.DUP_REMOVE, rightSelectors); joinNode.getLastChild().insertAsParent(rightDupRemoval); } } } return plan; } protected  ChooseJoinAlgorithm( boolean useOnlyNested ); @Override PlanNode execute( QueryContext context,
                             PlanNode plan,
                             LinkedList<OptimizerRule> ruleStack ); @Override String toString(); static final ChooseJoinAlgorithm USE_ONLY_NESTED_JOIN_ALGORITHM; static final ChooseJoinAlgorithm USE_BEST_JOIN_ALGORITHM; }
@Test public void shouldHaveNestedRuleAlwaysSetJoinAlgorithmToNestedLoop() { PlanNode join = new PlanNode(Type.JOIN, selector("Selector1"), selector("Selector2")); PlanNode s1Source = new PlanNode(Type.SOURCE, join, selector("Selector1")); PlanNode s2Source = new PlanNode(Type.SOURCE, join, selector("Selector2")); join.setProperty(Property.JOIN_TYPE, JoinType.INNER); PlanNode result = nestedRule.execute(context, join, new LinkedList<OptimizerRule>()); assertThat(result, is(sameInstance(join))); assertThat(join.getProperty(Property.JOIN_TYPE, JoinType.class), is(JoinType.INNER)); assertThat(join.getProperty(Property.JOIN_ALGORITHM, JoinAlgorithm.class), is(JoinAlgorithm.NESTED_LOOP)); assertChildren(join, s1Source, s2Source); }
@Test public void shouldHaveBestRuleAlwaysSetJoinAlgorithmToNestedLoopIfConditionIsDescendantNode() { PlanNode join = new PlanNode(Type.JOIN, selector("Ancestor"), selector("Descendant")); PlanNode ancestorSource = new PlanNode(Type.SOURCE, join, selector("Ancestor")); PlanNode descendantSource = new PlanNode(Type.SOURCE, join, selector("Descendant")); JoinCondition joinCondition = new DescendantNodeJoinCondition(selector("Ancestor"), selector("Descendant")); join.setProperty(Property.JOIN_CONDITION, joinCondition); join.setProperty(Property.JOIN_TYPE, JoinType.INNER); PlanNode result = bestRule.execute(context, join, new LinkedList<OptimizerRule>()); assertThat(result, is(sameInstance(join))); assertThat(join.getProperty(Property.JOIN_TYPE, JoinType.class), is(JoinType.INNER)); assertThat(join.getProperty(Property.JOIN_ALGORITHM, JoinAlgorithm.class), is(JoinAlgorithm.NESTED_LOOP)); assertThat(join.getProperty(Property.JOIN_CONDITION, JoinCondition.class), is(sameInstance(joinCondition))); assertChildren(join, ancestorSource, descendantSource); }
@Test public void shouldHaveBestRuleSetJoinAlgorithmToMergeIfConditionIsNotDescendantNode() { PlanNode join = new PlanNode(Type.JOIN, selector("Parent"), selector("Child")); PlanNode parentSource = new PlanNode(Type.SOURCE, join, selector("Parent")); PlanNode childSource = new PlanNode(Type.SOURCE, join, selector("Child")); JoinCondition joinCondition = new ChildNodeJoinCondition(selector("Parent"), selector("Child")); join.setProperty(Property.JOIN_CONDITION, joinCondition); join.setProperty(Property.JOIN_TYPE, JoinType.INNER); PlanNode result = bestRule.execute(context, join, new LinkedList<OptimizerRule>()); assertThat(result, is(sameInstance(join))); assertThat(join.getProperty(Property.JOIN_TYPE, JoinType.class), is(JoinType.INNER)); assertThat(join.getProperty(Property.JOIN_ALGORITHM, JoinAlgorithm.class), is(JoinAlgorithm.MERGE)); assertThat(join.getProperty(Property.JOIN_CONDITION, JoinCondition.class), is(sameInstance(joinCondition))); PlanNode leftDup = join.getFirstChild(); assertThat(leftDup.getType(), is(Type.DUP_REMOVE)); assertSelectors(leftDup, "Parent"); PlanNode leftSort = leftDup.getFirstChild(); assertThat(leftSort.getType(), is(Type.SORT)); assertSortOrderBy(leftSort, "Parent"); assertSelectors(leftSort, "Parent"); assertChildren(leftDup, leftSort); assertChildren(leftSort, parentSource); PlanNode rightDup = join.getLastChild(); assertThat(rightDup.getType(), is(Type.DUP_REMOVE)); assertSelectors(rightDup, "Child"); PlanNode rightSort = rightDup.getLastChild(); assertThat(rightSort.getType(), is(Type.SORT)); assertSortOrderBy(rightSort, "Child"); assertSelectors(rightSort, "Child"); assertChildren(rightDup, rightSort); assertChildren(rightSort, childSource); assertChildren(join, leftDup, rightDup); }