Search in sources :

Example 76 with PlanNode

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

the class RuleRaiseAccess method raiseAccessOverJoin.

static PlanNode raiseAccessOverJoin(PlanNode joinNode, PlanNode accessNode, Object modelID, CapabilitiesFinder capFinder, QueryMetadataInterface metadata, boolean insert) throws QueryMetadataException, TeiidComponentException {
    PlanNode leftAccess = joinNode.getFirstChild();
    PlanNode rightAccess = joinNode.getLastChild();
    boolean switchChildren = false;
    if (leftAccess.getGroups().size() != 1 && joinNode.getProperty(Info.JOIN_TYPE) == JoinType.JOIN_INNER && CapabilitiesUtil.getSupportedJoinCriteria(modelID, metadata, capFinder) == SupportedJoinCriteria.KEY) {
        switchChildren = true;
    }
    PlanNode other = leftAccess == accessNode ? rightAccess : leftAccess;
    // Remove old access nodes - this will automatically add children of access nodes to join node
    NodeEditor.removeChildNode(joinNode, leftAccess);
    if (rightAccess.getType() == NodeConstants.Types.SOURCE) {
        rightAccess.setProperty(NodeConstants.Info.INLINE_VIEW, Boolean.TRUE);
        // handle lateral join
        if (FrameUtil.getNonQueryCommand(rightAccess.getFirstChild()) != null) {
            // procedure case
            PlanNode access = NodeEditor.findNodePreOrder(rightAccess, NodeConstants.Types.ACCESS);
            NodeEditor.removeChildNode(access.getParent(), access);
        } else {
            Assertion.assertTrue(rightAccess.getFirstChild().getType() == NodeConstants.Types.ACCESS);
            NodeEditor.removeChildNode(rightAccess, rightAccess.getFirstChild());
        }
    } else {
        NodeEditor.removeChildNode(joinNode, rightAccess);
    }
    combineConformedSources(accessNode, other);
    // 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
    accessNode.addGroups(other.getGroups());
    // Combine hints if necessary
    RulePlaceAccess.copyProperties(other, accessNode);
    RulePlaceAccess.copyProperties(joinNode, accessNode);
    combineSourceHints(accessNode, other);
    if (other.hasBooleanProperty(Info.IS_MULTI_SOURCE)) {
        accessNode.setProperty(Info.IS_MULTI_SOURCE, Boolean.TRUE);
    }
    String sourceName = (String) other.getProperty(Info.SOURCE_NAME);
    if (sourceName != null) {
        accessNode.setProperty(Info.SOURCE_NAME, sourceName);
    }
    if (insert) {
        joinNode.addAsParent(accessNode);
    } else {
        accessNode.addFirstChild(joinNode);
    }
    if (switchChildren) {
        JoinUtil.swapJoinChildren(joinNode);
    }
    return accessNode;
}
Also used : PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode)

Example 77 with PlanNode

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

the class RuleRaiseAccess method canRaiseOverSelect.

/**
 * @param accessNode
 * @param metadata
 * @param capFinder
 * @param parentNode
 * @return
 * @throws QueryMetadataException
 * @throws TeiidComponentException
 * @throws QueryPlannerException
 */
static boolean canRaiseOverSelect(PlanNode accessNode, QueryMetadataInterface metadata, CapabilitiesFinder capFinder, PlanNode parentNode, AnalysisRecord record) throws QueryMetadataException, TeiidComponentException, QueryPlannerException {
    if (parentNode.hasBooleanProperty(NodeConstants.Info.IS_PHANTOM)) {
        return true;
    }
    // Find the model for this node by getting ACCESS node's model
    Object modelID = getModelIDFromAccess(accessNode, metadata);
    if (modelID == null) {
        // Couldn't determine model ID, so give up
        return false;
    }
    if (parentNode.hasBooleanProperty(NodeConstants.Info.IS_HAVING) && !CapabilitiesUtil.supports(Capability.QUERY_HAVING, modelID, metadata, capFinder) && !CapabilitiesUtil.supports(Capability.QUERY_FROM_INLINE_VIEWS, modelID, metadata, capFinder)) {
        // $NON-NLS-1$ //$NON-NLS-2$
        parentNode.recordDebugAnnotation("having is not supported by source", modelID, "cannot push having", record, metadata);
        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.isOrderedOrStrictLimit(limitNode)) {
        return false;
    }
    Criteria crit = (Criteria) parentNode.getProperty(NodeConstants.Info.SELECT_CRITERIA);
    if (!CriteriaCapabilityValidatorVisitor.canPushLanguageObject(crit, modelID, metadata, capFinder, record)) {
        return false;
    }
    if (accessNode.getFirstChild() != null && accessNode.getFirstChild().getType() == NodeConstants.Types.SET_OP) {
        // inconsistent select position - RulePushSelectCriteria is too greedy
        return false;
    }
    return true;
}
Also used : PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) SupportedJoinCriteria(org.teiid.translator.ExecutionFactory.SupportedJoinCriteria)

Example 78 with PlanNode

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

the class RuleRaiseAccess method execute.

