protected static ImmutableMultimap<RelationPredicate, ExtensionalDataNode> extractDataNodes(ImmutableList<QueryNode> siblings) { ImmutableMultimap.Builder<RelationPredicate, ExtensionalDataNode> mapBuilder = ImmutableMultimap.builder(); for (QueryNode node : siblings) { if (node instanceof ExtensionalDataNode) { ExtensionalDataNode dataNode = (ExtensionalDataNode) node; mapBuilder.put(dataNode.getProjectionAtom().getPredicate(), dataNode); } } return mapBuilder.build(); }
@Override public IQTree transformExtensionalData(ExtensionalDataNode dataNode) { return dataNode.acceptNodeTransformer(nodeTransformer); }
@Override public ExtensionalDataNode transform(ExtensionalDataNode extensionalDataNode) { return extensionalDataNode.clone(); }
Map.Entry::getValue)); DataAtom<RelationPredicate> rightProjectionAtom = rightDataNode.getProjectionAtom(); ImmutableList<? extends VariableOrGroundTerm> rightArguments = rightProjectionAtom.getArguments(); if (leftRelationArgumentMultimap.isEmpty()) { RelationDefinition rightRelation = rightDataNode.getProjectionAtom().getPredicate().getRelationDefinition(); ExtensionalDataNode newRightDataNode = rightDataNode.newAtom(computeNewRightAtom(rightProjectionAtom.getPredicate(), rightArguments, conflictingRightArgumentIndexes, variableGenerator)); ImmutableExpression newExpression = computeExpression(rightArguments, newRightDataNode.getProjectionAtom().getArguments());
@Override public boolean isSyntacticallyEquivalentTo(QueryNode node) { return (node instanceof ExtensionalDataNode) && ((ExtensionalDataNode) node).getProjectionAtom().equals(this.getProjectionAtom()); }
@Override public ExtensionalDataNode transform(ExtensionalDataNode extensionalDataNode) { return extensionalDataNode.clone(); }
@Override public boolean isEquivalentTo(QueryNode queryNode) { return (queryNode instanceof ExtensionalDataNode) && getProjectionAtom().equals(((ExtensionalDataNode) queryNode).getProjectionAtom()); }
@Override public boolean isSyntacticallyEquivalentTo(QueryNode node) { return (node instanceof ExtensionalDataNode) && ((ExtensionalDataNode) node).getProjectionAtom().equals(this.getProjectionAtom()); }
/** * TODO: explain */ private boolean isRemovable(ExtensionalDataNode node, ImmutableSet<Integer> independentIndexes, ImmutableSet<Variable> requiredAndCooccuringVariables) { ImmutableList<? extends VariableOrGroundTerm> arguments = node.getProjectionAtom().getArguments(); return independentIndexes.stream() .map(i -> arguments.get(i - 1)) .allMatch(t -> (t instanceof Variable) && (!requiredAndCooccuringVariables.contains(t))); }
/** * dataNodes and UC positions are given for the same predicate * TODO: explain */ private static ImmutableMultimap<ImmutableList<VariableOrGroundTerm>, ExtensionalDataNode> groupByUniqueConstraintArguments( ImmutableCollection<ExtensionalDataNode> dataNodes, ImmutableCollection<ImmutableList<Integer>> collectionOfUCPositions) { ImmutableMultimap.Builder<ImmutableList<VariableOrGroundTerm>, ExtensionalDataNode> groupingMapBuilder = ImmutableMultimap.builder(); for (ImmutableList<Integer> primaryKeyPositions : collectionOfUCPositions) { for (ExtensionalDataNode dataNode : dataNodes) { groupingMapBuilder.put(extractArguments(dataNode.getProjectionAtom(), primaryKeyPositions), dataNode); } } return groupingMapBuilder.build(); } }
private Collection<ImmutableSubstitution<VariableOrGroundTerm>> extractDependentUnifiersFromCluster( ImmutableList<Integer> dependentIndexes, Collection<ExtensionalDataNode> cluster, ImmutableSet<ExtensionalDataNode> nodesToRemove, ImmutableSet<Integer> nullableIndexes) throws AtomUnificationException { if (cluster.size() < 2) return ImmutableList.of(); ExtensionalDataNode referenceDataNode = cluster.stream() // Try to get the first kept data node .filter(n -> !nodesToRemove.contains(n)) .findFirst() // Otherwise if all the nodes will be removed, take the first one .orElseGet(() -> cluster.iterator().next()); /* * Ignores the reference data node * * NB: while loop due to the exception */ Collection<ImmutableSubstitution<VariableOrGroundTerm>> substitutionCollection = new ArrayList<>(); for (ExtensionalDataNode currentDataNode : cluster) { if (currentDataNode == referenceDataNode) continue; boolean willBeRemoved = nodesToRemove.contains(currentDataNode); unifyDependentTerms(referenceDataNode.getProjectionAtom(), currentDataNode.getProjectionAtom(), dependentIndexes, willBeRemoved, nullableIndexes) .ifPresent(substitutionCollection::add); } return substitutionCollection; }
/** * Predicates not having a DatabaseRelationDefinition are ignored */ private ImmutableMultimap<RelationDefinition, ExtensionalDataNode> extractDataNodeMap(IntermediateQuery query, InnerJoinNode joinNode) { return query.getChildren(joinNode).stream() .filter(c -> c instanceof ExtensionalDataNode) .map(c -> (ExtensionalDataNode) c) .map(c -> Maps.immutableEntry(c.getProjectionAtom().getPredicate().getRelationDefinition(), c)) .collect(ImmutableCollectors.toMultimap()); }
protected ImmutableSubstitution<VariableOrGroundTerm> unifyRedundantNodes( Collection<ExtensionalDataNode> redundantNodes) throws AtomUnificationException { // Non-final ImmutableSubstitution<VariableOrGroundTerm> accumulatedSubstitution = substitutionFactory.getSubstitution(); /* * Should normally not be called in this case. */ if (redundantNodes.size() < 2) { // Empty substitution return accumulatedSubstitution; } Iterator<ExtensionalDataNode> nodeIterator = redundantNodes.iterator(); // Non-final DataAtom accumulatedAtom = nodeIterator.next().getProjectionAtom(); while (nodeIterator.hasNext()) { DataAtom newAtom = nodeIterator.next().getProjectionAtom(); // May throw an exception accumulatedSubstitution = updateSubstitution(accumulatedSubstitution, accumulatedAtom, newAtom); accumulatedAtom = accumulatedSubstitution.applyToDataAtom(accumulatedAtom); } return accumulatedSubstitution; }
@Override public ExtensionalDataNode transform(ExtensionalDataNode extensionalDataNode) { return iqFactory.createExtensionalDataNode(renameDataAtom(extensionalDataNode.getProjectionAtom())); }
/** * * TODO: explain */ private boolean areMatching(ExtensionalDataNode sourceDataNode, ExtensionalDataNode targetDataNode, ForeignKeyConstraint constraint) { ImmutableList<? extends VariableOrGroundTerm> sourceArguments = sourceDataNode.getProjectionAtom().getArguments(); ImmutableList<? extends VariableOrGroundTerm> targetArguments = targetDataNode.getProjectionAtom().getArguments(); return constraint.getComponents().stream() .allMatch(c -> sourceArguments.get(c.getAttribute().getIndex() - 1) .equals(targetArguments.get(c.getReference().getIndex() - 1))); }
@Override public ExtensionalDataNode transform(ExtensionalDataNode extensionalDataNode) { return iqFactory.createExtensionalDataNode(renameDataAtom(extensionalDataNode.getProjectionAtom())); }
private ImmutableCollection<Collection<ExtensionalDataNode>> groupDataNodesPerConstraint( FunctionalDependency constraint, ImmutableCollection<ExtensionalDataNode> initialNodes) { ImmutableList<Integer> constraintDeterminantIndexes = constraint.getDeterminants().stream() .map(Attribute::getIndex) .collect(ImmutableCollectors.toList()); ImmutableMultimap<ImmutableList<VariableOrGroundTerm>, ExtensionalDataNode> nodeMultiMap = initialNodes.stream() .collect(ImmutableCollectors.toMultimap( n -> extractDeterminantArguments(n.getProjectionAtom(), constraintDeterminantIndexes), n -> n)); return nodeMultiMap.asMap().values(); }
private ImmutableSet<Variable> extractRequiredAndCooccuringVariables(IntermediateQuery query, InnerJoinNode joinNode) { Stream<Variable> requiredVariablesByAncestorStream = Stream.concat( query.getVariablesRequiredByAncestors(joinNode).stream(), joinNode.getRequiredVariables(query).stream()); /* * NB: looks fro into multiple occurrences of a variable within the same data node */ Stream<Variable> innerCooccuringVariableStream = query.getChildren(joinNode).stream() .filter(c -> c instanceof ExtensionalDataNode) .map(c -> (ExtensionalDataNode) c) .flatMap(c -> // Multiset c.getProjectionAtom().getArguments().stream() .filter(t -> t instanceof Variable) .map(v -> (Variable) v) .collect(ImmutableCollectors.toMultiset()) .entrySet().stream() .filter(e -> e.getCount() > 1) .map(Multiset.Entry::getElement)); return Stream.concat(requiredVariablesByAncestorStream, innerCooccuringVariableStream) .collect(ImmutableCollectors.toSet()); }
ForeignKeyConstraint constraint) { ImmutableList<? extends VariableOrGroundTerm> targetArguments = targetDataNode.getProjectionAtom().getArguments();