Search in sources :

Example 66 with TeiidProcessingException

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;
}
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 67 with TeiidProcessingException

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;
}
Also used : ScriptEngineFactory(javax.script.ScriptEngineFactory) ScriptEngineManager(javax.script.ScriptEngineManager) ScriptEngine(javax.script.ScriptEngine) TeiidComponentException(org.teiid.core.TeiidComponentException) QueryMetadataException(org.teiid.api.exception.query.QueryMetadataException) TeiidProcessingException(org.teiid.core.TeiidProcessingException) IOException(java.io.IOException) TeiidProcessingException(org.teiid.core.TeiidProcessingException)

Example 68 with TeiidProcessingException

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;
}
Also used : ProcessorPlan(org.teiid.query.processor.ProcessorPlan) QueryPlannerException(org.teiid.api.exception.query.QueryPlannerException) TeiidProcessingException(org.teiid.core.TeiidProcessingException)

Example 69 with TeiidProcessingException

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;
}
Also used : TempMetadataAdapter(org.teiid.query.metadata.TempMetadataAdapter) AnalysisRecord(org.teiid.query.analysis.AnalysisRecord) Determinism(org.teiid.metadata.FunctionMethod.Determinism) CommandContext(org.teiid.query.util.CommandContext) CreateProcedureCommand(org.teiid.query.sql.proc.CreateProcedureCommand) TempMetadataID(org.teiid.query.metadata.TempMetadataID) TempCapabilitiesFinder(org.teiid.query.metadata.TempCapabilitiesFinder) TeiidRuntimeException(org.teiid.core.TeiidRuntimeException) Insert(org.teiid.query.sql.lang.Insert) QueryResolverException(org.teiid.api.exception.query.QueryResolverException) TeiidProcessingException(org.teiid.core.TeiidProcessingException) RelationalPlanner(org.teiid.query.optimizer.relational.RelationalPlanner) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) PreparedPlan(org.teiid.dqp.internal.process.PreparedPlan) Procedure(org.teiid.metadata.Procedure) ProcessorPlan(org.teiid.query.processor.ProcessorPlan) IDGenerator(org.teiid.core.id.IDGenerator) QueryPlannerException(org.teiid.api.exception.query.QueryPlannerException) TempMetadataStore(org.teiid.query.metadata.TempMetadataStore)

Example 70 with TeiidProcessingException

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

TeiidProcessingException (org.teiid.core.TeiidProcessingException)92 TeiidComponentException (org.teiid.core.TeiidComponentException)30 IOException (java.io.IOException)17 ArrayList (java.util.ArrayList)17 TeiidRuntimeException (org.teiid.core.TeiidRuntimeException)17 SQLException (java.sql.SQLException)16 BlockedException (org.teiid.common.buffer.BlockedException)16 Test (org.junit.Test)14 CommandContext (org.teiid.query.util.CommandContext)14 LanguageObject (org.teiid.query.sql.LanguageObject)13 ElementSymbol (org.teiid.query.sql.symbol.ElementSymbol)13 GroupSymbol (org.teiid.query.sql.symbol.GroupSymbol)12 List (java.util.List)11 QueryMetadataInterface (org.teiid.query.metadata.QueryMetadataInterface)10 TransformationMetadata (org.teiid.query.metadata.TransformationMetadata)10 QueryPlannerException (org.teiid.api.exception.query.QueryPlannerException)9 TupleSource (org.teiid.common.buffer.TupleSource)9 TupleBatch (org.teiid.common.buffer.TupleBatch)8 CollectionTupleSource (org.teiid.query.processor.CollectionTupleSource)7 BasicSourceCapabilities (org.teiid.query.optimizer.capabilities.BasicSourceCapabilities)6