Search in sources :

Example 1 with TriggerActionPlanner

use of org.teiid.query.optimizer.TriggerActionPlanner in project teiid by teiid.

the class RelationalPlanner method addNestedProcedure.

private boolean addNestedProcedure(PlanNode sourceNode, ProcedureContainer container, Object metadataId) throws TeiidComponentException, QueryMetadataException, TeiidProcessingException {
    if (container instanceof StoredProcedure) {
        StoredProcedure sp = (StoredProcedure) container;
        if (sp.getProcedureID() instanceof Procedure) {
            context.accessedPlanningObject(sp.getProcedureID());
        }
    }
    for (SubqueryContainer<?> subqueryContainer : ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(container)) {
        if (subqueryContainer.getCommand().getCorrelatedReferences() != null) {
            continue;
        }
        List<Reference> correlatedReferences = new ArrayList<Reference>();
        CorrelatedReferenceCollectorVisitor.collectReferences(subqueryContainer.getCommand(), Arrays.asList(container.getGroup()), correlatedReferences, metadata);
        setCorrelatedReferences(subqueryContainer, correlatedReferences);
    }
    // $NON-NLS-1$
    String cacheString = "transformation/" + container.getClass().getSimpleName().toUpperCase();
    Command c = (Command) metadata.getFromMetadataCache(metadataId, cacheString);
    if (c == null) {
        c = QueryResolver.expandCommand(container, metadata, analysisRecord);
        if (c != null) {
            if (c instanceof CreateProcedureCommand) {
                // TODO: find a better way to do this
                ((CreateProcedureCommand) c).setProjectedSymbols(container.getProjectedSymbols());
            }
            Request.validateWithVisitor(new ValidationVisitor(), metadata, c);
            metadata.addToMetadataCache(metadataId, cacheString, c.clone());
        }
    } else {
        c = (Command) c.clone();
        if (c instanceof CreateProcedureCommand) {
            // TODO: find a better way to do this
            ((CreateProcedureCommand) c).setProjectedSymbols(container.getProjectedSymbols());
        }
    }
    boolean checkRowBasedSecurity = true;
    if (!container.getGroup().isProcedure() && !metadata.isVirtualGroup(metadataId)) {
        Set<PlanningStackEntry> entries = planningStack.get();
        if (entries.contains(new PlanningStackEntry(container, container.getGroup()))) {
            checkRowBasedSecurity = false;
        }
    }
    if (checkRowBasedSecurity) {
        c = RowBasedSecurityHelper.checkUpdateRowBasedFilters(container, c, this);
    }
    if (c != null) {
        if (c instanceof TriggerAction) {
            TriggerAction ta = (TriggerAction) c;
            ProcessorPlan plan = new TriggerActionPlanner().optimize((ProcedureContainer) container.clone(), ta, idGenerator, metadata, capFinder, analysisRecord, context);
            sourceNode.setProperty(NodeConstants.Info.PROCESSOR_PLAN, plan);
            return true;
        }
        if (c.getCacheHint() != null) {
            if (container instanceof StoredProcedure) {
                StoredProcedure sp = (StoredProcedure) container;
                boolean noCache = isNoCacheGroup(metadata, sp.getProcedureID(), option);
                if (!noCache) {
                    if (!context.isResultSetCacheEnabled()) {
                        // $NON-NLS-1$ //$NON-NLS-2$
                        recordAnnotation(analysisRecord, Annotation.CACHED_PROCEDURE, Priority.MEDIUM, "SimpleQueryResolver.procedure_cache_not_usable", container.getGroup(), "result set cache disabled");
                    } else if (!container.areResultsCachable()) {
                        // $NON-NLS-1$ //$NON-NLS-2$
                        recordAnnotation(analysisRecord, Annotation.CACHED_PROCEDURE, Priority.MEDIUM, "SimpleQueryResolver.procedure_cache_not_usable", container.getGroup(), "procedure performs updates");
                    } else if (LobManager.getLobIndexes(new ArrayList<ElementSymbol>(sp.getProcedureParameters().keySet())) != null) {
                        // $NON-NLS-1$ //$NON-NLS-2$
                        recordAnnotation(analysisRecord, Annotation.CACHED_PROCEDURE, Priority.MEDIUM, "SimpleQueryResolver.procedure_cache_not_usable", container.getGroup(), "lob parameters");
                    }
                    container.getGroup().setGlobalTable(true);
                    container.setCacheHint(c.getCacheHint());
                    // $NON-NLS-1$*/
                    recordAnnotation(analysisRecord, Annotation.CACHED_PROCEDURE, Priority.LOW, "SimpleQueryResolver.procedure_cache_used", container.getGroup());
                    return false;
                }
                // $NON-NLS-1$
                recordAnnotation(analysisRecord, Annotation.CACHED_PROCEDURE, Priority.LOW, "SimpleQueryResolver.procedure_cache_not_used", container.getGroup());
            }
        }
        // skip the rewrite here, we'll do that in the optimizer
        // so that we know what the determinism level is.
        addNestedCommand(sourceNode, container.getGroup(), container, c, false, true);
    }
    List<SubqueryContainer<?>> subqueries = ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(container);
    if (c == null && container instanceof FilteredCommand) {
        // we force the evaluation of procedure params - TODO: inserts are fine except for nonpushdown functions on columns
        // for non-temp source queries, we must pre-plan subqueries to know if they can be pushed down
        boolean compensate = false;
        boolean isTemp = container.getGroup().isTempTable() && metadata.getModelID(container.getGroup().getMetadataID()) == TempMetadataAdapter.TEMP_MODEL;
        try {
            planSubqueries(container, c, subqueries, true);
        } catch (QueryPlannerException e) {
            if (!isTemp) {
                throw e;
            }
            compensate = true;
        }
        if (!isTemp && !CriteriaCapabilityValidatorVisitor.canPushLanguageObject(container, metadata.getModelID(container.getGroup().getMetadataID()), metadata, capFinder, analysisRecord)) {
            compensate = true;
        }
        if (compensate) {
            // do a workaround of row-by-row processing for update/delete
            validateRowProcessing(container);
            // treat this as an update procedure
            if (container instanceof Update) {
                c = QueryRewriter.createUpdateProcedure((Update) container, metadata, context);
            } else {
                c = QueryRewriter.createDeleteProcedure((Delete) container, metadata, context);
            }
            addNestedCommand(sourceNode, container.getGroup(), container, c, false, true);
            return false;
        }
    }
    // plan any subqueries in criteria/parameters/values
    planSubqueries(container, c, subqueries, false);
    return false;
}
Also used : ValidationVisitor(org.teiid.query.validator.ValidationVisitor) TriggerAction(org.teiid.query.sql.proc.TriggerAction) CreateProcedureCommand(org.teiid.query.sql.proc.CreateProcedureCommand) CreateProcedureCommand(org.teiid.query.sql.proc.CreateProcedureCommand) Procedure(org.teiid.metadata.Procedure) ProcessorPlan(org.teiid.query.processor.ProcessorPlan) QueryPlannerException(org.teiid.api.exception.query.QueryPlannerException) TriggerActionPlanner(org.teiid.query.optimizer.TriggerActionPlanner)

Aggregations

QueryPlannerException (org.teiid.api.exception.query.QueryPlannerException)1 Procedure (org.teiid.metadata.Procedure)1 TriggerActionPlanner (org.teiid.query.optimizer.TriggerActionPlanner)1 ProcessorPlan (org.teiid.query.processor.ProcessorPlan)1 CreateProcedureCommand (org.teiid.query.sql.proc.CreateProcedureCommand)1 TriggerAction (org.teiid.query.sql.proc.TriggerAction)1 ValidationVisitor (org.teiid.query.validator.ValidationVisitor)1