The Teiid Spring Boot query engine uses the "ExecutionFactory" class to obtain the "Execution" interface for the command it is executing. The actual queries themselves are sent to translators in the form of a set of objects, which are further described in Command Language. Refer to Command Language. Translators are allowed to support any subset of the available execution modes.
|Execution Interface||Command interface(s)||Description|
A query corresponding to a SQL SELECT or set query statement.
An insert, update, or delete, corresponding to a SQL INSERT, UPDATE, or DELETE command
A procedure execution that may return a result set and/or output values.
Types of Execution Modes
All of the execution interfaces extend the base
Execution interface that defines how executions are cancelled and closed. ProcedureExecution also extends ResultSetExecution, since procedures may also return resultsets.
org.teiid.translator.ExecutionContext provides a considerable amount of information related to the current execution. An
ExecutionContext instance is made available to each
Execution. Specific usage is highlighted in this guide where applicable, but you may use any informational getter method as desired. Example usage would include calling
ExecutionContext.getSession(), etc. for logging purposes.
org.teiid.CommandContext is available via the
ExecutionContext.getCommandContext() method. The CommandContext contains information about the current user query, including the
VDB, the ability to add client warnings -
addWarning, or handle generated keys -
To see if the user query expects generated keys to be returned, consult the
CommandContext.isReturnAutoGeneratedKeys() method. If you wish to return generated keys, you must first create a
GeneratedKeys instance to hold the keys with the
returnGeneratedKeys method passing the column names and types of the key columns. Only one
GeneratedKeys may be associated with the
CommandContext at any given time.
The Teiid Spring Boot source meta-hint is used to provide hints directly to source executions via user or transformation queries. See the reference for more on source hints. If specified and applicable, the general and source specific hint will be supplied via the ExecutionContext methods
getSourceHint. See the source for the
OracleExecutionFactory for an example of how this source hint information can be utilized.
Typically most commands executed against translators are QueryExpression. While the command is being executed, the translator provides results via the ResultSetExecution’s "next" method. The "next" method should return null to indicate the end of results. Note: the expected batch size can be obtained from the
ExecutionContext.getBatchSize() method and used as a hint in fetching results from the EIS.
Each execution returns the update count(s) expected by the update command. If possible BatchedUpdates should be executed atomically. The
ExecutionContext.isTransactional() method can be used to determine if the execution is already under a transaction.
Procedure commands correspond to the execution of a stored procedure or some other functional construct. A procedure takes zero or more input values and can return a result set and zero or more output values. Examples of procedure execution would be a stored procedure in a relational database or a call to a web service.
If a result set is expected when a procedure is executed, all rows from it will be retrieved via the ResultSetExecution interface first. Then, if any output values are expected, they will be retrieved via the getOutputParameterValues() method.
In some scenarios, a translator needs to execute asynchronously and allow the executing thread to perform other work. To allow asynchronous execution, you should throw a
DataNotAvailableExecption during a retrieval method, rather than explicitly waiting or sleeping for the results. The
DataNotAvailableException may take a delay parameter or a
Date in its constructor to indicate when to poll next for results. Any non-negative delay value indicates the time in milliseconds until the next polling should be performed. The
DataNotAvailableException.NO_POLLING exception (or any DataNotAvailableException with a negative delay) can be thrown to indicate that the execution will call
ExecutionContext.dataAvailable() to indicate processing should resume.
|Since the execution and the associated connection are not closed until the work has completed, care should be taken if using asynchronous executions that hold a lot of state.|
A positive retry delay is not a guarantee of when the translator will be polled next. If the
DataNotAvailableException is consumed while the engine thinks more work can be performed or there are other shorter delays issued from other translators, then the plan may be re-queued earlier than expected. You should simply rethrow a
DataNotAvailableException if your execution is not yet ready. Alternatively the
DataNotAvailableException may be marked as strict, which does provide a guarantee that the
Execution will not be called until the delay has expired or the given
Date has been reached. Using the
Date constructor makes the
DataNotAvailableException automatically strict. Due to engine thread pool contention, platform time resolution, etc. a strict
DataNotAvailableException is not a real-time guarantee of when the next poll for results will occur, only that it will not occur before then.
A translator may return instances of
ReusableExecutions for the expected Execution objects. There can be one
ReusableExecution per query executing node in the processing plan. The lifecycle of a
ReusableExecution is different that a normal
Execution. After a normal creation/execute/close cycle the
ReusableExecution.reset is called for the next execution cycle. This may occur indefinitely depending on how many times a processing node executes its query. The behavior of the
close method is no different than a regular
Execution, it may not be called until the end of the statement if lobs are detected and any connection associated with the
Execution will also be closed. When the user command is finished, the
ReusableExecution.dispose() method will be called.
ReusableExecutions are most useful for continuous query
execution and will also make use of the
ExecutionCotext.dataAvailable() method for Asynchronous Executions. See the Client Developer’s Guide for executing continuous statements. In continuous mode the user query will be continuously re-executed. A
ReusableExecution allows the same
Execution object to be associated with the processing plan for a given processing node for the lifetime of the user query. This can simplify asynch resource management, such as establishing queue listeners. Returning a null result from the
ReusableExecution just as with normal
Executions indicates that the current pushdown command results have ended. Once the
reset() method has been called, the next set of results should be returned again terminated with a null result.
Insert, Update, Delete commands may have multi-valued
Parameter objects if the capabilities shows support for BulkUpdate. Commands with multi-valued
Parameters represent multiple executions of the same command with different values. As with BatchedUpdates, bulk operations should be executed atomically if possible.
All normal command executions end with the calling of
close() on the Execution object. Your implementation of this method should do the appropriate clean-up work for all state created in the Execution object.
Commands submitted to Teiid Spring Boot may be aborted in several scenarios:
Client cancellation via the JDBC API (or other client APIs)
Clean-up during session termination
Clean-up if a query fails during processing Unlike the other execution methods, which are handled in a single-threaded manner, calls to cancel happen asynchronously with respect to the execution thread.
Your connector implementation may choose to do nothing in response to this cancellation message. In this instance, Teiid Spring Boot will call close() on the execution object after current processing has completed. Implementing the cancel() method allows for faster termination of queries being processed and may allow the underlying data source to terminate its operations faster as well.