public PlanNode resolve(GroupReference groupReference) { return getNode(groupReference.getGroupId()); }
public PlanNode extract() { return extract(getNode(rootGroup)); }
private boolean exploreChildren(int group, Context context, Matcher matcher) { boolean progress = false; PlanNode expression = context.memo.getNode(group); for (PlanNode child : expression.getSources()) { checkState(child instanceof GroupReference, "Expected child to be a group reference. Found: " + child.getClass().getName()); if (exploreGroup(((GroupReference) child).getGroupId(), context, matcher)) { progress = true; } } return progress; }
private PlanNodeStatsEstimate getGroupStats(GroupReference groupReference) { int group = groupReference.getGroupId(); Memo memo = this.memo.orElseThrow(() -> new IllegalStateException("CachingStatsProvider without memo cannot handle GroupReferences")); Optional<PlanNodeStatsEstimate> stats = memo.getStats(group); if (stats.isPresent()) { return stats.get(); } PlanNodeStatsEstimate groupStats = statsCalculator.calculateStats(memo.getNode(group), this, lookup, session, types); verify(!memo.getStats(group).isPresent(), "Group stats already set"); memo.storeStats(group, groupStats); return groupStats; } }
private PlanNodeCostEstimate getGroupCost(GroupReference groupReference) { int group = groupReference.getGroupId(); Memo memo = this.memo.orElseThrow(() -> new IllegalStateException("CachingCostProvider without memo cannot handle GroupReferences")); Optional<PlanNodeCostEstimate> cost = memo.getCumulativeCost(group); if (cost.isPresent()) { return cost.get(); } PlanNodeCostEstimate cumulativeCost = calculateCumulativeCost(memo.getNode(group)); verify(!memo.getCumulativeCost(group).isPresent(), "Group cost already set"); memo.storeCumulativeCost(group, cumulativeCost); return cumulativeCost; }
private boolean exploreNode(int group, Context context, Matcher matcher) { PlanNode node = context.memo.getNode(group); boolean done = false; boolean progress = false; while (!done) { context.checkTimeoutNotExhausted(); done = true; Iterator<Rule<?>> possiblyMatchingRules = ruleIndex.getCandidates(node).iterator(); while (possiblyMatchingRules.hasNext()) { Rule<?> rule = possiblyMatchingRules.next(); if (!rule.isEnabled(context.session)) { continue; } Rule.Result result = transform(node, rule, matcher, context); if (result.getTransformedPlan().isPresent()) { node = context.memo.replace(group, result.getTransformedPlan().get(), rule.getClass().getName()); done = false; progress = true; } } } return progress; }
private int getChildGroup(Memo memo, int group) { PlanNode node = memo.getNode(group); GroupReference child = (GroupReference) node.getSources().get(0); return child.getGroupId(); }
public PlanNode replace(int group, PlanNode node, String reason) { PlanNode old = getGroup(group).membership; checkArgument(new HashSet<>(old.getOutputSymbols()).equals(new HashSet<>(node.getOutputSymbols())), "%s: transformed expression doesn't produce same outputs: %s vs %s", reason, old.getOutputSymbols(), node.getOutputSymbols()); if (node instanceof GroupReference) { node = getNode(((GroupReference) node).getGroupId()); } else { node = insertChildrenAndRewrite(node); } incrementReferenceCounts(node, group); getGroup(group).membership = node; decrementReferenceCounts(old, group); evictStatisticsAndCost(group); return node; }
private RuleApplication applyRule() { SymbolAllocator symbolAllocator = new SymbolAllocator(types.allTypes()); Memo memo = new Memo(idAllocator, plan); Lookup lookup = Lookup.from(planNode -> Stream.of(memo.resolve(planNode))); PlanNode memoRoot = memo.getNode(memo.getRootGroup()); return inTransaction(session -> applyRule(rule, memoRoot, ruleContext(statsCalculator, costCalculator, symbolAllocator, memo, lookup, session))); }
@Test public void testRemoveNode() { PlanNode z = node(); PlanNode y = node(z); PlanNode x = node(y); Memo memo = new Memo(idAllocator, x); assertEquals(memo.getGroupCount(), 3); int yGroup = getChildGroup(memo, memo.getRootGroup()); memo.replace(yGroup, memo.getNode(yGroup).getSources().get(0), "rule"); assertEquals(memo.getGroupCount(), 2); assertMatchesStructure( memo.extract(), node(x.getId(), node(z.getId()))); }
@Test public void testReplaceNode() { PlanNode z = node(); PlanNode y = node(z); PlanNode x = node(y); Memo memo = new Memo(idAllocator, x); assertEquals(memo.getGroupCount(), 3); // replace child of root node with another node, retaining child's child int yGroup = getChildGroup(memo, memo.getRootGroup()); GroupReference zRef = (GroupReference) getOnlyElement(memo.getNode(yGroup).getSources()); PlanNode transformed = node(zRef); memo.replace(yGroup, transformed, "rule"); assertEquals(memo.getGroupCount(), 3); assertMatchesStructure(memo.extract(), node(x.getId(), node(transformed.getId(), z))); }
@Test public void testInsertNode() { PlanNode z = node(); PlanNode x = node(z); Memo memo = new Memo(idAllocator, x); assertEquals(memo.getGroupCount(), 2); int zGroup = getChildGroup(memo, memo.getRootGroup()); PlanNode y = node(memo.getNode(zGroup)); memo.replace(zGroup, y, "rule"); assertEquals(memo.getGroupCount(), 3); assertMatchesStructure( memo.extract(), node(x.getId(), node(y.getId(), node(z.getId())))); }
@Test public void testReplaceNonLeafSubtree() { PlanNode w = node(); PlanNode z = node(w); PlanNode y = node(z); PlanNode x = node(y); Memo memo = new Memo(idAllocator, x); assertEquals(memo.getGroupCount(), 4); int yGroup = getChildGroup(memo, memo.getRootGroup()); int zGroup = getChildGroup(memo, yGroup); PlanNode rewrittenW = memo.getNode(zGroup).getSources().get(0); PlanNode newZ = node(rewrittenW); PlanNode newY = node(newZ); memo.replace(yGroup, newY, "rule"); assertEquals(memo.getGroupCount(), 4); assertMatchesStructure( memo.extract(), node(x.getId(), node(newY.getId(), node(newZ.getId(), node(w.getId()))))); }
@Test public void testMultipleReferences() { PlanNode z = node(); PlanNode y = node(z); PlanNode x = node(y); Memo memo = new Memo(idAllocator, x); assertEquals(memo.getGroupCount(), 3); int yGroup = getChildGroup(memo, memo.getRootGroup()); PlanNode rewrittenZ = memo.getNode(yGroup).getSources().get(0); PlanNode y1 = node(rewrittenZ); PlanNode y2 = node(rewrittenZ); PlanNode newX = node(y1, y2); memo.replace(memo.getRootGroup(), newX, "rule"); assertEquals(memo.getGroupCount(), 4); assertMatchesStructure( memo.extract(), node(newX.getId(), node(y1.getId(), node(z.getId())), node(y2.getId(), node(z.getId())))); }