Package org.teiid.query.optimizer.relational.plantree

Examples of org.teiid.query.optimizer.relational.plantree.PlanNode


     */
    static PlanNode raiseAccessNode(PlanNode rootNode, PlanNode accessNode, QueryMetadataInterface metadata,
        CapabilitiesFinder capFinder, boolean afterJoinPlanning, AnalysisRecord record)
    throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
       
        PlanNode parentNode = accessNode.getParent();
        if(parentNode == null) {
            // Nothing to raise over
            return null;
        }
        Object modelID = getModelIDFromAccess(accessNode, metadata);
        if(modelID == null) {
            return null;
        }
       
        switch(parentNode.getType()) {
            case NodeConstants.Types.JOIN:
            {
                modelID = canRaiseOverJoin(modelID, parentNode, metadata, capFinder, afterJoinPlanning, record);
                if(modelID != null) {
                    raiseAccessOverJoin(parentNode, modelID, true);                   
                    return rootNode;
                }
                return null;
            }           
            case NodeConstants.Types.PROJECT:
            {        
                // Check that the PROJECT contains only functions that can be pushed                              
                List projectCols = (List) parentNode.getProperty(NodeConstants.Info.PROJECT_COLS);
               
                for (int i = 0; i < projectCols.size(); i++) {
                    SingleElementSymbol symbol = (SingleElementSymbol)projectCols.get(i);
                    if(! canPushSymbol(symbol, true, modelID, metadata, capFinder, record)) {
                        return null;
                    }
                }
               
                /*
                 * TODO: this creates an extraneous project node in many circumstances.
                 * However we don't actually support project in this case, so allowing it to be pushed
                 * causes problems with stored procedures and the assumptions made for proc/relational
                 * planning.
                 */
                if (FrameUtil.isProcedure(parentNode)) {
                  return null;
                }
                               
                return performRaise(rootNode, accessNode, parentNode);               
            }
            case NodeConstants.Types.DUP_REMOVE:
            {    
                // If model supports the support constant parameter, then move access node
                if(!CapabilitiesUtil.supportsSelectDistinct(modelID, metadata, capFinder)) {
                  recordDebug("cannot push dupremove, since distinct is not supported by source", parentNode, record); //$NON-NLS-1$
                  return null;
                }
               
                //TODO: this check is too specific the columns could be used in expressions that are comparable
                if (!CapabilitiesUtil.checkElementsAreSearchable((List)NodeEditor.findNodePreOrder(parentNode, NodeConstants.Types.PROJECT).getProperty(NodeConstants.Info.PROJECT_COLS), metadata, SupportConstants.Element.SEARCHABLE_COMPARE)) {
                  recordDebug("cannot push dupremove, since not all columns are comparable at the source", parentNode, record); //$NON-NLS-1$
                  return null;
                }
               
                return performRaise(rootNode, accessNode, parentNode);
            }
            case NodeConstants.Types.SORT:
            {        
                if (canRaiseOverSort(accessNode, metadata, capFinder, parentNode, record, false)) {
                    return performRaise(rootNode, accessNode, parentNode);
                }
                return null;
            }           
            case NodeConstants.Types.GROUP:           
            {               
                Set<AggregateSymbol> aggregates = RulePushAggregates.collectAggregates(parentNode);
                if (canRaiseOverGroupBy(parentNode, accessNode, aggregates, metadata, capFinder, record)) {
                    return performRaise(rootNode, accessNode, parentNode);
                }
                return null;
            }
            case NodeConstants.Types.SET_OP:
              if (!canRaiseOverSetQuery(parentNode, metadata, capFinder)) {
                return null;
              }

              for (PlanNode node : new ArrayList<PlanNode>(parentNode.getChildren())) {
                if (node == accessNode) {
                  continue;
                }
              NodeEditor.removeChildNode(parentNode, node);
              }
              accessNode.getGroups().clear();
                return performRaise(rootNode, accessNode, parentNode);
            case NodeConstants.Types.SELECT:           
            {
              if (parentNode.hasBooleanProperty(NodeConstants.Info.IS_DEPENDENT_SET)) {
                return null;
              }
              if (canRaiseOverSelect(accessNode, metadata, capFinder, parentNode, record)) {
                    RulePushSelectCriteria.satisfyAccessPatterns(parentNode, accessNode);
                    return performRaise(rootNode, accessNode, parentNode);                     
              }
              //determine if we should push the select back up
              if (parentNode.getParent() == null) {
                return null;
              }
            PlanNode selectRoot = parentNode;
            while (selectRoot.getParent() != null && selectRoot.getParent().getType() == NodeConstants.Types.SELECT) {
              selectRoot = selectRoot.getParent();
            }
            if (selectRoot.getParent() == null || (selectRoot.getParent().getType() & (NodeConstants.Types.PROJECT|NodeConstants.Types.GROUP)) == selectRoot.getParent().getType()) {
              return null;
            }
          PlanNode grandParent = selectRoot.getParent();
          boolean isLeft = false;
        isLeft = grandParent.getFirstChild() == selectRoot;
        if (grandParent.getType() == NodeConstants.Types.JOIN) {
          JoinType jt = (JoinType)grandParent.getProperty(NodeConstants.Info.JOIN_TYPE);
          if (jt == JoinType.JOIN_FULL_OUTER || (jt == JoinType.JOIN_LEFT_OUTER && !isLeft)) {
            return null;
          }
        }
        grandParent.removeChild(selectRoot);
        if (isLeft) {
          grandParent.addFirstChild(accessNode);
        } else {
          grandParent.addLastChild(accessNode);
        }
          PlanNode newParent = grandParent.getParent();
        //TODO: use costing or heuristics instead of always raising
          PlanNode newRoot = raiseAccessNode(rootNode, accessNode, metadata, capFinder, afterJoinPlanning, record);
          if (newRoot == null) {
          //return the tree to its original state
            parentNode.addFirstChild(accessNode);
            if (isLeft) {
              grandParent.addFirstChild(selectRoot);
            } else {
              grandParent.addLastChild(selectRoot);
            }
          } else {
            //attach the select nodes above the access node
            accessNode = grandParent.getParent();
          if (newParent != null) {
              isLeft = newParent.getFirstChild() == accessNode;
              if (isLeft) {
                newParent.addFirstChild(selectRoot);
              } else {
                newParent.addLastChild(selectRoot);
              }
            } else {
              newRoot = selectRoot;
            }
          parentNode.addFirstChild(accessNode);
            return newRoot;
          }
                return null;
            }  
            case NodeConstants.Types.SOURCE:
            {
                //if a source has access patterns that are unsatisfied, then the raise cannot occur
                if (parentNode.hasCollectionProperty(NodeConstants.Info.ACCESS_PATTERNS)) {
                    return null;
                }
               
                SymbolMap references = (SymbolMap)parentNode.getProperty(NodeConstants.Info.CORRELATED_REFERENCES);
                if (references != null) {
                  return null;
                }
               
                //raise only if there is no intervening project into
                PlanNode parentProject = NodeEditor.findParent(parentNode, NodeConstants.Types.PROJECT);
                GroupSymbol intoGroup = (GroupSymbol)parentProject.getProperty(NodeConstants.Info.INTO_GROUP);
                if (intoGroup != null && parentProject.getParent() == null) {
                  if (CapabilitiesUtil.supports(Capability.INSERT_WITH_QUERYEXPRESSION, modelID, metadata, capFinder) && CapabilitiesUtil.isSameConnector(modelID, metadata.getModelID(intoGroup.getMetadataID()), metadata, capFinder)) {
                      rootNode = performRaise(rootNode, accessNode, parentNode);
                      return performRaise(rootNode, accessNode, parentProject);
                  }
                  return null;
View Full Code Here


          recordDebug("cannot push having, since having is not supported by source", parentNode, record); //$NON-NLS-1$
          return false;
        }
       
        //don't push criteria into an invalid location above an ordered limit - shouldn't happen
        PlanNode limitNode = NodeEditor.findNodePreOrder(accessNode, NodeConstants.Types.TUPLE_LIMIT, NodeConstants.Types.SOURCE);
        if (limitNode != null && FrameUtil.isOrderedLimit(limitNode)) {
          return false;
        }
       
        Criteria crit = (Criteria) parentNode.getProperty(NodeConstants.Info.SELECT_CRITERIA);
View Full Code Here

   
    static PlanNode performRaise(PlanNode rootNode, PlanNode accessNode, PlanNode parentNode) {
      accessNode.removeProperty(NodeConstants.Info.EST_CARDINALITY);
        NodeEditor.removeChildNode(parentNode, accessNode);
        parentNode.addAsParent(accessNode);
        PlanNode grandparentNode = accessNode.getParent();
        if(grandparentNode != null) {
            return rootNode;
        }
        return accessNode;
    }
View Full Code Here

            return null;
        }
       
        //if I'm on the inner side of an outer join, then and we have a criteria restriction, then I can't be pushed
    if (type.isOuter() && CapabilitiesUtil.getSupportedJoinCriteria(modelId, metadata, capFinder) != SupportedJoinCriteria.ANY) {
      PlanNode critNode = NodeEditor.findNodePreOrder(joinNode.getLastChild(), NodeConstants.Types.SELECT, NodeConstants.Types.SOURCE);
      if (critNode != null) {
        return null;
      }
      if (type == JoinType.JOIN_FULL_OUTER) {
        critNode = NodeEditor.findNodePreOrder(joinNode.getFirstChild(), NodeConstants.Types.SELECT, NodeConstants.Types.SOURCE);
View Full Code Here

    }
    return false;
  }
   
    static PlanNode raiseAccessOverJoin(PlanNode joinNode, Object modelID, boolean insert) {
    PlanNode leftAccess = joinNode.getFirstChild();
    PlanNode rightAccess = joinNode.getLastChild();

    // Remove old access nodes - this will automatically add children of access nodes to join node
    NodeEditor.removeChildNode(joinNode, leftAccess);
    NodeEditor.removeChildNode(joinNode, rightAccess);
       
        //Set for later possible use, even though this isn't an access node
        joinNode.setProperty(NodeConstants.Info.MODEL_ID, modelID);

    // Insert new access node above join node
    PlanNode newAccess = NodeFactory.getNewNode(NodeConstants.Types.ACCESS);
    newAccess.setProperty(NodeConstants.Info.MODEL_ID, modelID);
    newAccess.addGroups(rightAccess.getGroups());
    newAccess.addGroups(leftAccess.getGroups());
       
        // Combine hints if necessary
        Object leftHint = leftAccess.getProperty(NodeConstants.Info.MAKE_DEP);
        if(leftHint != null) {
            newAccess.setProperty(NodeConstants.Info.MAKE_DEP, leftHint);
        } else {
            Object rightHint = rightAccess.getProperty(NodeConstants.Info.MAKE_DEP);
            if(rightHint != null) {
                newAccess.setProperty(NodeConstants.Info.MAKE_DEP, rightHint);
            }   
        }
        RulePlaceAccess.copyDependentHints(leftAccess, newAccess);
        RulePlaceAccess.copyDependentHints(rightAccess, newAccess);
        RulePlaceAccess.copyDependentHints(joinNode, newAccess);
       
        if (insert) {
            joinNode.addAsParent(newAccess);
        } else {
            newAccess.addFirstChild(joinNode);
        }
       
        return newAccess;
  }
View Full Code Here

     * @param foundNodes Roots of criteria chains
     */
     void findCriteriaChains(PlanNode root, List<PlanNode> foundNodes, AnalysisRecord analysisRecord)
        throws QueryPlannerException, TeiidComponentException {

        PlanNode recurseRoot = root;
        if(root.getType() == NodeConstants.Types.SELECT) {
         
            // Walk to end of the chain and change recurse root
            while(recurseRoot.getType() == NodeConstants.Types.SELECT) {
              // Look for opportunities to replace with a semi-join
              recurseRoot = planMergeJoin(recurseRoot, root, analysisRecord);
              if (root.getChildCount() == 0) {
                root = recurseRoot.getFirstChild();
                if (root.getType() != NodeConstants.Types.SELECT) {
                  root = root.getParent();
                }
              }
              recurseRoot = recurseRoot.getFirstChild();
            }

            // Ignore trivial 1-node case
            if(recurseRoot.getParent() != root) {
                // Found root for chain
                foundNodes.add(root);
            }
        }
       
        if (recurseRoot.getType() != NodeConstants.Types.ACCESS) {
            for (PlanNode child : recurseRoot.getChildren()) {
                findCriteriaChains(child, foundNodes, analysisRecord);
            }
        }
    }
View Full Code Here

    static void mergeChain(PlanNode chainRoot, QueryMetadataInterface metadata) {
        // Remove all of chain except root, collect crit from each
        CompoundCriteria critParts = new CompoundCriteria();
        LinkedList<Criteria> subqueryCriteria = new LinkedList<Criteria>();
        PlanNode current = chainRoot;
        boolean isDependentSet = false;
        while(current.getType() == NodeConstants.Types.SELECT) {
          if (!current.getCorrelatedReferenceElements().isEmpty()) {
            //add at the end for delayed evaluation
            subqueryCriteria.add(0, (Criteria)current.getProperty(NodeConstants.Info.SELECT_CRITERIA));
          } else {
            critParts.getCriteria().add(0, (Criteria)current.getProperty(NodeConstants.Info.SELECT_CRITERIA))
          }
           
            isDependentSet |= current.hasBooleanProperty(NodeConstants.Info.IS_DEPENDENT_SET);
           
            // Recurse
            PlanNode last = current;
            current = current.getLastChild();

            // Remove current
            if(last != chainRoot) {
                NodeEditor.removeChildNode(last.getParent(), last);
            }
        }
        critParts.getCriteria().addAll(subqueryCriteria);
        Criteria combinedCrit = QueryRewriter.optimizeCriteria(critParts, metadata);
View Full Code Here

            }
                return current;
              }
      }
           
            PlanNode semiJoin = NodeFactory.getNewNode(NodeConstants.Types.JOIN);
            semiJoin.addGroups(current.getGroups());
            semiJoin.setProperty(NodeConstants.Info.JOIN_STRATEGY, JoinStrategyType.MERGE);
            semiJoin.setProperty(NodeConstants.Info.JOIN_TYPE, plannedResult.not?JoinType.JOIN_ANTI_SEMI:JoinType.JOIN_SEMI);
            semiJoin.setProperty(NodeConstants.Info.NON_EQUI_JOIN_CRITERIA, plannedResult.nonEquiJoinCriteria);
           
            semiJoin.setProperty(NodeConstants.Info.LEFT_EXPRESSIONS, plannedResult.leftExpressions);
            semiJoin.setProperty(NodeConstants.Info.RIGHT_EXPRESSIONS, plannedResult.rightExpressions);
            semiJoin.setProperty(NodeConstants.Info.SORT_RIGHT, SortOption.ALREADY_SORTED);
            semiJoin.setProperty(NodeConstants.Info.OUTPUT_COLS, root.getProperty(NodeConstants.Info.OUTPUT_COLS));
           
            List childOutput = (List)current.getFirstChild().getProperty(NodeConstants.Info.OUTPUT_COLS);
            PlanNode toCorrect = root;
            while (toCorrect != current) {
              toCorrect.setProperty(NodeConstants.Info.OUTPUT_COLS, childOutput);
              toCorrect = toCorrect.getFirstChild();
            }
           
            PlanNode node = NodeFactory.getNewNode(NodeConstants.Types.ACCESS);
            node.setProperty(NodeConstants.Info.PROCESSOR_PLAN, subPlan);
            node.setProperty(NodeConstants.Info.OUTPUT_COLS, projectedSymbols);
            node.setProperty(NodeConstants.Info.EST_CARDINALITY, planCardinality);
            root.addAsParent(semiJoin);
            semiJoin.addLastChild(node);
            PlanNode result = current.getParent();
            NodeEditor.removeChildNode(result, current);
            RuleImplementJoinStrategy.insertSort(semiJoin.getFirstChild(), (List<SingleElementSymbol>) plannedResult.leftExpressions, semiJoin, metadata, capFinder, true);
            return result;
    } catch (QueryPlannerException e) {
      //can't be done - probably access patterns - what about dependent
View Full Code Here

                treeChanged = true;
            }
            
            if (removeCopiedFlag) {
                //allow the criteria above the join to be eligible for pushing and copying
                PlanNode parent = node.getParent();
                while (parent != null && parent.getType() == NodeConstants.Types.SELECT) {
                    parent.setProperty(NodeConstants.Info.IS_COPIED, Boolean.FALSE);
                    parent = parent.getParent();
                }
            }           
        }
       
        if (treeChanged) {
View Full Code Here

     * @param tgtCrit
     * @return
     */
    private boolean pushCriteria(PlanNode joinNode,
                                  Criteria tgtCrit) {
        PlanNode newCritNode = RelationalPlanner.createSelectNode(tgtCrit, false);
       
        Set<GroupSymbol> groups = newCritNode.getGroups();
       
        PlanNode[] innerJoinNodes = JoinUtil.getInnerSideJoinNodes(joinNode);

        boolean pushed = false;

View Full Code Here

TOP

Related Classes of org.teiid.query.optimizer.relational.plantree.PlanNode

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.