private ImmutableSet<Variable> getChildProjectedVariables(IntermediateQuery query, Optional<ImmutableSet<Variable>> optionalChildVariables, ArgumentPosition position) { return optionalChildVariables .orElseGet(() -> query.getVariables(query.getChild(this, position) .orElseThrow(() -> new IllegalStateException("Missing child ")))); }
private ImmutableList<QueryNode> extractChildrenToVisit(IntermediateQuery query, QueryNode node) { if (node instanceof BinaryNonCommutativeOperatorNode) { if (node instanceof LeftJoinNode) { return ImmutableList.of(query.getChild(node, BinaryOrderedOperatorNode.ArgumentPosition.LEFT) .orElseThrow(() -> new InvalidIntermediateQueryException("A left join must have a left child"))); } /* * Not supported BinaryNonCommutativeOperatorNode: we ignore them */ else { return ImmutableList.of(); } } else { return query.getChildren(node); } }
/** * Routing method */ private Optional<PushDownBooleanExpressionProposal> makeProposal( IntermediateQuery currentQuery, JoinOrFilterNode focusNode) { /** * Commutative joins and filters */ if (focusNode instanceof CommutativeJoinOrFilterNode) { return makeProposalForJoinOrFilterNode(currentQuery, focusNode, currentQuery.getChildren(focusNode)); } /** * Left join: can only push its conditions on the right side */ else if (focusNode instanceof LeftJoinNode) { return makeProposalForJoinOrFilterNode(currentQuery, focusNode, ImmutableList.of(currentQuery.getChild(focusNode, RIGHT) .orElseThrow(() -> new IllegalStateException("Was not excepting to find a " + "LJ without a right element")))); } /** * Other node (useful for extension) */ else { return makeProposalForUnexpectedFocusNode(currentQuery, focusNode); } }
@Override public boolean isVariableNullable(IntermediateQuery query, Variable variable) { QueryNode leftChild = query.getChild(this, LEFT) .orElseThrow(() -> new InvalidIntermediateQueryException("A left child is required")); if (query.getVariables(leftChild).contains(variable)) return leftChild.isVariableNullable(query, variable); QueryNode rightChild = query.getChild(this, RIGHT) .orElseThrow(() -> new InvalidIntermediateQueryException("A right child is required")); if (!query.getVariables(rightChild).contains(variable)) throw new IllegalArgumentException("The variable " + variable + " is not projected by " + this); return false; }
/** * Routing method */ private Optional<PushDownBooleanExpressionProposal> makeProposal( IntermediateQuery currentQuery, JoinOrFilterNode focusNode) { /** * Commutative joins and filters */ if (focusNode instanceof CommutativeJoinOrFilterNode) { return makeProposalForJoinOrFilterNode(currentQuery, focusNode, currentQuery.getChildren(focusNode)); } /** * Left join: can only push its conditions on the right side */ else if (focusNode instanceof LeftJoinNode) { return makeProposalForJoinOrFilterNode(currentQuery, focusNode, ImmutableList.of(currentQuery.getChild(focusNode, RIGHT) .orElseThrow(() -> new IllegalStateException("Was not excepting to find a " + "LJ without a right element")))); } /** * Other node (useful for extension) */ else { return makeProposalForUnexpectedFocusNode(currentQuery, focusNode); } }
@Override public boolean isVariableNullable(IntermediateQuery query, Variable variable) { QueryNode leftChild = query.getChild(this, LEFT) .orElseThrow(() -> new InvalidIntermediateQueryException("A left child is required")); if (query.getVariables(leftChild).contains(variable)) return leftChild.isVariableNullable(query, variable); QueryNode rightChild = query.getChild(this, RIGHT) .orElseThrow(() -> new InvalidIntermediateQueryException("A right child is required")); if (!query.getVariables(rightChild).contains(variable)) throw new IllegalArgumentException("The variable " + variable + " is not projected by " + this); return false; }
/** * Recursive */ @Override public IQTree convertTree(IntermediateQuery query, QueryNode rootNode) { if (rootNode instanceof LeafIQTree) { return (LeafIQTree) rootNode; } else if (rootNode instanceof UnaryOperatorNode) { // Recursive IQTree childTree = convertTree(query, query.getFirstChild(rootNode).get()); return iqFactory.createUnaryIQTree((UnaryOperatorNode) rootNode, childTree); } else if (rootNode instanceof BinaryNonCommutativeOperatorNode) { IQTree leftChildTree = convertTree(query, query.getChild(rootNode, LEFT).get()); IQTree rightChildTree = convertTree(query, query.getChild(rootNode, RIGHT).get()); return iqFactory.createBinaryNonCommutativeIQTree((BinaryNonCommutativeOperatorNode) rootNode, leftChildTree, rightChildTree); } else if (rootNode instanceof NaryOperatorNode) { ImmutableList<IQTree> childTrees = query.getChildren(rootNode).stream() .map(c -> convertTree(query, c)) .collect(ImmutableCollectors.toList()); return iqFactory.createNaryIQTree((NaryOperatorNode) rootNode, childTrees); } throw new MinorOntopInternalBugException("Unexpected type of query node: " + rootNode); }
private Stream<Variable> extractPriorityVariables(IntermediateQuery query, QueryNode node, Optional<ArgumentPosition> childPosition) { if (node instanceof ExplicitVariableProjectionNode) return ((ExplicitVariableProjectionNode)node).getVariables().stream(); /* * LJ: look for variables on the left * only when the focus node is on the right */ else if (node instanceof LeftJoinNode) { switch (childPosition.get()) { case RIGHT: return query.getChild(node, LEFT) .map(c -> query.getVariables(c).stream()) .orElseThrow(() -> new IllegalStateException("A LJ must have a left child")); case LEFT: default: return Stream.empty(); } } else { return Stream.empty(); } }
private ImmutableSubstitution<ImmutableTerm> removeRightChildSubstitutionFromRight( IntermediateQuery query, ImmutableSubstitution<? extends ImmutableTerm> substitution, Optional<ImmutableSet<Variable>> optionalLeftVariables) { ImmutableSet<Variable> leftVariables = getChildProjectedVariables(query, optionalLeftVariables, LEFT); ImmutableSet<Variable> rightVariables = query.getVariables(query.getChild(this, RIGHT) .orElseThrow(() -> new IllegalStateException("Missing right child "))); ImmutableSet<Variable> newlyNullVariables = rightVariables.stream() .filter(v -> !leftVariables.contains(v)) .collect(ImmutableCollectors.toSet()); Stream<Map.Entry<Variable, ImmutableTerm>> nullEntries = newlyNullVariables.stream() .map(v -> new SimpleEntry<>(v, TermConstants.NULL)); Stream<Map.Entry<Variable, ImmutableTerm>> otherEntries = substitution.getImmutableMap().entrySet().stream() .filter(e -> !newlyNullVariables.contains(e.getKey())) .map(e -> (Map.Entry<Variable, ImmutableTerm>)e); return SUBSTITUTION_FACTORY.getSubstitution( Stream.concat(nullEntries, otherEntries) .collect(ImmutableCollectors.toMap())); }
private Stream<Variable> extractPriorityVariables(IntermediateQuery query, QueryNode node, Optional<ArgumentPosition> childPosition) { if (node instanceof ExplicitVariableProjectionNode) return ((ExplicitVariableProjectionNode)node).getVariables().stream(); /* * LJ: look for variables on the left * only when the focus node is on the right */ else if (node instanceof LeftJoinNode) { switch (childPosition.get()) { case RIGHT: return query.getChild(node, LEFT) .map(c -> query.getVariables(c).stream()) .orElseThrow(() -> new IllegalStateException("A LJ must have a left child")); case LEFT: default: return Stream.empty(); } } else { return Stream.empty(); } }
@Override public NodeTransformationProposal reactToTrueChildRemovalProposal(IntermediateQuery query, TrueNode trueChild) { ArgumentPosition trueNodePosition = query.getOptionalPosition(this, trueChild) .orElseThrow(() -> new IllegalStateException("The deleted child of a LJ must have a position")); QueryNode otherChild = query.getChild(this, (trueNodePosition == LEFT) ? RIGHT : LEFT) .orElseThrow(() -> new IllegalStateException("The other child of a LJ is missing")); switch(trueNodePosition) { case LEFT: throw new UnsupportedOperationException("A TrueNode in the left position of a LeftJoin should not be removed"); case RIGHT: Optional<ImmutableExpression> condition = getOptionalFilterCondition(); if (condition.isPresent()) { return new NodeTransformationProposalImpl( REPLACE_BY_NEW_NODE, query.getFactory().createFilterNode(condition.get()), ImmutableSet.of() ); } return new NodeTransformationProposalImpl(REPLACE_BY_UNIQUE_NON_EMPTY_CHILD, otherChild, ImmutableSet.of()); default: throw new IllegalStateException("Unknown position: " + trueNodePosition); } }
private SubstitutionResults<LeftJoinNode> applyAscendingSubstitutionFromLeft( ImmutableSubstitution<? extends ImmutableTerm> substitution, IntermediateQuery query) { QueryNode rightChild = query.getChild(this, RIGHT) .orElseThrow(() -> new IllegalStateException("No right child for the LJ")); ImmutableSet<Variable> rightVariables = query.getVariables(rightChild); /** * If the substitution will set some right variables to be null * -> remove the right part */ if (rightVariables.stream() .filter(substitution::isDefining) .anyMatch(v -> substitution.get(v).equals(TermConstants.NULL))) { return proposeToRemoveTheRightPart(query, substitution, Optional.of(rightVariables), Provenance.FROM_LEFT); } /** * Updates the joining conditions (may add new equalities) * and propagates the same substitution if the conditions still holds. * */ return computeAndEvaluateNewCondition(substitution, Optional.empty()) .map(ev -> applyEvaluation(query, ev, substitution, Optional.of(rightVariables), Provenance.FROM_LEFT)) .orElseGet(() -> DefaultSubstitutionResults.newNode(this, substitution)); }
private ImmutableSubstitution<ImmutableTerm> removeRightChildSubstitutionFromLeft( IntermediateQuery query, ImmutableSubstitution<? extends ImmutableTerm> substitution, Optional<ImmutableSet<Variable>> optionalRightVariables) { ImmutableSet<Variable> leftVariables = query.getVariables(query.getChild(this, LEFT) .orElseThrow(() -> new IllegalStateException("Missing left child "))); ImmutableSet<Variable> rightVariables = getChildProjectedVariables(query, optionalRightVariables, RIGHT); ImmutableMap<Variable, ? extends ImmutableTerm> substitutionMap = substitution.getImmutableMap(); ImmutableSet<Variable> newlyNullVariables = rightVariables.stream() .filter(v -> !leftVariables.contains(v)) .filter(v -> !substitutionMap.containsKey(v)) .collect(ImmutableCollectors.toSet()); Stream<Map.Entry<Variable, ImmutableTerm>> nullEntries = newlyNullVariables.stream() .map(v -> new SimpleEntry<>(v, TermConstants.NULL)); Stream<Map.Entry<Variable, ImmutableTerm>> alreadyExistingEntries = substitution.getImmutableMap().entrySet().stream() .map(e -> (Map.Entry<Variable, ImmutableTerm>)e); return SUBSTITUTION_FACTORY.getSubstitution( Stream.concat(nullEntries, alreadyExistingEntries) .collect(ImmutableCollectors.toMap())); }
@Override public NodeTransformationProposal reactToEmptyChild(IntermediateQuery query, EmptyNode emptyChild) { ArgumentPosition emptyNodePosition = query.getOptionalPosition(this, emptyChild) .orElseThrow(() -> new IllegalStateException("The deleted child of a LJ must have a position")); QueryNode otherChild = query.getChild(this, (emptyNodePosition == LEFT) ? RIGHT : LEFT) .orElseThrow(() -> new IllegalStateException("The other child of a LJ is missing")); ImmutableSet<Variable> variablesProjectedByOtherChild = query.getVariables(otherChild); ImmutableSet<Variable> nullVariables; switch(emptyNodePosition) { case LEFT: nullVariables = union(variablesProjectedByOtherChild, emptyChild.getVariables()); return new NodeTransformationProposalImpl(DECLARE_AS_EMPTY, nullVariables); case RIGHT: nullVariables = emptyChild.getVariables().stream() .filter(v -> !(variablesProjectedByOtherChild.contains(v))) .collect(ImmutableCollectors.toSet()); return new NodeTransformationProposalImpl(REPLACE_BY_UNIQUE_NON_EMPTY_CHILD, otherChild, nullVariables); default: throw new IllegalStateException("Unknown position: " + emptyNodePosition); } }
selectedSubtreeRootsBuilder.add(candidateSubtreeRoot); if (candidateSubtreeRoot instanceof LeftJoinNode) { QueryNode rightChild = query.getChild(candidateSubtreeRoot, RIGHT) .orElseThrow(() -> new IllegalTreeException("a LeftJoinNode is expected to have a right child")); if (query.getVariables(rightChild).containsAll(expressionVariables)) {
Optional<QueryNode> optionalLeftChild = currentQuery.getChild(currentNode, LEFT);
LeftJoinNode leftJoinNode = proposal.getFocusNode(); QueryNode leftChild = query.getChild(leftJoinNode, LEFT) .orElseThrow(() -> new InvalidIntermediateQueryException("A LJ must have a left child")); QueryNode rightChild = query.getChild(leftJoinNode, RIGHT) .orElseThrow(() -> new InvalidIntermediateQueryException("A LJ must have a right child"));
LeftJoinNode leftJoinNode = proposal.getFocusNode(); QueryNode leftChild = query.getChild(leftJoinNode, LEFT) .orElseThrow(() -> new InvalidIntermediateQueryException("A LJ must have a left child")); QueryNode rightChild = query.getChild(leftJoinNode, RIGHT) .orElseThrow(() -> new InvalidIntermediateQueryException("A LJ must have a right child"));
/** * This methods only propagates down an expression e coming from a provider parent p of a LJ node n, * and not the joining condition of n. * <p> * e is not added to the joining condition of n, * but may be propagated down d irectly to the left subtree of n */ private Push findPushInLeftJoinRootedSubtree(IntermediateQuery query, ImmutableExpression expression, JoinOrFilterNode providerNode, LeftJoinNode currentNode) { QueryNode leftChild = query.getChild(currentNode, LEFT) .orElseThrow(() -> new MinorOntopInternalBugException("Was expecting a left child")); return query.getVariables(leftChild).containsAll(expression.getVariables()) ? new Push(new Recipient(leftChild), expression) : getProviderAsPush(providerNode, expression); }
.flatMap(position -> query.getChild(originalNode, position)) .orElseGet(() -> query.getFirstChild(originalNode) .orElseThrow(() -> new IllegalStateException("No replacing child is available")));