/** * Recursive */ private void insertChildren(QueryNode parentNode, ImmutableList<IQTree> childrenTrees, IntermediateQueryBuilder queryBuilder) { AtomicInteger i = new AtomicInteger(0); childrenTrees.stream() .map(IQTree::getRootNode) .map(n -> queryBuilder.contains(n) ? n.clone() : n) .forEach(t -> insertChildTree(parentNode, t, childrenTrees.get(i.get()), queryBuilder, i.getAndIncrement())); }
public static ImmutableSet<Variable> collectVariables(List<QueryNode> nodes) { ImmutableSet.Builder<Variable> collectedVariableBuilder = ImmutableSet.builder(); for (QueryNode node : nodes) { collectedVariableBuilder.addAll(node.getLocalVariables()); } return collectedVariableBuilder.build(); }
@Override public boolean isVariableNullable(IntermediateQuery query, Variable variable) { for(QueryNode child : query.getChildren(this)) { if (child.isVariableNullable(query, variable)) return true; } return false; }
private ImmutableList<Variable> extractNullableVariables(IntermediateQuery query, QueryNode rootNode) { ImmutableSet<Variable> requiredVariables = rootNode instanceof ConstructionNode ? rootNode.getRequiredVariables(query): query.getVariables(rootNode); return requiredVariables.stream() .filter(v -> rootNode.isVariableNullable(query, v)) .collect(ImmutableCollectors.toList()); }
/** * 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))); }
.applyDescendingSubstitution(substitution, query);
@Override public void validate(IntermediateQuery query) throws InvalidIntermediateQueryException { validateProjectedVariables(query); QueryNodeVisitor visitor = createVisitor(query); /* * May throw an InvalidIntermediateQueryException */ query.getNodesInTopDownOrder() .forEach(n -> n.acceptVisitor(visitor)); }
@Override public ImmutableSet<Variable> getVariablesRequiredByAncestors(QueryNode queryNode) { ImmutableSet.Builder<Variable> requiredVariableBuilder = ImmutableSet.builder(); // Non-final Optional<QueryNode> optionalAncestor = getParent(queryNode); while (optionalAncestor.isPresent()) { QueryNode ancestor = optionalAncestor.get(); ancestor.getRequiredVariables(this) .forEach(requiredVariableBuilder::add); if (ancestor instanceof ExplicitVariableProjectionNode) break; optionalAncestor = getParent(ancestor); } ImmutableSet<Variable> requiredVariables = requiredVariableBuilder.build(); /* * Restrict to variables which can actually be provided. * Assumption: variables defined by a node should not appear in its subtree */ return getVariables(queryNode).stream() .filter(requiredVariables::contains) .collect(ImmutableCollectors.toSet()); }
@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))); }
@Override public IntermediateQuery optimize(IntermediateQuery query) { /** * Contains all (non discarded) variables projected out by some node previously traversed, * plus all variables appearing in an (explicit or implicit) condition of some join node already traversed * * Immutable only for safety (updated in practice). * Question: shall we keep it as immutable ? */ QueryNode rootNode = query.getRootNode(); Optional<QueryNode> rootChild = query.getFirstChild(rootNode); if (rootChild.isPresent()) { return optimizeSubtree( rootChild.get(), query, rootNode.getLocallyRequiredVariables() ); } return query; }
final SubstitutionResults<? extends QueryNode> substitutionResults = currentAncestor.applyAscendingSubstitution( currentSubstitution, childOfAncestor, query);
/** * TODO: explain * <p> * TODO: avoid the use of a recursive method. Use a stack instead. */ protected IntermediateQueryBuilder convertToBuilderAndTransform(IntermediateQuery originalQuery, HomogeneousQueryNodeTransformer nodeTransformer, DistinctVariableOnlyDataAtom transformedProjectionAtom) { IntermediateQueryBuilder queryBuilder = originalQuery.newBuilder(); // Clone the original root node and apply the transformer if available. QueryNode originalRootNode = originalQuery.getRootNode(); QueryNode newRootNode; newRootNode = originalRootNode.acceptNodeTransformer(nodeTransformer); queryBuilder.init(transformedProjectionAtom, newRootNode); return copyChildrenNodesToBuilder(originalQuery, queryBuilder, originalRootNode, newRootNode, nodeTransformer); }
SubstitutionResults<? extends QueryNode> results = originalNode.applyDescendingSubstitution( substitutionToApply.get(), query);
@Override public void validate(IntermediateQuery query) throws InvalidIntermediateQueryException { validateProjectedVariables(query); QueryNodeVisitor visitor = createVisitor(query); /* * May throw an InvalidIntermediateQueryException */ query.getNodesInTopDownOrder() .forEach(n -> n.acceptVisitor(visitor)); }
@Override public ImmutableSet<Variable> getVariablesRequiredByAncestors(QueryNode queryNode) { ImmutableSet.Builder<Variable> requiredVariableBuilder = ImmutableSet.builder(); // Non-final Optional<QueryNode> optionalAncestor = getParent(queryNode); while (optionalAncestor.isPresent()) { QueryNode ancestor = optionalAncestor.get(); ancestor.getRequiredVariables(this) .forEach(requiredVariableBuilder::add); if (ancestor instanceof ExplicitVariableProjectionNode) break; optionalAncestor = getParent(ancestor); } ImmutableSet<Variable> requiredVariables = requiredVariableBuilder.build(); /* * Restrict to variables which can actually be provided. * Assumption: variables defined by a node should not appear in its subtree */ return getVariables(queryNode).stream() .filter(requiredVariables::contains) .collect(ImmutableCollectors.toSet()); }
@Override public boolean isVariableNullable(IntermediateQuery query, Variable variable) { for(QueryNode child : query.getChildren(this)) { if (child.isVariableNullable(query, variable)) return true; } return false; }
public static ImmutableSet<Variable> collectVariables(List<QueryNode> nodes) { ImmutableSet.Builder<Variable> collectedVariableBuilder = ImmutableSet.builder(); for (QueryNode node : nodes) { collectedVariableBuilder.addAll(node.getLocalVariables()); } return collectedVariableBuilder.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); } } }
/** * TODO: explain * <p> * TODO: avoid the use of a recursive method. Use a stack instead. */ protected IntermediateQueryBuilder convertToBuilderAndTransform(IntermediateQuery originalQuery, HomogeneousQueryNodeTransformer nodeTransformer, DistinctVariableOnlyDataAtom transformedProjectionAtom) { IntermediateQueryBuilder queryBuilder = originalQuery.newBuilder(); // Clone the original root node and apply the transformer if available. QueryNode originalRootNode = originalQuery.getRootNode(); QueryNode newRootNode; newRootNode = originalRootNode.acceptNodeTransformer(nodeTransformer); queryBuilder.init(transformedProjectionAtom, newRootNode); return copyChildrenNodesToBuilder(originalQuery, queryBuilder, originalRootNode, newRootNode, nodeTransformer); }
Optional<NodeTracker> optionalTracker) throws EmptyQueryException { SubstitutionResults<? extends QueryNode> substitutionResults = node.applyDescendingSubstitution(substitution, query);