Search in sources :

Example 1 with TriggerAction

use of org.teiid.query.sql.proc.TriggerAction in project teiid by teiid.

the class TestIsDistinctCriteria method testParseClone.

@Test
public void testParseClone() throws QueryParserException {
    TriggerAction ta = (TriggerAction) QueryParser.getQueryParser().parseProcedure("for each row begin atomic if (\"new\" is not distinct from \"old\") raise sqlexception ''; end", true);
    assertEquals("FOR EACH ROW\nBEGIN ATOMIC\nIF(\"new\" IS NOT DISTINCT FROM \"old\")\nBEGIN\nRAISE SQLEXCEPTION '';\nEND\nEND", ta.toString());
    QueryParser.getQueryParser().parseProcedure(ta.toString(), true);
    TriggerAction clone = ta.clone();
    assertEquals(ta.toString(), clone.toString());
    UnitTestUtil.helpTestEquivalence(0, ta, ta.clone());
}
Also used : TriggerAction(org.teiid.query.sql.proc.TriggerAction) Test(org.junit.Test)

Example 2 with TriggerAction

use of org.teiid.query.sql.proc.TriggerAction in project teiid by teiid.

the class SourceTriggerActionPlanner method optimize.

@Override
public ProcessorPlan optimize(Command command, IDGenerator idGenerator, QueryMetadataInterface metadata, CapabilitiesFinder capFinder, AnalysisRecord analysisRecord, CommandContext context) throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
    SourceEventCommand sec = (SourceEventCommand) command;
    Map<Expression, Integer> lookup = new HashMap<Expression, Integer>();
    Map<ElementSymbol, Expression> params = new HashMap<ElementSymbol, Expression>();
    List<Object> tuple = new ArrayList<Object>();
    Map<String, Integer> map = null;
    if (sec.getColumnNames() != null) {
        map = new TreeMap<String, Integer>(String.CASE_INSENSITIVE_ORDER);
        for (String name : sec.getColumnNames()) {
            map.put(name, map.size());
        }
    }
    GroupSymbol changingGroup = new GroupSymbol(ProcedureReservedWords.CHANGING);
    if (sec.newValues != null) {
        GroupSymbol newGroup = new GroupSymbol(SQLConstants.Reserved.NEW);
        newGroup.setMetadataID(sec.table);
        for (int i = 0; i < sec.getTable().getColumns().size(); i++) {
            Column c = sec.getTable().getColumns().get(i);
            Integer index = null;
            if (map != null) {
                index = map.get(c.getName());
            } else {
                index = i;
            }
            ElementSymbol newElement = new ElementSymbol(c.getName(), newGroup);
            newElement.setMetadataID(c);
            ElementSymbol changingElement = new ElementSymbol(c.getName(), changingGroup);
            lookup.put(newElement, tuple.size());
            lookup.put(changingElement, tuple.size() + 1);
            params.put(newElement, newElement);
            params.put(changingElement, changingElement);
            if (index == null) {
                // not changing
                tuple.add(new Constant(null));
                tuple.add(new Constant(Boolean.FALSE));
            } else {
                // changing
                tuple.add(new Constant(DataTypeManager.convertToRuntimeType(sec.newValues[index], true)));
                tuple.add(new Constant(Boolean.TRUE));
            }
        }
    }
    if (sec.oldValues != null) {
        GroupSymbol oldGroup = new GroupSymbol(SQLConstants.Reserved.OLD);
        oldGroup.setMetadataID(sec.table);
        for (int i = 0; i < sec.getTable().getColumns().size(); i++) {
            Column c = sec.getTable().getColumns().get(i);
            Integer index = null;
            if (map != null) {
                index = map.get(c.getName());
            } else {
                index = i;
            }
            ElementSymbol oldElement = new ElementSymbol(c.getName(), oldGroup);
            oldElement.setMetadataID(c);
            lookup.put(oldElement, tuple.size());
            params.put(oldElement, oldElement);
            if (index != null) {
                tuple.add(new Constant(DataTypeManager.convertToRuntimeType(sec.oldValues[index], true)));
            }
        }
    }
    List<ProcessorPlan> plans = new ArrayList<ProcessorPlan>();
    List<String> names = new ArrayList<String>();
    for (Trigger tr : sec.getTable().getTriggers().values()) {
        int updateType = Command.TYPE_UPDATE;
        switch(tr.getEvent()) {
            case DELETE:
                updateType = Command.TYPE_DELETE;
                if (sec.newValues != null) {
                    continue;
                }
                break;
            case INSERT:
                updateType = Command.TYPE_INSERT;
                if (sec.oldValues != null) {
                    continue;
                }
                break;
            case UPDATE:
                if (sec.oldValues == null || sec.newValues == null) {
                    continue;
                }
                break;
        }
        // create plan
        ForEachRowPlan result = new ForEachRowPlan();
        result.setSingleRow(true);
        result.setParams(params);
        TriggerAction parseProcedure;
        GroupSymbol gs = new GroupSymbol(sec.table.getFullName());
        try {
            parseProcedure = (TriggerAction) QueryParser.getQueryParser().parseProcedure(tr.getPlan(), true);
            QueryResolver.resolveCommand(parseProcedure, gs, updateType, metadata.getDesignTimeMetadata(), false);
        } catch (QueryParserException e) {
            // should have been validated
            throw new TeiidComponentException(e);
        } catch (QueryResolverException e) {
            // should have been validated
            throw new TeiidComponentException(e);
        }
        CreateProcedureCommand cpc = new CreateProcedureCommand(parseProcedure.getBlock());
        gs.setMetadataID(sec.table);
        cpc.setVirtualGroup(gs);
        cpc.setUpdateType(updateType);
        ProcedurePlan rowProcedure = (ProcedurePlan) QueryOptimizer.optimizePlan(cpc, metadata, idGenerator, capFinder, analysisRecord, context);
        rowProcedure.setRunInContext(false);
        result.setRowProcedure(rowProcedure);
        result.setLookupMap(lookup);
        result.setTupleSource(new CollectionTupleSource(Arrays.asList(tuple).iterator()));
        plans.add(result);
        names.add(tr.getName());
    }
    return new CompositeProcessorPlan(plans, names, sec.table);
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) QueryParserException(org.teiid.api.exception.query.QueryParserException) TriggerAction(org.teiid.query.sql.proc.TriggerAction) CreateProcedureCommand(org.teiid.query.sql.proc.CreateProcedureCommand) HashMap(java.util.HashMap) Constant(org.teiid.query.sql.symbol.Constant) ArrayList(java.util.ArrayList) CollectionTupleSource(org.teiid.query.processor.CollectionTupleSource) QueryResolverException(org.teiid.api.exception.query.QueryResolverException) Trigger(org.teiid.metadata.Trigger) Column(org.teiid.metadata.Column) ForEachRowPlan(org.teiid.query.processor.proc.ForEachRowPlan) Expression(org.teiid.query.sql.symbol.Expression) ProcedurePlan(org.teiid.query.processor.proc.ProcedurePlan) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) TeiidComponentException(org.teiid.core.TeiidComponentException) ProcessorPlan(org.teiid.query.processor.ProcessorPlan)

