Search in sources :

Example 46 with SymbolMap

use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.

the class FrameUtil method convertNode.

// If newGroup == null, this will be performing a straight symbol swap - that is,
// an oldGroup is undergoing a name change and that is the only difference in the
// symbols.  In that case, some additional work can be done because we can assume
// that an oldElement isn't being replaced by an expression using elements from
// multiple new groups.
static void convertNode(PlanNode node, GroupSymbol oldGroup, Set<GroupSymbol> newGroups, Map symbolMap, QueryMetadataInterface metadata, boolean rewrite) throws QueryPlannerException {
    if (node.getType() == NodeConstants.Types.GROUP) {
        correctSymbolMap(symbolMap, node);
    }
    // Convert expressions from correlated subquery references;
    List<SymbolMap> refMaps = node.getAllReferences();
    LinkedList<Expression> correlatedExpression = new LinkedList<Expression>();
    for (SymbolMap refs : refMaps) {
        for (Map.Entry<ElementSymbol, Expression> ref : refs.asUpdatableMap().entrySet()) {
            Expression expr = ref.getValue();
            Expression convertedExpr = convertExpression(expr, symbolMap);
            ref.setValue(convertedExpr);
            correlatedExpression.add(convertedExpr);
        }
    }
    // Update groups for current node
    Set<GroupSymbol> groups = node.getGroups();
    boolean hasOld = groups.remove(oldGroup);
    int type = node.getType();
    boolean singleMapping = newGroups != null && newGroups.size() == 1;
    if (singleMapping) {
        if (!hasOld) {
            return;
        }
        groups.addAll(newGroups);
    } else if ((type & (NodeConstants.Types.ACCESS | NodeConstants.Types.JOIN | NodeConstants.Types.SOURCE)) == type) {
        if (newGroups != null) {
            groups.addAll(newGroups);
        }
    } else {
        groups.clear();
    }
    groups.addAll(GroupsUsedByElementsVisitor.getGroups(correlatedExpression));
    if (type == NodeConstants.Types.SELECT) {
        Criteria crit = (Criteria) node.getProperty(NodeConstants.Info.SELECT_CRITERIA);
        crit = convertCriteria(crit, symbolMap, metadata, rewrite);
        node.setProperty(NodeConstants.Info.SELECT_CRITERIA, crit);
        if (!singleMapping) {
            GroupsUsedByElementsVisitor.getGroups(crit, groups);
        }
    } else if (type == NodeConstants.Types.PROJECT) {
        List<Expression> projectedSymbols = (List<Expression>) node.getProperty(NodeConstants.Info.PROJECT_COLS);
        Select select = new Select(projectedSymbols);
        ExpressionMappingVisitor.mapExpressions(select, symbolMap);
        if (rewrite) {
            for (LanguageObject expr : select.getSymbols()) {
                rewriteSingleElementSymbol(metadata, (Expression) expr);
            }
        }
        node.setProperty(NodeConstants.Info.PROJECT_COLS, select.getSymbols());
        if (!singleMapping) {
            GroupsUsedByElementsVisitor.getGroups(select, groups);
        }
    } else if (type == NodeConstants.Types.JOIN) {
        // Convert join criteria property
        List<Criteria> joinCrits = (List<Criteria>) node.getProperty(NodeConstants.Info.JOIN_CRITERIA);
        if (joinCrits != null && !joinCrits.isEmpty()) {
            Criteria crit = new CompoundCriteria(joinCrits);
            crit = convertCriteria(crit, symbolMap, metadata, rewrite);
            if (crit instanceof CompoundCriteria && ((CompoundCriteria) crit).getOperator() == CompoundCriteria.AND) {
                node.setProperty(NodeConstants.Info.JOIN_CRITERIA, ((CompoundCriteria) crit).getCriteria());
            } else {
                joinCrits = new ArrayList<Criteria>();
                joinCrits.add(crit);
                node.setProperty(NodeConstants.Info.JOIN_CRITERIA, joinCrits);
            }
        }
        convertAccessPatterns(symbolMap, node);
    } else if (type == NodeConstants.Types.SORT) {
        OrderBy orderBy = (OrderBy) node.getProperty(NodeConstants.Info.SORT_ORDER);
        ExpressionMappingVisitor.mapExpressions(orderBy, symbolMap);
        if (rewrite) {
            for (OrderByItem item : orderBy.getOrderByItems()) {
                rewriteSingleElementSymbol(metadata, item.getSymbol());
            }
        }
        if (!singleMapping) {
            GroupsUsedByElementsVisitor.getGroups(orderBy, groups);
        }
    } else if (type == NodeConstants.Types.GROUP) {
        List<Expression> groupCols = (List<Expression>) node.getProperty(NodeConstants.Info.GROUP_COLS);
        if (groupCols != null) {
            GroupBy groupBy = new GroupBy(groupCols);
            ExpressionMappingVisitor.mapExpressions(groupBy, symbolMap);
            node.setProperty(NodeConstants.Info.GROUP_COLS, groupBy.getSymbols());
            if (!singleMapping) {
                GroupsUsedByElementsVisitor.getGroups(groupBy, groups);
            }
        }
        if (!singleMapping) {
            // add back the anon group
            SymbolMap property = (SymbolMap) node.getProperty(Info.SYMBOL_MAP);
            if (!property.asMap().isEmpty()) {
                groups.add(property.asMap().keySet().iterator().next().getGroupSymbol());
            }
        }
    } else if (type == NodeConstants.Types.SOURCE || type == NodeConstants.Types.ACCESS) {
        convertAccessPatterns(symbolMap, node);
    }
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) OrderBy(org.teiid.query.sql.lang.OrderBy) GroupBy(org.teiid.query.sql.lang.GroupBy) SymbolMap(org.teiid.query.sql.util.SymbolMap) CompoundCriteria(org.teiid.query.sql.lang.CompoundCriteria) Criteria(org.teiid.query.sql.lang.Criteria) OrderByItem(org.teiid.query.sql.lang.OrderByItem) Expression(org.teiid.query.sql.symbol.Expression) CompoundCriteria(org.teiid.query.sql.lang.CompoundCriteria) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) Select(org.teiid.query.sql.lang.Select) SymbolMap(org.teiid.query.sql.util.SymbolMap) LanguageObject(org.teiid.query.sql.LanguageObject)

