@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 static EmptyNode replaceByEmptyNode(QueryNode rejectedNode, ImmutableSubstitution descendingSubstitution, IntermediateQuery query, Optional<NodeTracker> optionalTracker) { optionalTracker.ifPresent(tr -> tr.recordUpcomingRemoval(query, rejectedNode)); /** * The new set of projected variables have to take into account * the changes proposed by the descending substitution. */ ImmutableSet<Variable> newProjectedVariables = query.getVariables(rejectedNode).stream() .flatMap(v -> descendingSubstitution.apply(v).getVariableStream()) .collect(ImmutableCollectors.toSet()); return query.getFactory().createEmptyNode(newProjectedVariables); }
@Override public NodeTransformationProposal reactToTrueChildRemovalProposal(IntermediateQuery query, TrueNode trueChild) { ImmutableList<QueryNode> remainingChildren = query.getChildrenStream(this) .filter(c -> c != trueChild) .collect(ImmutableCollectors.toList()); switch (remainingChildren.size()) { case 0: return new NodeTransformationProposalImpl(DECLARE_AS_TRUE, ImmutableSet.of()); case 1: 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, remainingChildren.get(0),ImmutableSet.of()); default: return new NodeTransformationProposalImpl(NO_LOCAL_CHANGE, ImmutableSet.of()); } }
/** * Returns results centered on the removed node. */ private static NodeTrackingResults<EmptyNode> reactToEmptinessDeclaration( IntermediateQuery query, QueryNode currentAncestor, QueryTreeComponent treeComponent, Optional<NodeTracker> optionalAncestryTracker) throws EmptyQueryException { ImmutableSet<Variable> nullVariables = query.getVariables(currentAncestor); EmptyNode replacingEmptyNode = query.getFactory().createEmptyNode(nullVariables); treeComponent.replaceSubTree(currentAncestor, replacingEmptyNode); RemoveEmptyNodeProposal proposal = optionalAncestryTracker.isPresent() ? new RemoveEmptyNodeProposalImpl(replacingEmptyNode, optionalAncestryTracker.get()) : new RemoveEmptyNodeProposalImpl(replacingEmptyNode, false); return query.applyProposal(proposal, true); } }
return new AnalysisResults(originalNode, query.getFactory().createTrueNode(), Optional.empty()); return analyze(query, query.getFactory().createEmptyNode(query.getVariables(originalNode)), substitutionToApply);
QueryNode filterNode = query.getFactory().createFilterNode(optionalFilter.get()); treeComponent.replaceNode(joinNode, filterNode); N newJoinNode = joinNode.getOptionalFilterCondition() .map(cond -> { FilterNode parentFilter = query.getFactory().createFilterNode(cond); treeComponent.insertParent(joinNode, parentFilter);
newTopNode = query.getFactory().createFilterNode(optionalFilter.get()); treeComponent.replaceNode(joinNode, newTopNode);
/** * Blocks an ascending substitution by inserting a construction node. * * Note that expects that the substitution does not rename a projected variable * into a non-projected one (this would produce an invalid construction node). * That is the responsibility of the SubstitutionPropagationExecutor * to prevent such bindings from appearing. */ @Override public SubstitutionResults<UnionNode> applyAscendingSubstitution( ImmutableSubstitution<? extends ImmutableTerm> substitution, QueryNode childNode, IntermediateQuery query) { /** * Reduce the domain of the substitution to the variables projected out by the union node */ ImmutableSubstitution reducedSubstitution = substitution.reduceDomainToIntersectionWith(projectedVariables); if (reducedSubstitution.isEmpty()) { return DefaultSubstitutionResults.noChange(); } /** * Asks for inserting a construction node between the child node and this node. * Such a construction node will contain the substitution. */ else { ConstructionNode newParentOfChildNode = query.getFactory().createConstructionNode(projectedVariables, (ImmutableSubstitution<ImmutableTerm>) reducedSubstitution); return DefaultSubstitutionResults.insertConstructionNode(newParentOfChildNode, childNode); } }
TrueNode replacingNode = query.getFactory().createTrueNode();