Search in sources :

Example 31 with Criteria

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

the class RuleCopyCriteria method tryToCopy.

/**
 * Recursively tries to copy criteria across join nodes.  toCopy will contain only the single group criteria
 * that has not yet been copied.  allCriteria will contain all criteria present at the join that can effect
 * copying.
 *
 * @param node
 * @return true if criteria has been created
 */
private boolean tryToCopy(PlanNode node, Set<Criteria>[] criteriaInfo, QueryMetadataInterface metadata, boolean underAccess) {
    boolean changedTree = false;
    if (node == null) {
        return false;
    }
    // visit join nodes in order
    if (node.getType() == NodeConstants.Types.JOIN) {
        JoinType jt = (JoinType) node.getProperty(NodeConstants.Info.JOIN_TYPE);
        if (jt == JoinType.JOIN_FULL_OUTER) {
            return visitChildern(node, criteriaInfo, changedTree, metadata, underAccess);
        }
        Set<Criteria>[] leftChildCriteria = new Set[2];
        Set<Criteria>[] rightChildCriteria = new Set[2];
        changedTree |= tryToCopy(node.getFirstChild(), leftChildCriteria, metadata, underAccess);
        changedTree |= tryToCopy(node.getLastChild(), rightChildCriteria, metadata, underAccess);
        List<Criteria> joinCrits = (List<Criteria>) node.getProperty(NodeConstants.Info.JOIN_CRITERIA);
        Set<Criteria> combinedCriteria = null;
        if (joinCrits != null) {
            combinedCriteria = new LinkedHashSet<Criteria>(joinCrits);
            combinedCriteria.addAll(leftChildCriteria[1]);
            combinedCriteria.addAll(rightChildCriteria[1]);
        }
        // combine the criteria
        leftChildCriteria[0].addAll(rightChildCriteria[0]);
        leftChildCriteria[1].addAll(rightChildCriteria[1]);
        // set the applicable criteria
        criteriaInfo[0] = leftChildCriteria[0];
        // set the all criteria
        criteriaInfo[1] = leftChildCriteria[1];
        // there's no join criteria here, so just let the criteria go up
        if (jt == JoinType.JOIN_CROSS) {
            return changedTree;
        }
        Set<Criteria> toCopy = criteriaInfo[0];
        Set<Criteria> allCriteria = criteriaInfo[1];
        if (joinCrits != null && !joinCrits.isEmpty()) {
            List<Criteria> newJoinCrits = new LinkedList<Criteria>();
            // we don't want to continue discovery since that could be recursive
            Map<Expression, Expression> srcToTgt = buildElementMap(joinCrits, node.hasBooleanProperty(NodeConstants.Info.IS_COPIED) ? null : newJoinCrits, combinedCriteria, metadata, underAccess);
            changedTree |= !newJoinCrits.isEmpty();
            if (!toCopy.isEmpty()) {
                changedTree |= createCriteria(false, toCopy, combinedCriteria, srcToTgt, newJoinCrits, metadata, underAccess);
                srcToTgt = buildElementMap(allCriteria, null, null, metadata, underAccess);
                changedTree |= createCriteria(true, joinCrits, combinedCriteria, srcToTgt, newJoinCrits, metadata, underAccess);
            }
            joinCrits.addAll(newJoinCrits);
        }
        // before returning, filter out criteria that cannot go above the join node
        if (jt == JoinType.JOIN_RIGHT_OUTER || jt == JoinType.JOIN_ANTI_SEMI || jt == JoinType.JOIN_SEMI || jt == JoinType.JOIN_UNION) {
            // $NON-NLS-1$
            throw new AssertionError("Unexpected join type");
        } else if (jt == JoinType.JOIN_LEFT_OUTER) {
            criteriaInfo[0].removeAll(rightChildCriteria[0]);
            criteriaInfo[1].removeAll(rightChildCriteria[1]);
        } else if (node.getSubqueryContainers().isEmpty()) {
            if (!node.hasBooleanProperty(NodeConstants.Info.IS_COPIED)) {
                toCopy.addAll(combinedCriteria);
            }
            allCriteria.addAll(joinCrits);
        }
        return changedTree;
    }
    changedTree = visitChildern(node, criteriaInfo, changedTree, metadata, underAccess);
    // visit select nodes on the way back up
    switch(node.getType()) {
        case NodeConstants.Types.SELECT:
            {
                if (criteriaInfo[0] != null) {
                    visitSelectNode(node, criteriaInfo[0], criteriaInfo[1]);
                }
                break;
            }
        // clear the criteria when hitting the following
        case NodeConstants.Types.NULL:
        case NodeConstants.Types.SOURCE:
        case NodeConstants.Types.GROUP:
        case NodeConstants.Types.SET_OP:
        case NodeConstants.Types.PROJECT:
            {
                if (criteriaInfo[0] == null) {
                    criteriaInfo[0] = new LinkedHashSet<Criteria>();
                    criteriaInfo[1] = new LinkedHashSet<Criteria>();
                } else {
                    criteriaInfo[0].clear();
                    criteriaInfo[1].clear();
                }
                break;
            }
    }
    return changedTree;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) LinkedHashSet(java.util.LinkedHashSet) Set(java.util.Set) JoinType(org.teiid.query.sql.lang.JoinType) IsNullCriteria(org.teiid.query.sql.lang.IsNullCriteria) Criteria(org.teiid.query.sql.lang.Criteria) CompareCriteria(org.teiid.query.sql.lang.CompareCriteria) LinkedList(java.util.LinkedList) Expression(org.teiid.query.sql.symbol.Expression) LinkedList(java.util.LinkedList) List(java.util.List)

