@Override public boolean hasAChildWithLiftableDefinition(Variable variable, ImmutableList<IQTree> children) { return children.stream() .anyMatch(c -> (c.getRootNode() instanceof ConstructionNode) && ((ConstructionNode) c.getRootNode()).getSubstitution().isDefining(variable)); }
private Optional<ImmutableExpression> getOptionalChildExpression(IQTree child) { QueryNode root = child.getRootNode(); return root instanceof FilterNode? Optional.of(((FilterNode) root).getFilterCondition()): Optional.empty(); }
private Stream<IQTree> splitRootUnion(IQTree tree) { return (tree.getRootNode() instanceof UnionNode) ? tree.getChildren().stream() : Stream.of(tree); }
private ImmutableList<ImmutableExpression> getChildExpressions(ImmutableList<IQTree> children) { return children.stream() .filter(t -> t.getRootNode() instanceof FilterNode) .map(t -> ((FilterNode) t.getRootNode()).getFilterCondition()) .collect(ImmutableCollectors.toList()); }
private IQTree trimRootFilter(IQTree tree) { return tree.getRootNode() instanceof FilterNode ? ((UnaryIQTree) tree).getChild() : tree; }
private Optional<NaryIQTree> findFirstSplittableUnion(IQ query) { Queue<IQTree> nodesToVisit = new LinkedList<>(); nodesToVisit.add(query.getTree()); while(!nodesToVisit.isEmpty()) { IQTree childTree = nodesToVisit.poll(); if (childTree.getRootNode() instanceof UnionNode) { return Optional.of((NaryIQTree) childTree); } else { nodesToVisit.addAll(extractChildrenToVisit(childTree)); } } return Optional.empty(); }
/** * Recursive */ private static String printSubtree(IQTree subTree, String offset) { String childOffset = offset + TAB_STR; return offset + subTree.getRootNode() + "\n" + subTree.getChildren().stream() .map(c -> printSubtree(c, childOffset)) .reduce("", (c, a) -> c + a); }
private Optional<ConstructionNode> getIdleCn(IQTree tree) { QueryNode root = tree.getRootNode(); if (root instanceof ConstructionNode) { ConstructionNode cn = ((ConstructionNode) root); if (cn.getSubstitution().isEmpty()) { return Optional.of(cn); } } return Optional.empty(); }
/** * Assumes that ORDER BY is ABOVE the first construction node */ private IQTree getFirstNonQueryModifierTree(IQ query) { // Non-final IQTree iqTree = query.getTree(); while (iqTree.getRootNode() instanceof QueryModifierNode) { iqTree = ((UnaryIQTree) iqTree).getChild(); } return iqTree; }
@Override public boolean isEquivalentTo(IQTree tree) { if (!getRootNode().isEquivalentTo(tree.getRootNode())) return false; ImmutableList<IQTree> otherChildren = tree.getChildren(); return (children.size() == otherChildren.size()) && IntStream.range(0, children.size()) .allMatch(i -> children.get(i).isEquivalentTo(otherChildren.get(i))); }
private ChildLiftingState liftRightChild(ChildLiftingState state, VariableGenerator variableGenerator) { IQTree liftedRightChild = state.rightChild.liftBinding(variableGenerator); if (!(liftedRightChild.getRootNode() instanceof ConstructionNode)) { if (state.rightChild.equals(liftedRightChild)) return state; return new ChildLiftingState(state.leftChild, liftedRightChild, state.ljCondition.filter(c -> !liftedRightChild.isDeclaredAsEmpty()), state.ascendingSubstitution); } ConstructionNode rightConstructionNode = (ConstructionNode) liftedRightChild.getRootNode(); IQTree rightGrandChild = ((UnaryIQTree) liftedRightChild).getChild(); ImmutableSubstitution<ImmutableTerm> rightSubstitution = rightConstructionNode.getSubstitution(); return liftRightChild(state, rightGrandChild, rightSubstitution, variableGenerator); }
/** * Move ORDER BY above the highest construction node (required by Datalog) */ private IQ liftOrderBy(IQ iq) { IQTree topNonQueryModifierTree = getFirstNonQueryModifierTree(iq); if ((topNonQueryModifierTree instanceof UnaryIQTree) && (((UnaryIQTree) topNonQueryModifierTree).getChild().getRootNode() instanceof OrderByNode)) { return orderByLifter.liftOrderBy(iq); } return iq; } }
private ImmutableList<IQ> normalizeIQ(IQ query) { IQTree tree = query.getTree(); while(tree.getRootNode() instanceof QueryModifierNode){ tree = ((UnaryIQTree)tree).getChild(); } return splitRootUnion(tree) .map(t -> enforceRootCn(t, query.getProjectionAtom().getVariables())) .map(t -> iqFactory.createIQ(query.getProjectionAtom(), t)) .collect(ImmutableCollectors.toList()); }
@Override public IQTree liftBinding(IQTree child, VariableGenerator variableGenerator, IQProperties currentIQProperties) { IQTree newChild = child.liftBinding(variableGenerator); QueryNode newChildRoot = newChild.getRootNode(); if (newChildRoot instanceof ConstructionNode) return liftBindingConstructionChild(newChild, (ConstructionNode) newChildRoot, currentIQProperties); else if (newChildRoot instanceof DistinctNode) return newChild; else if (newChildRoot instanceof EmptyNode) return newChild; else return iqFactory.createUnaryIQTree(this, newChild, currentIQProperties.declareLifted()); }
@Override public NodeCentricOptimizationResults<N> apply(SubstitutionPropagationProposal<N> proposal, IntermediateQuery query, QueryTreeComponent treeComponent) throws InvalidQueryOptimizationProposalException { N focusNode = proposal.getFocusNode(); IQTree propagatedSubTree = propagate(iqConverter.convertTree(query, focusNode), proposal.getSubstitution()); treeComponent.replaceSubTreeByIQ(focusNode, propagatedSubTree); return new NodeCentricOptimizationResultsImpl<>(query, Optional.of(propagatedSubTree.getRootNode())); }
@Override public QueryNode replaceSubTreeByIQ(QueryNode subTreeRoot, IQTree replacingSubTree) { QueryNode iqRoot = replacingSubTree.getRootNode(); QueryNode newSubTreeRoot = contains(iqRoot) ? iqRoot.clone() : iqRoot; replaceSubTree(subTreeRoot, newSubTreeRoot); insertIQChildren(newSubTreeRoot, replacingSubTree.getChildren()); return newSubTreeRoot; }
private IQTree liftBindingAfterPropagatingCondition(IQTree childIQTree, VariableGenerator variableGenerator, IQProperties currentIQProperties) { IQTree liftedChildIQTree = childIQTree.liftBinding(variableGenerator); QueryNode childRoot = liftedChildIQTree.getRootNode(); if (childRoot instanceof ConstructionNode) return liftBinding((ConstructionNode) childRoot, (UnaryIQTree) liftedChildIQTree, currentIQProperties, variableGenerator); else if (liftedChildIQTree.isDeclaredAsEmpty()) { return liftedChildIQTree; } else return iqFactory.createUnaryIQTree(this, liftedChildIQTree, currentIQProperties.declareLifted()); }
@Override public IQTree liftBinding(IQTree childIQTree, VariableGenerator variableGenerator, IQProperties currentIQProperties) { IQTree liftedChildIQTree = childIQTree.liftBinding(variableGenerator); QueryNode liftedChildRoot = liftedChildIQTree.getRootNode(); if (liftedChildRoot instanceof ConstructionNode) return liftBinding((ConstructionNode) liftedChildRoot, (UnaryIQTree) liftedChildIQTree, currentIQProperties); else if (liftedChildIQTree.isDeclaredAsEmpty()) { return iqFactory.createEmptyNode(projectedVariables); } else return iqFactory.createUnaryIQTree(this, liftedChildIQTree, currentIQProperties.declareLifted()); }
private IQTree getProjection(ImmutableSet<Variable> signature, IQTree tree) { QueryNode root = tree.getRootNode(); if (root instanceof ConstructionNode){ return iqFactory.createUnaryIQTree( iqFactory.createConstructionNode(signature, ((ConstructionNode)root).getSubstitution()), ((UnaryIQTree)tree).getChild() ); } return iqFactory.createUnaryIQTree( iqFactory.createConstructionNode(signature), tree ); } }
@Override public IntermediateQuery convert(IQ query, DBMetadata dbMetadata, ExecutorRegistry executorRegistry) throws EmptyQueryException { if (query.getTree().isDeclaredAsEmpty()) throw new EmptyQueryException(); IntermediateQueryBuilder queryBuilder = iqFactory.createIQBuilder(dbMetadata, executorRegistry); IQTree topTree = query.getTree(); QueryNode rootNode = topTree.getRootNode(); queryBuilder.init(query.getProjectionAtom(), rootNode); insertChildren(rootNode, topTree.getChildren(), queryBuilder); return queryBuilder.build(); }