Search in sources :

Example 16 with SymbolMap

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

the class RuleAssignOutputElements method removeGroupBy.

static PlanNode removeGroupBy(PlanNode root, QueryMetadataInterface metadata) throws QueryPlannerException {
    PlanNode next = root.getFirstChild();
    NodeEditor.removeChildNode(root.getParent(), root);
    SymbolMap symbolMap = (SymbolMap) root.getProperty(NodeConstants.Info.SYMBOL_MAP);
    if (!symbolMap.asMap().isEmpty()) {
        FrameUtil.convertFrame(next.getParent(), symbolMap.asMap().keySet().iterator().next().getGroupSymbol(), null, symbolMap.asMap(), metadata);
    }
    PlanNode parent = next.getParent();
    while (parent.getParent() != null && parent.getParent().getType() != NodeConstants.Types.SOURCE && parent.getParent().getType() != NodeConstants.Types.SET_OP) {
        parent = parent.getParent();
    }
    return parent;
}
Also used : PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) SymbolMap(org.teiid.query.sql.util.SymbolMap)

Example 17 with SymbolMap

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

the class RuleAssignOutputElements method filterVirtualElements.

/**
 * <p>This method looks at a source node, which defines a virtual group, and filters the
 * virtual elements defined by the group down into just the output elements needed
 * by that source node.  This means, for instance, that the PROJECT node at the top
 * of the virtual group might need to have some elements removed from the project as
 * those elements are no longer needed.  </p>
 *
 * <p>One special case that is handled here is when a virtual group is defined by
 * a UNION ALL.  In this case, the various branches of the union have elements defined
 * and filtering must occur identically in all branches of the union.  </p>
 *
 * @param sourceNode Node to filter
 * @param metadata Metadata implementation
 * @return The filtered list of columns for this node (used in recursing tree)
 * @throws QueryPlannerException
 */
static List<Expression> filterVirtualElements(PlanNode sourceNode, List<Expression> outputColumns, QueryMetadataInterface metadata) throws QueryPlannerException {
    PlanNode virtualRoot = sourceNode.getLastChild();
    // Update project cols - typically there is exactly one and that node can
    // just get the filteredCols determined above.  In the case of one or more
    // nested set operations (UNION, INTERSECT, EXCEPT) there will be 2 or more
    // projects.
    List<PlanNode> allProjects = NodeEditor.findAllNodes(virtualRoot, NodeConstants.Types.PROJECT, NodeConstants.Types.PROJECT);
    int[] filteredIndex = new int[outputColumns.size()];
    Arrays.fill(filteredIndex, -1);
    SymbolMap symbolMap = (SymbolMap) sourceNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
    List<ElementSymbol> originalOrder = symbolMap.getKeys();
    boolean updateGroups = outputColumns.size() != originalOrder.size();
    boolean[] seenIndex = new boolean[outputColumns.size()];
    boolean newSymbols = false;
    int newSymbolIndex = 0;
    for (int i = 0; i < outputColumns.size(); i++) {
        Expression expr = outputColumns.get(i);
        filteredIndex[i] = originalOrder.indexOf(expr);
        if (filteredIndex[i] == -1) {
            updateGroups = true;
            // we're adding this symbol, which needs to be updated against respective symbol maps
            newSymbols = true;
        } else {
            newSymbolIndex++;
        }
        if (!updateGroups) {
            seenIndex[filteredIndex[i]] = true;
        }
    }
    if (!updateGroups) {
        for (boolean b : seenIndex) {
            if (!b) {
                updateGroups = true;
                break;
            }
        }
    }
    List<Expression> newCols = null;
    for (int i = allProjects.size() - 1; i >= 0; i--) {
        PlanNode projectNode = allProjects.get(i);
        List<Expression> projectCols = (List<Expression>) projectNode.getProperty(NodeConstants.Info.PROJECT_COLS);
        newCols = RelationalNode.projectTuple(filteredIndex, projectCols, true);
        if (newSymbols) {
            SymbolMap childMap = SymbolMap.createSymbolMap(symbolMap.getKeys(), projectCols);
            for (int j = 0; j < filteredIndex.length; j++) {
                if (filteredIndex[j] != -1) {
                    continue;
                }
                Expression ex = (Expression) outputColumns.get(j).clone();
                ExpressionMappingVisitor.mapExpressions(ex, childMap.asMap());
                newCols.set(j, ex);
                if (i == 0) {
                    filteredIndex[j] = newSymbolIndex++;
                }
            }
        }
        projectNode.setProperty(NodeConstants.Info.PROJECT_COLS, newCols);
        if (updateGroups) {
            projectNode.getGroups().clear();
            projectNode.addGroups(GroupsUsedByElementsVisitor.getGroups(newCols));
            projectNode.addGroups(GroupsUsedByElementsVisitor.getGroups(projectNode.getCorrelatedReferenceElements()));
        }
    }
    if (!updateGroups) {
        for (int i : filteredIndex) {
            if (i != filteredIndex[i]) {
                updateGroups = true;
                break;
            }
        }
    }
    if (updateGroups) {
        SymbolMap newMap = new SymbolMap();
        List<Expression> originalExpressionOrder = symbolMap.getValues();
        for (int i = 0; i < filteredIndex.length; i++) {
            if (filteredIndex[i] < originalOrder.size()) {
                newMap.addMapping(originalOrder.get(filteredIndex[i]), originalExpressionOrder.get(filteredIndex[i]));
            }
        // else TODO: we may need to create a fake symbol
        }
        sourceNode.setProperty(NodeConstants.Info.SYMBOL_MAP, newMap);
    }
    // Create output columns for virtual group project
    return newCols;
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) Expression(org.teiid.query.sql.symbol.Expression) SymbolMap(org.teiid.query.sql.util.SymbolMap) List(java.util.List) ArrayList(java.util.ArrayList)