Example 32 with Criteria

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

the class RuleCopyCriteria method buildElementMap.

/**
 * Construct a mapping of element symbol to value map based upon equality CompareCriteria in crits
 *
 * @param crits
 * @param newJoinCrits
 * @param metadata
 * @return
 */
Map<Expression, Expression> buildElementMap(Collection<Criteria> crits, List<Criteria> newJoinCrits, Set<Criteria> allCriteria, QueryMetadataInterface metadata, boolean underAccess) {
    Map<Expression, Expression> srcToTgt = null;
    for (Iterator<Criteria> iter = crits.iterator(); iter.hasNext(); ) {
        Criteria theCrit = iter.next();
        if (theCrit instanceof IsNullCriteria) {
            IsNullCriteria isNull = (IsNullCriteria) theCrit;
            if (!isNull.isNegated() && isNull.getExpression() instanceof ElementSymbol) {
                if (srcToTgt == null) {
                    srcToTgt = new HashMap<Expression, Expression>();
                }
                srcToTgt.put(isNull.getExpression(), new Constant(null, isNull.getExpression().getType()));
            }
            continue;
        }
        if (!(theCrit instanceof CompareCriteria)) {
            continue;
        }
        CompareCriteria crit = (CompareCriteria) theCrit;
        if (crit.getOperator() == CompareCriteria.EQ) {
            if (srcToTgt == null) {
                srcToTgt = new HashMap<Expression, Expression>();
            }
            Expression oldValue = srcToTgt.put(crit.getLeftExpression(), crit.getRightExpression());
            boolean removed = false;
            if (checkWithinJoin(crit, newJoinCrits, allCriteria, oldValue, crit.getRightExpression(), metadata, underAccess)) {
                iter.remove();
                removed = true;
            }
            oldValue = srcToTgt.put(crit.getRightExpression(), crit.getLeftExpression());
            if (checkWithinJoin(crit, newJoinCrits, allCriteria, oldValue, crit.getLeftExpression(), metadata, underAccess) && !removed) {
                iter.remove();
            }
        }
    }
    if (srcToTgt == null) {
        return Collections.emptyMap();
    }
    return srcToTgt;
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) Expression(org.teiid.query.sql.symbol.Expression) Constant(org.teiid.query.sql.symbol.Constant) 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) IsNullCriteria(org.teiid.query.sql.lang.IsNullCriteria)

