/** * TODO: explain * * TODO: move it to the NonCommutativeOperatorNodeImpl when the latter will be created. */ protected boolean isFromRightBranch(QueryNode childNode, IntermediateQuery query) { Optional<ArgumentPosition> optionalPosition = query.getOptionalPosition(this, childNode); if (optionalPosition.isPresent()) { switch(optionalPosition.get()) { case LEFT: return false; case RIGHT: return true; default: throw new RuntimeException("Unexpected position: " + optionalPosition.get()); } } else { throw new RuntimeException("Inconsistent tree: no argument position after " + this); } } }
private boolean isRemovableTrueNode(TrueNode node, IntermediateQuery query) { QueryNode parentNode = query.getParent(node) .orElseThrow(() -> new InvalidIntermediateQueryException("a TrueNode should have a parent node")); return parentNode instanceof InnerJoinNode || parentNode instanceof TrueNode || (parentNode instanceof LeftJoinNode && query.getOptionalPosition(node) .orElseThrow(() -> new IllegalStateException("Children of a LJ must have positions")) == RIGHT); }
private ImmutableList<ParentAndChildPosition> extractAncestors(IntermediateQuery query, QueryNode node) { // Non-final Optional<QueryNode> optionalAncestor = query.getParent(node); QueryNode ancestorChild = node; ImmutableList.Builder<ParentAndChildPosition> listBuilder = ImmutableList.builder(); while (optionalAncestor.isPresent()) { QueryNode ancestor = optionalAncestor.get(); listBuilder.add(new ParentAndChildPosition(ancestor, query.getOptionalPosition(ancestor, ancestorChild))); optionalAncestor = query.getParent(ancestor); ancestorChild = ancestor; } return listBuilder.build(); }
private ImmutableList<ParentAndChildPosition> extractAncestors(IntermediateQuery query, QueryNode node) { // Non-final Optional<QueryNode> optionalAncestor = query.getParent(node); QueryNode ancestorChild = node; ImmutableList.Builder<ParentAndChildPosition> listBuilder = ImmutableList.builder(); while (optionalAncestor.isPresent()) { QueryNode ancestor = optionalAncestor.get(); listBuilder.add(new ParentAndChildPosition(ancestor, query.getOptionalPosition(ancestor, ancestorChild))); optionalAncestor = query.getParent(ancestor); ancestorChild = ancestor; } return listBuilder.build(); }
@Override public void addSubTree(IntermediateQuery subQuery, QueryNode subQueryTopNode, QueryNode localTopNode) throws IllegalTreeUpdateException { Queue<QueryNode> localParents = new LinkedList<>(); localParents.add(localTopNode); Map<QueryNode, QueryNode> localToExternalNodeMap = new HashMap<>(); localToExternalNodeMap.put(localTopNode, subQueryTopNode); while(!localParents.isEmpty()) { QueryNode localParent = localParents.poll(); QueryNode externalParent = localToExternalNodeMap.get(localParent); for (QueryNode externalChild : subQuery.getChildren(externalParent)) { QueryNode localChild = externalChild.clone(); localToExternalNodeMap.put(localChild, externalChild); localParents.add(localChild); addChild(localParent, localChild, subQuery.getOptionalPosition(externalParent, externalChild), false); } } }
@Override public void addSubTree(IntermediateQuery subQuery, QueryNode subQueryTopNode, QueryNode localTopNode) throws IllegalTreeUpdateException { Queue<QueryNode> localParents = new LinkedList<>(); localParents.add(localTopNode); Map<QueryNode, QueryNode> localToExternalNodeMap = new HashMap<>(); localToExternalNodeMap.put(localTopNode, subQueryTopNode); while(!localParents.isEmpty()) { QueryNode localParent = localParents.poll(); QueryNode externalParent = localToExternalNodeMap.get(localParent); for (QueryNode externalChild : subQuery.getChildren(externalParent)) { QueryNode localChild = externalChild.clone(); localToExternalNodeMap.put(localChild, externalChild); localParents.add(localChild); addChild(localParent, localChild, subQuery.getOptionalPosition(externalParent, externalChild), false); } } }
private ArgumentPosition getDescendantPosition(LeftJoinNode ancestorNode, QueryNode descendantNode, IntermediateQuery query) throws InvalidQueryOptimizationProposalException{ // Non-final Optional<QueryNode> optionalCurrentAncestor = query.getParent(descendantNode); QueryNode currentChild = descendantNode; while (optionalCurrentAncestor.isPresent()) { QueryNode currentAncestor = optionalCurrentAncestor.get(); if (currentAncestor == ancestorNode) { return query.getOptionalPosition(currentAncestor, currentChild) .orElseThrow(() -> new IllegalStateException("The child of a LJ must have a position") ); } optionalCurrentAncestor = query.getParent(currentAncestor); currentChild = currentAncestor; } throw new InvalidQueryOptimizationProposalException("The focus must be a descendant of the target node"); }
private ArgumentPosition getDescendantPosition(LeftJoinNode ancestorNode, QueryNode descendantNode, IntermediateQuery query) throws InvalidQueryOptimizationProposalException{ // Non-final Optional<QueryNode> optionalCurrentAncestor = query.getParent(descendantNode); QueryNode currentChild = descendantNode; while (optionalCurrentAncestor.isPresent()) { QueryNode currentAncestor = optionalCurrentAncestor.get(); if (currentAncestor == ancestorNode) { return query.getOptionalPosition(currentAncestor, currentChild) .orElseThrow(() -> new IllegalStateException("The child of a LJ must have a position") ); } optionalCurrentAncestor = query.getParent(currentAncestor); currentChild = currentAncestor; } throw new InvalidQueryOptimizationProposalException("The focus must be a descendant of the target node"); }
/** * Appends the first definition which is known to BE SAFE. * * Side-effect on the queryBuilder * */ private static void appendFirstDefinition(IntermediateQueryBuilder queryBuilder, UnionNode topUnionNode, IntermediateQuery subQuery) { // First add the root of the sub-query queryBuilder.addChild(topUnionNode, subQuery.getRootNode()); subQuery.getNodesInTopDownOrder().stream() .skip(1) .forEach(node -> queryBuilder.addChild( subQuery.getParent(node).orElseThrow(()-> new IllegalStateException("Unknown parent")), node, subQuery.getOptionalPosition(node))); }
@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); } }
/** Recursive */ private QueryNode getRecipientChild(QueryNode focusNode, IntermediateQuery query) { QueryNode parent = query.getParent(focusNode) .orElseThrow(() -> new InvalidIntermediateQueryException("Node "+focusNode+" has no parent")); if(parent instanceof LeftJoinNode) { BinaryOrderedOperatorNode.ArgumentPosition position = query.getOptionalPosition(parent, focusNode) .orElseThrow(() -> new InvalidIntermediateQueryException("No position for left join child " + focusNode)); if (position.equals(BinaryOrderedOperatorNode.ArgumentPosition.LEFT)) { return getRecipientChild(parent, query); } } return focusNode; }
private void copyChildren(IntermediateQuery sourceQuery, QueryNode sourceParent, IntermediateQueryBuilder builder, QueryNode targetParent) { for (QueryNode child : sourceQuery.getChildren(sourceParent)) { builder.addChild( targetParent, child, sourceQuery.getOptionalPosition( sourceParent, child )); copyChildren(sourceQuery, child, builder, child); } } }
querySnapshot.getOptionalPosition(originalParent, originalNode), false);
/** * Appends a definition under the union node after renaming it. */ private void appendDefinition(IntermediateQueryBuilder queryBuilder, UnionNode unionNode, IntermediateQuery definition, InjectiveVar2VarSubstitution renamingSubstitution) { QueryNodeRenamer nodeRenamer = new QueryNodeRenamer(iqFactory, renamingSubstitution); ImmutableList<QueryNode> originalNodesInTopDownOrder = definition.getNodesInTopDownOrder(); /** * Renames all the nodes (new objects) and maps them to original nodes */ ImmutableMap<QueryNode, QueryNode> renamedNodeMap = originalNodesInTopDownOrder.stream() .map(n -> new AbstractMap.SimpleEntry<>(n, n.acceptNodeTransformer(nodeRenamer))) .collect(ImmutableCollectors.toMap()); /** * Adds the renamed root of the definition */ queryBuilder.addChild(unionNode, renamedNodeMap.get(definition.getRootNode())); /** * Add the other renamed nodes */ originalNodesInTopDownOrder.stream() .skip(1) .forEach(node -> queryBuilder.addChild( renamedNodeMap.get(definition.getParent(node) .orElseThrow(()-> new IllegalStateException("Unknown parent"))), renamedNodeMap.get(node), definition.getOptionalPosition(node))); }
@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); } }
querySnapshot.getOptionalPosition(originalParent, originalNode), false);
private IntermediateQuery split(IntermediateQuery originalQuery, UnionNode unionNode, QueryNode replacingChildNode) { IntermediateQueryBuilder queryBuilder = originalQuery.newBuilder(); QueryNode rootNode = originalQuery.getRootNode(); queryBuilder.init(originalQuery.getProjectionAtom(), rootNode); Queue<QueryNode> parentNodes = new LinkedList<>(); parentNodes.add(rootNode); while(!parentNodes.isEmpty()) { QueryNode parentNode = parentNodes.poll(); for(QueryNode originalChildNode : originalQuery.getChildren(parentNode)) { QueryNode childNode = originalChildNode == unionNode ? replacingChildNode : originalChildNode; queryBuilder.addChild(parentNode, childNode, originalQuery.getOptionalPosition( parentNode, originalChildNode)); parentNodes.add(childNode); } } return queryBuilder.build(); }
/** * TODO: replace this implementation by a non-recursive one. */ private IntermediateQueryBuilder copyChildrenNodesToBuilder(final IntermediateQuery originalQuery, IntermediateQueryBuilder queryBuilder, final QueryNode originalParentNode, final QueryNode newParentNode, HomogeneousQueryNodeTransformer nodeTransformer) { for (QueryNode originalChildNode : originalQuery.getChildren(originalParentNode)) { QueryNode newChildNode; newChildNode = originalChildNode.acceptNodeTransformer(nodeTransformer); Optional<BinaryOrderedOperatorNode.ArgumentPosition> optionalPosition = originalQuery.getOptionalPosition(originalParentNode, originalChildNode); queryBuilder.addChild(newParentNode, newChildNode, optionalPosition); // Recursive call queryBuilder = copyChildrenNodesToBuilder(originalQuery, queryBuilder, originalChildNode, newChildNode, nodeTransformer); } return queryBuilder; }
/** * TODO: replace this implementation by a non-recursive one. */ private IntermediateQueryBuilder copyChildrenNodesToBuilder(final IntermediateQuery originalQuery, IntermediateQueryBuilder queryBuilder, final QueryNode originalParentNode, final QueryNode newParentNode, HomogeneousQueryNodeTransformer nodeTransformer) { for (QueryNode originalChildNode : originalQuery.getChildren(originalParentNode)) { QueryNode newChildNode; newChildNode = originalChildNode.acceptNodeTransformer(nodeTransformer); Optional<BinaryOrderedOperatorNode.ArgumentPosition> optionalPosition = originalQuery.getOptionalPosition(originalParentNode, originalChildNode); queryBuilder.addChild(newParentNode, newChildNode, optionalPosition); // Recursive call queryBuilder = copyChildrenNodesToBuilder(originalQuery, queryBuilder, originalChildNode, newChildNode, nodeTransformer); } return queryBuilder; }
&& currentQuery.getOptionalPosition(currentConstructionNode) .filter(p -> p == RIGHT) .isPresent())) {