Search in sources :

Example 41 with Criteria

use of org.teiid.query.sql.lang.Criteria in project teiid by teiid.

the class RulePushAggregates method collectAggregates.

/**
 * Walk up the plan from the GROUP node. Should encounter only (optionally) a SELECT and can stop at the PROJECT node. Need to
 * collect any AggregateSymbols used in the select criteria or projected columns.
 *
 * @param groupNode
 * @return the set of aggregate symbols found
 * @since 4.2
 */
static LinkedHashSet<AggregateSymbol> collectAggregates(PlanNode groupNode) {
    LinkedHashSet<AggregateSymbol> aggregates = new LinkedHashSet<AggregateSymbol>();
    PlanNode currentNode = groupNode.getParent();
    SymbolMap symbolMap = (SymbolMap) groupNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
    while (currentNode != null) {
        if (currentNode.getType() == NodeConstants.Types.PROJECT) {
            List<Expression> projectedSymbols = (List<Expression>) currentNode.getProperty(NodeConstants.Info.PROJECT_COLS);
            for (Expression symbol : projectedSymbols) {
                mapAggregates(ElementCollectorVisitor.getAggregates(symbol, true), symbolMap, aggregates);
            }
            break;
        }
        if (currentNode.getType() == NodeConstants.Types.SELECT) {
            Criteria crit = (Criteria) currentNode.getProperty(NodeConstants.Info.SELECT_CRITERIA);
            mapAggregates(ElementCollectorVisitor.getAggregates(crit, true), symbolMap, aggregates);
        }
        currentNode = currentNode.getParent();
    }
    return aggregates;
}
Also used : PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) SymbolMap(org.teiid.query.sql.util.SymbolMap) IsNullCriteria(org.teiid.query.sql.lang.IsNullCriteria) Criteria(org.teiid.query.sql.lang.Criteria) CompareCriteria(org.teiid.query.sql.lang.CompareCriteria)

Example 42 with Criteria

use of org.teiid.query.sql.lang.Criteria in project teiid by teiid.

the class RulePushAggregates method canPush.

/**
 * Ensures that we are only pushing through inner equi joins or cross joins.  Also collects the necessary staged grouping symbols
 * @param aggregates
 * @param metadata
 * @return null if we cannot push otherwise the target join node
 */
