@Override public boolean isVariableNullable(IntermediateQuery query, Variable variable) { if (!getVariables().contains(variable)) throw new IllegalArgumentException("The variable " + variable + " is not projected by " + this); DataAtom<RelationPredicate> atom = getProjectionAtom(); RelationDefinition relation = atom.getPredicate().getRelationDefinition(); ImmutableList<? extends VariableOrGroundTerm> arguments = atom.getArguments(); // NB: DB column indexes start at 1. return IntStream.range(1, arguments.size() + 1) .filter(i -> arguments.get(i - 1).equals(variable)) .mapToObj(relation::getAttribute) .allMatch(Attribute::canNull); }
/** * 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()); }
@Override public VariableNullability getVariableNullability() { if (variableNullability == null) { DataAtom<RelationPredicate> atom = getProjectionAtom(); RelationDefinition relation = atom.getPredicate().getRelationDefinition(); ImmutableList<? extends VariableOrGroundTerm> arguments = atom.getArguments(); ImmutableMultiset<? extends VariableOrGroundTerm> argMultiset = ImmutableMultiset.copyOf(arguments); // NB: DB column indexes start at 1. ImmutableSet<ImmutableSet<Variable>> nullableGroups = IntStream.range(0, arguments.size()) .filter(i -> arguments.get(i) instanceof Variable) .filter(i -> relation.getAttribute(i + 1).canNull()) .mapToObj(arguments::get) .map(a -> (Variable) a) // An implicit filter condition makes them non-nullable .filter(a -> argMultiset.count(a) < 2) .map(ImmutableSet::of) .collect(ImmutableCollectors.toSet()); variableNullability = new VariableNullabilityImpl(nullableGroups); } return variableNullability; }
@Override protected Optional<PredicateLevelProposal> proposePerPredicate(InnerJoinNode joinNode, ImmutableCollection<ExtensionalDataNode> initialNodes, RelationPredicate predicate, DBMetadata dbMetadata, ImmutableList<Variable> priorityVariables, IntermediateQuery query) throws AtomUnificationException { if (initialNodes.size() < 2) return Optional.empty(); RelationDefinition relation = predicate.getRelationDefinition(); /* * Does nothing */ if (relation == null) return Optional.empty(); ImmutableMap<FunctionalDependency, ImmutableCollection<Collection<ExtensionalDataNode>>> constraintNodeMap = relation.getOtherFunctionalDependencies().stream() .collect(ImmutableCollectors.toMap( c -> c, c -> groupDataNodesPerConstraint(c, initialNodes))); ImmutableSet<Variable> requiredAndCooccuringVariables = extractRequiredAndCooccuringVariables(query, joinNode); ImmutableSet<ExtensionalDataNode> nodesToRemove = selectNodesToRemove(requiredAndCooccuringVariables, constraintNodeMap, predicate); ImmutableList<ImmutableSubstitution<VariableOrGroundTerm>> dependentUnifiers = extractDependentUnifiers( relation, constraintNodeMap, nodesToRemove); return (dependentUnifiers.isEmpty() && nodesToRemove.isEmpty()) ? Optional.empty() : Optional.of(new PredicateLevelProposal(dependentUnifiers, nodesToRemove)); }
.map(ExtensionalDataNode::getProjectionAtom) .map(a -> Maps.immutableEntry( a.getPredicate().getRelationDefinition(), a.getArguments())) .collect(ImmutableCollectors.toMultimap( Map.Entry::getKey, RelationDefinition rightRelation = rightDataNode.getProjectionAtom().getPredicate().getRelationDefinition();