Example 47 with SymbolMap

use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.

the class FrameUtil method convertFrame.

public static void convertFrame(PlanNode startNode, GroupSymbol oldGroup, Set<GroupSymbol> newGroups, Map symbolMap, QueryMetadataInterface metadata) throws QueryPlannerException {
    PlanNode current = startNode;
    // correct the partition info keys
    if (oldGroup != null && newGroups != null && newGroups.size() == 1 && startNode.getType() == NodeConstants.Types.SOURCE) {
        Map<ElementSymbol, List<Set<Constant>>> partitionInfo = (Map<ElementSymbol, List<Set<Constant>>>) startNode.getProperty(Info.PARTITION_INFO);
        if (partitionInfo != null) {
            startNode.setProperty(Info.PARTITION_INFO, RelationalPlanner.remapPartitionInfo(newGroups.iterator().next(), partitionInfo));
        }
    }
    PlanNode endNode = NodeEditor.findParent(startNode.getType() == NodeConstants.Types.SOURCE ? startNode.getParent() : startNode, NodeConstants.Types.SOURCE);
    boolean rewrite = false;
    if (newGroups != null && newGroups.size() == 1) {
        for (Expression expression : (Collection<Expression>) symbolMap.values()) {
            if (!(expression instanceof ElementSymbol)) {
                rewrite = true;
                break;
            }
        }
    } else {
        rewrite = true;
    }
    while (current != endNode) {
        // Make translations as defined in node in each current node
        convertNode(current, oldGroup, newGroups, symbolMap, metadata, rewrite);
        PlanNode parent = current.getParent();
        // check if this is not the first set op branch
        if (parent != null && parent.getType() == NodeConstants.Types.SET_OP && parent.getFirstChild() != current) {
            return;
        }
        // Move up the tree
        current = parent;
    }
    if (endNode == null) {
        return;
    }
    correctSymbolMap(symbolMap, endNode);
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) Expression(org.teiid.query.sql.symbol.Expression) Constant(org.teiid.query.sql.symbol.Constant) SymbolMap(org.teiid.query.sql.util.SymbolMap)

Example 48 with SymbolMap

use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.

the class FrameUtil method canConvertAccessPatterns.

static boolean canConvertAccessPatterns(PlanNode sourceNode) {
    List<AccessPattern> accessPatterns = (List) sourceNode.getProperty(NodeConstants.Info.ACCESS_PATTERNS);
    if (accessPatterns == null) {
        return true;
    }
    SymbolMap symbolMap = (SymbolMap) sourceNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
    for (Iterator<AccessPattern> i = accessPatterns.iterator(); i.hasNext(); ) {
        AccessPattern ap = i.next();
        for (Iterator<ElementSymbol> elems = ap.getUnsatisfied().iterator(); elems.hasNext(); ) {
            ElementSymbol symbol = elems.next();
            Expression mapped = convertExpression(symbol, symbolMap.asMap());
            if (ElementCollectorVisitor.getElements(mapped, true).isEmpty()) {
                return false;
            }
        }
    }
    return true;
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) AccessPattern(org.teiid.query.resolver.util.AccessPattern) Expression(org.teiid.query.sql.symbol.Expression) SymbolMap(org.teiid.query.sql.util.SymbolMap)

