Search in sources :

Example 66 with PlanNode

use of org.teiid.query.optimizer.relational.plantree.PlanNode in project teiid by teiid.

the class RulePushNonJoinCriteria method pushCriteria.

/**
 * True if the criteria is pushed.
 *
 * It's possible to push to the inner side of the join if the new criteria node
 * originates there
 *
 * @param joinNode
 * @param tgtCrit
 * @param metadata
 * @return
 */
private boolean pushCriteria(PlanNode joinNode, Criteria tgtCrit, Iterator iter, QueryMetadataInterface metadata) {
    PlanNode newCritNode = RelationalPlanner.createSelectNode(tgtCrit, false);
    Set<GroupSymbol> groups = newCritNode.getGroups();
    PlanNode[] innerJoinNodes = JoinUtil.getInnerSideJoinNodes(joinNode);
    boolean pushed = false;
    for (int i = 0; i < innerJoinNodes.length; i++) {
        if (FrameUtil.findOriginatingNode(innerJoinNodes[i], groups) != null) {
            if (pushed) {
                // create a new copy since the old one has been used
                newCritNode = RelationalPlanner.createSelectNode(tgtCrit, false);
            }
            innerJoinNodes[i].addAsParent(newCritNode);
            pushed = true;
        }
    }
    if (pushed) {
        iter.remove();
    } else if (firstRun && tgtCrit instanceof CompareCriteria) {
        CompareCriteria crit = (CompareCriteria) tgtCrit;
        Expression leftExpr = crit.getLeftExpression();
        Expression rightExpr = crit.getRightExpression();
        for (int i = 0; i < innerJoinNodes.length; i++) {
            PlanNode node = FrameUtil.findJoinSourceNode(innerJoinNodes[i]);
            boolean outer = false;
            for (PlanNode child : NodeEditor.findAllNodes(node, NodeConstants.Types.JOIN)) {
                if (((JoinType) child.getProperty(Info.JOIN_TYPE)).isOuter()) {
                    outer = true;
                    break;
                }
            }
            if (!outer) {
                continue;
            }
            Set<GroupSymbol> leftExprGroups = GroupsUsedByElementsVisitor.getGroups(leftExpr);
            Set<GroupSymbol> rightExprGroups = GroupsUsedByElementsVisitor.getGroups(rightExpr);
            ArrayList<ElementSymbol> notNull = new ArrayList<ElementSymbol>(2);
            if (node.getGroups().containsAll(leftExprGroups)) {
                collectNotNull(leftExpr, notNull);
            } else if (node.getGroups().containsAll(rightExprGroups)) {
                collectNotNull(rightExpr, notNull);
            }
            if (!notNull.isEmpty()) {
                pushed = true;
                for (ElementSymbol es : notNull) {
                    IsNullCriteria inc = new IsNullCriteria(es);
                    inc.setNegated(true);
                    PlanNode notNullCrit = RelationalPlanner.createSelectNode(inc, false);
                    notNullCrit.setProperty(NodeConstants.Info.IS_TEMPORARY, true);
                    innerJoinNodes[i].addAsParent(notNullCrit);
                }
            }
        }
    }
    return pushed;
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) Set(java.util.Set) ArrayList(java.util.ArrayList) CompareCriteria(org.teiid.query.sql.lang.CompareCriteria) PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) Expression(org.teiid.query.sql.symbol.Expression) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) IsNullCriteria(org.teiid.query.sql.lang.IsNullCriteria)

Example 67 with PlanNode

use of org.teiid.query.optimizer.relational.plantree.PlanNode in project teiid by teiid.

the class RulePushSelectCriteria method pushAcrossGroupBy.

