@Test public void shouldPushDownAllSelectNodesThatApplyToOneSelectorToBelowAccessNodeForThatSelector() { PlanNode project = new PlanNode(Type.PROJECT, selector("Selector1"), selector("Selector2")); PlanNode select1 = new PlanNode(Type.SELECT, project, selector("Selector1")); PlanNode select2 = new PlanNode(Type.SELECT, select1, selector("Selector2")); PlanNode select3 = new PlanNode(Type.SELECT, select2, selector("Selector1"), selector("Selector2")); PlanNode select4 = new PlanNode(Type.SELECT, select3, selector("Selector1")); PlanNode join = new PlanNode(Type.JOIN, select4, selector("Selector1"), selector("Selector2")); PlanNode s1Access = new PlanNode(Type.ACCESS, join, selector("Selector1")); PlanNode s1Source = new PlanNode(Type.SOURCE, s1Access, selector("Selector1")); PlanNode s2Access = new PlanNode(Type.ACCESS, join, selector("Selector2")); PlanNode s2Source = new PlanNode(Type.SOURCE, s2Access, selector("Selector2")); join.setProperty(Property.JOIN_TYPE, JoinType.INNER); PlanNode result = rule.execute(context, project, new LinkedList<OptimizerRule>()); assertThat(result, is(sameInstance(project))); assertChildren(project, select3); assertChildren(select3, join); assertChildren(join, s1Access, s2Access); assertChildren(s1Access, select1); assertChildren(select1, select4); assertChildren(select4, s1Source); assertChildren(s2Access, select2); assertChildren(select2, s2Source); assertChildren(s2Source); assertChildren(s1Source); }
@Override public PlanNode execute( QueryContext context, PlanNode plan, LinkedList<OptimizerRule> ruleStack ) { Set<PlanNode> deadNodes = new HashSet<PlanNode>(); boolean movedSomeNode = true; while (movedSomeNode) { movedSomeNode = false; List<PlanNode> criteriaNodes = plan.findAllAtOrBelow(Type.SELECT); List<PlanNode> originatingNodes = plan.findAllAtOrBelow(ORIGINATING_TYPES); Collections.reverse(criteriaNodes); for (PlanNode criteriaNode : criteriaNodes) { if (deadNodes.contains(criteriaNode)) continue; PlanNode originatingNode = findOriginatingNode(criteriaNode, originatingNodes); if (originatingNode == null || originatingNode == criteriaNode) { deadNodes.add(criteriaNode); continue; } if (!pushTowardsOriginatingNode(criteriaNode, originatingNode)) { deadNodes.add(criteriaNode); continue; } boolean adjusted = false; switch (originatingNode.getType()) { case SOURCE: break; case JOIN: if (!criteriaNode.hasAncestorOfType(Type.ACCESS)) { adjusted = pushDownJoinCriteria(criteriaNode, originatingNode); } break; default: } if (adjusted) { movedSomeNode = true; } else { deadNodes.add(criteriaNode); } } } return plan; }
PushSelectCriteria implements OptimizerRule { @Override public PlanNode execute( QueryContext context, PlanNode plan, LinkedList<OptimizerRule> ruleStack ) { Set<PlanNode> deadNodes = new HashSet<PlanNode>(); boolean movedSomeNode = true; while (movedSomeNode) { movedSomeNode = false; List<PlanNode> criteriaNodes = plan.findAllAtOrBelow(Type.SELECT); List<PlanNode> originatingNodes = plan.findAllAtOrBelow(ORIGINATING_TYPES); Collections.reverse(criteriaNodes); for (PlanNode criteriaNode : criteriaNodes) { if (deadNodes.contains(criteriaNode)) continue; PlanNode originatingNode = findOriginatingNode(criteriaNode, originatingNodes); if (originatingNode == null || originatingNode == criteriaNode) { deadNodes.add(criteriaNode); continue; } if (!pushTowardsOriginatingNode(criteriaNode, originatingNode)) { deadNodes.add(criteriaNode); continue; } boolean adjusted = false; switch (originatingNode.getType()) { case SOURCE: break; case JOIN: if (!criteriaNode.hasAncestorOfType(Type.ACCESS)) { adjusted = pushDownJoinCriteria(criteriaNode, originatingNode); } break; default: } if (adjusted) { movedSomeNode = true; } else { deadNodes.add(criteriaNode); } } } return plan; } }
PushSelectCriteria implements OptimizerRule { @Override public PlanNode execute( QueryContext context, PlanNode plan, LinkedList<OptimizerRule> ruleStack ) { Set<PlanNode> deadNodes = new HashSet<PlanNode>(); boolean movedSomeNode = true; while (movedSomeNode) { movedSomeNode = false; List<PlanNode> criteriaNodes = plan.findAllAtOrBelow(Type.SELECT); List<PlanNode> originatingNodes = plan.findAllAtOrBelow(ORIGINATING_TYPES); Collections.reverse(criteriaNodes); for (PlanNode criteriaNode : criteriaNodes) { if (deadNodes.contains(criteriaNode)) continue; PlanNode originatingNode = findOriginatingNode(criteriaNode, originatingNodes); if (originatingNode == null || originatingNode == criteriaNode) { deadNodes.add(criteriaNode); continue; } if (!pushTowardsOriginatingNode(criteriaNode, originatingNode)) { deadNodes.add(criteriaNode); continue; } boolean adjusted = false; switch (originatingNode.getType()) { case SOURCE: break; case JOIN: if (!criteriaNode.hasAncestorOfType(Type.ACCESS)) { adjusted = pushDownJoinCriteria(criteriaNode, originatingNode); } break; default: } if (adjusted) { movedSomeNode = true; } else { deadNodes.add(criteriaNode); } } } return plan; }  }
PushSelectCriteria implements OptimizerRule { @Override public PlanNode execute( QueryContext context, PlanNode plan, LinkedList<OptimizerRule> ruleStack ) { Set<PlanNode> deadNodes = new HashSet<PlanNode>(); boolean movedSomeNode = true; while (movedSomeNode) { movedSomeNode = false; List<PlanNode> criteriaNodes = plan.findAllAtOrBelow(Type.SELECT); List<PlanNode> originatingNodes = plan.findAllAtOrBelow(ORIGINATING_TYPES); Collections.reverse(criteriaNodes); for (PlanNode criteriaNode : criteriaNodes) { if (deadNodes.contains(criteriaNode)) continue; PlanNode originatingNode = findOriginatingNode(criteriaNode, originatingNodes); if (originatingNode == null || originatingNode == criteriaNode) { deadNodes.add(criteriaNode); continue; } if (!pushTowardsOriginatingNode(criteriaNode, originatingNode)) { deadNodes.add(criteriaNode); continue; } boolean adjusted = false; switch (originatingNode.getType()) { case SOURCE: break; case JOIN: if (!criteriaNode.hasAncestorOfType(Type.ACCESS)) { adjusted = pushDownJoinCriteria(criteriaNode, originatingNode); } break; default: } if (adjusted) { movedSomeNode = true; } else { deadNodes.add(criteriaNode); } } } return plan; }  @Override PlanNode execute( QueryContext context,
                             PlanNode plan,
                             LinkedList<OptimizerRule> ruleStack ); @Override String toString(); }