Example 49 with SymbolMap

use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.

the class RuleAssignOutputElements method determineSourceOutput.

/**
 * A special case to consider is when the virtual group is defined by a
 * UNION (no ALL) or a SELECT DISTINCT.  In this case, the dup removal means
 * that all columns need to be used to determine duplicates.  So, filtering the
 * columns at all will alter the number of rows flowing through the frame.
 * So, in this case filtering should not occur.  In fact the output columns
 * that were set on root above are filtered, but we actually want all the
 * virtual elements - so just reset it and proceed as before
 * @throws TeiidComponentException
 * @throws QueryMetadataException
 * @throws QueryPlannerException
 */
static List<? extends Expression> determineSourceOutput(PlanNode root, List<Expression> outputElements, QueryMetadataInterface metadata, CapabilitiesFinder capFinder) throws QueryMetadataException, TeiidComponentException, QueryPlannerException {
    PlanNode virtualRoot = root.getLastChild();
    if (hasDupRemoval(virtualRoot)) {
        // Reset the outputColumns for this source node to be all columns for the virtual group
        SymbolMap symbolMap = (SymbolMap) root.getProperty(NodeConstants.Info.SYMBOL_MAP);
        if (!symbolMap.asMap().keySet().containsAll(outputElements)) {
            outputElements.removeAll(symbolMap.asMap().keySet());
            throw new QueryPlannerException(QueryPlugin.Event.TEIID30259, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30259, outputElements));
        }
        return symbolMap.getKeys();
    }
    PlanNode limit = NodeEditor.findNodePreOrder(root, NodeConstants.Types.TUPLE_LIMIT, NodeConstants.Types.PROJECT);
    if (limit == null) {
        return outputElements;
    }
    // reset the output elements to be the output columns + what's required by the sort
    PlanNode sort = NodeEditor.findNodePreOrder(limit, NodeConstants.Types.SORT, NodeConstants.Types.PROJECT);
    if (sort == null) {
        return outputElements;
    }
    PlanNode access = NodeEditor.findParent(sort, NodeConstants.Types.ACCESS);
    if (sort.hasBooleanProperty(NodeConstants.Info.UNRELATED_SORT) || (access != null && capFinder != null && CapabilitiesUtil.supports(Capability.QUERY_ORDERBY_UNRELATED, RuleRaiseAccess.getModelIDFromAccess(access, metadata), metadata, capFinder))) {
        return outputElements;
    }
    OrderBy sortOrder = (OrderBy) sort.getProperty(NodeConstants.Info.SORT_ORDER);
    List<Expression> topCols = FrameUtil.findTopCols(sort);
    SymbolMap symbolMap = (SymbolMap) root.getProperty(NodeConstants.Info.SYMBOL_MAP);
    List<ElementSymbol> symbolOrder = symbolMap.getKeys();
    for (OrderByItem item : sortOrder.getOrderByItems()) {
        final Expression expr = item.getSymbol();
        int index = topCols.indexOf(expr);
        if (index < 0) {
            continue;
        }
        ElementSymbol symbol = symbolOrder.get(index);
        if (!outputElements.contains(symbol)) {
            outputElements.add(symbol);
        }
    }
    return outputElements;
}
Also used : OrderBy(org.teiid.query.sql.lang.OrderBy) ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) OrderByItem(org.teiid.query.sql.lang.OrderByItem) Expression(org.teiid.query.sql.symbol.Expression) SymbolMap(org.teiid.query.sql.util.SymbolMap) QueryPlannerException(org.teiid.api.exception.query.QueryPlannerException)

Example 50 with SymbolMap

use of org.teiid.query.sql.util.SymbolMap in project teiid by teiid.

the class TriggerActionPlanner method rewritePlan.

/**
 * look for the simple case of a mapping to a single insert statement trigger action - and reconstruct the plan as a single insert
 * TODO: need internal primitives for delete/update batching in a loop for delete/update cases
 */