boolean pushAcrossGroupBy(PlanNode sourceNode, PlanNode critNode, QueryMetadataInterface metadata, boolean inPlan, CapabilitiesFinder capFinder) throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
    if (critNode.hasBooleanProperty(NodeConstants.Info.IS_HAVING)) {
        return false;
    }
    if (critNode.hasBooleanProperty(NodeConstants.Info.IS_DEPENDENT_SET)) {
        PlanNode accessNode = NodeEditor.findParent(critNode, NodeConstants.Types.ACCESS);
        if (accessNode != null) {
            List<Expression> cols = (List<Expression>) sourceNode.getProperty(Info.GROUP_COLS);
            if (cols != null) {
                boolean hasExpression = false;
                boolean hasLiteral = false;
                for (final Iterator<Expression> iterator = cols.iterator(); iterator.hasNext(); ) {
                    Expression ex = iterator.next();
                    hasExpression |= !(ex instanceof ElementSymbol);
                    hasLiteral |= EvaluatableVisitor.willBecomeConstant(ex, true);
                }
                if (hasLiteral || (hasExpression && !CapabilitiesUtil.supports(Capability.QUERY_FUNCTIONS_IN_GROUP_BY, RuleRaiseAccess.getModelIDFromAccess(accessNode, metadata), metadata, capFinder))) {
                    markDependent(critNode, accessNode, metadata, capFinder);
                    critNode.setProperty(Info.IS_HAVING, true);
                    return false;
                }
            }
        }
    }
    if (sourceNode.hasBooleanProperty(Info.ROLLUP)) {
        // but instead we'll just clone the node
        if (inPlan) {
            PlanNode copy = copyNode(critNode);
            critNode.setProperty(Info.IS_PUSHED, true);
            critNode.setProperty(Info.IS_HAVING, true);
            critNode.getFirstChild().addAsParent(copy);
            critNode = copy;
        }
    }
    boolean moved = false;
    SymbolMap symbolMap = (SymbolMap) sourceNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
    FrameUtil.convertNode(critNode, null, null, symbolMap.asMap(), metadata, true);
    if (inPlan) {
        NodeEditor.removeChildNode(critNode.getParent(), critNode);
        sourceNode.getFirstChild().addAsParent(critNode);
    }
    moved = true;
    if (critNode.hasBooleanProperty(NodeConstants.Info.IS_DEPENDENT_SET)) {
        PlanNode accessNode = NodeEditor.findParent(critNode, NodeConstants.Types.ACCESS);
        if (accessNode != null) {
            markDependent(critNode, accessNode, metadata, capFinder);
            // terminal position
            moved = false;
        }
    }
    return moved;
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) Expression(org.teiid.query.sql.symbol.Expression) SymbolMap(org.teiid.query.sql.util.SymbolMap)

Example 68 with PlanNode

use of org.teiid.query.optimizer.relational.plantree.PlanNode in project teiid by teiid.

the class RulePushSelectCriteria method findOriginatingNode.

private PlanNode findOriginatingNode(QueryMetadataInterface metadata, CapabilitiesFinder capFinder, PlanNode critNode, AnalysisRecord record) throws TeiidComponentException, QueryMetadataException {
    if (critNode.getGroups().isEmpty()) {
        // check to see if pushing may impact cardinality
        PlanNode groupNode = NodeEditor.findNodePreOrder(critNode, NodeConstants.Types.GROUP, NodeConstants.Types.SOURCE);
        if (groupNode != null && !groupNode.hasCollectionProperty(NodeConstants.Info.GROUP_COLS)) {
            return groupNode;
        }
        Object modelId = getSubqueryModelId(metadata, capFinder, critNode, record);
        if (modelId != null) {
            for (PlanNode node : NodeEditor.findAllNodes(critNode, NodeConstants.Types.SOURCE)) {
                GroupSymbol group = node.getGroups().iterator().next();
                Object srcModelID = metadata.getModelID(group.getMetadataID());
                if (CapabilitiesUtil.isSameConnector(srcModelID, modelId, metadata, capFinder)) {
                    return node;
                }
            }
        }
    }
    return FrameUtil.findOriginatingNode(critNode, critNode.getGroups());
}
Also used : PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) LanguageObject(org.teiid.query.sql.LanguageObject)

Example 69 with PlanNode

use of org.teiid.query.optimizer.relational.plantree.PlanNode in project teiid by teiid.

the class RulePushSelectCriteria method moveNodeAcrossFrame.

Boolean moveNodeAcrossFrame(PlanNode critNode, PlanNode sourceNode, final QueryMetadataInterface metadata) throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
    // Check that sourceNode has a child to push across
    if (sourceNode.getChildCount() == 0) {
        return false;
    }
    final PlanNode projectNode = NodeEditor.findNodePreOrder(sourceNode.getFirstChild(), NodeConstants.Types.PROJECT, NodeConstants.Types.SOURCE);
    if (FrameUtil.isProcedure(projectNode)) {
        return false;
    }
    final SymbolMap symbolMap = (SymbolMap) sourceNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
    final GroupSymbol sourceGroup = sourceNode.getGroups().iterator().next();
    if (!placeConvertedSelectNode(critNode, sourceGroup, projectNode, symbolMap, metadata)) {
        if (createdNodes == null) {
            Criteria crit = (Criteria) critNode.getProperty(NodeConstants.Info.SELECT_CRITERIA);
            if (isMultiAttributeDependentSet(crit) && splitSet(critNode, new DependentNodeTest() {

                @Override
                public boolean isValid(PlanNode copyNode) throws QueryMetadataException, QueryPlannerException, TeiidComponentException {
                    return createConvertedSelectNode(copyNode, sourceGroup, projectNode, symbolMap, metadata) != null;
                }
            }, (DependentSetCriteria) crit, sourceNode)) {
                return null;
            }
        }
        return false;
    }
    if (createdNodes == null) {
        satisfyConditions(critNode, sourceNode, metadata);
    }
    // Mark critNode as a "phantom"
    critNode.setProperty(NodeConstants.Info.IS_PHANTOM, Boolean.TRUE);
    return true;
}
Also used : DependentSetCriteria(org.teiid.query.sql.lang.DependentSetCriteria) PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) SymbolMap(org.teiid.query.sql.util.SymbolMap) CompoundCriteria(org.teiid.query.sql.lang.CompoundCriteria) DependentSetCriteria(org.teiid.query.sql.lang.DependentSetCriteria) Criteria(org.teiid.query.sql.lang.Criteria) CompareCriteria(org.teiid.query.sql.lang.CompareCriteria)

