private boolean isFirstOcc(Variable variable, ImmutableList<IQTree> children, IQTree tree) { return children.stream().sequential() .filter(t -> t.getVariables().contains(variable)) .findFirst().get() .equals(tree); }
@SuppressWarnings("OptionalUsedAsFieldOrParameterType") private Stream<Variable> extractCandidateVariables(IQTree tree, Optional<ImmutableExpression> optionalFilterCondition, ImmutableList<IQTree> newChildren) { Stream<Variable> coOccurringVariables = IntStream.range(0, newChildren.size() - 1) .boxed() .flatMap(i -> newChildren.get(i).getVariables().stream() .filter(v1 -> IntStream.range(i + 1, newChildren.size()) .anyMatch(j -> newChildren.get(j).getVariables().stream(). anyMatch(v1::equals)))); return Stream.concat( optionalFilterCondition .map(ImmutableTerm::getVariableStream) .orElseGet(Stream::empty), coOccurringVariables) .distinct() .filter(tree::isConstructed); }
private ImmutableSet<Variable> getProjectedVariables(ImmutableList<IQTree> children) { return children.stream() .flatMap(c -> c.getVariables().stream()) .collect(ImmutableCollectors.toSet()); }
@Override public ImmutableSet<Variable> getVariables() { if (rootNode instanceof ExplicitVariableProjectionNode) return ((ExplicitVariableProjectionNode) rootNode).getVariables(); else return children.stream() .flatMap(c -> c.getVariables().stream()) .collect(ImmutableCollectors.toSet()); }
private Optional<RightProvenance> createProvenanceElements(Map.Entry<Variable, Constant> provenanceVariableDefinition, IQTree rightTree) { Variable rightProvenanceVariable = provenanceVariableDefinition.getKey(); ImmutableSet<Variable> newRightProjectedVariables = Stream.concat(Stream.of(rightProvenanceVariable), rightTree.getVariables().stream()) .collect(ImmutableCollectors.toSet()); ConstructionNode newRightConstructionNode = iqFactory.createConstructionNode( newRightProjectedVariables, substitutionFactory.getSubstitution(rightProvenanceVariable, provenanceVariableDefinition.getValue())); return Optional.of(new RightProvenance(rightProvenanceVariable, newRightConstructionNode)); }
@Override protected IQTree transformNaryCommutativeNode(IQTree tree, NaryOperatorNode rootNode, ImmutableList<IQTree> children) { ImmutableList<ConstructionNode> idleCns = getIdleCns(children.stream()); return idleCns.isEmpty() ? tree : getProjection( tree.getVariables(), iqFactory.createNaryIQTree( rootNode, children.stream() .map(this::trimIdleCn) .collect(ImmutableCollectors.toList()) )); }
protected void checkExpression(ImmutableExpression expression, ImmutableList<IQTree> children) throws InvalidIntermediateQueryException { ImmutableSet<Variable> childrenVariables = children.stream() .flatMap(c -> c.getVariables().stream()) .collect(ImmutableCollectors.toSet()); ImmutableSet<Variable> unboundVariables = expression.getVariableStream() .filter(v -> !childrenVariables.contains(v)) .collect(ImmutableCollectors.toSet()); if (!unboundVariables.isEmpty()) { throw new InvalidIntermediateQueryException("Expression " + expression + " of " + expression + " uses unbound variables (" + unboundVariables + ").\n" + this); } }
private InjectiveVar2VarSubstitution computeSubstitution(ImmutableSet<Variable> repeatedVars, ImmutableList<IQTree> children, IQTree tree) { return substitutionFactory.getInjectiveVar2VarSubstitution( tree.getVariables().stream() .filter(repeatedVars::contains) .filter(v -> !isFirstOcc(v, children, tree)) .collect(ImmutableCollectors.toMap( v -> v, variableGenerator::generateNewVariableFromVar ))); }
private IQTree liftUnionChild(int childIndex, NaryIQTree newUnionChild, ImmutableList<IQTree> initialChildren) { UnionNode newUnionNode = iqFactory.createUnionNode(initialChildren.stream() .flatMap(c -> c.getVariables().stream()) .collect(ImmutableCollectors.toSet())); return iqFactory.createNaryIQTree(newUnionNode, newUnionChild.getChildren().stream() .map(unionGrandChild -> createJoinSubtree(childIndex, unionGrandChild, initialChildren)) .collect(ImmutableCollectors.toList())); }
private IQTree liftLJJoin(BinaryNonCommutativeIQTree queryTree, IQTree newLeftChild, IQTree newRightChild, VariableGenerator variableGenerator) { LeftJoinNode leftJoinNode = (LeftJoinNode) queryTree.getRootNode(); BinaryNonCommutativeIQTree newQueryTree = newLeftChild.equals(queryTree.getLeftChild()) && newRightChild.equals(queryTree.getRightChild()) ? queryTree : iqFactory.createBinaryNonCommutativeIQTree(leftJoinNode, newLeftChild, newRightChild); return extractCandidateVariables(queryTree, leftJoinNode.getOptionalFilterCondition(), ImmutableList.of(newLeftChild, newRightChild)) .filter(v -> newLeftChild.getVariables().contains(v)) .map(newQueryTree::liftIncompatibleDefinitions) .filter(t -> !t.equals(queryTree)) .findFirst() .orElse(newQueryTree) .liftBinding(variableGenerator); }
@Override public IQTree transformUnaryNode(IQTree tree, UnaryOperatorNode rootNode, IQTree child) { ImmutableList<ConstructionNode> idleCns = getIdleCns(Stream.of(child)); return idleCns.isEmpty() ? tree : getProjection( tree.getVariables(), iqFactory.createUnaryIQTree( rootNode, trimIdleCn(child) )); }
@Override public void validateNode(IQTree child) throws InvalidIntermediateQueryException { if (!child.getVariables().containsAll(getLocalVariables())) { throw new InvalidIntermediateQueryException("Some variables used in the node " + this + " are not provided by its child " + child); } }
@Override public ImmutableSet<Variable> getVariables() { UnaryOperatorNode rootNode = getRootNode(); if (rootNode instanceof ExplicitVariableProjectionNode) return ((ExplicitVariableProjectionNode) rootNode).getVariables(); else return getChild().getVariables(); }
@Override public void validateNode(ImmutableList<IQTree> children) throws InvalidIntermediateQueryException { if (children.size() < 2) { throw new InvalidIntermediateQueryException("UNION node " + this +" does not have at least 2 children node."); } ImmutableSet<Variable> unionVariables = getVariables(); for (IQTree child : children) { if (!child.getVariables().containsAll(unionVariables)) { throw new InvalidIntermediateQueryException("This child " + child + " does not project all the variables " + "required by the UNION node (" + unionVariables + ")\n" + this); } } }
private IQTree propagate(IQTree subTree, ImmutableSubstitution<? extends ImmutableTerm> substitution) throws InvalidQueryOptimizationProposalException { IQTree newSubTree = subTree.applyDescendingSubstitution(substitution.getVariableOrGroundTermFragment(), Optional.empty()); if (substitution.getNonGroundFunctionalTermFragment().getDomain().stream() .anyMatch(v -> newSubTree.getVariables().contains(v))) throw new InvalidQueryOptimizationProposalException("Non ground functional terms are not supported for propagation down " + "(only for up)"); ConstructionNode constructionNode = iqFactory.createConstructionNode( Sets.union(newSubTree.getVariables(), substitution.getDomain()).immutableCopy(), (ImmutableSubstitution<ImmutableTerm>) substitution); return iqFactory.createUnaryIQTree(constructionNode, newSubTree); } }
@Override protected IQTree transformBinaryNonCommutativeNode(IQTree tree, BinaryNonCommutativeOperatorNode rootNode, IQTree leftChild, IQTree rightChild) { ImmutableList<ConstructionNode> idleCns = getIdleCns(Stream.of(leftChild, rightChild)); return idleCns.isEmpty() ? tree : getProjection( tree.getVariables(), iqFactory.createBinaryNonCommutativeIQTree( rootNode, trimIdleCn(leftChild), trimIdleCn(rightChild) )); }
@Override public IQTree liftIncompatibleDefinitions(Variable variable, IQTree leftChild, IQTree rightChild) { if (leftChild.getVariables().contains(variable)) { IQTree liftedLeftChild = leftChild.liftIncompatibleDefinitions(variable); QueryNode leftChildRoot = liftedLeftChild.getRootNode(); if (leftChildRoot instanceof UnionNode && ((UnionNode) leftChildRoot).hasAChildWithLiftableDefinition(variable, leftChild.getChildren())) { UnionNode newUnionNode = iqFactory.createUnionNode( Stream.of(leftChild, rightChild) .flatMap(c -> c.getVariables().stream()) .collect(ImmutableCollectors.toSet())); return iqFactory.createNaryIQTree(newUnionNode, liftedLeftChild.getChildren().stream() .map(unionChild -> (IQTree) iqFactory.createBinaryNonCommutativeIQTree(this, unionChild, rightChild)) .collect(ImmutableCollectors.toList())); } } // By default, nothing lifted return iqFactory.createBinaryNonCommutativeIQTree(this, leftChild, rightChild); }
@Override public void validateNode(IQTree child) throws InvalidQueryNodeException, InvalidIntermediateQueryException { validateNode(); ImmutableSet<Variable> requiredChildVariables = getChildVariables(); ImmutableSet<Variable> childVariables = child.getVariables(); if (!childVariables.containsAll(requiredChildVariables)) { throw new InvalidIntermediateQueryException("This child " + child + " does not project all the variables " + "required by the CONSTRUCTION node (" + requiredChildVariables + ")\n" + this); } }
private void validateProjectedVariables() throws InvalidIntermediateQueryException { ImmutableSet<Variable> projectedVariables = tree.getVariables(); if (!projectedVariables.equals(projectionAtom.getVariables())) { throw new InvalidIntermediateQueryException("The variables projected by the root node" + projectedVariables + " do not match the projection atom " + projectionAtom.getVariables()); } }
@Override public IQTree transformInnerJoin(IQTree tree, InnerJoinNode rootNode, ImmutableList<IQTree> children) { ImmutableList<InjectiveVar2VarSubstitution> substitutions = computeSubstitutions(children); if (substitutions.stream().allMatch(ImmutableSubstitution::isEmpty)) return tree; ImmutableList<IQTree> updatedChildren = updateJoinChildren(substitutions, children); return iqFactory.createUnaryIQTree( iqFactory.createConstructionNode(tree.getVariables()), iqFactory.createNaryIQTree( iqFactory.createInnerJoinNode( Optional.of(updateJoinCondition( rootNode.getOptionalFilterCondition(), substitutions ))), updatedChildren )); }