Search in sources :

Example 6 with WindowFunction

use of org.teiid.query.sql.symbol.WindowFunction in project teiid by teiid.

the class RuleApplySecurity method execute.

@Override
public PlanNode execute(PlanNode plan, QueryMetadataInterface metadata, CapabilitiesFinder capabilitiesFinder, RuleStack rules, AnalysisRecord analysisRecord, CommandContext context) throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
    try {
        for (PlanNode sourceNode : NodeEditor.findAllNodes(plan, NodeConstants.Types.SOURCE)) {
            GroupSymbol group = sourceNode.getGroups().iterator().next();
            if (!RowBasedSecurityHelper.applyRowSecurity(metadata, group, context)) {
                continue;
            }
            List<ElementSymbol> cols = null;
            Command command = (Command) sourceNode.getProperty(Info.VIRTUAL_COMMAND);
            if (group.isProcedure()) {
                if (command == null) {
                    // proc relational, will instead apply at the proc level
                    continue;
                }
                if (cols == null) {
                    cols = (List) command.getProjectedSymbols();
                }
            } else if (command != null && !command.returnsResultSet()) {
                // should be handled in the planner
                continue;
            }
            if (cols == null) {
                cols = ResolverUtil.resolveElementsInGroup(group, metadata);
            }
            // apply masks first
            List<? extends Expression> masked = ColumnMaskingHelper.maskColumns(cols, group, metadata, context);
            Map<ElementSymbol, Expression> mapping = null;
            // TODO: we don't actually allow window function masks yet becuase they won't pass
            // validation.  but if we do, we need to check for them here
            List<WindowFunction> windowFunctions = new ArrayList<WindowFunction>(2);
            for (int i = 0; i < masked.size(); i++) {
                Expression maskedCol = masked.get(i);
                AggregateSymbolCollectorVisitor.getAggregates(maskedCol, null, null, null, windowFunctions, null);
                if (maskedCol.equals(cols.get(i))) {
                    continue;
                }
                if (mapping == null) {
                    mapping = new HashMap<ElementSymbol, Expression>();
                }
                mapping.put(cols.get(i), maskedCol);
            }
            PlanNode parentJoin = NodeEditor.findParent(sourceNode.getParent(), NodeConstants.Types.JOIN, NodeConstants.Types.SOURCE);
            if (mapping != null) {
                // some element symbol has been replaced
                PlanNode project = null;
                if (group.isProcedure()) {
                    project = NodeEditor.findParent(sourceNode, NodeConstants.Types.PROJECT);
                    project.setProperty(NodeConstants.Info.PROJECT_COLS, masked);
                }
                if (windowFunctions.isEmpty() && RuleMergeVirtual.checkProjectedSymbols(group, parentJoin, metadata, masked, Collections.singleton(group), true)) {
                    if (!group.isProcedure()) {
                        // just upwardly project - TODO: we could also handle some subquery simple projection situations here
                        FrameUtil.convertFrame(sourceNode.getParent(), group, Collections.singleton(group), mapping, metadata);
                    }
                } else {
                    if (!group.isProcedure()) {
                        project = RelationalPlanner.createProjectNode(masked);
                    }
                    rules.getPlanner().planSubqueries(sourceNode.getGroups(), project, project.getSubqueryContainers(), true);
                    project.addGroups(GroupsUsedByElementsVisitor.getGroups(project.getCorrelatedReferenceElements()));
                    if (!group.isProcedure()) {
                        // we need to insert a view to give a single place to evaluate the subqueries
                        PlanNode root = sourceNode;
                        if (sourceNode.getParent().getType() == NodeConstants.Types.ACCESS) {
                            root = sourceNode.getParent();
                        }
                        root.addAsParent(project);
                        addView(metadata, context, group, cols, masked, project);
                        parentJoin = null;
                    }
                }
                if (!windowFunctions.isEmpty() && project != null) {
                    project.setProperty(Info.HAS_WINDOW_FUNCTIONS, true);
                }
            }
            // logically filters are applied below masking
            Criteria filter = RowBasedSecurityHelper.getRowBasedFilters(metadata, group, context, false);
            if (filter == null) {
                continue;
            }
            List<Criteria> crits = Criteria.separateCriteriaByAnd(filter);
            PlanNode root = sourceNode;
            if (sourceNode.getParent().getType() == NodeConstants.Types.ACCESS) {
                root = sourceNode.getParent();
            }
            PlanNode parent = null;
            for (Criteria crit : crits) {
                PlanNode critNode = RelationalPlanner.createSelectNode(crit, false);
                if (parent == null) {
                    parent = critNode;
                }
                rules.getPlanner().planSubqueries(sourceNode.getGroups(), critNode, critNode.getSubqueryContainers(), true);
                critNode.addGroups(GroupsUsedByElementsVisitor.getGroups(critNode.getCorrelatedReferenceElements()));
                root.addAsParent(critNode);
            }
            if (!RuleMergeVirtual.checkJoinCriteria(parent, group, parentJoin)) {
                PlanNode project = RelationalPlanner.createProjectNode(cols);
                parent.addAsParent(project);
                // a view is needed to keep the logical placement of the criteria
                addView(metadata, context, group, cols, cols, project);
            }
        }
    } catch (TeiidProcessingException e) {
        throw new QueryPlannerException(e);
    }
    return plan;
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) ArrayList(java.util.ArrayList) Criteria(org.teiid.query.sql.lang.Criteria) TeiidProcessingException(org.teiid.core.TeiidProcessingException) WindowFunction(org.teiid.query.sql.symbol.WindowFunction) PlanNode(org.teiid.query.optimizer.relational.plantree.PlanNode) Command(org.teiid.query.sql.lang.Command) Expression(org.teiid.query.sql.symbol.Expression) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) QueryPlannerException(org.teiid.api.exception.query.QueryPlannerException)