Example 3 with TriggerAction

use of org.teiid.query.sql.proc.TriggerAction 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 4 with TriggerAction

use of org.teiid.query.sql.proc.TriggerAction in project teiid by teiid.

the class ProcedureContainerResolver method findChildCommandMetadata.

/**
 * Set the appropriate "external" metadata for the given command
 * @param inferProcedureResultSetColumns
 * @throws QueryResolverException
 */
public static void findChildCommandMetadata(Command currentCommand, GroupSymbol container, int type, QueryMetadataInterface metadata, boolean inferProcedureResultSetColumns) throws QueryMetadataException, TeiidComponentException, QueryResolverException {
    // find the childMetadata using a clean metadata store
    TempMetadataStore childMetadata = new TempMetadataStore();
    TempMetadataAdapter tma = new TempMetadataAdapter(metadata, childMetadata);
    GroupContext externalGroups = new GroupContext();
    if (currentCommand instanceof TriggerAction) {
        TriggerAction ta = (TriggerAction) currentCommand;
        ta.setView(container);
        // TODO: it seems easier to just inline the handling here rather than have each of the resolvers check for trigger actions
        List<ElementSymbol> viewElements = ResolverUtil.resolveElementsInGroup(ta.getView(), metadata);
        if (type == Command.TYPE_UPDATE || type == Command.TYPE_INSERT) {
            ProcedureContainerResolver.addChanging(tma.getMetadataStore(), externalGroups, viewElements);
            ProcedureContainerResolver.addScalarGroup(SQLConstants.Reserved.NEW, tma.getMetadataStore(), externalGroups, viewElements, false);
            if (type == Command.TYPE_INSERT) {
                List<ElementSymbol> key = InsertResolver.getAutoIncrementKey(ta.getView().getMetadataID(), viewElements, metadata);
                if (key != null) {
                    ProcedureContainerResolver.addScalarGroup(SQLConstants.NonReserved.KEY, tma.getMetadataStore(), externalGroups, key, true);
                }
            }
        }
        if (type == Command.TYPE_UPDATE || type == Command.TYPE_DELETE) {
            ProcedureContainerResolver.addScalarGroup(SQLConstants.Reserved.OLD, tma.getMetadataStore(), externalGroups, viewElements, false);
        }
    } else if (currentCommand instanceof CreateProcedureCommand) {
        CreateProcedureCommand cupc = (CreateProcedureCommand) currentCommand;
        cupc.setVirtualGroup(container);
        if (type == Command.TYPE_STORED_PROCEDURE) {
            StoredProcedureInfo info = metadata.getStoredProcedureInfoForProcedure(container.getName());
            // Create temporary metadata that defines a group based on either the stored proc
            // name or the stored query name - this will be used later during planning
            String procName = info.getProcedureCallableName();
            // Look through parameters to find input elements - these become child metadata
            List<ElementSymbol> tempElements = new ArrayList<ElementSymbol>(info.getParameters().size());
            boolean[] updatable = new boolean[info.getParameters().size()];
            int i = 0;
            List<ElementSymbol> rsColumns = Collections.emptyList();
            for (SPParameter param : info.getParameters()) {
                if (param.getParameterType() != ParameterInfo.RESULT_SET) {
                    ElementSymbol symbol = param.getParameterSymbol();
                    tempElements.add(symbol);
                    updatable[i++] = param.getParameterType() != ParameterInfo.IN;
                    if (param.getParameterType() == ParameterInfo.RETURN_VALUE) {
                        cupc.setReturnVariable(symbol);
                    }
                } else {
                    rsColumns = param.getResultSetColumns();
                }
            }
            if (inferProcedureResultSetColumns) {
                rsColumns = null;
            }
            GroupSymbol gs = ProcedureContainerResolver.addScalarGroup(procName, childMetadata, externalGroups, tempElements, updatable);
            if (cupc.getReturnVariable() != null) {
                ResolverVisitor.resolveLanguageObject(cupc.getReturnVariable(), Arrays.asList(gs), metadata);
            }
            cupc.setResultSetColumns(rsColumns);
            // the relational planner will override this with the appropriate value
            cupc.setProjectedSymbols(rsColumns);
        } else {
            cupc.setUpdateType(type);
        }
    }
    QueryResolver.setChildMetadata(currentCommand, childMetadata, externalGroups);
}
Also used : TempMetadataAdapter(org.teiid.query.metadata.TempMetadataAdapter) ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) TriggerAction(org.teiid.query.sql.proc.TriggerAction) CreateProcedureCommand(org.teiid.query.sql.proc.CreateProcedureCommand) SPParameter(org.teiid.query.sql.lang.SPParameter) StoredProcedureInfo(org.teiid.query.metadata.StoredProcedureInfo) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) ArrayList(java.util.ArrayList) List(java.util.List) TempMetadataStore(org.teiid.query.metadata.TempMetadataStore) GroupContext(org.teiid.query.sql.lang.GroupContext)

