Search in sources :

Example 6 with ValidationVisitor

use of org.teiid.query.validator.ValidationVisitor 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)

Example 7 with ValidationVisitor

use of org.teiid.query.validator.ValidationVisitor in project teiid by teiid.

the class ExecDynamicSqlInstruction method process.

/**
 * <p>
 * Processing this instruction executes the ProcessorPlan for the command on
 * the CommandStatement of the update procedure language. Executing this
 * plan does not effect the values of any of the variables defined as part
 * of the update procedure and hence the results of the ProcessPlan
 * execution need not be stored for further processing. The results are
 * removed from the buffer manager immediately after execution. The program
 * counter is incremented after execution of the plan.
 * </p>
 *
 * @throws BlockedException
 *             if this processing the plan throws a currentVarContext
 */
public void process(ProcedurePlan procEnv) throws BlockedException, TeiidComponentException, TeiidProcessingException {
    VariableContext localContext = procEnv.getCurrentVariableContext();
    String query = null;
    try {
        Clob value = (Clob) procEnv.evaluateExpression(dynamicCommand.getSql());
        if (value == null) {
            throw new QueryProcessingException(QueryPlugin.Util.getString(// $NON-NLS-1$
            "ExecDynamicSqlInstruction.0"));
        }
        if (value.length() > MAX_SQL_LENGTH) {
            throw new QueryProcessingException(QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31204, MAX_SQL_LENGTH));
        }
        query = value.getSubString(1, MAX_SQL_LENGTH);
        LogManager.logTrace(org.teiid.logging.LogConstants.CTX_DQP, // $NON-NLS-1$
        new Object[] { "Executing dynamic sql ", query });
        Command command = QueryParser.getQueryParser().parseCommand(query);
        // special handling for dynamic anon blocks
        if (command instanceof CreateProcedureCommand) {
            if (dynamicCommand.getIntoGroup() != null || returnable) {
                // and the creation of an inline view
                throw new QueryProcessingException(QueryPlugin.Event.TEIID31250, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31250));
            }
            ((CreateProcedureCommand) command).setResultSetColumns(Collections.EMPTY_LIST);
        }
        command.setExternalGroupContexts(dynamicCommand.getExternalGroupContexts());
        command.setTemporaryMetadata(dynamicCommand.getTemporaryMetadata().clone());
        updateContextWithUsingValues(procEnv, localContext);
        TempMetadataStore metadataStore = command.getTemporaryMetadata();
        if (dynamicCommand.getUsing() != null && !dynamicCommand.getUsing().isEmpty()) {
            metadataStore.addTempGroup(Reserved.USING, new LinkedList<ElementSymbol>(dynamicCommand.getUsing().getClauseMap().keySet()));
            GroupSymbol using = new GroupSymbol(Reserved.USING);
            using.setMetadataID(metadataStore.getTempGroupID(Reserved.USING));
            command.addExternalGroupToContext(using);
            metadataStore.addTempGroup(ProcedureReservedWords.DVARS, new LinkedList<ElementSymbol>(dynamicCommand.getUsing().getClauseMap().keySet()));
            using = new GroupSymbol(ProcedureReservedWords.DVARS);
            using.setMetadataID(metadataStore.getTempGroupID(ProcedureReservedWords.DVARS));
            command.addExternalGroupToContext(using);
        }
        QueryResolver.resolveCommand(command, metadata.getDesignTimeMetadata());
        validateDynamicCommand(procEnv, command, value.toString());
        // create a new set of variables including vars
        Map<ElementSymbol, Expression> nameValueMap = createVariableValuesMap(localContext);
        ValidationVisitor visitor = new ValidationVisitor();
        Request.validateWithVisitor(visitor, metadata, command);
        boolean insertInto = false;
        boolean updateCommand = false;
        if (!command.returnsResultSet() && !(command instanceof StoredProcedure)) {
            if (dynamicCommand.isAsClauseSet()) {
                if (dynamicCommand.getProjectedSymbols().size() != 1 || ((Expression) dynamicCommand.getProjectedSymbols().get(0)).getType() != DataTypeManager.DefaultDataClasses.INTEGER) {
                    throw new QueryProcessingException(QueryPlugin.Event.TEIID31157, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31157));
                }
            }
            updateCommand = true;
        } else if (dynamicCommand.getAsColumns() != null && !dynamicCommand.getAsColumns().isEmpty()) {
            // $NON-NLS-1$
            command = QueryRewriter.createInlineViewQuery(new GroupSymbol("X"), command, metadata, dynamicCommand.getAsColumns());
            if (dynamicCommand.getIntoGroup() != null) {
                Insert insert = new Insert(dynamicCommand.getIntoGroup(), dynamicCommand.getAsColumns(), Collections.emptyList());
                insert.setQueryExpression((Query) command);
                command = insert;
                insertInto = true;
            }
        }
        // if this is an update procedure, it could reassign variables
        command = QueryRewriter.rewrite(command, metadata, procEnv.getContext(), command instanceof CreateProcedureCommand ? Collections.EMPTY_MAP : nameValueMap);
        ProcessorPlan commandPlan = QueryOptimizer.optimizePlan(command, metadata, idGenerator, capFinder, AnalysisRecord.createNonRecordingRecord(), procEnv.getContext());
        if (command instanceof CreateProcedureCommand && commandPlan instanceof ProcedurePlan) {
            ((ProcedurePlan) commandPlan).setValidateAccess(procEnv.isValidateAccess());
        }
        CreateCursorResultSetInstruction inst = new CreateCursorResultSetInstruction(null, commandPlan, (insertInto || updateCommand) ? Mode.UPDATE : returnable ? Mode.HOLD : Mode.NOHOLD) {

            @Override
            public void process(ProcedurePlan procEnv) throws BlockedException, TeiidComponentException, TeiidProcessingException {
                boolean done = true;
                try {
                    super.process(procEnv);
                } catch (BlockedException e) {
                    done = false;
                    throw e;
                } finally {
                    if (done) {
                        procEnv.getContext().popCall();
                    }
                }
            }
        };
        dynamicProgram = new Program(false);
        dynamicProgram.addInstruction(inst);
        if (dynamicCommand.getIntoGroup() != null) {
            String groupName = dynamicCommand.getIntoGroup().getName();
            if (!procEnv.getTempTableStore().hasTempTable(groupName, true)) {
                // create the temp table in the parent scope
                Create create = new Create();
                create.setTable(new GroupSymbol(groupName));
                for (ElementSymbol es : (List<ElementSymbol>) dynamicCommand.getAsColumns()) {
                    Column c = new Column();
                    c.setName(es.getShortName());
                    c.setRuntimeType(DataTypeManager.getDataTypeName(es.getType()));
                    create.getColumns().add(c);
                }
                procEnv.getDataManager().registerRequest(procEnv.getContext(), create, TempMetadataAdapter.TEMP_MODEL.getName(), new RegisterRequestParameter());
            }
            // backwards compatibility to support into with a rowcount
            if (updateCommand) {
                Insert insert = new Insert();
                insert.setGroup(new GroupSymbol(groupName));
                for (ElementSymbol es : (List<ElementSymbol>) dynamicCommand.getAsColumns()) {
                    ElementSymbol col = new ElementSymbol(es.getShortName(), insert.getGroup());
                    col.setType(es.getType());
                    insert.addVariable(col);
                }
                insert.addValue(new Constant(procEnv.getCurrentVariableContext().getValue(ProcedurePlan.ROWCOUNT)));
                QueryResolver.resolveCommand(insert, metadata.getDesignTimeMetadata());
                TupleSource ts = procEnv.getDataManager().registerRequest(procEnv.getContext(), insert, TempMetadataAdapter.TEMP_MODEL.getName(), new RegisterRequestParameter());
                ts.nextTuple();
                ts.closeSource();
            }
        }
        // Add group to recursion stack
        if (parentProcCommand.getUpdateType() != Command.TYPE_UNKNOWN) {
            // $NON-NLS-1$
            procEnv.getContext().pushCall(Command.getCommandToken(parentProcCommand.getUpdateType()) + " " + parentProcCommand.getVirtualGroup());
        } else {
            if (parentProcCommand.getVirtualGroup() != null) {
                procEnv.getContext().pushCall(parentProcCommand.getVirtualGroup().toString());
            }
        }
        procEnv.push(dynamicProgram);
    } catch (SQLException e) {
        Object[] params = { dynamicCommand, dynamicCommand.getSql(), e.getMessage() };
        throw new QueryProcessingException(QueryPlugin.Event.TEIID30168, e, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30168, params));
    } catch (TeiidProcessingException e) {
        Object[] params = { dynamicCommand, query == null ? dynamicCommand.getSql() : query, e.getMessage() };
        throw new QueryProcessingException(QueryPlugin.Event.TEIID30168, e, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30168, params));
    }
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) ValidationVisitor(org.teiid.query.validator.ValidationVisitor) CreateProcedureCommand(org.teiid.query.sql.proc.CreateProcedureCommand) Query(org.teiid.query.sql.lang.Query) SQLException(java.sql.SQLException) Constant(org.teiid.query.sql.symbol.Constant) Insert(org.teiid.query.sql.lang.Insert) BlockedException(org.teiid.common.buffer.BlockedException) TeiidProcessingException(org.teiid.core.TeiidProcessingException) Column(org.teiid.metadata.Column) Create(org.teiid.query.sql.lang.Create) List(java.util.List) LinkedList(java.util.LinkedList) VariableContext(org.teiid.query.sql.util.VariableContext) RegisterRequestParameter(org.teiid.query.processor.RegisterRequestParameter) StoredProcedure(org.teiid.query.sql.lang.StoredProcedure) CreateProcedureCommand(org.teiid.query.sql.proc.CreateProcedureCommand) Command(org.teiid.query.sql.lang.Command) DynamicCommand(org.teiid.query.sql.lang.DynamicCommand) Expression(org.teiid.query.sql.symbol.Expression) TupleSource(org.teiid.common.buffer.TupleSource) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) Clob(java.sql.Clob) ProcessorPlan(org.teiid.query.processor.ProcessorPlan) TempMetadataStore(org.teiid.query.metadata.TempMetadataStore) QueryProcessingException(org.teiid.api.exception.query.QueryProcessingException)