private PlanNode canPush(PlanNode groupNode, Set<Expression> stagedGroupingSymbols, PlanNode planNode, Collection<AggregateSymbol> aggregates, QueryMetadataInterface metadata) {
    PlanNode parentJoin = planNode.getParent();
    Set<GroupSymbol> groups = FrameUtil.findJoinSourceNode(planNode).getGroups();
    PlanNode result = planNode;
    while (parentJoin != groupNode) {
        if (parentJoin.getType() != NodeConstants.Types.JOIN) {
            return null;
        }
        JoinType joinType = (JoinType) parentJoin.getProperty(NodeConstants.Info.JOIN_TYPE);
        if (joinType.isOuter() && aggregates != null) {
            for (AggregateSymbol as : aggregates) {
                if (as.getArgs().length != 1) {
                    continue;
                }
                Collection<GroupSymbol> expressionGroups = GroupsUsedByElementsVisitor.getGroups(as.getArg(0));
                Collection<GroupSymbol> innerGroups = null;
                if (joinType == JoinType.JOIN_LEFT_OUTER) {
                    innerGroups = FrameUtil.findJoinSourceNode(parentJoin.getLastChild()).getGroups();
                } else {
                    // full outer
                    innerGroups = parentJoin.getGroups();
                }
                if (Collections.disjoint(expressionGroups, innerGroups)) {
                    continue;
                }
                if (as.getFunctionDescriptor() != null && as.getFunctionDescriptor().isNullDependent()) {
                    return null;
                }
                if (as.getArgs().length == 1 && JoinUtil.isNullDependent(metadata, innerGroups, as.getArg(0))) {
                    return null;
                }
            }
        }
        // check for sideways correlation
        PlanNode other = null;
        if (planNode == parentJoin.getFirstChild()) {
            other = parentJoin.getLastChild();
        } else {
            other = parentJoin.getFirstChild();
        }
        SymbolMap map = (SymbolMap) other.getProperty(NodeConstants.Info.CORRELATED_REFERENCES);
        if (map != null) {
            return null;
        // TODO: handle this case. the logic would look something like below,
        // but we would need to handle the updating of the symbol maps in addGroupBy
        /*filterExpressions(stagedGroupingSymbols, groups, map.getKeys(), true);
        		for (ElementSymbol ex : map.getKeys()) {
    				if (DataTypeManager.isNonComparable(DataTypeManager.getDataTypeName(ex.getType()))) {
    					return null;
    				}
	        	}*/
        }
        if (!parentJoin.hasCollectionProperty(NodeConstants.Info.LEFT_EXPRESSIONS) || !parentJoin.hasCollectionProperty(NodeConstants.Info.RIGHT_EXPRESSIONS)) {
            List<Criteria> criteria = (List<Criteria>) parentJoin.getProperty(Info.JOIN_CRITERIA);
            if (!findStagedGroupingExpressions(groups, criteria, stagedGroupingSymbols)) {
                return null;
            }
        } else {
            List<Criteria> criteria = (List<Criteria>) parentJoin.getProperty(Info.NON_EQUI_JOIN_CRITERIA);
            if (!findStagedGroupingExpressions(groups, criteria, stagedGroupingSymbols)) {
                return null;
            }
            // we move the target up if the filtered expressions introduce outside groups
            if (planNode == parentJoin.getFirstChild()) {
                if (filterExpressions(stagedGroupingSymbols, groups, (List<Expression>) parentJoin.getProperty(NodeConstants.Info.LEFT_EXPRESSIONS), true)) {
                    result = parentJoin;
                    groups = result.getGroups();
                }
            } else {
                if (filterExpressions(stagedGroupingSymbols, groups, (List<Expression>) parentJoin.getProperty(NodeConstants.Info.RIGHT_EXPRESSIONS), true)) {
                    result = parentJoin;
                    groups = result.getGroups();
                }
            }
        }
        planNode = parentJoin;
        parentJoin = parentJoin.getParent();
    }
    if (result.getParent() == groupNode) {
        // can't be pushed as we are already at the direct child
        return null;
    }
    return result;
}
Also used : PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) JoinType(org.teiid.query.sql.lang.JoinType) SymbolMap(org.teiid.query.sql.util.SymbolMap) IsNullCriteria(org.teiid.query.sql.lang.IsNullCriteria) Criteria(org.teiid.query.sql.lang.Criteria) CompareCriteria(org.teiid.query.sql.lang.CompareCriteria)

Example 43 with Criteria

use of org.teiid.query.sql.lang.Criteria in project teiid by teiid.

the class RuleChooseJoinStrategy method chooseJoinStrategy.

/**
 * Determines whether this node should be converted to a merge join node
 * @param joinNode The join node
 * @param metadata The metadata
 */