Example 33 with Criteria

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

the class RuleDecomposeJoin method buildUnion.

private PlanNode buildUnion(PlanNode unionNode, PlanNode otherSide, List<Criteria> criteria, List<int[]> matches, List<PlanNode> branches, List<PlanNode> otherBranches, JoinType joinType) {
    SymbolMap symbolMap = (SymbolMap) unionNode.getParent().getProperty(Info.SYMBOL_MAP);
    SymbolMap otherSymbolMap = (SymbolMap) otherSide.getProperty(Info.SYMBOL_MAP);
    List<PlanNode> joins = new LinkedList<PlanNode>();
    for (int i = 0; i < matches.size(); i++) {
        int[] is = matches.get(i);
        PlanNode branch = branches.get(is[0]);
        PlanNode branchSource = createSource(unionNode.getParent().getGroups().iterator().next(), branch, symbolMap);
        PlanNode otherBranch = otherBranches.get(is[1]);
        PlanNode otherBranchSource = createSource(otherSide.getGroups().iterator().next(), otherBranch, otherSymbolMap);
        PlanNode newJoinNode = NodeFactory.getNewNode(NodeConstants.Types.JOIN);
        newJoinNode.addLastChild(branchSource);
        newJoinNode.addLastChild(otherBranchSource);
        newJoinNode.setProperty(Info.JOIN_STRATEGY, JoinStrategyType.NESTED_LOOP);
        newJoinNode.setProperty(Info.JOIN_TYPE, joinType);
        newJoinNode.setProperty(Info.JOIN_CRITERIA, LanguageObject.Util.deepClone(criteria, Criteria.class));
        newJoinNode.addGroups(branchSource.getGroups());
        newJoinNode.addGroups(otherBranchSource.getGroups());
        PlanNode projectPlanNode = NodeFactory.getNewNode(NodeConstants.Types.PROJECT);
        newJoinNode.addAsParent(projectPlanNode);
        Select allSymbols = new Select(symbolMap.getKeys());
        allSymbols.addSymbols(otherSymbolMap.getKeys());
        if (i == 0) {
            QueryRewriter.makeSelectUnique(allSymbols, false);
        }
        projectPlanNode.setProperty(NodeConstants.Info.PROJECT_COLS, allSymbols.getSymbols());
        projectPlanNode.addGroups(newJoinNode.getGroups());
        joins.add(projectPlanNode);
    }
    PlanNode newUnion = RulePlanUnions.buildUnionTree(unionNode, joins);
    return newUnion;
}
Also used : PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) Select(org.teiid.query.sql.lang.Select) SymbolMap(org.teiid.query.sql.util.SymbolMap) Criteria(org.teiid.query.sql.lang.Criteria) LinkedList(java.util.LinkedList)

Example 34 with Criteria

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

the class RuleDecomposeJoin method decomposeJoin.

