private Stream<IQTree> splitRootUnion(IQTree tree) { return (tree.getRootNode() instanceof UnionNode) ? tree.getChildren().stream() : Stream.of(tree); }
@Override // merge consecutive unions public IQTree transformUnion(IQTree tree, UnionNode rootNode, ImmutableList<IQTree> children) { ImmutableList<IQTree> transformedChildren = children.stream() .map(t -> t.acceptTransformer(this)) .collect(ImmutableCollectors.toList()); ImmutableList<IQTree> unionGrandChildren = transformedChildren.stream() .filter(t -> t.getRootNode() instanceof UnionNode) .flatMap(t -> t.getChildren().stream()) .collect(ImmutableCollectors.toList()); return iqFactory.createNaryIQTree( rootNode, Stream.concat( transformedChildren.stream() .filter(t -> !(t.getRootNode() instanceof UnionNode)), unionGrandChildren.stream() ).collect(ImmutableCollectors.toList()) ); } }
private IQTree optimize(IQTree tree) { QueryMergingTransformer transformer = createTransformer(tree.getKnownVariables()); return tree.acceptTransformer(transformer); }
/** * TODO: explain */ @Override public IQTree liftBinding(ImmutableList<IQTree> initialChildren, VariableGenerator variableGenerator, IQProperties currentIQProperties) { IQTree newParentTree = propagateDownCondition(Optional.empty(), initialChildren); /* * If after propagating down the condition the root is still a join node, goes to the next step */ if (newParentTree.getRootNode() instanceof InnerJoinNodeImpl) { return ((InnerJoinNodeImpl)newParentTree.getRootNode()).liftBindingAfterPropagatingCondition( newParentTree.getChildren(), variableGenerator, currentIQProperties); } else /* * Otherwise, goes back to the general method */ return newParentTree.liftBinding(variableGenerator); }
private IQTree liftBindingAfterPropagatingCondition(IQTree childIQTree, VariableGenerator variableGenerator, IQProperties currentIQProperties) { IQTree liftedChildIQTree = childIQTree.liftBinding(variableGenerator); QueryNode childRoot = liftedChildIQTree.getRootNode(); if (childRoot instanceof ConstructionNode) return liftBinding((ConstructionNode) childRoot, (UnaryIQTree) liftedChildIQTree, currentIQProperties, variableGenerator); else if (liftedChildIQTree.isDeclaredAsEmpty()) { return liftedChildIQTree; } else return iqFactory.createUnaryIQTree(this, liftedChildIQTree, currentIQProperties.declareLifted()); }
@Override public IQTree liftBinding(IQTree childIQTree, VariableGenerator variableGenerator, IQProperties currentIQProperties) { IQTree newParentTree = propagateDownCondition(childIQTree, Optional.empty()); /* * If after propagating down the condition the root is still a filter node, goes to the next step */ if (newParentTree.getRootNode() instanceof FilterNodeImpl) { return ((FilterNodeImpl)newParentTree.getRootNode()) .liftBindingAfterPropagatingCondition(((UnaryIQTree)newParentTree).getChild(), variableGenerator, currentIQProperties); } else /* * Otherwise, goes back to the general method */ return newParentTree.liftBinding(variableGenerator); }
@Override public IQTree liftIncompatibleDefinitions(Variable variable, IQTree leftChild, IQTree rightChild) { if (leftChild.getVariables().contains(variable)) { IQTree liftedLeftChild = leftChild.liftIncompatibleDefinitions(variable); QueryNode leftChildRoot = liftedLeftChild.getRootNode(); if (leftChildRoot instanceof UnionNode && ((UnionNode) leftChildRoot).hasAChildWithLiftableDefinition(variable, leftChild.getChildren())) { UnionNode newUnionNode = iqFactory.createUnionNode( Stream.of(leftChild, rightChild) .flatMap(c -> c.getVariables().stream()) .collect(ImmutableCollectors.toSet())); return iqFactory.createNaryIQTree(newUnionNode, liftedLeftChild.getChildren().stream() .map(unionChild -> (IQTree) iqFactory.createBinaryNonCommutativeIQTree(this, unionChild, rightChild)) .collect(ImmutableCollectors.toList())); } } // By default, nothing lifted return iqFactory.createBinaryNonCommutativeIQTree(this, leftChild, rightChild); }
@Override public IntermediateQuery convert(IQ query, DBMetadata dbMetadata, ExecutorRegistry executorRegistry) throws EmptyQueryException { if (query.getTree().isDeclaredAsEmpty()) throw new EmptyQueryException(); IntermediateQueryBuilder queryBuilder = iqFactory.createIQBuilder(dbMetadata, executorRegistry); IQTree topTree = query.getTree(); QueryNode rootNode = topTree.getRootNode(); queryBuilder.init(query.getProjectionAtom(), rootNode); insertChildren(rootNode, topTree.getChildren(), queryBuilder); return queryBuilder.build(); }
@Override public IQTree liftIncompatibleDefinitions(Variable variable, ImmutableList<IQTree> children) { return IntStream.range(0, children.size()).boxed() .map(i -> Maps.immutableEntry(i, children.get(i))) .filter(e -> e.getValue().isConstructed(variable)) // index -> new child .map(e -> Maps.immutableEntry(e.getKey(), e.getValue().liftIncompatibleDefinitions(variable))) .filter(e -> { QueryNode newRootNode = e.getValue().getRootNode(); return (newRootNode instanceof UnionNode) && ((UnionNode) newRootNode).hasAChildWithLiftableDefinition(variable, e.getValue().getChildren()); }) .findFirst() .map(e -> liftUnionChild(e.getKey(), (NaryIQTree) e.getValue(), children)) .orElseGet(() -> iqFactory.createNaryIQTree(this, children)); }
@Override public IQTree liftIncompatibleDefinitions(Variable variable, IQTree child) { IQTree newChild = child.liftIncompatibleDefinitions(variable); QueryNode newChildRoot = newChild.getRootNode(); /* * Lift the union above the filter */ if ((newChildRoot instanceof UnionNode) && ((UnionNode) newChildRoot).hasAChildWithLiftableDefinition(variable, newChild.getChildren())) { UnionNode unionNode = (UnionNode) newChildRoot; ImmutableList<IQTree> grandChildren = newChild.getChildren(); ImmutableList<IQTree> newChildren = grandChildren.stream() .map(c -> (IQTree) iqFactory.createUnaryIQTree(this, c)) .collect(ImmutableCollectors.toList()); return iqFactory.createNaryIQTree(unionNode, newChildren); } return iqFactory.createUnaryIQTree(this, newChild); }
@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))); }
private ImmutableList<ImmutableExpression> getChildExpressions(ImmutableList<IQTree> children) { return children.stream() .filter(t -> t.getRootNode() instanceof FilterNode) .map(t -> ((FilterNode) t.getRootNode()).getFilterCondition()) .collect(ImmutableCollectors.toList()); }
private ChildLiftingState liftLeftChild(IQTree liftedLeftChild, IQTree rightChild, Optional<ImmutableExpression> ljCondition, VariableGenerator variableGenerator) { if (liftedLeftChild.getRootNode() instanceof ConstructionNode) { ConstructionNode leftConstructionNode = (ConstructionNode) liftedLeftChild.getRootNode(); IQTree leftGrandChild = ((UnaryIQTree) liftedLeftChild).getChild(); try { return liftRegularChildBinding(leftConstructionNode, 0, leftGrandChild, ImmutableList.of(liftedLeftChild,rightChild), leftGrandChild.getVariables(), ljCondition, variableGenerator, this::convertIntoChildLiftingResults); } /* * Replaces the LJ by the left child */ catch (UnsatisfiableConditionException e) { EmptyNode newRightChild = iqFactory.createEmptyNode(rightChild.getVariables()); return new ChildLiftingState(leftGrandChild, newRightChild, Optional.empty(), leftConstructionNode.getSubstitution()); } } else if (liftedLeftChild.isDeclaredAsEmpty()) return new ChildLiftingState(liftedLeftChild, iqFactory.createEmptyNode(rightChild.getVariables()), Optional.empty(), substitutionFactory.getSubstitution()); else return new ChildLiftingState(liftedLeftChild, rightChild, ljCondition, substitutionFactory.getSubstitution()); }
@Override public VariableNullability getVariableNullability(ImmutableList<IQTree> children) { ImmutableMap<Variable, Collection<IQTree>> variableProvenanceMap = children.stream() .flatMap(c -> c.getVariables().stream() .map(v -> Maps.immutableEntry(v, c))) .collect(ImmutableCollectors.toMultimap()) .asMap(); ImmutableSet<Variable> coOccuringVariables = variableProvenanceMap.entrySet().stream() .filter(e -> e.getValue().size() > 1) .map(Map.Entry::getKey) .collect(ImmutableCollectors.toSet()); ImmutableSet<ImmutableSet<Variable>> nullableGroups = children.stream() .flatMap(c -> c.getVariableNullability().getNullableGroups().stream()) .filter(g -> g.stream() .noneMatch(coOccuringVariables::contains)) .collect(ImmutableCollectors.toSet()); return getOptionalFilterCondition() .map(e -> updateWithFilter(e, nullableGroups)) .orElseGet(() -> new VariableNullabilityImpl(nullableGroups)); }
@Override public IQTree liftBinding(IQTree initialLeftChild, IQTree initialRightChild, VariableGenerator variableGenerator, IQProperties currentIQProperties) { ImmutableSet<Variable> projectedVariables = Stream.of(initialLeftChild, initialRightChild) .flatMap(c -> c.getVariables().stream()) .collect(ImmutableCollectors.toSet()); IQTree liftedLeftChild = initialLeftChild.liftBinding(variableGenerator); if (liftedLeftChild.isDeclaredAsEmpty()) return iqFactory.createEmptyNode(projectedVariables); // Non-final ChildLiftingState liftingState = liftLeftChild(liftedLeftChild, initialRightChild, getOptionalFilterCondition(), variableGenerator); boolean hasConverged = false; int i = 0; while ((!hasConverged) && (i++ < MAX_ITERATIONS)) { ChildLiftingState newLiftingState = liftRightChild( optimizeLeftJoinCondition(liftingState, variableGenerator), variableGenerator); hasConverged = liftingState.equals(newLiftingState); liftingState = newLiftingState; } if (i >= MAX_ITERATIONS) throw new MinorOntopInternalBugException("LJ.liftBinding() did not converge after " + i); return convertResults2IQTree(projectedVariables, liftingState, currentIQProperties); }
/** * Does NOT look for intensional data nodes inside the definitions * */ private IQTree replaceIntensionalData(IntensionalDataNode dataNode, IQ definition) { InjectiveVar2VarSubstitution renamingSubstitution = substitutionFactory.generateNotConflictingRenaming( variableGenerator, definition.getTree().getKnownVariables()); IQ renamedIQ; if(renamingSubstitution.isEmpty()){ renamedIQ = definition; } else { QueryRenamer queryRenamer = transformerFactory.createRenamer(renamingSubstitution); renamedIQ = queryRenamer.transform(definition); } ImmutableSubstitution<VariableOrGroundTerm> descendingSubstitution = extractSubstitution( renamingSubstitution.applyToDistinctVariableOnlyDataAtom(renamedIQ.getProjectionAtom()), dataNode.getProjectionAtom()); return renamedIQ.getTree() .applyDescendingSubstitution(descendingSubstitution, Optional.empty()) .liftBinding(variableGenerator); }
private IQTree propagate(IQTree subTree, ImmutableSubstitution<? extends ImmutableTerm> substitution) throws InvalidQueryOptimizationProposalException { IQTree newSubTree = subTree.applyDescendingSubstitution(substitution.getVariableOrGroundTermFragment(), Optional.empty()); if (substitution.getNonGroundFunctionalTermFragment().getDomain().stream() .anyMatch(v -> newSubTree.getVariables().contains(v))) throw new InvalidQueryOptimizationProposalException("Non ground functional terms are not supported for propagation down " + "(only for up)"); ConstructionNode constructionNode = iqFactory.createConstructionNode( Sets.union(newSubTree.getVariables(), substitution.getDomain()).immutableCopy(), (ImmutableSubstitution<ImmutableTerm>) substitution); return iqFactory.createUnaryIQTree(constructionNode, newSubTree); } }
default IQTree transform(IQTree tree) { return tree.acceptTransformer(this); } }
ImmutableList.Builder<IQTree> builderChildren = ImmutableList.builder(); for (IQTree child : children) { if (child.getRootNode() instanceof IntensionalDataNode) { builderBGP.add((IntensionalDataNode)child); if (!currentBGP.isEmpty()) builderChildren.addAll(transformBGP(currentBGP)); builderChildren.add(child.acceptTransformer(this));
.applyDescendingSubstitution(descendingSubstitution, constraint); IQTree updatedLeftChild = leftChild.applyDescendingSubstitution(descendingSubstitution, constraint); try { ExpressionAndSubstitution expressionAndCondition = applyDescendingSubstitutionToExpression( initialExpression.get(), descendingSubstitution, leftChild.getVariables(), rightChild.getVariables()); .composeWith2(descendingSubstitution); IQTree updatedRightChild = rightChild.applyDescendingSubstitution(rightDescendingSubstitution, newConstraint); return updatedRightChild.isDeclaredAsEmpty() ? updatedLeftChild : iqFactory.createBinaryNonCommutativeIQTree( IQTree updatedRightChild = rightChild.applyDescendingSubstitution(descendingSubstitution, constraint); if (updatedRightChild.isDeclaredAsEmpty()) { ImmutableSet<Variable> leftVariables = updatedLeftChild.getVariables(); ImmutableSet<Variable> projectedVariables = Sets.union(leftVariables, updatedRightChild.getVariables()).immutableCopy();