... |
The {{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.getRequestId()}}, {{ExecutionContext.getSession()}}, etc. for logging purposes. |
h2. A {{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 - {{isReturnAutoGeneratedKeys}}, {{returnGeneratedKeys}}, and {{getGeneratedKeys}}. |
|
h3. 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. |
h2. Source Hints |
... |
The Teiid 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 |
---|---|---|
ResultSetExecution | QueryExpression | A query corresponding to a SQL SELECT or set query statement. |
UpdateExecution | Insert, Update, Delete, BatchedUpdates | An insert, update, or delete, corresponding to a SQL INSERT, UPDATE, or DELETE command |
ProcedureExecution | Call | 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.
The 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.getRequestId(), ExecutionContext.getSession(), etc. for logging purposes.
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 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 getGeneralHint and 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.
A DataNotAvailableException should not be thrown by the execute method, as that can result in the execute method being called multiple times. |
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.
If your ExecutionFactory returns only asynch executions that perform minimal work, then consider having ExecutionFactory.isForkable return false so that the engine knows not to spawn a separate thread for accessing your Execution. |
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.
In general 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 next() method 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.
See the kit examples for a reusable execution example.
Non batched Insert, Update, Delete commands may have multi-valued Parameter objects if the capabilities shows support for BulkUpdate. Commands with multi-valued {{Parameters}}s 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 may be aborted in several scenarios:
Your connector implementation may choose to do nothing in response to this cancellation message. In this instance, Teiid 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.