Search in sources :

Example 31 with PlanNode

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

the class RulePlaceAccess method addAccessNode.

/**
 * Adds a access node if the node is a source leaf node.
 *
 * @param metadata
 * @param sourceNode
 * @return true if the source node has an access pattern
 * @throws QueryMetadataException
 * @throws TeiidComponentException
 */
private void addAccessNode(QueryMetadataInterface metadata, PlanNode sourceNode, CapabilitiesFinder finder, boolean[] additionalRules) throws QueryMetadataException, TeiidComponentException {
    boolean isInsert = false;
    Object req = sourceNode.getProperty(NodeConstants.Info.ATOMIC_REQUEST);
    if (req == null) {
        req = sourceNode.getProperty(NodeConstants.Info.NESTED_COMMAND);
    }
    if (sourceNode.getProperty(NodeConstants.Info.TABLE_FUNCTION) != null) {
        return;
    }
    if (req instanceof Insert) {
        isInsert = true;
    } else {
        PlanNode parent = sourceNode.getParent();
        if (parent.getType() == NodeConstants.Types.PROJECT && parent.getProperty(NodeConstants.Info.INTO_GROUP) != null) {
            isInsert = true;
        }
    }
    PlanNode apNode = sourceNode;
    if (sourceNode.getChildCount() == 0) {
        // Create the access node and insert
        PlanNode accessNode = NodeFactory.getNewNode(NodeConstants.Types.ACCESS);
        accessNode.addGroups(sourceNode.getGroups());
        copyProperties(sourceNode, accessNode);
        SourceHint sourceHint = (SourceHint) sourceNode.removeProperty(Info.SOURCE_HINT);
        // TODO: trim the hint to only the sources possible under this model (typically 1, but could be more in
        // multi-source
        accessNode.setProperty(Info.SOURCE_HINT, sourceHint);
        Object hint = sourceNode.removeProperty(NodeConstants.Info.IS_OPTIONAL);
        if (hint != null) {
            accessNode.setProperty(NodeConstants.Info.IS_OPTIONAL, hint);
        }
        Object modelId = null;
        if (sourceNode.getGroups().size() == 1) {
            GroupSymbol gs = sourceNode.getGroups().iterator().next();
            modelId = gs.getModelMetadataId();
            if (modelId != null) {
                accessNode.setProperty(NodeConstants.Info.MODEL_ID, modelId);
            }
        }
        if (req instanceof Create || req instanceof Drop) {
            modelId = TempMetadataAdapter.TEMP_MODEL;
        } else {
            modelId = RuleRaiseAccess.getModelIDFromAccess(accessNode, metadata);
        }
        if (modelId != null) {
            boolean multiSource = metadata.isMultiSource(modelId);
            if (multiSource) {
                accessNode.setProperty(Info.IS_MULTI_SOURCE, multiSource);
            }
            accessNode.setProperty(NodeConstants.Info.MODEL_ID, modelId);
        }
        if (req == null && modelId != null) {
            // add "conformed" sources if they exist
            GroupSymbol group = sourceNode.getGroups().iterator().next();
            Object gid = group.getMetadataID();
            String sources = metadata.getExtensionProperty(gid, CONFORMED_SOURCES, false);
            if (sources != null) {
                Set<Object> conformed = new LinkedHashSet<Object>();
                conformed.add(modelId);
                for (String source : StringUtil.split(sources, ",")) {
                    // $NON-NLS-1$
                    Object mid = metadata.getModelID(source.trim());
                    if (metadata.isVirtualModel(mid)) {
                        // TODO: could validate this up-front
                        throw new QueryMetadataException(QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31148, metadata.getName(mid), group));
                    }
                    conformed.add(mid);
                }
                accessNode.setProperty(Info.CONFORMED_SOURCES, conformed);
            }
        }
        // Insert
        sourceNode.addAsParent(accessNode);
        apNode = accessNode;
        // set additional information
        for (GroupSymbol group : accessNode.getGroups()) {
            if (group.getCheckMatViewStatus() != null) {
                LinkedHashSet<Object> viewsToCheck = new LinkedHashSet<Object>();
                viewsToCheck.add(group.getCheckMatViewStatus());
                accessNode.setProperty(Info.CHECK_MAT_VIEW, viewsToCheck);
            }
            Object modelID = metadata.getModelID(group.getMetadataID());
            if (CapabilitiesUtil.requiresCriteria(modelID, metadata, finder)) {
                additionalRules[1] = true;
            }
        }
    }
    // Add access pattern(s), if any, as property of access node
    if (!isInsert && addAccessPatternsProperty(apNode, metadata)) {
        additionalRules[0] = true;
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Insert(org.teiid.query.sql.lang.Insert) QueryMetadataException(org.teiid.api.exception.query.QueryMetadataException) SourceHint(org.teiid.query.sql.lang.SourceHint) Drop(org.teiid.query.sql.lang.Drop) PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) Create(org.teiid.query.sql.lang.Create) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol)