PushSelectCriteria implements OptimizerRule { @Override public PlanNode execute( QueryContext context, PlanNode plan, LinkedList<OptimizerRule> ruleStack ) { Set<PlanNode> deadNodes = new HashSet<PlanNode>(); boolean movedSomeNode = true; while (movedSomeNode) { movedSomeNode = false; List<PlanNode> criteriaNodes = plan.findAllAtOrBelow(Type.SELECT); List<PlanNode> originatingNodes = plan.findAllAtOrBelow(ORIGINATING_TYPES); Collections.reverse(criteriaNodes); for (PlanNode criteriaNode : criteriaNodes) { if (deadNodes.contains(criteriaNode)) continue; PlanNode originatingNode = findOriginatingNode(criteriaNode, originatingNodes); if (originatingNode == null || originatingNode == criteriaNode) { deadNodes.add(criteriaNode); continue; } if (!pushTowardsOriginatingNode(criteriaNode, originatingNode)) { deadNodes.add(criteriaNode); continue; } boolean adjusted = false; switch (originatingNode.getType()) { case SOURCE: break; case JOIN: if (!criteriaNode.hasAncestorOfType(Type.ACCESS)) { adjusted = pushDownJoinCriteria(criteriaNode, originatingNode); } break; default: } if (adjusted) { movedSomeNode = true; } else { deadNodes.add(criteriaNode); } } } return plan; }  @Override PlanNode execute( QueryContext context,
                             PlanNode plan,
                             LinkedList<OptimizerRule> ruleStack ); @Override String toString(); static final PushSelectCriteria INSTANCE; }