public PlanNode decomposeJoin(PlanNode joinNode, PlanNode root, QueryMetadataInterface metadata, CommandContext context) throws TeiidComponentException, QueryPlannerException {
    if (joinNode.getParent() == null) {
        // already processed
        return root;
    }
    JoinType joinType = (JoinType) joinNode.getProperty(Info.JOIN_TYPE);
    if (joinType == JoinType.JOIN_ANTI_SEMI || joinType == JoinType.JOIN_CROSS) {
        return root;
    }
    PlanNode left = joinNode.getFirstChild();
    while (left.getType() != NodeConstants.Types.SOURCE) {
        if (left.getType() == NodeConstants.Types.SELECT && left.hasBooleanProperty(Info.IS_PHANTOM)) {
            left = left.getFirstChild();
        } else {
            return root;
        }
    }
    Map<ElementSymbol, List<Set<Constant>>> partitionInfo = (Map<ElementSymbol, List<Set<Constant>>>) left.getProperty(Info.PARTITION_INFO);
    if (partitionInfo == null) {
        return root;
    }
    PlanNode unionNode = left.getFirstChild();
    if (unionNode.getType() != NodeConstants.Types.SET_OP) {
        return root;
    }
    PlanNode right = joinNode.getLastChild();
    while (right.getType() != NodeConstants.Types.SOURCE) {
        if (right.getType() == NodeConstants.Types.SELECT && right.hasBooleanProperty(Info.IS_PHANTOM)) {
            right = right.getFirstChild();
        } else {
            return root;
        }
    }
    Map<ElementSymbol, List<Set<Constant>>> rightPartionInfo = (Map<ElementSymbol, List<Set<Constant>>>) right.getProperty(Info.PARTITION_INFO);
    if (rightPartionInfo == null) {
        return root;
    }
    List<Criteria> criteria = (List<Criteria>) joinNode.getProperty(Info.JOIN_CRITERIA);
    List<Expression> expr = new ArrayList<Expression>();
    List<Expression> exprOther = new ArrayList<Expression>();
    RuleChooseJoinStrategy.separateCriteria(unionNode.getParent().getGroups(), right.getGroups(), expr, exprOther, criteria, new LinkedList<Criteria>());
    // if implicit, we assume that partitions match
    ElementSymbol es = getImplicitPartitionColumn(metadata, left);
    ElementSymbol esOther = getImplicitPartitionColumn(metadata, right);
    if (es != null && esOther != null && getEffectiveModelId(metadata, es.getGroupSymbol()) == getEffectiveModelId(metadata, esOther.getGroupSymbol())) {
        expr.add(es);
        exprOther.add(esOther);
    }
    if (expr.isEmpty()) {
        // no equi-join
        return root;
    }
    List<int[]> matches = findMatches(partitionInfo, rightPartionInfo, expr, exprOther);
    if (matches == null) {
        // no non-overlapping partitions
        return root;
    }
    int branchSize = partitionInfo.values().iterator().next().size();
    int otherBranchSize = rightPartionInfo.values().iterator().next().size();
    if (matches.isEmpty()) {
        if (joinType == JoinType.JOIN_INNER || joinType == JoinType.JOIN_SEMI) {
            // no matches mean that we can just insert a null node (false criteria) and be done with it
            PlanNode critNode = NodeFactory.getNewNode(NodeConstants.Types.SELECT);
            critNode.setProperty(Info.SELECT_CRITERIA, QueryRewriter.FALSE_CRITERIA);
            unionNode.addAsParent(critNode);
        } else if (joinType == JoinType.JOIN_LEFT_OUTER) {
            joinNode.getParent().replaceChild(joinNode, left);
        } else if (joinType == JoinType.JOIN_FULL_OUTER) {
            joinNode.setProperty(Info.JOIN_CRITERIA, QueryRewriter.FALSE_CRITERIA);
        }
        return root;
    }
    List<PlanNode> branches = new ArrayList<PlanNode>();
    // TODO: find union children from RulePushAggregates
    RulePushSelectCriteria.collectUnionChildren(unionNode, branches);
    if (branches.size() != branchSize) {
        // sanity check
        return root;
    }
    List<PlanNode> otherBranches = new ArrayList<PlanNode>();
    RulePushSelectCriteria.collectUnionChildren(right.getFirstChild(), otherBranches);
    if (otherBranches.size() != otherBranchSize) {
        // sanity check
        return root;
    }
    PlanNode newUnion = buildUnion(unionNode, right, criteria, matches, branches, otherBranches, joinType);
    GroupSymbol leftGroup = left.getGroups().iterator().next();
    PlanNode view = rebuild(leftGroup, joinNode, newUnion, metadata, context, left, right);
    // preserve the model of the virtual group as we'll look for this when checking for implicit behavior
    ((TempMetadataID) (view.getGroups().iterator().next().getMetadataID())).getTableData().setModel(getEffectiveModelId(metadata, leftGroup));
    SymbolMap symbolmap = (SymbolMap) view.getProperty(Info.SYMBOL_MAP);
    HashMap<ElementSymbol, List<Set<Constant>>> newPartitionInfo = new LinkedHashMap<ElementSymbol, List<Set<Constant>>>();
    Map<Expression, ElementSymbol> inverse = symbolmap.inserseMapping();
    for (int[] match : matches) {
        updatePartitionInfo(partitionInfo, matches, inverse, newPartitionInfo, match[0]);
        updatePartitionInfo(rightPartionInfo, matches, inverse, newPartitionInfo, match[1]);
    }
    view.setProperty(Info.PARTITION_INFO, newPartitionInfo);
    // since we've created a new union node, there's a chance we can decompose again
    if (view.getParent().getType() == NodeConstants.Types.JOIN) {
        return decomposeJoin(view.getParent(), root, metadata, context);
    }
    return root;
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) Set(java.util.Set) Constant(org.teiid.query.sql.symbol.Constant) ArrayList(java.util.ArrayList) JoinType(org.teiid.query.sql.lang.JoinType) SymbolMap(org.teiid.query.sql.util.SymbolMap) Criteria(org.teiid.query.sql.lang.Criteria) LinkedHashMap(java.util.LinkedHashMap) 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) LinkedList(java.util.LinkedList) List(java.util.List) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) SymbolMap(org.teiid.query.sql.util.SymbolMap)