Example 32 with PlanNode

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

the class RulePlanJoins method createJoinNode.

private PlanNode createJoinNode(PlanNode accessNode1, PlanNode accessNode2, List<Criteria> joinCriteria, JoinType joinType) {
    PlanNode joinNode = createJoinNode();
    joinNode.getGroups().addAll(accessNode1.getGroups());
    joinNode.getGroups().addAll(accessNode2.getGroups());
    joinNode.addFirstChild(accessNode2);
    joinNode.addLastChild(accessNode1);
    joinNode.setProperty(NodeConstants.Info.JOIN_TYPE, joinType);
    joinNode.setProperty(NodeConstants.Info.JOIN_CRITERIA, joinCriteria);
    return joinNode;
}
Also used : PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode)

Example 33 with PlanNode

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

the class RulePlanJoins method createJoinNode.

static PlanNode createJoinNode() {
    PlanNode joinNode = NodeFactory.getNewNode(NodeConstants.Types.JOIN);
    joinNode.setProperty(NodeConstants.Info.JOIN_TYPE, JoinType.JOIN_CROSS);
    joinNode.setProperty(NodeConstants.Info.JOIN_STRATEGY, JoinStrategyType.NESTED_LOOP);
    return joinNode;
}
Also used : PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode)

Example 34 with PlanNode

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

the class RulePlanJoins method groupAcrossLeftOuter.

private void groupAcrossLeftOuter(QueryMetadataInterface metadata, CapabilitiesFinder capabilitiesFinder, CommandContext context, JoinRegion joinRegion) throws QueryMetadataException, TeiidComponentException, AssertionError {
    if (joinRegion.getLeft() == null || joinRegion.getJoinRoot().getLastChild().getType() != NodeConstants.Types.ACCESS || joinRegion.getJoinRoot().getFirstChild().getType() == NodeConstants.Types.ACCESS) {
        return;
    }
    PlanNode planNodeRight = joinRegion.getJoinRoot().getLastChild();
    Object modelId = RuleRaiseAccess.getModelIDFromAccess(planNodeRight, metadata);
    Map<Object, List<PlanNode>> accessMapLeft = getAccessMap(metadata, capabilitiesFinder, joinRegion.getLeft());
    // TODO: what about same connector, but not the same model
    List<PlanNode> joinSourcesLeft = accessMapLeft.get(modelId);
    if (joinSourcesLeft == null) {
        return;
    }
    SupportedJoinCriteria sjc = CapabilitiesUtil.getSupportedJoinCriteria(modelId, metadata, capabilitiesFinder);
    Set<GroupSymbol> groups = new HashSet<GroupSymbol>();
    List<Criteria> joinCriteria = (List<Criteria>) joinRegion.getJoinRoot().getProperty(Info.JOIN_CRITERIA);
    for (Criteria crit : joinCriteria) {
        if (!RuleRaiseAccess.isSupportedJoinCriteria(sjc, crit, modelId, metadata, capabilitiesFinder, null)) {
            return;
        }
    }
    GroupsUsedByElementsVisitor.getGroups(joinCriteria, groups);
    groups.removeAll(planNodeRight.getGroups());
    for (PlanNode planNode : joinSourcesLeft) {
        if (!planNode.getGroups().containsAll(groups)) {
            continue;
        }
        // see if we can group the planNode with the other side
        if (RuleRaiseAccess.canRaiseOverJoin(Arrays.asList(planNode, planNodeRight), metadata, capabilitiesFinder, joinCriteria, JoinType.JOIN_LEFT_OUTER, null, context, false, false) == null) {
            continue;
        }
        // remove the parent loj, create a new loj
        joinRegion.getLeft().getJoinSourceNodes().remove(planNode);
        PlanNode joinNode = createJoinNode(planNode, planNodeRight, joinCriteria, JoinType.JOIN_LEFT_OUTER);
        PlanNode newAccess = RuleRaiseAccess.raiseAccessOverJoin(joinNode, joinNode.getFirstChild(), modelId, capabilitiesFinder, metadata, false);
        for (Set<PlanNode> source : joinRegion.getLeft().getCritieriaToSourceMap().values()) {
            if (source.remove(planNode)) {
                source.add(newAccess);
            }
        }
        joinRegion.getLeft().getJoinSourceNodes().put(newAccess, newAccess);
        PlanNode root = joinRegion.getJoinRoot();
        root.getParent().replaceChild(root, root.getFirstChild());
        joinRegion.getLeft().reconstructJoinRegoin();
        break;
    }
}
Also used : PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) SupportedJoinCriteria(org.teiid.translator.ExecutionFactory.SupportedJoinCriteria) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) Criteria(org.teiid.query.sql.lang.Criteria) CompareCriteria(org.teiid.query.sql.lang.CompareCriteria) SupportedJoinCriteria(org.teiid.translator.ExecutionFactory.SupportedJoinCriteria)