static void chooseJoinStrategy(PlanNode joinNode, QueryMetadataInterface metadata) {
    // Check that join is an inner join
    JoinType jtype = (JoinType) joinNode.getProperty(NodeConstants.Info.JOIN_TYPE);
    if (jtype.equals(JoinType.JOIN_CROSS)) {
        return;
    }
    PlanNode leftChild = joinNode.getFirstChild();
    leftChild = FrameUtil.findJoinSourceNode(leftChild);
    if (leftChild == null) {
        return;
    }
    PlanNode rightChild = joinNode.getLastChild();
    rightChild = FrameUtil.findJoinSourceNode(rightChild);
    if (rightChild == null) {
        return;
    }
    Collection<GroupSymbol> leftGroups = leftChild.getGroups();
    Collection<GroupSymbol> rightGroups = rightChild.getGroups();
    List<Expression> leftExpressions = new ArrayList<Expression>();
    List<Expression> rightExpressions = new ArrayList<Expression>();
    // Check that join criteria are all equality criteria and that there are elements from
    // no more than one group on each side
    List<Criteria> crits = (List<Criteria>) joinNode.getProperty(NodeConstants.Info.JOIN_CRITERIA);
    filterOptionalCriteria(crits, true);
    if (crits.isEmpty() && jtype == JoinType.JOIN_INNER) {
        joinNode.setProperty(NodeConstants.Info.JOIN_TYPE, JoinType.JOIN_CROSS);
        return;
    }
    List<Criteria> nonEquiJoinCriteria = new ArrayList<Criteria>();
    separateCriteria(leftGroups, rightGroups, leftExpressions, rightExpressions, crits, nonEquiJoinCriteria);
    if (!leftExpressions.isEmpty()) {
        joinNode.setProperty(NodeConstants.Info.LEFT_EXPRESSIONS, createExpressionSymbols(leftExpressions));
        joinNode.setProperty(NodeConstants.Info.RIGHT_EXPRESSIONS, createExpressionSymbols(rightExpressions));
        // make use of the one side criteria
        joinNode.setProperty(NodeConstants.Info.JOIN_STRATEGY, JoinStrategyType.MERGE);
        joinNode.setProperty(NodeConstants.Info.NON_EQUI_JOIN_CRITERIA, nonEquiJoinCriteria);
    } else if (nonEquiJoinCriteria.isEmpty()) {
        joinNode.setProperty(NodeConstants.Info.JOIN_CRITERIA, nonEquiJoinCriteria);
        if (joinNode.getProperty(NodeConstants.Info.JOIN_TYPE) == JoinType.JOIN_INNER) {
            joinNode.setProperty(NodeConstants.Info.JOIN_TYPE, JoinType.JOIN_CROSS);
        }
    }
}
Also used : PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) Expression(org.teiid.query.sql.symbol.Expression) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) ArrayList(java.util.ArrayList) JoinType(org.teiid.query.sql.lang.JoinType) ArrayList(java.util.ArrayList) List(java.util.List) Criteria(org.teiid.query.sql.lang.Criteria) CompareCriteria(org.teiid.query.sql.lang.CompareCriteria)

Example 44 with Criteria

use of org.teiid.query.sql.lang.Criteria in project teiid by teiid.

the class RuleCopyCriteria method createCriteria.

private boolean createCriteria(boolean copyingJoinCriteria, Collection<Criteria> toCopy, Set<Criteria> combinedCriteria, Map<Expression, Expression> srcToTgt, List<Criteria> newJoinCrits, QueryMetadataInterface metadata, boolean underAccess) {
    boolean changedTree = false;
    if (srcToTgt.size() == 0) {
        return changedTree;
    }
    Iterator<Criteria> i = toCopy.iterator();
    while (i.hasNext()) {
        Criteria crit = i.next();
        Integer endGroups = copyCriteria(crit, srcToTgt, newJoinCrits, combinedCriteria, copyingJoinCriteria, metadata, underAccess);
        if (endGroups != null) {
            changedTree = true;
            if (copyingJoinCriteria && endGroups < 2) {
                if (crit instanceof CompareCriteria) {
                    CompareCriteria cc = (CompareCriteria) crit;
                    // don't remove theta criteria, just mark it as optional
                    cc.setOptional(null);
                    continue;
                }
                i.remove();
            }
        }
    }
    return changedTree;
}
Also used : IsNullCriteria(org.teiid.query.sql.lang.IsNullCriteria) Criteria(org.teiid.query.sql.lang.Criteria) CompareCriteria(org.teiid.query.sql.lang.CompareCriteria) CompareCriteria(org.teiid.query.sql.lang.CompareCriteria)

Example 45 with Criteria

use of org.teiid.query.sql.lang.Criteria in project teiid by teiid.

the class RulePushSelectCriteria method createConvertedSelectNode.

