Search in sources :

Example 1 with Info

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

the class RuleImplementJoinStrategy method execute.

/**
 * @see org.teiid.query.optimizer.relational.OptimizerRule#execute(org.teiid.query.optimizer.relational.plantree.PlanNode, org.teiid.query.metadata.QueryMetadataInterface, org.teiid.query.optimizer.capabilities.CapabilitiesFinder, org.teiid.query.optimizer.relational.RuleStack, org.teiid.query.analysis.AnalysisRecord, org.teiid.query.util.CommandContext)
 */
public PlanNode execute(PlanNode plan, QueryMetadataInterface metadata, CapabilitiesFinder capabilitiesFinder, RuleStack rules, AnalysisRecord analysisRecord, CommandContext context) throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
    for (PlanNode sourceNode : NodeEditor.findAllNodes(plan, NodeConstants.Types.SOURCE, NodeConstants.Types.ACCESS)) {
        SymbolMap references = (SymbolMap) sourceNode.getProperty(NodeConstants.Info.CORRELATED_REFERENCES);
        if (references != null) {
            Set<GroupSymbol> groups = GroupsUsedByElementsVisitor.getGroups(references.getValues());
            PlanNode joinNode = NodeEditor.findParent(sourceNode, NodeConstants.Types.JOIN, NodeConstants.Types.SOURCE);
            while (joinNode != null) {
                if (joinNode.getGroups().containsAll(groups)) {
                    joinNode.setProperty(NodeConstants.Info.JOIN_STRATEGY, JoinStrategyType.NESTED_TABLE);
                    Info info = Info.RIGHT_NESTED_REFERENCES;
                    if (!FrameUtil.findJoinSourceNode(joinNode.getFirstChild()).getGroups().containsAll(groups)) {
                        // $NON-NLS-1$
                        throw new AssertionError("Should not have reordered the join tree to reverse the lateral join");
                    }
                    SymbolMap map = (SymbolMap) joinNode.getProperty(info);
                    if (map == null) {
                        map = new SymbolMap();
                    }
                    joinNode.setProperty(info, map);
                    map.asUpdatableMap().putAll(references.asMap());
                    if (joinNode.getProperty(NodeConstants.Info.DEPENDENT_VALUE_SOURCE) != null) {
                        // $NON-NLS-1$
                        throw new AssertionError("Cannot use a depenedent join when the join involves a correlated nested table.");
                    }
                    break;
                }
                joinNode = NodeEditor.findParent(joinNode, NodeConstants.Types.JOIN, NodeConstants.Types.SOURCE);
            }
        }
    }
    for (PlanNode joinNode : NodeEditor.findAllNodes(plan, NodeConstants.Types.JOIN, NodeConstants.Types.ACCESS)) {
        JoinStrategyType stype = (JoinStrategyType) joinNode.getProperty(NodeConstants.Info.JOIN_STRATEGY);
        if (!JoinStrategyType.MERGE.equals(stype)) {
            continue;
        }
        List<Expression> leftExpressions = (List<Expression>) joinNode.getProperty(NodeConstants.Info.LEFT_EXPRESSIONS);
        List<Expression> rightExpressions = (List<Expression>) joinNode.getProperty(NodeConstants.Info.RIGHT_EXPRESSIONS);
        int origExpressionCount = leftExpressions.size();
        // check index information on each side
        // TODO: don't do null order compensation - in fact we should check what the order actually is, but we don't have that metadata
        Object key = null;
        boolean right = true;
        // we check the right first, since it should be larger
        if (joinNode.getLastChild().getType() == NodeConstants.Types.ACCESS && NewCalculateCostUtil.isSingleTable(joinNode.getLastChild())) {
            key = NewCalculateCostUtil.getKeyUsed(rightExpressions, null, metadata, null);
        }
        if (key == null && joinNode.getFirstChild().getType() == NodeConstants.Types.ACCESS && NewCalculateCostUtil.isSingleTable(joinNode.getFirstChild())) {
            key = NewCalculateCostUtil.getKeyUsed(leftExpressions, null, metadata, null);
            right = false;
        }
        JoinType joinType = (JoinType) joinNode.getProperty(NodeConstants.Info.JOIN_TYPE);
        /**
         * Don't push sorts for unbalanced inner joins, we prefer to use a processing time cost based decision
         */
        boolean pushLeft = true;
        boolean pushRight = true;
        if ((joinType == JoinType.JOIN_INNER || joinType == JoinType.JOIN_LEFT_OUTER) && context != null) {
            float leftCost = NewCalculateCostUtil.computeCostForTree(joinNode.getFirstChild(), metadata);
            float rightCost = NewCalculateCostUtil.computeCostForTree(joinNode.getLastChild(), metadata);
            if (leftCost != NewCalculateCostUtil.UNKNOWN_VALUE && rightCost != NewCalculateCostUtil.UNKNOWN_VALUE && (leftCost > context.getProcessorBatchSize() || rightCost > context.getProcessorBatchSize())) {
                // we use a larger constant here to ensure that we don't unwisely prevent pushdown
                pushLeft = leftCost < context.getProcessorBatchSize() || leftCost / rightCost < 8 || (key != null && !right);
                pushRight = rightCost < context.getProcessorBatchSize() || rightCost / leftCost < 8 || joinType == JoinType.JOIN_LEFT_OUTER || (key != null && right);
            }
        }
        if (key != null && joinNode.getProperty(NodeConstants.Info.DEPENDENT_VALUE_SOURCE) == null) {
            // redo the join predicates based upon the key alone
            List<Object> keyCols = metadata.getElementIDsInKey(key);
            int[] reorder = new int[keyCols.size()];
            LinkedHashSet<Integer> toCriteria = new LinkedHashSet<Integer>();
            List<Expression> keyExpressions = right ? rightExpressions : leftExpressions;
            Map<Object, Integer> indexMap = new LinkedHashMap<Object, Integer>();
            for (int i = 0; i < keyExpressions.size(); i++) {
                Expression ses = keyExpressions.get(i);
                if (!(ses instanceof ElementSymbol)) {
                    toCriteria.add(i);
                    continue;
                }
                Integer existing = indexMap.put(((ElementSymbol) ses).getMetadataID(), i);
                if (existing != null) {
                    toCriteria.add(existing);
                }
            }
            boolean found = true;
            for (int i = 0; i < keyCols.size(); i++) {
                Object id = keyCols.get(i);
                Integer index = indexMap.remove(id);
                if (index == null) {
                    found = false;
                    break;
                }
                reorder[i] = index;
            }
            if (found) {
                toCriteria.addAll(indexMap.values());
                List<Criteria> joinCriteria = (List<Criteria>) joinNode.getProperty(Info.NON_EQUI_JOIN_CRITERIA);
                for (int index : toCriteria) {
                    Expression lses = leftExpressions.get(index);
                    Expression rses = rightExpressions.get(index);
                    CompareCriteria cc = new CompareCriteria(lses, CompareCriteria.EQ, rses);
                    if (joinCriteria == null || joinCriteria.isEmpty()) {
                        joinCriteria = new ArrayList<Criteria>();
                    }
                    joinCriteria.add(cc);
                }
                joinNode.setProperty(Info.NON_EQUI_JOIN_CRITERIA, joinCriteria);
                leftExpressions = RelationalNode.projectTuple(reorder, leftExpressions);
                rightExpressions = RelationalNode.projectTuple(reorder, rightExpressions);
                joinNode.setProperty(NodeConstants.Info.LEFT_EXPRESSIONS, leftExpressions);
                joinNode.setProperty(NodeConstants.Info.RIGHT_EXPRESSIONS, rightExpressions);
            }
        }
        boolean pushedLeft = insertSort(joinNode.getFirstChild(), leftExpressions, joinNode, metadata, capabilitiesFinder, pushLeft, context);
        if (origExpressionCount == 1 && joinType == JoinType.JOIN_INNER && joinNode.getProperty(NodeConstants.Info.DEPENDENT_VALUE_SOURCE) != null && !joinNode.hasCollectionProperty(Info.NON_EQUI_JOIN_CRITERIA)) {
            Collection<Expression> output = (Collection<Expression>) joinNode.getProperty(NodeConstants.Info.OUTPUT_COLS);
            Collection<GroupSymbol> groups = GroupsUsedByElementsVisitor.getGroups(output);
            if (Collections.disjoint(groups, FrameUtil.findJoinSourceNode(joinNode.getFirstChild()).getGroups())) {
                pushRight = false;
                joinNode.setProperty(Info.IS_SEMI_DEP, Boolean.TRUE);
            }
        }
        boolean pushedRight = insertSort(joinNode.getLastChild(), rightExpressions, joinNode, metadata, capabilitiesFinder, pushRight, context);
        if ((!pushedRight || !pushedLeft) && (joinType == JoinType.JOIN_INNER || (joinType == JoinType.JOIN_LEFT_OUTER && !pushedLeft))) {
            joinNode.setProperty(NodeConstants.Info.JOIN_STRATEGY, JoinStrategyType.ENHANCED_SORT);
        }
    }
    return plan;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) Criteria(org.teiid.query.sql.lang.Criteria) CompareCriteria(org.teiid.query.sql.lang.CompareCriteria) LinkedHashMap(java.util.LinkedHashMap) PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) ArrayList(java.util.ArrayList) List(java.util.List) JoinStrategyType(org.teiid.query.processor.relational.JoinNode.JoinStrategyType) JoinType(org.teiid.query.sql.lang.JoinType) SymbolMap(org.teiid.query.sql.util.SymbolMap) Info(org.teiid.query.optimizer.relational.plantree.NodeConstants.Info) CompareCriteria(org.teiid.query.sql.lang.CompareCriteria) Expression(org.teiid.query.sql.symbol.Expression) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) Collection(java.util.Collection)

Aggregations

ArrayList (java.util.ArrayList)1 Collection (java.util.Collection)1 LinkedHashMap (java.util.LinkedHashMap)1 LinkedHashSet (java.util.LinkedHashSet)1 List (java.util.List)1 Info (org.teiid.query.optimizer.relational.plantree.NodeConstants.Info)1 PlanNode (org.teiid.query.optimizer.relational.plantree.PlanNode)1 JoinStrategyType (org.teiid.query.processor.relational.JoinNode.JoinStrategyType)1 CompareCriteria (org.teiid.query.sql.lang.CompareCriteria)1 Criteria (org.teiid.query.sql.lang.Criteria)1 JoinType (org.teiid.query.sql.lang.JoinType)1 ElementSymbol (org.teiid.query.sql.symbol.ElementSymbol)1 Expression (org.teiid.query.sql.symbol.Expression)1 GroupSymbol (org.teiid.query.sql.symbol.GroupSymbol)1 SymbolMap (org.teiid.query.sql.util.SymbolMap)1