Example 18 with SymbolMap

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

the class RulePushAggregates method createSymbolMap.

static SymbolMap createSymbolMap(GroupSymbol group, List<? extends Expression> virtualElements, PlanNode child, QueryMetadataInterface metadata) throws TeiidComponentException, QueryMetadataException {
    List<ElementSymbol> projectedSymbols = defineNewGroup(group, virtualElements, metadata);
    SymbolMap symbolMap = SymbolMap.createSymbolMap(projectedSymbols, (List<Expression>) NodeEditor.findNodePreOrder(child, NodeConstants.Types.PROJECT).getProperty(NodeConstants.Info.PROJECT_COLS));
    return symbolMap;
}
Also used : SymbolMap(org.teiid.query.sql.util.SymbolMap)

Example 19 with SymbolMap

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

the class RulePushSelectCriteria method pushAcrossGroupBy.

boolean pushAcrossGroupBy(PlanNode sourceNode, PlanNode critNode, QueryMetadataInterface metadata, boolean inPlan, CapabilitiesFinder capFinder) throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
    if (critNode.hasBooleanProperty(NodeConstants.Info.IS_HAVING)) {
        return false;
    }
    if (critNode.hasBooleanProperty(NodeConstants.Info.IS_DEPENDENT_SET)) {
        PlanNode accessNode = NodeEditor.findParent(critNode, NodeConstants.Types.ACCESS);
        if (accessNode != null) {
            List<Expression> cols = (List<Expression>) sourceNode.getProperty(Info.GROUP_COLS);
            if (cols != null) {
                boolean hasExpression = false;
                boolean hasLiteral = false;
                for (final Iterator<Expression> iterator = cols.iterator(); iterator.hasNext(); ) {
                    Expression ex = iterator.next();
                    hasExpression |= !(ex instanceof ElementSymbol);
                    hasLiteral |= EvaluatableVisitor.willBecomeConstant(ex, true);
                }
                if (hasLiteral || (hasExpression && !CapabilitiesUtil.supports(Capability.QUERY_FUNCTIONS_IN_GROUP_BY, RuleRaiseAccess.getModelIDFromAccess(accessNode, metadata), metadata, capFinder))) {
                    markDependent(critNode, accessNode, metadata, capFinder);
                    critNode.setProperty(Info.IS_HAVING, true);
                    return false;
                }
            }
        }
    }
    if (sourceNode.hasBooleanProperty(Info.ROLLUP)) {
        // but instead we'll just clone the node
        if (inPlan) {
            PlanNode copy = copyNode(critNode);
            critNode.setProperty(Info.IS_PUSHED, true);
            critNode.setProperty(Info.IS_HAVING, true);
            critNode.getFirstChild().addAsParent(copy);
            critNode = copy;
        }
    }
    boolean moved = false;
    SymbolMap symbolMap = (SymbolMap) sourceNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
    FrameUtil.convertNode(critNode, null, null, symbolMap.asMap(), metadata, true);
    if (inPlan) {
        NodeEditor.removeChildNode(critNode.getParent(), critNode);
        sourceNode.getFirstChild().addAsParent(critNode);
    }
    moved = true;
    if (critNode.hasBooleanProperty(NodeConstants.Info.IS_DEPENDENT_SET)) {
        PlanNode accessNode = NodeEditor.findParent(critNode, NodeConstants.Types.ACCESS);
        if (accessNode != null) {
            markDependent(critNode, accessNode, metadata, capFinder);
            // terminal position
            moved = false;
        }
    }
    return moved;
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) Expression(org.teiid.query.sql.symbol.Expression) SymbolMap(org.teiid.query.sql.util.SymbolMap)

Example 20 with SymbolMap

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

the class RulePushSelectCriteria method moveNodeAcrossFrame.

Boolean moveNodeAcrossFrame(PlanNode critNode, PlanNode sourceNode, final QueryMetadataInterface metadata) throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
    // Check that sourceNode has a child to push across
    if (sourceNode.getChildCount() == 0) {
        return false;
    }
    final PlanNode projectNode = NodeEditor.findNodePreOrder(sourceNode.getFirstChild(), NodeConstants.Types.PROJECT, NodeConstants.Types.SOURCE);
    if (FrameUtil.isProcedure(projectNode)) {
        return false;
    }
    final SymbolMap symbolMap = (SymbolMap) sourceNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
    final GroupSymbol sourceGroup = sourceNode.getGroups().iterator().next();
    if (!placeConvertedSelectNode(critNode, sourceGroup, projectNode, symbolMap, metadata)) {
        if (createdNodes == null) {
            Criteria crit = (Criteria) critNode.getProperty(NodeConstants.Info.SELECT_CRITERIA);
            if (isMultiAttributeDependentSet(crit) && splitSet(critNode, new DependentNodeTest() {

                @Override
                public boolean isValid(PlanNode copyNode) throws QueryMetadataException, QueryPlannerException, TeiidComponentException {
                    return createConvertedSelectNode(copyNode, sourceGroup, projectNode, symbolMap, metadata) != null;
                }
            }, (DependentSetCriteria) crit, sourceNode)) {
                return null;
            }
        }
        return false;
    }
    if (createdNodes == null) {
        satisfyConditions(critNode, sourceNode, metadata);
    }
    // Mark critNode as a "phantom"
    critNode.setProperty(NodeConstants.Info.IS_PHANTOM, Boolean.TRUE);
    return true;
}
Also used : DependentSetCriteria(org.teiid.query.sql.lang.DependentSetCriteria) PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) SymbolMap(org.teiid.query.sql.util.SymbolMap) 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

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