public PlanNode execute(PlanNode plan, QueryMetadataInterface metadata, CapabilitiesFinder capFinder, RuleStack rules, AnalysisRecord analysisRecord, CommandContext context) throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
    boolean afterJoinPlanning = !rules.contains(RuleConstants.PLAN_JOINS);
    for (PlanNode accessNode : NodeEditor.findAllNodes(plan, NodeConstants.Types.ACCESS)) {
        while (true) {
            PlanNode newRoot = raiseAccessNode(plan, accessNode, metadata, capFinder, afterJoinPlanning, analysisRecord, context);
            if (newRoot == null) {
                break;
            }
            plan = newRoot;
        }
    }
    return plan;
}
Also used : PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode)

Example 79 with PlanNode

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

the class RuleRaiseNull method raiseNullThroughJoin.

/**
 * Given a joinNode that should be an outer join and a null node as one of its children, replace elements in
 * the current frame from the null node groups with null values
 *
 * @param metadata
 * @param joinNode
 * @param nullNode
 * @throws QueryPlannerException
 * @throws QueryMetadataException
 * @throws TeiidComponentException
 */
static void raiseNullThroughJoin(QueryMetadataInterface metadata, PlanNode joinNode, PlanNode nullNode) throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
    Assertion.assertTrue(joinNode.getType() == NodeConstants.Types.JOIN);
    Assertion.assertTrue(nullNode.getType() == NodeConstants.Types.NULL);
    Assertion.assertTrue(nullNode.getParent() == joinNode);
    PlanNode frameStart = joinNode.getParent();
    NodeEditor.removeChildNode(joinNode, nullNode);
    NodeEditor.removeChildNode(joinNode.getParent(), joinNode);
    for (GroupSymbol group : nullNode.getGroups()) {
        Map<ElementSymbol, Expression> nullSymbolMap = FrameUtil.buildSymbolMap(group, null, metadata);
        FrameUtil.convertFrame(frameStart, group, null, nullSymbolMap, metadata);
    }
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) Expression(org.teiid.query.sql.symbol.Expression) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol)

Example 80 with PlanNode

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

the class RuleRemoveOptionalJoins method isOptionalUsingKey.

private boolean isOptionalUsingKey(PlanNode joinNode, PlanNode optionalNode, QueryMetadataInterface metadata, boolean isRight) throws TeiidComponentException, QueryMetadataException {
    // for now we just look for a single group
    if (optionalNode.getGroups().size() != 1) {
        return false;
    }
    PlanNode left = isRight ? joinNode.getFirstChild() : joinNode.getLastChild();
    LinkedList<Expression> leftExpressions = new LinkedList<Expression>();
    LinkedList<Expression> rightExpressions = new LinkedList<Expression>();
    LinkedList<Criteria> nonEquiJoinCriteria = new LinkedList<Criteria>();
    RuleChooseJoinStrategy.separateCriteria(left.getGroups(), optionalNode.getGroups(), leftExpressions, rightExpressions, (List<Criteria>) joinNode.getProperty(NodeConstants.Info.JOIN_CRITERIA), nonEquiJoinCriteria);
    if (!nonEquiJoinCriteria.isEmpty()) {
        for (Criteria crit : nonEquiJoinCriteria) {
            if (!Collections.disjoint(GroupsUsedByElementsVisitor.getGroups(crit), optionalNode.getGroups())) {
                // additional predicates still need to be applied, or ignored via hint
                return false;
            }
        }
    }
    ArrayList<Object> leftIds = new ArrayList<Object>(leftExpressions.size());
    ArrayList<Object> rightIds = new ArrayList<Object>(rightExpressions.size());
    for (Expression expr : leftExpressions) {
        if (expr instanceof ElementSymbol) {
            leftIds.add(((ElementSymbol) expr).getMetadataID());
        }
    }
    for (Expression expr : rightExpressions) {
        if (expr instanceof ElementSymbol) {
            rightIds.add(((ElementSymbol) expr).getMetadataID());
        } else {
            // only allow a key join
            return false;
        }
    }
    outer: for (GroupSymbol group : left.getGroups()) {
        Collection fks = metadata.getForeignKeysInGroup(group.getMetadataID());
        for (Object fk : fks) {
            List fkColumns = metadata.getElementIDsInKey(fk);
            if (!leftIds.containsAll(fkColumns)) {
                continue;
            }
            Object pk = metadata.getPrimaryKeyIDForForeignKeyID(fk);
            List pkColumns = metadata.getElementIDsInKey(pk);
            if ((rightIds.size() != pkColumns.size()) || !rightIds.containsAll(pkColumns)) {
                continue;
            }
            if (!isRight) {
                // match up to the replacement logic below
                JoinUtil.swapJoinChildren(joinNode);
            }
            return true;
        }
    }
    return false;
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) ArrayList(java.util.ArrayList) Criteria(org.teiid.query.sql.lang.Criteria) LinkedList(java.util.LinkedList) PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) Expression(org.teiid.query.sql.symbol.Expression) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) Collection(java.util.Collection) LanguageObject(org.teiid.query.sql.LanguageObject) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) List(java.util.List)

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