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;
}
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 });
}
}
}
Aggregations