Example 5 with TriggerAction

use of org.teiid.query.sql.proc.TriggerAction in project teiid by teiid.

the class TestProcedureResolving method testProcedureScoping.

@Test
public void testProcedureScoping() throws Exception {
    StringBuffer proc = // $NON-NLS-1$
    new StringBuffer("FOR EACH ROW").append(// $NON-NLS-1$
    "\nBEGIN").append(// $NON-NLS-1$
    "\n  declare integer e1 = 1;").append(// $NON-NLS-1$
    "\n  e1 = e1;").append(// $NON-NLS-1$
    "\n  LOOP ON (SELECT pm1.g1.e1 FROM pm1.g1) AS loopCursor").append(// $NON-NLS-1$
    "\n  BEGIN").append(// $NON-NLS-1$
    "\n    variables.e1 = convert(e1, integer);").append(// $NON-NLS-1$
    "\n  END").append(// $NON-NLS-1$
    "\nEND");
    // $NON-NLS-1$
    String userUpdateStr = "UPDATE vm1.g1 SET e1='x'";
    TriggerAction command = helpResolveUpdateProcedure(proc.toString(), userUpdateStr, Table.TriggerEvent.UPDATE);
    Block block = command.getBlock();
    AssignmentStatement assStmt = (AssignmentStatement) block.getStatements().get(1);
    assertEquals(ProcedureReservedWords.VARIABLES, assStmt.getVariable().getGroupSymbol().getName());
    assertEquals(ProcedureReservedWords.VARIABLES, ((ElementSymbol) assStmt.getExpression()).getGroupSymbol().getName());
    Block inner = ((LoopStatement) block.getStatements().get(2)).getBlock();
    assStmt = (AssignmentStatement) inner.getStatements().get(0);
    ElementSymbol value = ElementCollectorVisitor.getElements(assStmt.getExpression(), false).iterator().next();
    // $NON-NLS-1$
    assertEquals("loopCursor", value.getGroupSymbol().getName());
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) TriggerAction(org.teiid.query.sql.proc.TriggerAction) AssignmentStatement(org.teiid.query.sql.proc.AssignmentStatement) Block(org.teiid.query.sql.proc.Block) LoopStatement(org.teiid.query.sql.proc.LoopStatement) Test(org.junit.Test)