Aggregations

ValidationVisitor (org.teiid.query.validator.ValidationVisitor)7 GroupSymbol (org.teiid.query.sql.symbol.GroupSymbol)4 ProcessorPlan (org.teiid.query.processor.ProcessorPlan)3 Command (org.teiid.query.sql.lang.Command)3 QueryMetadataException (org.teiid.api.exception.query.QueryMetadataException)2 TeiidException (org.teiid.core.TeiidException)2 CreateProcedureCommand (org.teiid.query.sql.proc.CreateProcedureCommand)2 ElementSymbol (org.teiid.query.sql.symbol.ElementSymbol)2 Expression (org.teiid.query.sql.symbol.Expression)2 AbstractValidationVisitor (org.teiid.query.validator.AbstractValidationVisitor)2 ValidatorFailure (org.teiid.query.validator.ValidatorFailure)2 ValidatorReport (org.teiid.query.validator.ValidatorReport)2 Clob (java.sql.Clob)1 SQLException (java.sql.SQLException)1 ArrayList (java.util.ArrayList)1 LinkedList (java.util.LinkedList)1 List (java.util.List)1 Map (java.util.Map)1 DataPolicy (org.teiid.adminapi.DataPolicy)1 DataPolicyMetadata (org.teiid.adminapi.impl.DataPolicyMetadata)1