Example 35 with Criteria

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

the class PartitionAnalyzer method extractPartitionInfo.

private static Map<ElementSymbol, Set<Constant>> extractPartitionInfo(Query query, List<ElementSymbol> projectedSymbols) {
    List<Expression> projected = query.getSelect().getProjectedSymbols();
    List<Criteria> crits = Criteria.separateCriteriaByAnd(query.getCriteria());
    Map<Expression, Set<Constant>> inMap = new HashMap<Expression, Set<Constant>>();
    for (Criteria criteria : crits) {
        if (criteria instanceof CompareCriteria) {
            CompareCriteria cc = (CompareCriteria) criteria;
            if (cc.getOperator() != CompareCriteria.EQ) {
                continue;
            }
            if (cc.getLeftExpression() instanceof Constant) {
                inMap.put(cc.getRightExpression(), new HashSet<Constant>(Arrays.asList((Constant) cc.getLeftExpression())));
            } else if (cc.getRightExpression() instanceof Constant) {
                inMap.put(cc.getLeftExpression(), new HashSet<Constant>(Arrays.asList((Constant) cc.getRightExpression())));
            }
            continue;
        }
        if (!(criteria instanceof SetCriteria)) {
            continue;
        }
        SetCriteria sc = (SetCriteria) criteria;
        HashSet<Constant> values = new HashSet<Constant>();
        boolean allConstants = true;
        for (Expression exp : (Collection<Expression>) sc.getValues()) {
            if (exp instanceof Constant) {
                values.add((Constant) exp);
            } else {
                allConstants = false;
                break;
            }
        }
        if (allConstants) {
            inMap.put(sc.getExpression(), values);
        }
    }
    Map<ElementSymbol, Set<Constant>> result = new HashMap<ElementSymbol, Set<Constant>>();
    for (int i = 0; i < projected.size(); i++) {
        Expression ex = SymbolMap.getExpression(projected.get(i));
        if (DataTypeManager.isNonComparable(DataTypeManager.getDataTypeName(ex.getType()))) {
            continue;
        }
        if (ex instanceof Constant) {
            result.put(projectedSymbols.get(i), Collections.singleton((Constant) ex));
        } else {
            Set<Constant> values = inMap.get(ex);
            if (values != null) {
                result.put(projectedSymbols.get(i), values);
            }
        }
    }
    return result;
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) Constant(org.teiid.query.sql.symbol.Constant) Criteria(org.teiid.query.sql.lang.Criteria) CompareCriteria(org.teiid.query.sql.lang.CompareCriteria) SetCriteria(org.teiid.query.sql.lang.SetCriteria) CompareCriteria(org.teiid.query.sql.lang.CompareCriteria) Expression(org.teiid.query.sql.symbol.Expression) SetCriteria(org.teiid.query.sql.lang.SetCriteria)

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