Example 7 with WindowFunction

use of org.teiid.query.sql.symbol.WindowFunction in project teiid by teiid.

the class WindowFunctionProjectNode method init.

/**
 * This state can be determined prior to initialize and is the same for all nodes,
 * so it is moved into it's own init routine
 */
public void init() {
    expressionIndexes = new LinkedHashMap<Expression, Integer>();
    for (int i = 0; i < getElements().size(); i++) {
        Expression ex = SymbolMap.getExpression(getElements().get(i));
        if (ex instanceof WindowFunction) {
            WindowFunction wf = (WindowFunction) ex;
            WindowSpecification ws = wf.getWindowSpecification();
            WindowSpecificationInfo wsi = windows.get(ws);
            if (wsi == null) {
                wsi = new WindowSpecificationInfo();
                windows.put(wf.getWindowSpecification(), wsi);
                if (ws.getPartition() != null) {
                    for (Expression ex1 : ws.getPartition()) {
                        Integer index = GroupingNode.getIndex(ex1, expressionIndexes);
                        wsi.groupIndexes.add(index);
                        wsi.orderType.add(OrderBy.ASC);
                        wsi.nullOrderings.add(null);
                    }
                }
                if (ws.getOrderBy() != null) {
                    for (OrderByItem item : ws.getOrderBy().getOrderByItems()) {
                        Expression ex1 = SymbolMap.getExpression(item.getSymbol());
                        Integer index = GroupingNode.getIndex(ex1, expressionIndexes);
                        wsi.sortIndexes.add(index);
                        wsi.orderType.add(item.isAscending());
                        wsi.nullOrderings.add(item.getNullOrdering());
                    }
                }
            }
            WindowFunctionInfo wfi = new WindowFunctionInfo();
            wfi.function = wf;
            // collect the agg expressions
            for (Expression e : wf.getFunction().getArgs()) {
                GroupingNode.getIndex(e, expressionIndexes);
            }
            if (wf.getFunction().getOrderBy() != null) {
                for (OrderByItem item : wf.getFunction().getOrderBy().getOrderByItems()) {
                    GroupingNode.getIndex(item.getSymbol(), expressionIndexes);
                }
            }
            if (wf.getFunction().getCondition() != null) {
                GroupingNode.getIndex(wf.getFunction().getCondition(), expressionIndexes);
            }
            wfi.outputIndex = i;
            if (wf.getFunction().isRowValueFunction()) {
                wsi.rowValuefunctions.add(wfi);
            } else {
                wsi.functions.add(wfi);
            }
        } else {
            int index = GroupingNode.getIndex(ex, expressionIndexes);
            passThrough.add(new int[] { i, index });
        }
    }
}
Also used : WindowFunction(org.teiid.query.sql.symbol.WindowFunction) OrderByItem(org.teiid.query.sql.lang.OrderByItem) Expression(org.teiid.query.sql.symbol.Expression) WindowSpecification(org.teiid.query.sql.symbol.WindowSpecification)

Aggregations

Expression (org.teiid.query.sql.symbol.Expression)7 WindowFunction (org.teiid.query.sql.symbol.WindowFunction)7 PlanNode (org.teiid.query.optimizer.relational.plantree.PlanNode)5 ElementSymbol (org.teiid.query.sql.symbol.ElementSymbol)4 ArrayList (java.util.ArrayList)3 Criteria (org.teiid.query.sql.lang.Criteria)3 GroupSymbol (org.teiid.query.sql.symbol.GroupSymbol)3 SymbolMap (org.teiid.query.sql.util.SymbolMap)3 HashSet (java.util.HashSet)2 List (java.util.List)2 QueryPlannerException (org.teiid.api.exception.query.QueryPlannerException)2 TeiidProcessingException (org.teiid.core.TeiidProcessingException)2 AggregateSymbol (org.teiid.query.sql.symbol.AggregateSymbol)2 ExpressionSymbol (org.teiid.query.sql.symbol.ExpressionSymbol)2 WindowSpecification (org.teiid.query.sql.symbol.WindowSpecification)2 LinkedHashSet (java.util.LinkedHashSet)1 LinkedList (java.util.LinkedList)1 Map (java.util.Map)1 Set (java.util.Set)1 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1