use of org.teiid.core.TeiidProcessingException 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.core.TeiidProcessingException in project teiid by teiid.
the class TransformationMetadata method getScriptEngineDirect.
@Override
public ScriptEngine getScriptEngineDirect(String language) throws TeiidProcessingException {
if (this.scriptEngineManager == null) {
this.scriptEngineManager = new ScriptEngineManager();
}
ScriptEngine engine = null;
if (allowedLanguages == null || allowedLanguages.contains(language)) {
/*
* because of state caching in the engine, we'll return a new instance for each
* usage. we can pool if needed and add a returnEngine method
*/
ScriptEngineFactory sef = this.scriptEngineFactories.get(language);
if (sef != null) {
try {
engine = sef.getScriptEngine();
engine.setBindings(scriptEngineManager.getBindings(), ScriptContext.ENGINE_SCOPE);
} catch (Exception e) {
// just swallow the exception to mimic the jsr behavior
}
}
engine = this.scriptEngineManager.getEngineByName(language);
}
if (engine == null) {
Set<String> names = new LinkedHashSet<String>();
for (ScriptEngineFactory factory : this.scriptEngineManager.getEngineFactories()) {
names.addAll(factory.getNames());
}
if (allowedLanguages != null) {
names.retainAll(allowedLanguages);
}
names.add(ObjectTable.DEFAULT_LANGUAGE);
throw new TeiidProcessingException(QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31109, language, names));
}
this.scriptEngineFactories.put(language, engine.getFactory());
return engine;
}
use of org.teiid.core.TeiidProcessingException in project teiid by teiid.
the class QueryOptimizer method planProcedure.
private static ProcessorPlan planProcedure(Command command, QueryMetadataInterface metadata, IDGenerator idGenerator, CapabilitiesFinder capFinder, AnalysisRecord analysisRecord, CommandContext context) throws TeiidComponentException, QueryPlannerException, QueryMetadataException {
ProcessorPlan result;
try {
command = QueryRewriter.rewrite(command, metadata, context);
} catch (TeiidProcessingException e) {
throw new QueryPlannerException(e);
}
result = PROCEDURE_PLANNER.optimize(command, idGenerator, metadata, capFinder, analysisRecord, context);
return result;
}
use of org.teiid.core.TeiidProcessingException in project teiid by teiid.
the class QueryOptimizer method optimizePlan.
public static ProcessorPlan optimizePlan(Command command, QueryMetadataInterface metadata, IDGenerator idGenerator, CapabilitiesFinder capFinder, AnalysisRecord analysisRecord, CommandContext context) throws QueryMetadataException, TeiidComponentException, QueryPlannerException {
if (analysisRecord == null) {
analysisRecord = new AnalysisRecord(false, false);
}
if (context == null) {
context = new CommandContext();
}
if (!(capFinder instanceof TempCapabilitiesFinder)) {
capFinder = new TempCapabilitiesFinder(capFinder);
}
boolean debug = analysisRecord.recordDebug();
if (!(metadata instanceof TempMetadataAdapter)) {
metadata = new TempMetadataAdapter(metadata, new TempMetadataStore());
}
if (context.getMetadata() == null) {
context.setMetadata(metadata);
}
// Create an ID generator that can be used for all plans to generate unique data node IDs
if (idGenerator == null) {
idGenerator = new IDGenerator();
}
if (debug) {
// $NON-NLS-1$
analysisRecord.println("\n----------------------------------------------------------------------------");
// $NON-NLS-1$
analysisRecord.println("OPTIMIZE: \n" + command);
}
if (command instanceof Insert) {
Insert insert = (Insert) command;
if (insert.isUpsert()) {
// if not supported or there are trigger actions, then rewrite as a procedure
// we do this here since we're changing the command type.
// TODO: we could push this back into the rewrite, but it will need to be capabilities aware
GroupSymbol group = insert.getGroup();
Object modelId = metadata.getModelID(group.getMetadataID());
boolean supportsUpsert = CapabilitiesUtil.supports(Capability.UPSERT, modelId, metadata, capFinder);
if (!supportsUpsert) {
try {
command = QueryRewriter.rewriteAsUpsertProcedure(insert, metadata, context);
} catch (TeiidProcessingException e) {
throw new QueryPlannerException(e);
}
if (debug) {
// $NON-NLS-1$
analysisRecord.println("\n----------------------------------------------------------------------------");
// $NON-NLS-1$
analysisRecord.println("OPTIMIZE UPSERT PROCEDURE: \n" + command);
}
}
}
}
ProcessorPlan result = null;
switch(command.getType()) {
case Command.TYPE_UPDATE_PROCEDURE:
CreateProcedureCommand cupc = (CreateProcedureCommand) command;
if (cupc.getUpdateType() != Command.TYPE_UNKNOWN || cupc.getVirtualGroup() == null) {
// row update procedure or anon block
result = planProcedure(command, metadata, idGenerator, capFinder, analysisRecord, context);
} else {
Object pid = cupc.getVirtualGroup().getMetadataID();
if (pid instanceof TempMetadataID) {
TempMetadataID tid = (TempMetadataID) pid;
if (tid.getOriginalMetadataID() != null) {
pid = tid.getOriginalMetadataID();
}
}
String fullName = metadata.getFullName(pid);
// $NON-NLS-1$
fullName = "procedure cache:" + fullName;
PreparedPlan pp = context.getPlan(fullName);
if (pp == null) {
Determinism determinismLevel = context.resetDeterminismLevel();
try {
CommandContext clone = context.clone();
ProcessorPlan plan = planProcedure(command, metadata, idGenerator, capFinder, analysisRecord, clone);
// note that this is not a full prepared plan. It is not usable by user queries.
if (pid instanceof Procedure) {
clone.accessedPlanningObject(pid);
}
pp = new PreparedPlan();
pp.setPlan(plan, clone);
context.putPlan(fullName, pp, context.getDeterminismLevel());
} finally {
context.setDeterminismLevel(determinismLevel);
}
}
result = pp.getPlan().clone();
for (Object id : pp.getAccessInfo().getObjectsAccessed()) {
context.accessedPlanningObject(id);
}
}
break;
case Command.TYPE_BATCHED_UPDATE:
result = BATCHED_UPDATE_PLANNER.optimize(command, idGenerator, metadata, capFinder, analysisRecord, context);
break;
case Command.TYPE_ALTER_PROC:
case Command.TYPE_ALTER_TRIGGER:
case Command.TYPE_ALTER_VIEW:
result = DDL_PLANNER.optimize(command, idGenerator, metadata, capFinder, analysisRecord, context);
break;
case Command.TYPE_SOURCE_EVENT:
result = SOURCE_EVENT_PLANNER.optimize(command, idGenerator, metadata, capFinder, analysisRecord, context);
break;
default:
try {
RelationalPlanner planner = new RelationalPlanner();
planner.initialize(command, idGenerator, metadata, capFinder, analysisRecord, context);
result = planner.optimize(command);
} catch (QueryResolverException e) {
throw new TeiidRuntimeException(QueryPlugin.Event.TEIID30245, e);
}
}
if (debug) {
// $NON-NLS-1$
analysisRecord.println("\n----------------------------------------------------------------------------");
// $NON-NLS-1$
analysisRecord.println("OPTIMIZATION COMPLETE:");
// $NON-NLS-1$
analysisRecord.println("PROCESSOR PLAN:\n" + result);
// $NON-NLS-1$
analysisRecord.println("============================================================================");
}
return result;
}
use of org.teiid.core.TeiidProcessingException 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);
}
Aggregations