public interface DBConnection
Connection to the "database" (whatever is the type or whether it is linked to a true DBMS connection).
It lets executing ADQL queries and updating the TAP datamodel (with the list of schemas, tables and columns published in TAP, or with uploaded tables).
IMPORTANT:
This connection aims only to provide a common and known interface for any kind of database connection.
A connection MUST be opened/created and closed/freed ONLY by the TAPFactory
, which will usually merely wrap
the real database connection by a DBConnection
object. That's why this interface does not provide anymore
a close() function.
Modifier and Type | Method and Description |
---|---|
boolean |
addUploadedTable(TAPTable tableDef,
TableIterator data)
Add the defined and given table inside the TAP_UPLOAD schema.
|
void |
cancel(boolean rollback)
Stop the execution of the current query.
|
boolean |
dropUploadedTable(TAPTable tableDef)
Drop the specified uploaded table from the database.
|
void |
endQuery()
End the last query performed by this
DBConnection and free some associated resources
opened just for this last query. |
TableIterator |
executeQuery(ADQLQuery adqlQuery)
Let executing the given ADQL query.
|
java.lang.String |
getID()
Get any identifier for this connection.
|
TAPMetadata |
getTAPSchema()
Fetch the whole content of TAP_SCHEMA.
|
void |
setFetchSize(int size)
Set the number of rows to fetch before searching/getting the following.
|
void |
setTAPSchema(TAPMetadata metadata)
Empty and then fill all the TAP_SCHEMA tables with the given list of metadata.
|
java.lang.String getID()
Get any identifier for this connection.
note: it is used only for logging purpose.
TAPMetadata getTAPSchema() throws DBException
Fetch the whole content of TAP_SCHEMA.
This function SHOULD be used only once: at the starting of the TAP service. It is an alternative way
to get the published schemas, tables and columns. The other way is to build a TAPMetadata
object
yourself in function of the schemas/tables/columns you want to publish (i.e. which can be done by reading
metadata from a XML document - following the same schema - XSD- as for the TAP resource tables)
and then to load them in the DB (see setTAPSchema(TAPMetadata)
for more details).
CAUTION: This function MUST NOT be used if the tables to publish or the standard TAP_SCHEMA tables have names in DB different from the ones defined by the TAP standard. So, if DB names are different from the ADQL names, you have to write yourself a way to get the metadata from the DB.
Important note: If the schema or some standard tables or columns are missing, TAP_SCHEMA will be considered as incomplete and an exception will be thrown.
Note: This function MUST be able to read the standard tables and columns described by the IVOA. All other tables/columns will be merely ignored.
DBException
- If TAP_SCHEMA can not be found, is incomplete or if some important metadata can not be retrieved.void setTAPSchema(TAPMetadata metadata) throws DBCancelledException, DBException
Empty and then fill all the TAP_SCHEMA tables with the given list of metadata.
This function SHOULD be used only once: at the starting of the TAP service, when metadata are loaded from a XML document (following the same schema - XSD- as for the TAP resource tables).
THIS FUNCTION IS MANIPULATING THE SCHEMAS AND TABLES OF YOUR DATABASE. SO IT SHOULD HAVE A SPECIFIC BEHAVIOR DESCRIBED BELOW. SO PLEASE READ THE FOLLOWINGS AND TRY TO RESPECT IT AS MUCH AS POSSIBLE IN THE IMPLEMENTATIONS
This function MAY drop and then re-create the schema TAP_SCHEMA and all its tables listed in the TAP standard (TAP_SCHEMA.schemas, .tables, .columns, .keys and .key_columns). All other tables inside TAP_SCHEMA SHOULD NOT be modified!
The schema and the tables MUST be created using either the standard definition or the
definition provided in the TAPMetadata
object (if provided). Indeed, if your definition of these TAP tables
is different from the standard (i.e. the standard + new elements), you MUST provide your modifications in parameter
through the TAPMetadata
object so that they can be applied and taken into account in TAP_SCHEMA.
Note:
DB names provided in the given TAPMetadata (see TAPTable.getDBSchemaName()
, TAPTable.getDBName()
and TAPColumn.getDBName()
)
are used for the creation and filling of the tables.
Whether these requests must be case sensitive or not SHOULD be managed by ADQLTranslator.
This object MUST contain all schemas, tables and columns that MUST be published. All its content will be used in order to fill the TAP_SCHEMA tables.
Of course, TAP_SCHEMA and its tables MAY be provided in this object. But:
TAPMetadata
object AND into TAP_SCHEMA.
TAPMetadata
object AND into TAP_SCHEMA.
Note: By default, all implementations of this interface in the TAP library will fill only standard columns and tables of TAP_SCHEMA. To fill your own, you MUST implement yourself this interface or to extend an existing implementation.
WARNING: (b) lets consider a TAP_SCHEMA different from the standard one. BUT, these differences MUST be only additions, NOT modifications or deletion of the standard definition! This function MUST be able to work AT LEAST on a standard definition of TAP_SCHEMA.
The TAP_SCHEMA tables SHOULD be completely emptied (in SQL: "DELETE FROM <table_name>;" or merely "DROP TABLE <table_name>") before insertions can be processed.
If any error occurs while executing any "DB" queries (in SQL: DROP, DELETE, INSERT, CREATE, ...), all queries executed before in this function MUST be canceled (in SQL: ROLLBACK).
metadata
- List of all schemas, tables, columns and foreign keys to insert in the TAP_SCHEMA.DBCancelledException
- If cancel(boolean)
has been called during the processing.DBException
- If any error occurs while updating the database.boolean addUploadedTable(TAPTable tableDef, TableIterator data) throws DBCancelledException, DBException, DataReadException
If the TAP_UPLOAD schema does not already exist, it will be created.
note: A table of TAP_UPLOAD MUST be transient and persistent only for the lifetime of the query.
So, this function should always be used with dropUploadedTable(TAPTable)
, which is called at
the end of each query execution.
tableDef
- Definition of the table to upload (list of all columns and of their type).data
- Rows and columns of the table to upload.DBCancelledException
- If cancel(boolean)
has been called during the processing.DBException
- If any error occurs while adding the table.DataReadException
- If any error occurs while reading the given data (particularly if any limit - in byte or row - set in the TableIterator is reached).boolean dropUploadedTable(TAPTable tableDef) throws DBException
Drop the specified uploaded table from the database. More precisely, it means dropping a table from the TAP_UPLOAD schema.
Note: This function SHOULD drop only one table. So, if more than one table match in the "database" to the given one, an exception MAY be thrown. This behavior is implementation-dependent.
tableDef
- Definition of the uploaded table to drop (the whole object is needed in order to get the DB schema and tables names).DBException
- If any error occurs while dropping the specified uploaded table.TableIterator executeQuery(ADQLQuery adqlQuery) throws DBCancelledException, DBException
Let executing the given ADQL query.
The result of this query must be formatted as a table, and so must be iterable using a TableIterator
.
note: the interpretation of the ADQL query is up to the implementation. In most of the cases, it is just needed to translate this ADQL query into an SQL query (understandable by the chosen DBMS).
IMPORTANT:
A DBConnection
implementation may open resources to perform the query and get the result,
but it may especially KEEP them OPENED in order to let the returned TableIterator
iterates on
the result set. So that closing these resources, the function endQuery()
should be called
when the result is no longer needed. A good implementation of TableIterator
SHOULD call this
function when TableIterator.close()
is called. So, do not forget to call TableIterator.close()
when you do not need any more the query result.
adqlQuery
- ADQL query to execute.DBCancelledException
- If cancel(boolean)
has been called (i.e. query aborted) during the processing.DBException
- If any errors occurs while executing the query.endQuery()
,
TableIterator.close()
void setFetchSize(int size)
Set the number of rows to fetch before searching/getting the following. Thus, rows are fetched by block whose the size is set by this function.
This feature may not be supported. In such case or if an exception occurs while setting the fetch size, this function must not send any exception and the connection stays with its default fetch size. A message may be however logged.
Note:
The "fetch size" should be taken into account only for SELECT queries executed by executeQuery(ADQLQuery)
.
This feature is generally implemented by JDBC drivers using the V3 protocol. Thus, here is how the PostgreSQL JDBC documentation (https://jdbc.postgresql.org/documentation/head/query.html#query-with-cursor) describes this feature:
By default the driver collects all the results for the query at once. This can be inconvenient for large data sets so the JDBC driver provides a means of basing a ResultSet on a database cursor and only fetching a small number of rows.
A small number of rows are cached on the client side of the connection and when exhausted the next block of rows is retrieved by repositioning the cursor.
size
- Blocks size (in number of rows) to fetch.void cancel(boolean rollback)
Stop the execution of the current query.
If asked, a rollback of the current transaction can also be performed before the function returns. This rollback operation is totally independent from the cancellation. It means that the rollback is always performed whatever is the cancellation result (or whatever the cancellation can be performed or not).
This function should never throw any kind of exception. This is particularly important in the following cases:
However, if an exception occurs it should be directly logged at least as a WARNING.
rollback
- true
to cancel the statement AND rollback the current connection transaction,
false
to just cancel the statement.void endQuery()
End the last query performed by this DBConnection
and free some associated resources
opened just for this last query.
Originally, this function aims to be called when the result of executeQuery(ADQLQuery)
is no longer needed, in order to clean/free what the DBConnection
needed to keep this
result set open. In other words, if we take the example of a JDBC connection, this function will
close the ResultSet
, the Statement
and will end any transaction eventually opened
by the DBConnection
(for instance if a fetchSize is set).
However, this function could also be used after any other operation performed by the DBConnection
.
You should just be aware that, depending of the implementation, if a transaction has been opened, this
function may end it, which means generally that a rollback is performed.
Similarly, since it is supposed to end any query lastly performed, this function must also cancel
any processing. So, the function cancel(boolean)
should be called.
Finally, like cancel(boolean)
, this function should never throw any kind of exception.
If internally an exception occurs, it should be directly logged at least as a WARNING.