Aggregations

TriggerAction (org.teiid.query.sql.proc.TriggerAction)5 CreateProcedureCommand (org.teiid.query.sql.proc.CreateProcedureCommand)3 ElementSymbol (org.teiid.query.sql.symbol.ElementSymbol)3 ArrayList (java.util.ArrayList)2 Test (org.junit.Test)2 ProcessorPlan (org.teiid.query.processor.ProcessorPlan)2 GroupSymbol (org.teiid.query.sql.symbol.GroupSymbol)2 HashMap (java.util.HashMap)1 List (java.util.List)1 QueryParserException (org.teiid.api.exception.query.QueryParserException)1 QueryPlannerException (org.teiid.api.exception.query.QueryPlannerException)1 QueryResolverException (org.teiid.api.exception.query.QueryResolverException)1 TeiidComponentException (org.teiid.core.TeiidComponentException)1 Column (org.teiid.metadata.Column)1 Procedure (org.teiid.metadata.Procedure)1 Trigger (org.teiid.metadata.Trigger)1 StoredProcedureInfo (org.teiid.query.metadata.StoredProcedureInfo)1 TempMetadataAdapter (org.teiid.query.metadata.TempMetadataAdapter)1 TempMetadataStore (org.teiid.query.metadata.TempMetadataStore)1 TriggerActionPlanner (org.teiid.query.optimizer.TriggerActionPlanner)1