private PlanNode createConvertedSelectNode(PlanNode critNode, GroupSymbol sourceGroup, PlanNode projectNode, SymbolMap symbolMap, QueryMetadataInterface metadata) throws QueryPlannerException {
    // If projectNode has children, then it is from a SELECT without a FROM and the criteria should not be pushed
    if (projectNode.getChildCount() == 0) {
        return null;
    }
    Criteria crit = (Criteria) critNode.getProperty(NodeConstants.Info.SELECT_CRITERIA);
    Collection<ElementSymbol> cols = ElementCollectorVisitor.getElements(crit, true);
    if (projectNode.hasBooleanProperty(Info.HAS_WINDOW_FUNCTIONS)) {
        // we can push iff the predicate is against partitioning columns in all projected window functions
        Set<WindowFunction> windowFunctions = RuleAssignOutputElements.getWindowFunctions((List<Expression>) projectNode.getProperty(Info.PROJECT_COLS));
        for (WindowFunction windowFunction : windowFunctions) {
            WindowSpecification spec = windowFunction.getWindowSpecification();
            if (spec.getPartition() == null) {
                return null;
            }
            for (ElementSymbol col : cols) {
                if (!spec.getPartition().contains(symbolMap.getMappedExpression(col))) {
                    return null;
                }
            }
        }
    }
    Boolean conversionResult = checkConversion(symbolMap, cols);
    if (conversionResult == Boolean.FALSE) {
        // not convertable
        return null;
    }
    if (!critNode.getSubqueryContainers().isEmpty() && checkConversion(symbolMap, critNode.getCorrelatedReferenceElements()) != null) {
        // not convertable, or has an aggregate for a correlated reference
        return null;
    }
    PlanNode copyNode = copyNode(critNode);
    if (conversionResult == Boolean.TRUE) {
        copyNode.setProperty(NodeConstants.Info.IS_HAVING, Boolean.TRUE);
    }
    FrameUtil.convertNode(copyNode, sourceGroup, null, symbolMap.asMap(), metadata, true);
    // any proc relational criteria that is not input criteria should stay above the source
    if (sourceGroup.isProcedure() && !copyNode.getGroups().isEmpty()) {
        if (this.createdNodes != null) {
            this.createdNodes.remove(this.createdNodes.size() - 1);
        }
        return null;
    }
    return copyNode;
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) WindowFunction(org.teiid.query.sql.symbol.WindowFunction) PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) Expression(org.teiid.query.sql.symbol.Expression) WindowSpecification(org.teiid.query.sql.symbol.WindowSpecification) 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)

Aggregations

Criteria (org.teiid.query.sql.lang.Criteria)67 CompareCriteria (org.teiid.query.sql.lang.CompareCriteria)40 PlanNode (org.teiid.query.optimizer.relational.plantree.PlanNode)35 ElementSymbol (org.teiid.query.sql.symbol.ElementSymbol)22 Expression (org.teiid.query.sql.symbol.Expression)22 GroupSymbol (org.teiid.query.sql.symbol.GroupSymbol)22 CompoundCriteria (org.teiid.query.sql.lang.CompoundCriteria)19 ArrayList (java.util.ArrayList)16 List (java.util.List)15 DependentSetCriteria (org.teiid.query.sql.lang.DependentSetCriteria)13 IsNullCriteria (org.teiid.query.sql.lang.IsNullCriteria)12 Constant (org.teiid.query.sql.symbol.Constant)11 SymbolMap (org.teiid.query.sql.util.SymbolMap)11 JoinType (org.teiid.query.sql.lang.JoinType)10 SetCriteria (org.teiid.query.sql.lang.SetCriteria)10 LinkedList (java.util.LinkedList)7 Reference (org.teiid.query.sql.symbol.Reference)6 LinkedHashSet (java.util.LinkedHashSet)5 LanguageObject (org.teiid.query.sql.LanguageObject)5 Collection (java.util.Collection)4