private ProcessorPlan rewritePlan(TriggerAction ta, IDGenerator idGenerator, QueryMetadataInterface metadata, CapabilitiesFinder capFinder, AnalysisRecord analysisRecord, CommandContext context, QueryCommand query, Map<ElementSymbol, Expression> mapping, Insert insert) throws QueryMetadataException, QueryResolverException, TeiidComponentException, QueryPlannerException {
    if (ta.getBlock().getStatements().size() != 1) {
        return null;
    }
    Statement s = ta.getBlock().getStatements().get(0);
    if (!(s instanceof CommandStatement)) {
        return null;
    }
    CommandStatement cs = (CommandStatement) s;
    if (!(cs.getCommand() instanceof Insert)) {
        return null;
    }
    Insert mapped = (Insert) cs.getCommand();
    if (mapped.getQueryExpression() != null) {
        return null;
    }
    if (insert.getQueryExpression() != null) {
        // use a unique inline view name to make the final remapping easier
        GroupSymbol group = new GroupSymbol("X");
        Collection<GroupSymbol> groups = GroupCollectorVisitor.getGroups(query, true);
        for (int i = 0; groups.contains(group); i++) {
            group.setName("X_" + i);
        }
        List<Expression> projectedSymbols = query.getProjectedSymbols();
        Query queryExpression = QueryRewriter.createInlineViewQuery(group, query, metadata, projectedSymbols);
        List<Expression> viewSymbols = new ArrayList<Expression>(queryExpression.getSelect().getSymbols());
        // switch to the values
        queryExpression.getSelect().clearSymbols();
        List<Expression> values = mapped.getValues();
        queryExpression.getSelect().addSymbols(values);
        values.clear();
        // update the mapping to the view symbols
        for (int i = 0; i < projectedSymbols.size(); i++) {
            ElementSymbol es = insert.getVariables().get(i);
            mapping.put(new ElementSymbol(es.getShortName(), new GroupSymbol(SQLConstants.Reserved.NEW)), SymbolMap.getExpression(viewSymbols.get(i)));
        }
        // map to the query form - changes references back to element form
        SymbolMap queryMapping = new SymbolMap();
        queryMapping.asUpdatableMap().putAll(mapping);
        ExpressionMappingVisitor visitor = new RuleMergeCriteria.ReferenceReplacementVisitor(queryMapping);
        DeepPostOrderNavigator.doVisit(queryExpression.getSelect(), visitor);
        // now we can return a plan based off a single insert statement
        mapped.setQueryExpression(queryExpression);
        return QueryOptimizer.optimizePlan(mapped, metadata, idGenerator, capFinder, analysisRecord, context);
    }
    List<Expression> values = mapped.getValues();
    SymbolMap queryMapping = new SymbolMap();
    queryMapping.asUpdatableMap().putAll(mapping);
    ExpressionMappingVisitor visitor = new RuleMergeCriteria.ReferenceReplacementVisitor(queryMapping);
    Select select = new Select();
    select.addSymbols(values);
    DeepPostOrderNavigator.doVisit(select, visitor);
    values.clear();
    for (Expression ex : select.getSymbols()) {
        try {
            values.add(QueryRewriter.rewriteExpression(SymbolMap.getExpression(ex), context, metadata));
        } catch (TeiidProcessingException e) {
            throw new QueryPlannerException(e);
        }
    }
    return QueryOptimizer.optimizePlan(mapped, metadata, idGenerator, capFinder, analysisRecord, context);
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) CommandStatement(org.teiid.query.sql.proc.CommandStatement) Statement(org.teiid.query.sql.proc.Statement) ArrayList(java.util.ArrayList) SymbolMap(org.teiid.query.sql.util.SymbolMap) ExpressionMappingVisitor(org.teiid.query.sql.visitor.ExpressionMappingVisitor) TeiidProcessingException(org.teiid.core.TeiidProcessingException) CommandStatement(org.teiid.query.sql.proc.CommandStatement) Expression(org.teiid.query.sql.symbol.Expression) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) QueryPlannerException(org.teiid.api.exception.query.QueryPlannerException)

Aggregations

SymbolMap (org.teiid.query.sql.util.SymbolMap)56 PlanNode (org.teiid.query.optimizer.relational.plantree.PlanNode)37 ElementSymbol (org.teiid.query.sql.symbol.ElementSymbol)28 Expression (org.teiid.query.sql.symbol.Expression)28 GroupSymbol (org.teiid.query.sql.symbol.GroupSymbol)21 ArrayList (java.util.ArrayList)16 List (java.util.List)15 Criteria (org.teiid.query.sql.lang.Criteria)10 LinkedList (java.util.LinkedList)8 Map (java.util.Map)8 HashMap (java.util.HashMap)6 Constant (org.teiid.query.sql.symbol.Constant)6 LinkedHashSet (java.util.LinkedHashSet)5 QueryPlannerException (org.teiid.api.exception.query.QueryPlannerException)5 CompareCriteria (org.teiid.query.sql.lang.CompareCriteria)5 OrderBy (org.teiid.query.sql.lang.OrderBy)5 HashSet (java.util.HashSet)4 ExpressionMappingVisitor (org.teiid.query.sql.visitor.ExpressionMappingVisitor)4 LinkedHashMap (java.util.LinkedHashMap)3 Set (java.util.Set)3