Example 70 with PlanNode

use of org.teiid.query.optimizer.relational.plantree.PlanNode in project teiid by teiid.

the class RulePushSelectCriteria method markDependent.

private void markDependent(PlanNode critNode, PlanNode accessNode, QueryMetadataInterface metadata, CapabilitiesFinder capFinder) throws QueryMetadataException, TeiidComponentException {
    // once a dependent crit node is pushed, don't bother pushing it further into the command
    // dependent access node will use this as an assumption for where dependent sets can appear in the command
    critNode.setProperty(NodeConstants.Info.IS_PUSHED, Boolean.TRUE);
    if (createdNodes != null) {
        // this is during a planning run and should not cause additional side-effects
        return;
    }
    accessNode.setProperty(NodeConstants.Info.IS_DEPENDENT_SET, Boolean.TRUE);
    Criteria crit = (Criteria) critNode.getProperty(NodeConstants.Info.SELECT_CRITERIA);
    if (isMultiAttributeDependentSet(crit)) {
        // split the criteria as needed
        List<DependentSetCriteria> crits = splitDependentSetCriteria((DependentSetCriteria) crit, CapabilitiesUtil.supports(Capability.ARRAY_TYPE, RuleRaiseAccess.getModelIDFromAccess(accessNode, metadata), metadata, capFinder), metadata);
        critNode.setProperty(NodeConstants.Info.SELECT_CRITERIA, new CompoundCriteria(crits));
    }
    Collection<ElementSymbol> elements = null;
    for (PlanNode joinNode : NodeEditor.findAllNodes(accessNode, NodeConstants.Types.JOIN, NodeConstants.Types.SOURCE)) {
        List<Criteria> joinCriteria = (List<Criteria>) joinNode.getProperty(Info.JOIN_CRITERIA);
        if (joinCriteria == null) {
            continue;
        }
        for (Criteria joinPredicate : joinCriteria) {
            if (!(joinPredicate instanceof CompareCriteria)) {
                continue;
            }
            CompareCriteria cc = (CompareCriteria) joinPredicate;
            if (!cc.isOptional()) {
                continue;
            }
            if (elements == null) {
                elements = ElementCollectorVisitor.getElements((LanguageObject) critNode.getProperty(Info.SELECT_CRITERIA), true);
            }
            if (!Collections.disjoint(elements, ElementCollectorVisitor.getElements(cc, false))) {
                cc.setOptional(false);
            }
        }
    }
}
Also used : DependentSetCriteria(org.teiid.query.sql.lang.DependentSetCriteria) ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) CompoundCriteria(org.teiid.query.sql.lang.CompoundCriteria) CompoundCriteria(org.teiid.query.sql.lang.CompoundCriteria) DependentSetCriteria(org.teiid.query.sql.lang.DependentSetCriteria) Criteria(org.teiid.query.sql.lang.Criteria) CompareCriteria(org.teiid.query.sql.lang.CompareCriteria) CompareCriteria(org.teiid.query.sql.lang.CompareCriteria) LanguageObject(org.teiid.query.sql.LanguageObject)

Aggregations

PlanNode (org.teiid.query.optimizer.relational.plantree.PlanNode)204 Expression (org.teiid.query.sql.symbol.Expression)50 GroupSymbol (org.teiid.query.sql.symbol.GroupSymbol)50 ArrayList (java.util.ArrayList)47 List (java.util.List)43 SymbolMap (org.teiid.query.sql.util.SymbolMap)42 ElementSymbol (org.teiid.query.sql.symbol.ElementSymbol)36 Criteria (org.teiid.query.sql.lang.Criteria)35 LinkedList (java.util.LinkedList)24 CompareCriteria (org.teiid.query.sql.lang.CompareCriteria)24 Test (org.junit.Test)22 HashSet (java.util.HashSet)17 JoinType (org.teiid.query.sql.lang.JoinType)17 LinkedHashSet (java.util.LinkedHashSet)16 CompoundCriteria (org.teiid.query.sql.lang.CompoundCriteria)12 DependentSetCriteria (org.teiid.query.sql.lang.DependentSetCriteria)12 QueryPlannerException (org.teiid.api.exception.query.QueryPlannerException)11 LanguageObject (org.teiid.query.sql.LanguageObject)11 OrderBy (org.teiid.query.sql.lang.OrderBy)10 IsNullCriteria (org.teiid.query.sql.lang.IsNullCriteria)9