public class ADQLExecutor
extends java.lang.Object
Let process completely an ADQL query.
Thus, this class aims to apply the following actions (in the given order):
This executor is able to process queries coming from a synchronous job (the result must be written directly in the HTTP response)
and from an asynchronous job (the result must be written, generally, in a file). Two start(...) functions let deal with
the differences between the two job execution modes: start(AsyncThread)
for asynchronous jobs
and start(Thread, String, TAPParameters, HttpServletResponse)
for synchronous jobs.
Uploaded tables must be provided in VOTable format.
Query results must be formatted in the format specified by the user in the job parameters. A corresponding formatter (OutputFormat
)
is asked to the description of the TAP service (ServiceConnection
). If none can be found, VOTable will be chosen by default.
It is totally possible to customize some parts of the ADQL query processing. However, the main algorithm must remain the same and is implemented
by start()
. This function is final, like start(AsyncThread)
and start(Thread, String, TAPParameters, HttpServletResponse)
,
which are just preparing the execution for start()
in function of the job execution mode (asynchronous or synchronous).
Note:
start()
is using the Template Method Design Pattern: it defines the skeleton/algorithm of the processing, and defers some steps
to other functions.
So, you are able to customize almost all individual steps of the ADQL query processing: parseADQL()
, executeADQL(ADQLQuery)
and
writeResult(TableIterator, OutputFormat, OutputStream)
.
Note: Note that the formatting of the result is done by an OutputFormat and that the executor is just calling the appropriate function of the formatter.
There is no way in this executor to customize the upload. However, it does not mean it can not be customized.
Indeed you can do it easily by extending Uploader
and by providing the new class inside your TAPFactory
implementation
(see TAPFactory.createUploader(DBConnection)
).
Modifier and Type | Field and Description |
---|---|
protected TAPLog |
logger
The logger to use.
|
protected TAPExecutionReport |
report
The execution report to fill gradually while the processing of the query.
|
protected javax.servlet.http.HttpServletResponse |
response
The HTTP response in which the query execution must be written.
|
protected ServiceConnection |
service
Description of the current TAP service.
|
protected TAPParameters |
tapParams
List of all TAP parameters needed for the query execution (and particularly the ADQL query itself).
|
protected java.lang.Thread |
thread
The thread which is using this executor.
|
protected TAPSchema |
uploadSchema
Description of the ADQL schema containing all the tables uploaded by the user for this specific query execution.
|
Constructor and Description |
---|
ADQLExecutor(ServiceConnection service)
Build an
ADQLExecutor . |
Modifier and Type | Method and Description |
---|---|
void |
cancelQuery()
Cancel the current SQL query execution or result set fetching if any is currently running.
|
protected void |
dropUploadedTables()
Drop all tables uploaded by the user from the database.
|
protected TableIterator |
executeADQL(ADQLQuery adql)
Execute in "database" the given object representation of an ADQL query.
|
TAPExecutionReport |
getExecReport()
Get the report of the query execution.
|
protected OutputFormat |
getFormatter()
Get the object to use in order to write the query result in the appropriate format
(either the asked one, or else VOTable).
|
TAPLog |
getLogger()
Get the logger used by this executor.
|
void |
initDBConnection(java.lang.String jobID)
Create the database connection required for the ADQL execution.
|
protected ADQLQuery |
parseADQL()
Parse the ADQL query provided in the parameters by the user.
|
protected TAPExecutionReport |
start()
Process the ADQL query.
|
TAPExecutionReport |
start(AsyncThread thread)
Start the asynchronous processing of the ADQL query.
|
TAPExecutionReport |
start(java.lang.Thread thread,
java.lang.String jobId,
TAPParameters params,
javax.servlet.http.HttpServletResponse response)
Start the synchronous processing of the ADQL query.
|
protected void |
writeResult(TableIterator queryResult)
Write the given query result into the appropriate format in the appropriate output
(HTTP response for a synchronous execution, otherwise a file or any output provided by UWS).
|
protected void |
writeResult(TableIterator queryResult,
OutputFormat formatter,
java.io.OutputStream output)
Format and write the given result in the given output with the given formatter.
|
protected final ServiceConnection service
protected final TAPLog logger
protected java.lang.Thread thread
protected TAPParameters tapParams
protected TAPSchema uploadSchema
protected javax.servlet.http.HttpServletResponse response
protected TAPExecutionReport report
public ADQLExecutor(ServiceConnection service)
ADQLExecutor
.service
- The description of the TAP service.public final TAPLog getLogger()
public final TAPExecutionReport getExecReport()
Get the report of the query execution. It helps indicating the execution progression and the duration of each step.
Note: Before starting the execution (= before the call of a "start(...)" function), this function will return NULL. It is set when the query processing starts and remains not NULL after that (even when the execution is finished).
protected OutputFormat getFormatter() throws TAPException
Get the object to use in order to write the query result in the appropriate format (either the asked one, or else VOTable).
TAPException
- If no format corresponds to the asked one and if no default format (for VOTable) can be found.ServiceConnection.getOutputFormat(String)
public final TAPExecutionReport start(AsyncThread thread) throws UWSException, java.lang.InterruptedException
Start the asynchronous processing of the ADQL query.
This function initialize the execution report, get the execution parameters (including the query to process)
and then call start()
.
thread
- The asynchronous thread which asks the query processing.UWSException
- If any error occurs while executing the ADQL query.java.lang.InterruptedException
- If the job has been interrupted (by the user or a time-out).start()
public final void initDBConnection(java.lang.String jobID) throws TAPException
Create the database connection required for the ADQL execution.
Note: This function has no effect if the DB connection already exists.
jobID
- ID of the job which will be executed by this ADQLExecutor
.
This ID will be the database connection ID.TAPException
- If the DB connection creation fails.TAPFactory.getConnection(String)
public final void cancelQuery()
public final TAPExecutionReport start(java.lang.Thread thread, java.lang.String jobId, TAPParameters params, javax.servlet.http.HttpServletResponse response) throws TAPException, java.io.IOException, java.lang.InterruptedException
Start the synchronous processing of the ADQL query.
This function initialize the execution report and then call start()
.
thread
- The synchronous thread which asks the query processing.jobId
- ID of the corresponding job.params
- All execution parameters (including the query to process).response
- Object in which the result or the error must be written.TAPException
- If any error occurs while executing the ADQL query.java.io.IOException
- If any error occurs while writing the result in the given HttpServletResponse
.java.lang.InterruptedException
- If the job has been interrupted (by the user or a time-out).start()
protected final TAPExecutionReport start() throws TAPException, UWSException, java.io.IOException, java.lang.InterruptedException
Process the ADQL query.
This function calls the following function (in the same order):
TAPFactory.getConnection(String)
uploadTables()
parseADQL()
executeADQL(ADQLQuery)
writeResult(TableIterator)
dropUploadedTables()
TAPFactory.freeConnection(DBConnection)
The execution report is updated gradually. Besides a job parameter - progression - is set at each step of the process in order to notify the user of the progression of the query execution. This parameter is removed at the end of the execution if it is successful.
The "interrupted" flag of the associated thread is often tested so that stopping the execution as soon as possible.
TAPException
- If any error occurs while executing the ADQL query.UWSException
- If any error occurs while executing the ADQL query.java.io.IOException
- If an error happens while writing the result in the specified HttpServletResponse
.
That kind of error can be thrown only in synchronous mode.
In asynchronous, the error is stored as job error report and is never propagated.java.lang.InterruptedException
- If the job has been interrupted (by the user or a time-out).protected ADQLQuery parseADQL() throws ParseException, java.lang.InterruptedException, TAPException
Parse the ADQL query provided in the parameters by the user.
The query factory and the query checker are got from the TAP factory.
The configuration of this TAP service list all allowed coordinate systems. These are got here and provided to the query checker in order to ensure the coordinate systems used in the query are in this list.
The row limit specified in the ADQL query (with TOP) is checked and adjusted (if needed). Indeed, this limit can not exceed MAXREC given in parameter and the maximum value specified in the configuration of this TAP service. In the case no row limit is specified in the query or the given value is greater than MAXREC, (MAXREC+1) is used by default. The "+1" aims to detect overflows.
ParseException
- If the given ADQL query can not be parsed or if the construction of the object representation has failed.java.lang.InterruptedException
- If the thread has been interrupted.TAPException
- If the TAP factory is unable to create the ADQL factory or the query checker.protected TableIterator executeADQL(ADQLQuery adql) throws java.lang.InterruptedException, DBCancelledException, TAPException
Execute in "database" the given object representation of an ADQL query.
By default, this function is just calling DBConnection.executeQuery(ADQLQuery)
and then it returns the value returned by this call.
Note: An INFO message is logged at the end of the query execution in order to report the result status (success or error) and the execution duration.
adql
- The object representation of the ADQL query to execute.java.lang.InterruptedException
- If the thread has been interrupted.DBCancelledException
- If the inner DB connection has been canceled.TAPException
- If the DBConnection
has failed to deal with the given ADQL query.DBConnection.executeQuery(ADQLQuery)
protected final void writeResult(TableIterator queryResult) throws java.lang.InterruptedException, java.io.IOException, TAPException, UWSException
Write the given query result into the appropriate format in the appropriate output (HTTP response for a synchronous execution, otherwise a file or any output provided by UWS).
This function prepare the output in function of the execution type (synchronous or asynchronous).
Once prepared, the result, the output and the formatter to use are given to writeResult(TableIterator, OutputFormat, OutputStream)
which will really process the result formatting and writing.
queryResult
- The result of the query execution in database.java.lang.InterruptedException
- If the thread has been interrupted.java.io.IOException
- If an error happens while writing the result in the HttpServletResponse
.
That kind of error can be thrown only in synchronous mode.
In asynchronous, the error is stored as job error report and is never propagated.TAPException
- If an error occurs while getting the appropriate formatter or while formatting or writing (synchronous execution) the result.UWSException
- If an error occurs while getting the output stream or while writing (asynchronous execution) the result.writeResult(TableIterator, OutputFormat, OutputStream)
protected void writeResult(TableIterator queryResult, OutputFormat formatter, java.io.OutputStream output) throws java.lang.InterruptedException, java.io.IOException, TAPException
Format and write the given result in the given output with the given formatter.
By default, this function is just calling OutputFormat.writeResult(TableIterator, OutputStream, TAPExecutionReport, Thread)
.
Note:
OutputFormat.writeResult(TableIterator, OutputStream, TAPExecutionReport, Thread)
is often testing the "interrupted" flag of the
thread in order to stop as fast as possible if the user has cancelled the job or if the thread has been interrupted for another reason.
queryResult
- Query result to format and to output.formatter
- The object able to write the result in the appropriate format.output
- The stream in which the result must be written.java.lang.InterruptedException
- If the thread has been interrupted.java.io.IOException
- If there is an error while writing the result in the given stream.TAPException
- If there is an error while formatting the result.protected void dropUploadedTables() throws TAPException
Drop all tables uploaded by the user from the database.
Note: By default, if an error occurs while dropping a table from the database, the error will just be logged ; it won't be thrown/propagated.
TAPException
- If a grave error occurs. By default, no exception is thrown ; they are just logged.