Example 35 with PlanNode

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

the class RulePlanOuterJoins method checkLeftOrdering.

/**
 * Check if the current join spans inner/left outer joins, such that
 * a different tree structure would group the join for pushing
 *
 * TODO: this is not tolerant to more complex left nesting structures
 *
 * @param metadata
 * @param capabilitiesFinder
 * @param analysisRecord
 * @param context
 * @param join
 * @return true if the current join has been restructured
 * @throws QueryMetadataException
 * @throws TeiidComponentException
 */
private boolean checkLeftOrdering(QueryMetadataInterface metadata, CapabilitiesFinder capabilitiesFinder, AnalysisRecord analysisRecord, CommandContext context, PlanNode join) throws QueryMetadataException, TeiidComponentException {
    if (join.getFirstChild().getType() != NodeConstants.Types.JOIN || !(join.getFirstChild().getProperty(Info.JOIN_TYPE) == JoinType.JOIN_LEFT_OUTER || join.getFirstChild().getProperty(Info.JOIN_TYPE) == JoinType.JOIN_INNER)) {
        return false;
    }
    PlanNode childJoin = null;
    PlanNode left = join.getFirstChild();
    PlanNode right = join.getLastChild();
    boolean nested = false;
    boolean hasOuter = join.getProperty(Info.JOIN_TYPE) == JoinType.JOIN_LEFT_OUTER;
    childJoin = left;
    while (childJoin.getFirstChild() != null && childJoin.getFirstChild().getType() != NodeConstants.Types.ACCESS) {
        if (childJoin.getType() != NodeConstants.Types.JOIN || !(childJoin.getProperty(Info.JOIN_TYPE) == JoinType.JOIN_LEFT_OUTER || childJoin.getProperty(Info.JOIN_TYPE) == JoinType.JOIN_INNER)) {
            return false;
        }
        hasOuter |= childJoin.getProperty(Info.JOIN_TYPE) == JoinType.JOIN_LEFT_OUTER;
        List<Criteria> childJoinCriteria = (List<Criteria>) childJoin.getProperty(Info.JOIN_CRITERIA);
        if (!isCriteriaValid(childJoinCriteria, metadata, childJoin)) {
            return false;
        }
        childJoin = childJoin.getFirstChild();
        left = childJoin;
        nested = true;
    }
    if (nested && hasOuter && !left.hasBooleanProperty(Info.PRESERVE)) {
        if (right.getType() != NodeConstants.Types.ACCESS) {
            return false;
        }
        List<Criteria> joinCriteria = (List<Criteria>) join.getProperty(Info.JOIN_CRITERIA);
        if (!isCriteriaValid(joinCriteria, metadata, join)) {
            return false;
        }
        joinCriteria = new ArrayList<>(joinCriteria);
        RuleChooseJoinStrategy.filterOptionalCriteria(joinCriteria, false);
        Set<GroupSymbol> groups = GroupsUsedByElementsVisitor.getGroups(joinCriteria);
        if (groups.containsAll(left.getFirstChild().getGroups()) && groups.containsAll(right.getGroups()) && groups.size() == left.getFirstChild().getGroups().size() + right.getGroups().size()) {
            Object modelId = RuleRaiseAccess.canRaiseOverJoin(Arrays.asList(left.getFirstChild(), right), metadata, capabilitiesFinder, joinCriteria, JoinType.JOIN_LEFT_OUTER, analysisRecord, context, false, false);
            if (modelId == null) {
                return false;
            }
            PlanNode parent = join.getParent();
            parent.replaceChild(join, join.getFirstChild());
            join.removeAllChildren();
            left.getFirstChild().addAsParent(join);
            join.addLastChild(right);
            join.getGroups().clear();
            updateGroups(join);
            parent.getGroups().clear();
            updateGroups(parent);
            return true;
        }
    }
    return false;
}
Also used : PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) ArrayList(java.util.ArrayList) List(java.util.List) Criteria(org.teiid.query.sql.lang.Criteria)

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