private static Optional<QueryNode> getDepthFirstNextNode(IntermediateQuery query, QueryNode currentNode, boolean alreadyExploredSubTree) { /** * First choice: first child */ if (!alreadyExploredSubTree) { Optional<QueryNode> optionalFirstChild = query.getFirstChild(currentNode); if (optionalFirstChild.isPresent()) { return optionalFirstChild; } } /** * Second choice: next sibling of the current node or of an ancestor */ return skipSubTreeAndContinueDepthFirst(query, currentNode); }
static Optional<DataNodeAndSubstitution> extract(ConstructionNode rightChild, IntermediateQuery query) { QueryNode grandChild = query.getFirstChild(rightChild).get(); if (grandChild instanceof ExtensionalDataNode) return Optional.of(new DataNodeAndSubstitution((ExtensionalDataNode) grandChild, Optional.empty(), Optional.of(rightChild))); else if (grandChild instanceof FilterNode) { FilterNode filterNode = (FilterNode) grandChild; return query.getFirstChild(grandChild) .filter(n -> n instanceof ExtensionalDataNode) .map(n -> (ExtensionalDataNode)n) .map(n -> new DataNodeAndSubstitution(n, Optional.of(filterNode), Optional.of(rightChild))); } else return Optional.empty(); }
private static Optional<QueryNode> getDepthFirstNextNode(IntermediateQuery query, QueryNode currentNode, boolean alreadyExploredSubTree) { /** * First choice: first child */ if (!alreadyExploredSubTree) { Optional<QueryNode> optionalFirstChild = query.getFirstChild(currentNode); if (optionalFirstChild.isPresent()) { return optionalFirstChild; } } /** * Second choice: next sibling of the current node or of an ancestor */ return skipSubTreeAndContinueDepthFirst(query, currentNode); }
@Override public boolean isVariableNullable(IntermediateQuery query, Variable variable) { return query.getFirstChild(this) .map(c -> c.isVariableNullable(query, variable)) .orElseThrow(() -> new InvalidIntermediateQueryException("A query modifier node must have a child")); } }
private boolean isChildVariableNullable(IntermediateQuery query, Variable variable) { return query.getFirstChild(this) .map(c -> c.isVariableNullable(query, variable)) .orElseThrow(() -> new InvalidIntermediateQueryException( "A construction node with child variables must have a child")); }
private boolean isChildVariableNullable(IntermediateQuery query, Variable variable) { return query.getFirstChild(this) .map(c -> c.isVariableNullable(query, variable)) .orElseThrow(() -> new InvalidIntermediateQueryException( "A construction node with child variables must have a child")); }
/** * Recursive */ private Optional<CommutativeJoinOrFilterNode> getCandidateProvider(QueryNode subtreeRoot, IntermediateQuery query) { if (subtreeRoot instanceof ConstructionNode) { Optional<QueryNode> optChild = query.getFirstChild(subtreeRoot); return optChild.isPresent() ? getCandidateProvider(optChild.get(), query) : Optional.empty(); } if (subtreeRoot instanceof CommutativeJoinOrFilterNode) { CommutativeJoinOrFilterNode castNode = (CommutativeJoinOrFilterNode) subtreeRoot; if (castNode.getOptionalFilterCondition().isPresent()) { return Optional.of(castNode); } } return Optional.empty(); }
static Optional<DataNodeAndSubstitution> extract(ConstructionNode rightChild, IntermediateQuery query) { /* * Not supported */ if (rightChild.getOptionalModifiers().isPresent()) return Optional.empty(); QueryNode grandChild = query.getFirstChild(rightChild).get(); if (grandChild instanceof DataNode) return Optional.of(new DataNodeAndSubstitution((DataNode) grandChild, Optional.empty(), Optional.of(rightChild))); else if (grandChild instanceof FilterNode) { FilterNode filterNode = (FilterNode) grandChild; return query.getFirstChild(grandChild) .filter(n -> n instanceof DataNode) .map(n -> (DataNode)n) .map(n -> new DataNodeAndSubstitution(n, Optional.of(filterNode), Optional.of(rightChild))); } else return Optional.empty(); }
/** * Recursive */ private Optional<CommutativeJoinOrFilterNode> getCandidateProvider(QueryNode subtreeRoot, IntermediateQuery query) { if (subtreeRoot instanceof ConstructionNode) { Optional<QueryNode> optChild = query.getFirstChild(subtreeRoot); return optChild.isPresent() ? getCandidateProvider(optChild.get(), query) : Optional.empty(); } if (subtreeRoot instanceof CommutativeJoinOrFilterNode) { CommutativeJoinOrFilterNode castNode = (CommutativeJoinOrFilterNode) subtreeRoot; if (castNode.getOptionalFilterCondition().isPresent()) { return Optional.of(castNode); } } return Optional.empty(); }
@Override public boolean isVariableNullable(IntermediateQuery query, Variable variable) { if (isFilteringNullValue(variable)) return false; return query.getFirstChild(this) .map(c -> c.isVariableNullable(query, variable)) .orElseThrow(() -> new InvalidIntermediateQueryException("A filter node must have a child")); }
@Override public boolean isVariableNullable(IntermediateQuery query, Variable variable) { if (isFilteringNullValue(variable)) return false; return query.getFirstChild(this) .map(c -> c.isVariableNullable(query, variable)) .orElseThrow(() -> new InvalidIntermediateQueryException("A filter node must have a child")); }
@Override protected Optional<ConstructionNodeCleaningProposal> evaluateNode(QueryNode node, IntermediateQuery query) { if (node instanceof ConstructionNode) { ConstructionNode castNode = (ConstructionNode) node; Optional<ImmutableQueryModifiers> optModifiers = castNode.getOptionalModifiers(); ImmutableQueryModifiers modifiers = optModifiers.isPresent() ? optModifiers.get() : new ImmutableQueryModifiersImpl( false, -1, -1, ImmutableList.of() ); return makeProposal( query, castNode, modifiers, castNode, query.getFirstChild(castNode) ); } return Optional.empty(); }
/** * * Looks at the projected variables by all the child sub-trees and does the appropriate renamings. * */ private NextNodeAndQuery optimizeJoinLikeNodeChildren(IntermediateQuery query, JoinLikeNode initialJoinLikeNode) throws EmptyQueryException { // Non-final Optional<QueryNode> optionalCurrentChild = query.getFirstChild(initialJoinLikeNode); JoinLikeNode currentJoinLikeNode = initialJoinLikeNode; while (optionalCurrentChild.isPresent()) { ParentNextChild parentNextChild = optimizeFollowingChildren(query, optionalCurrentChild.get(), currentJoinLikeNode); optionalCurrentChild = parentNextChild.nextChild; currentJoinLikeNode = parentNextChild.parent; } return new NextNodeAndQuery(getDepthFirstNextNode(query, currentJoinLikeNode), query); }
@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; }
/** * TODO: explain */ @Override public NodeCentricOptimizationResults<JoinOrFilterNode> apply(PushDownBooleanExpressionProposal proposal, IntermediateQuery query, QueryTreeComponent treeComponent) throws InvalidQueryOptimizationProposalException { JoinOrFilterNode focusNode = proposal.getFocusNode(); for (Map.Entry<CommutativeJoinOrFilterNode, Collection<ImmutableExpression>> targetEntry : proposal.getNewDirectRecipientNodes().asMap().entrySet()) { updateNewDirectRecipientNode(treeComponent, targetEntry.getKey(), targetEntry.getValue()); } for (Map.Entry<QueryNode, Collection<ImmutableExpression>> targetEntry : proposal.getIndirectRecipientNodes().asMap().entrySet()) { updateIndirectRecipientNode(treeComponent, targetEntry.getKey(), targetEntry.getValue()); } QueryNode firstChild = query.getFirstChild(focusNode) .orElseThrow(() -> new InvalidQueryOptimizationProposalException("The focus node has no child")); return updateFocusNode(treeComponent, focusNode, proposal.getExpressionsToKeep()) .map(n -> new NodeCentricOptimizationResultsImpl<>(query, n)) .orElseGet(() -> new NodeCentricOptimizationResultsImpl<>(query, Optional.of(firstChild))); }
/** * TODO: explain */ @Override public NodeCentricOptimizationResults<JoinOrFilterNode> apply(PushDownBooleanExpressionProposal proposal, IntermediateQuery query, QueryTreeComponent treeComponent) throws InvalidQueryOptimizationProposalException { JoinOrFilterNode focusNode = proposal.getFocusNode(); for (Map.Entry<CommutativeJoinOrFilterNode, Collection<ImmutableExpression>> targetEntry : proposal.getNewDirectRecipientNodes().asMap().entrySet()) { updateNewDirectRecipientNode(treeComponent, targetEntry.getKey(), targetEntry.getValue()); } for (Map.Entry<QueryNode, Collection<ImmutableExpression>> targetEntry : proposal.getIndirectRecipientNodes().asMap().entrySet()) { updateIndirectRecipientNode(treeComponent, targetEntry.getKey(), targetEntry.getValue()); } QueryNode firstChild = query.getFirstChild(focusNode) .orElseThrow(() -> new InvalidQueryOptimizationProposalException("The focus node has no child")); return updateFocusNode(treeComponent, focusNode, proposal.getExpressionsToKeep()) .map(n -> new NodeCentricOptimizationResultsImpl<>(query, n)) .orElseGet(() -> new NodeCentricOptimizationResultsImpl<>(query, Optional.of(firstChild))); }
/** * Tries to optimize all the JoinOrFilterNodes, ONE BY ONE. * Navigates in a top-down fashion. */ private IntermediateQuery pushDownExpressions(final IntermediateQuery initialQuery) { // Non-final Optional<QueryNode> optionalCurrentNode = initialQuery.getFirstChild(initialQuery.getRootNode()); // Non-final IntermediateQuery currentQuery = initialQuery; while (optionalCurrentNode.isPresent()) { final QueryNode currentNode = optionalCurrentNode.get(); /** * InnerJoinNode, LeftJoinNode, FilterNode or some extensions */ if (currentNode instanceof JoinOrFilterNode) { NextNodeAndQuery nextNodeAndQuery = optimizeJoinOrFilter(currentQuery, (JoinOrFilterNode) currentNode); optionalCurrentNode = nextNodeAndQuery.getOptionalNextNode(); currentQuery = nextNodeAndQuery.getNextQuery(); } else { optionalCurrentNode = getDepthFirstNextNode(currentQuery, currentNode); } } return currentQuery; }
/** * Tries to optimize all the JoinOrFilterNodes, ONE BY ONE. * Navigates in a top-down fashion. */ private IntermediateQuery pushDownExpressions(final IntermediateQuery initialQuery) { // Non-final Optional<QueryNode> optionalCurrentNode = initialQuery.getFirstChild(initialQuery.getRootNode()); // Non-final IntermediateQuery currentQuery = initialQuery; while (optionalCurrentNode.isPresent()) { final QueryNode currentNode = optionalCurrentNode.get(); /* * InnerJoinNode, LeftJoinNode, FilterNode or some extensions */ if (currentNode instanceof JoinOrFilterNode) { NextNodeAndQuery nextNodeAndQuery = optimizeJoinOrFilter(currentQuery, (JoinOrFilterNode) currentNode); optionalCurrentNode = nextNodeAndQuery.getOptionalNextNode(); currentQuery = nextNodeAndQuery.getNextQuery(); } else { optionalCurrentNode = getDepthFirstNextNode(currentQuery, currentNode); } } return currentQuery; }
throw new IllegalStateException("Redundant join elimination should not eliminate all the children"); case 1: QueryNode replacingChild = query.getFirstChild(joinNode).get();
/** * Recursive */ @Override public IQTree convertTree(IntermediateQuery query, QueryNode rootNode) { if (rootNode instanceof LeafIQTree) { return (LeafIQTree) rootNode; } else if (rootNode instanceof UnaryOperatorNode) { // Recursive IQTree childTree = convertTree(query, query.getFirstChild(rootNode).get()); return iqFactory.createUnaryIQTree((UnaryOperatorNode) rootNode, childTree); } else if (rootNode instanceof BinaryNonCommutativeOperatorNode) { IQTree leftChildTree = convertTree(query, query.getChild(rootNode, LEFT).get()); IQTree rightChildTree = convertTree(query, query.getChild(rootNode, RIGHT).get()); return iqFactory.createBinaryNonCommutativeIQTree((BinaryNonCommutativeOperatorNode) rootNode, leftChildTree, rightChildTree); } else if (rootNode instanceof NaryOperatorNode) { ImmutableList<IQTree> childTrees = query.getChildren(rootNode).stream() .map(c -> convertTree(query, c)) .collect(ImmutableCollectors.toList()); return iqFactory.createNaryIQTree((NaryOperatorNode) rootNode, childTrees); } throw new MinorOntopInternalBugException("Unexpected type of query node: " + rootNode); }