public class JDBCConnection extends java.lang.Object implements DBConnection
This DBConnection
implementation is theoretically able to deal with any DBMS JDBC connection.
Note: "Theoretically", because its design has been done using information about Postgres, SQLite, Oracle, MySQL, Java DB (Derby) and H2. Then it has been really tested successfully with Postgres, SQLite and H2.
With a single instance of JDBCConnection
it is possible to execute only one query (whatever the type: SELECT, UPDATE, DELETE, ...)
at a time. This is indeed the simple way chosen with this implementation in order to allow the cancellation of any query by managing only
one Statement
. Indeed, only a Statement
has a cancel function able to stop any query execution on the database.
So all queries are executed with the same Statement
. Thus, allowing the execution of one query at a time lets
abort only one query rather than several in once (though just one should have been stopped).
All the following functions are synchronized in order to prevent parallel execution of them by several threads:
addUploadedTable(TAPTable, TableIterator)
, dropUploadedTable(TAPTable)
, executeQuery(ADQLQuery)
,
getTAPSchema()
and setTAPSchema(TAPMetadata)
.
To cancel a query execution the function cancel(boolean)
must be called. No error is returned by this function in case
no query is currently executing. When called, the flag isCancelled()
is set to true
. Any potentially long
running function is checking this flag and may then stop immediately by throwing a DBCancelledException
as soon as
the flag turns true
. It should be the case for addUploadedTable(TAPTable, TableIterator)
,
executeQuery(ADQLQuery)
and setTAPSchema(TAPMetadata)
.
Update queries are taking into account whether the following features are supported by the DBMS:
DBException
;
only executeQuery(ADQLQuery)
will be possibly called.DBConnection
implementation is able to adapt itself in function of the way identifiers are stored and
researched in the database. How the case sensitivity is managed by the DBMS is the problem
of only one function (which can be overwritten if needed): equals(String, String, boolean)
.Warning:
All these features have no impact at all on ADQL query executions (executeQuery(ADQLQuery)
).
All datatype conversions done while fetching a query result (via a ResultSet
)
are done exclusively by the returned TableIterator
(so, here ResultSetTableIterator
).
However, datatype conversions done while uploading a table are done here by the function
convertTypeToDB(DBType)
. This function uses first the conversion function of the translator
(JDBCTranslator.convertTypeToDB(DBType)
), and then defaultTypeConversion(DBType)
if it fails.
In this default conversion, all typical DBMS datatypes are taken into account, EXCEPT the geometrical types (POINT and REGION). That's why it is recommended to use a translator in which the geometrical types are supported and managed.
The possibility to specify a "fetch size" to the JDBC driver (and more exactly to a Statement
) may reveal
very helpful when dealing with large datasets. Thus, it is possible to fetch rows by block of a size represented
by this "fetch size". This is also possible with this DBConnection
thanks to the function setFetchSize(int)
.
However, some JDBC driver or DBMS may not support this feature. In such case, it is then automatically disabled by
JDBCConnection
so that any subsequent queries do not attempt to use it again. The supportsFetchSize
is however reset to true
when setFetchSize(int)
is called.
Note 1:
The "fetch size" feature is used only for SELECT queries executed by executeQuery(ADQLQuery)
. In all other functions,
results of SELECT queries are fetched with the default parameter of the JDBC driver and its Statement
implementation.
Note 2:
By default, this feature is disabled. So the default value of the JDBC driver is used.
To enable it, a simple call to setFetchSize(int)
is enough, whatever is the given value.
Note 3:
Generally set a fetch size starts a transaction in the database. So, after the result of the fetched query
is not needed any more, do not forget to call endQuery()
in order to end the implicitly opened transaction.
However, generally closing the returned TableIterator
is fully enough (see the sources of
ResultSetTableIterator.close()
for more details).
Modifier and Type | Field and Description |
---|---|
protected java.sql.Connection |
connection
JDBC connection (created and initialized at the creation of this
JDBCConnection instance). |
protected static java.lang.String |
COOSYS_ID_COLUMN
Name of the database column giving the coordinate system ID associated
with a TAP column.
|
protected static java.lang.String |
DB_NAME_COLUMN
Name of the database column giving the database name of a TAP column,
table or schema.
|
protected java.util.Map<java.lang.String,java.lang.String> |
dbMapping
Mapping of the TAP_SCHEMA items between their ADQL name and their name in the database.
|
protected java.lang.String |
dbms
Name (in lower-case) of the DBMS with which the connection is linked.
|
protected static java.lang.String |
DBMS_MYSQL
DBMS name of MySQL used in the database URL.
|
protected static java.lang.String |
DBMS_ORACLE
DBMS name of Oracle used in the database URL.
|
protected static java.lang.String |
DBMS_POSTGRES
DBMS name of PostgreSQL used in the database URL.
|
protected static java.lang.String |
DBMS_SQLITE
DBMS name of SQLite used in the database URL.
|
static int |
DEFAULT_FETCH_SIZE
Default fetch size.
|
protected int |
fetchSize
Fetch size to set in the
Statement in charge of executing a SELECT query. |
protected java.lang.String |
ID
Connection ID (typically, the job ID).
|
static int |
IGNORE_FETCH_SIZE
Special fetch size meaning that the JDBC driver is free to set its own guess for this value.
|
static java.lang.String |
JDBC_PREFIX
JDBC prefix of any database URL (for instance: jdbc:postgresql://127.0.0.1/myDB or jdbc:postgresql:myDB).
|
protected TAPLog |
logger
Object to use if any message needs to be logged.
|
protected boolean |
lowerCaseQuoted
Indicate whether the quoted identifiers are stored in lower case in the DBMS.
|
protected boolean |
lowerCaseUnquoted
Indicate whether the unquoted identifiers are stored in lower case in the DBMS.
|
protected boolean |
mixedCaseQuoted
Indicate whether the quoted identifiers are stored in mixed case in the DBMS.
|
protected java.sql.Statement |
stmt
The only
Statement instance that should be used in this JDBCConnection . |
protected boolean |
supportsBatchUpdates
Indicate whether the DBMS supports several updates in once (using
Statement.addBatch(String) and Statement.executeBatch() ). |
protected boolean |
supportsCancel
Indicate whether a DBMS statement is able to cancel a query execution.
|
protected boolean |
supportsDataDefinition
Indicate whether the DBMS supports the definition of data (create, update, drop, insert into schemas and tables).
|
protected boolean |
supportsFetchSize
Indicate whether the last fetch size operation works.
|
protected boolean |
supportsMixedCaseQuotedIdentifier
Indicate whether quoted identifiers will be considered as case INsensitive and stored in mixed case by the DBMS.
|
protected boolean |
supportsMixedCaseUnquotedIdentifier
Indicate whether UNquoted identifiers will be considered as case INsensitive and stored in mixed case by the DBMS.
|
protected boolean |
supportsSchema
Indicate whether the DBMS has the notion of SCHEMA.
|
protected boolean |
supportsTransaction
Indicate whether the DBMS supports transactions (start, commit, rollback and end).
|
protected JDBCTranslator |
translator
The translator this connection must use to translate ADQL into SQL.
|
protected boolean |
upperCaseQuoted
Indicate whether the quoted identifiers are stored in upper case in the DBMS.
|
protected boolean |
upperCaseUnquoted
Indicate whether the unquoted identifiers are stored in upper case in the DBMS.
|
Constructor and Description |
---|
JDBCConnection(java.sql.Connection conn,
JDBCTranslator translator,
java.lang.String connID,
TAPLog logger)
Create a JDBC connection by wrapping the given connection.
|
JDBCConnection(java.lang.String driverPath,
java.lang.String dbUrl,
java.lang.String dbUser,
java.lang.String dbPassword,
JDBCTranslator translator,
java.lang.String connID,
TAPLog logger)
Creates a JDBC connection to the specified database and with the specified JDBC driver.
|
Modifier and Type | Method and Description |
---|---|
boolean |
addUploadedTable(TAPTable tableDef,
TableIterator data)
Important note:
Only tables uploaded by users can be created in the database.
|
void |
cancel(boolean rollback)
Cancel (and rollback when possible) the currently running query of this
JDBCConnection instance. |
protected boolean |
cancel(java.sql.Statement stmt,
boolean rollback)
Cancel (and rollback when asked and if possible) the given statement.
|
protected void |
checkUploadedTableDef(TAPTable tableDef)
Ensures that the given table MUST be inside the upload schema in ADQL.
|
protected void |
close(java.sql.ResultSet rs)
Close silently the given
ResultSet . |
protected void |
close(java.sql.Statement stmt)
Close silently the given
Statement . |
protected void |
closeStatement()
Close the only statement associated with this
JDBCConnection . |
protected void |
commit()
Commit the current transaction.
|
protected java.lang.String |
convertTypeToDB(DBType type)
Convert the given TAP type into the corresponding DBMS column type.
|
protected TableIterator |
createTableIterator(java.sql.ResultSet rs,
DBColumn[] resultingColumns)
Create a
TableIterator instance which lets reading the given result table. |
protected void |
createTAPSchemaTable(TAPTable table,
java.sql.Statement stmt)
Create the specified standard TAP_SCHEMA tables into the database.
|
protected void |
createTAPTableIndexes(TAPTable table,
java.sql.Statement stmt)
Create the DB indexes corresponding to the given TAP_SCHEMA table.
|
protected java.lang.String |
defaultTypeConversion(DBType datatype)
Get the DBMS compatible datatype corresponding to the given column
DBType . |
boolean |
dropUploadedTable(TAPTable tableDef)
Important note:
Only tables uploaded by users can be dropped from the database.
|
void |
endQuery()
End the last query performed by this
DBConnection and free some associated resources
opened just for this last query. |
protected void |
endTransaction()
End the current transaction.
|
protected void |
endTransaction(boolean log)
End the current transaction.
|
protected boolean |
equals(java.lang.String dbName,
java.lang.String metaName,
boolean caseSensitive)
Tell whether the given DB name is equals (case sensitively or not, in function of the given parameter)
to the given name coming from a
TAPMetadata object. |
protected void |
executeBatchUpdates(java.sql.PreparedStatement stmt,
int nbRows)
Execute all batched queries.
|
TableIterator |
executeQuery(ADQLQuery adqlQuery)
Let executing the given ADQL query.
|
protected void |
executeUpdate(java.sql.PreparedStatement stmt,
int indRow)
"Execute" the query update.
|
protected void |
fillTAPSchema(TAPMetadata meta)
Fill all the standard tables of TAP_SCHEMA (schemas, tables, columns, keys and key_columns).
|
protected int |
fillUploadedTable(TAPTable metaTable,
TableIterator data)
Fill the table uploaded by the user with the given data.
|
protected int |
getCreationOrder(TAPMetadata.STDTable table)
Tell when, compared to the other TAP standard tables, a given standard TAP table should be created.
|
protected java.sql.ResultSet |
getDBMetaColumns(java.sql.DatabaseMetaData dbMeta,
java.lang.String schemaPattern,
java.lang.String tablePattern,
java.lang.String columnPattern)
Get all columns matching the given column name pattern and being inside
the specified table(s) and schema(s).
|
protected java.sql.ResultSet |
getDBMetaSchemas(java.sql.DatabaseMetaData dbMeta)
Get all schemas available in the database.
|
protected java.sql.ResultSet |
getDBMetaTables(java.sql.DatabaseMetaData dbMeta,
java.lang.String schemaPattern,
java.lang.String tablePattern)
Get all tables matching the given table name pattern and being inside
the specified schema(s).
|
protected static java.lang.String |
getDBMSName(java.lang.String dbUrl)
Deprecated.
(since 2.1) Should be replaced by
. |
java.lang.String |
getID()
Get any identifier for this connection.
|
java.sql.Connection |
getInnerConnection()
Get the JDBC connection wrapped by this
JDBCConnection object. |
protected java.sql.Statement |
getStatement()
Get the only statement associated with this
JDBCConnection . |
protected TAPSchema |
getStdSchema()
Get the standard definition of TAP_SCHEMA with eventually DB names provided by the set mapping (see
setDBMapping(Map) ). |
protected int |
getTableSchemaIndexInMetadata()
Get the index of the column returning the schema name in the ResultSet
returned by
DatabaseMetaData.getTables(String, String, String, String[]) . |
TAPMetadata |
getTAPSchema()
In this implementation, this function is first creating a virgin
TAPMetadata object
that will be filled progressively by calling the following functions: |
protected boolean |
hasStatement()
Tell whether this
JDBCConnection is already associated with a Statement . |
protected boolean |
isCancelled()
Tell whether the last query execution has been canceled.
|
protected boolean |
isColumnExisting(java.lang.String schemaName,
java.lang.String tableName,
java.lang.String columnName,
java.sql.DatabaseMetaData dbMeta)
Tell whether the specified column exists in the specified table of the database.
|
protected boolean |
isSchemaExisting(java.lang.String schemaName,
java.sql.DatabaseMetaData dbMeta)
Tell whether the specified schema exists in the database.
|
protected TAPMetadata.STDTable |
isStdTable(java.lang.String dbTableName,
TAPTable[] stdTables,
boolean caseSensitive)
Tell whether the specified table (using its DB name only) is a standard one or not.
|
protected boolean |
isTableExisting(java.lang.String schemaName,
java.lang.String tableName,
java.sql.DatabaseMetaData dbMeta)
Tell whether the specified table exists in the database.
|
protected void |
loadColumns(TAPTable tableDef,
java.util.List<TAPTable> lstTables,
java.util.Map<java.lang.String,TAPCoosys> mapCoosys,
java.sql.Statement stmt)
Load into the corresponding tables all columns listed in TAP_SCHEMA.columns.
|
protected void |
loadColumns(TAPTable tableDef,
java.util.List<TAPTable> lstTables,
java.sql.Statement stmt)
Deprecated.
This method is now replaced by
loadColumns(TAPTable, List, Map, Statement) which has an additional parameter:
the list of declared coordinate systems. |
protected java.util.Map<java.lang.String,TAPCoosys> |
loadCoosys(TAPTable tableDef,
TAPMetadata metadata,
java.sql.Statement stmt)
Load all coordinate systems declared in the TAP_SCHEMA.
|
protected void |
loadKeys(TAPTable keysDef,
TAPTable keyColumnsDef,
java.util.List<TAPTable> lstTables,
java.sql.Statement stmt)
Load into the corresponding tables all keys listed in TAP_SCHEMA.keys and detailed in TAP_SCHEMA.key_columns.
|
protected void |
loadSchemas(TAPTable tableDef,
TAPMetadata metadata,
java.sql.Statement stmt)
Load into the given metadata all schemas listed in TAP_SCHEMA.schemas.
|
protected java.util.List<TAPTable> |
loadTables(TAPTable tableDef,
TAPMetadata metadata,
java.sql.Statement stmt)
Load into the corresponding metadata all tables listed in TAP_SCHEMA.tables.
|
protected TAPTable[] |
mergeTAPSchemaDefs(TAPMetadata metadata)
Merge the definition of TAP_SCHEMA tables given in parameter with the definition provided in the TAP standard.
|
protected java.lang.String |
nullifyIfNeeded(java.lang.String dbValue)
Return NULL if the given column value is an empty string (or it just contains space characters) or NULL.
|
protected void |
resetCancel()
Reset the
cancelled flag to false . |
protected void |
resetTAPSchema(java.sql.Statement stmt,
TAPTable[] stdTables)
Ensure the TAP_SCHEMA schema exists in the database AND it must especially drop all of its standard tables
(schemas, tables, columns, keys and key_columns), if they exist.
|
protected void |
rollback()
Rollback the current transaction.
|
protected void |
rollback(boolean log)
Rollback the current transaction.
|
void |
setDBMapping(java.util.Map<java.lang.String,java.lang.String> mapping)
Let specify for all item of the standard TAP_SCHEMA a different name in the database.
|
void |
setFetchSize(int size)
Set the number of rows to fetch before searching/getting the following.
|
void |
setTAPSchema(TAPMetadata metadata)
This function is just calling the following functions:
|
protected void |
startTransaction()
Start a transaction.
|
protected boolean |
toBoolean(java.lang.Object colValue)
Transform the given column value in a boolean value.
|
protected static final java.lang.String DBMS_POSTGRES
protected static final java.lang.String DBMS_SQLITE
protected static final java.lang.String DBMS_MYSQL
protected static final java.lang.String DBMS_ORACLE
protected static final java.lang.String DB_NAME_COLUMN
protected static final java.lang.String COOSYS_ID_COLUMN
protected final java.lang.String ID
protected final java.sql.Connection connection
JDBCConnection
instance).protected java.sql.Statement stmt
The only Statement
instance that should be used in this JDBCConnection
.
Having the same Statement
for all the interactions with the database lets cancel any when needed (e.g. when the execution is too long).
This statement is by default NULL ; it must be initialized by the function getStatement()
.
protected final JDBCTranslator translator
protected final TAPLog logger
public static final java.lang.String JDBC_PREFIX
protected final java.lang.String dbms
protected boolean supportsTransaction
protected boolean supportsDataDefinition
setTAPSchema(TAPMetadata)
) and to upload/drop tables (see addUploadedTable(TAPTable, TableIterator)
and dropUploadedTable(TAPTable)
).protected boolean supportsBatchUpdates
Statement.addBatch(String)
and Statement.executeBatch()
). note: If not supported, every updates will be done one by one. So it is not really a problem, but just a loss of optimization.protected boolean supportsSchema
protected boolean supportsCancel
Indicate whether a DBMS statement is able to cancel a query execution.
Since this information is not provided by DatabaseMetaData
a first attempt is always performed.
In case a SQLFeatureNotSupportedException
is caught, this flag is set to false preventing any further
attempt of canceling a query.
protected boolean supportsMixedCaseUnquotedIdentifier
lowerCaseUnquoted
and upperCaseUnquoted
). If none of these two flags is TRUE, the storage case will be though considered as mixed.protected boolean lowerCaseUnquoted
protected boolean upperCaseUnquoted
protected boolean supportsMixedCaseQuotedIdentifier
lowerCaseQuoted
, upperCaseQuoted
and mixedCaseQuoted
). If none of these three flags is TRUE, the storage case will be mixed case.protected boolean lowerCaseQuoted
protected boolean mixedCaseQuoted
protected boolean upperCaseQuoted
public static final int IGNORE_FETCH_SIZE
public static final int DEFAULT_FETCH_SIZE
IGNORE_FETCH_SIZE
.protected boolean supportsFetchSize
Indicate whether the last fetch size operation works.
By default, this attribute is set to false
, meaning that the "fetch size" feature is
disabled. To enable it, a simple call to setFetchSize(int)
is enough, whatever is the given value.
If just once this operation fails, the fetch size feature will be always considered as unsupported in this JDBCConnection
until the next call of setFetchSize(int)
.
protected int fetchSize
Fetch size to set in the Statement
in charge of executing a SELECT query.
Note 1: this value must always be positive. If negative or null, it will be ignored and the Statement
will keep its default behavior.
Note 2: if this feature is enabled (i.e. has a value > 0), the AutoCommit will be disabled.
protected java.util.Map<java.lang.String,java.lang.String> dbMapping
IMPORTANT: Keys of the map MUST be the full ADQL name of an item (e.g. TAP_SCHEMA, TAP_SCHEMA.tables, TAP_SCHEMA.columns.ucd). Values MUST be the name of the corresponding item in the database. Keys and values are case sensitive.
public JDBCConnection(java.lang.String driverPath, java.lang.String dbUrl, java.lang.String dbUser, java.lang.String dbPassword, JDBCTranslator translator, java.lang.String connID, TAPLog logger) throws DBException
Creates a JDBC connection to the specified database and with the specified JDBC driver. This connection is established using the given user name and password.
note: the JDBC driver is loaded using Class.forName(driverPath)
and the connection is created with DriverManager.getConnection(dbUrl, dbUser, dbPassword)
.
Warning:
This constructor really creates a new SQL connection. Creating a SQL connection is time consuming!
That's why it is recommended to use a pool of connections. When doing so, you should use the other constructor of this class
(JDBCConnection(Connection, JDBCTranslator, String, TAPLog)
).
driverPath
- Full class name of the JDBC driver.dbUrl
- URL to the database. note This URL may not be prefixed by "jdbc:". If not, the prefix will be automatically added.dbUser
- Name of the database user.dbPassword
- Password of the given database user.translator
- ADQLTranslator
to use in order to get SQL from an ADQL query and to get qualified DB table names.connID
- ID of this connection. note: may be NULL ; but in this case, logs concerning this connection will be more difficult to localize.logger
- Logger to use in case of need. note: may be NULL ; in this case, error will never be logged, but sometimes DBException may be raised.DBException
- If the driver can not be found or if the connection can not merely be created (usually because DB parameters are wrong).public JDBCConnection(java.sql.Connection conn, JDBCTranslator translator, java.lang.String connID, TAPLog logger) throws DBException
conn
- Connection to wrap.translator
- ADQLTranslator
to use in order to get SQL from an ADQL query and to get qualified DB table names.connID
- ID of this connection. note: may be NULL ; but in this case, logs concerning this connection will be more difficult to localize.logger
- Logger to use in case of need. note: may be NULL ; in this case, error will never be logged, but sometimes DBException may be raised.DBException
@Deprecated protected static final java.lang.String getDBMSName(java.lang.String dbUrl) throws DBException
DatabaseMetaData.getDatabaseProductName()
.toLowerCase()
.dbUrl
- JDBC URL to access the database. This URL must start with "jdbc:" ; otherwise an exception will be thrown.DBException
- If NULL has been given, if the URL is not a JDBC one (starting with "jdbc:") or if the DBMS name is missing.public final java.lang.String getID()
DBConnection
Get any identifier for this connection.
note: it is used only for logging purpose.
getID
in interface DBConnection
public final java.sql.Connection getInnerConnection()
Get the JDBC connection wrapped by this JDBCConnection
object.
Note: This is the best way to get the JDBC connection in order to properly close it.
protected boolean hasStatement() throws java.sql.SQLException
Tell whether this JDBCConnection
is already associated with a Statement
.
true
if a Statement
instance is already associated with this JDBCConnection
false
otherwise.java.sql.SQLException
- In case the open/close status of the current Statement
instance can not be checked.protected java.sql.Statement getStatement() throws java.sql.SQLException
Get the only statement associated with this JDBCConnection
.
If no Statement
is yet existing, one is created, stored in this JDBCConnection
(for further uses)
and then returned.
Statement
instance associated with this JDBCConnection
. Never NULLjava.sql.SQLException
- In case a Statement
can not be created.protected void closeStatement()
JDBCConnection
.public final void cancel(boolean rollback)
Cancel (and rollback when possible) the currently running query of this JDBCConnection
instance.
Important note:
This function tries canceling the current JDBC statement. This can work only if the JDBC driver and
the DBMS both support this operation. If the statement cancellation fails, the flag supportsCancel
is set to false
so that any subsequent call of this function for this instance of
JDBCConnection
does not try any other cancellation attempt. HOWEVER the rollback will
still continue to be performed if the parameter rollback
is set to true
.
In any case, this function sets anyway the flag isCancelled()
to true
so that after
a DB processing this DBConnection
can interrupt immediately any potentially long running functions
(i.e. addUploadedTable(TAPTable, TableIterator)
, executeQuery(ADQLQuery)
and
setTAPSchema(TAPMetadata)
). When these functions realize this flag is set, they immediately stop
by throwing a DBCancelledException
.
Note 1: A failure of a rollback is not considered as a not supported cancellation feature by the JDBC driver or the DBMS. So if the cancellation succeeds but a rollback fails, a next call of this function will still try canceling the given statement. In case of a rollback failure, only a WARNING is written in the log file ; no exception is thrown.
Note 2:
This function is synchronized on the cancelled
flag.
Thus, it may block until another synchronized block on this same flag is finished.
cancel
in interface DBConnection
rollback
- true
to cancel the statement AND rollback the current connection transaction,
false
to just cancel the statement.DBConnection.cancel(boolean)
,
cancel(Statement, boolean)
protected boolean cancel(java.sql.Statement stmt, boolean rollback)
Cancel (and rollback when asked and if possible) the given statement.
Important note:
This function tries canceling the current JDBC statement. This can work only if the JDBC driver and
the DBMS both support this operation. If the statement cancellation fails, the flag supportsCancel
is set to false
so that any subsequent call of this function for this instance of
JDBCConnection
does not try any other cancellation attempt. HOWEVER the rollback will
still continue to be performed if the parameter rollback
is set to true
.
Note: A failure of a rollback is not considered as a not supported cancellation feature by the JDBC driver or the DBMS. So if the cancellation succeeds but a rollback fails, a next call of this function will still try canceling the given statement. In case of a rollback failure, only a WARNING is written in the log file ; no exception is thrown.
stmt
- The statement to cancel. Note: if closed or NULL, no exception will be thrown and only a rollback will be attempted if asked in parameter.rollback
- true
to cancel the statement AND rollback the current connection transaction,
false
to just cancel the statement.true
if the cancellation succeeded (or none was running),
false
otherwise (and especially if the "cancel" operation is not supported).protected final boolean isCancelled()
Tell whether the last query execution has been canceled.
Note:
This function is synchronized on the cancelled
flag.
Thus, it may block until another synchronized block on this same flag is finished.
true
if the last query execution has been cancelled,
false
otherwise.protected final void resetCancel()
Reset the cancelled
flag to false
.
Note:
This function is synchronized on the cancelled
flag.
Thus, it may block until another synchronized block on this same flag is finished.
public void endQuery()
DBConnection
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 DBConnection.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 DBConnection.cancel(boolean)
should be called.
Finally, like DBConnection.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.
endQuery
in interface DBConnection
public TableIterator executeQuery(ADQLQuery adqlQuery) throws DBException
DBConnection
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 DBConnection.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.
executeQuery
in interface DBConnection
adqlQuery
- ADQL query to execute.DBCancelledException
- If DBConnection.cancel(boolean)
has been called (i.e. query aborted) during the processing.DBException
- If any errors occurs while executing the query.DBConnection.endQuery()
,
TableIterator.close()
protected TableIterator createTableIterator(java.sql.ResultSet rs, DBColumn[] resultingColumns) throws DataReadException
Create a TableIterator
instance which lets reading the given result table.
Note:
The statement currently opened is not closed by this function. Actually, it is still associated with
this JDBCConnection
. However, this latter is provided to the TableIterator
returned by
this function. Thus, when the TableIterator.close()
is called, the function endQuery()
will be called. It will then close the ResultSet
, the Statement
and end any opened
transaction (with rollback). See endQuery()
for more details.
rs
- Result of an SQL query.resultingColumns
- Metadata corresponding to each columns of the result.TableIterator
instance.DataReadException
- If the metadata (columns count and types) can not be fetched
or if any other error occurs.ResultSetTableIterator.ResultSetTableIterator(DBConnection, ResultSet, DBColumn[], JDBCTranslator, String)
protected int getCreationOrder(TAPMetadata.STDTable table)
table
- Standard TAP table.public void setDBMapping(java.util.Map<java.lang.String,java.lang.String> mapping)
For instance: if in the database "TAP_SCHEMA" is called "MY_TAP_SCHEMA".
IMPORTANT: TAP_SCHEMA items (i.e. keys in the map) MUST be fully qualified ADQL names (e.g. TAP_SCHEMA.columns.name). The values MUST be single database names (i.e. no catalogue, schema or table prefix). Both keys and values are case sensitive.
Note: TAP_SCHEMA items keeping the same name in the database than in ADQL do not need to be listed in the given map.
mapping
- Mapping between ADQL names and DB names.
If null
, DB names will be considered equals to the ADQL names.protected TAPSchema getStdSchema()
setDBMapping(Map)
).public TAPMetadata getTAPSchema() throws DBException
In this implementation, this function is first creating a virgin TAPMetadata
object
that will be filled progressively by calling the following functions:
loadSchemas(TAPTable, TAPMetadata, Statement)
loadTables(TAPTable, TAPMetadata, Statement)
loadCoosys(TAPTable, TAPMetadata, Statement)
loadColumns(TAPTable, List, Statement)
loadKeys(TAPTable, TAPTable, List, Statement)
Note: If schemas are not supported by this DBMS connection, the DB name of all tables will be set to NULL and the DB name of all tables will be prefixed by the ADQL name of their respective schema.
getTAPSchema
in interface DBConnection
DBException
- If TAP_SCHEMA can not be found, is incomplete or if some important metadata can not be retrieved.DBConnection.getTAPSchema()
protected void loadSchemas(TAPTable tableDef, TAPMetadata metadata, java.sql.Statement stmt) throws DBException
Load into the given metadata all schemas listed in TAP_SCHEMA.schemas.
Note 1: If schemas are not supported by this DBMS connection, the DB name of the loaded schemas is set to NULL.
Note 2: Schema entries are retrieved ordered by ascending schema_name.
tableDef
- Definition of the table TAP_SCHEMA.schemas.metadata
- Metadata to fill with all found schemas.stmt
- Statement to use in order to interact with the database.DBException
- If any error occurs while interacting with the database.protected java.util.List<TAPTable> loadTables(TAPTable tableDef, TAPMetadata metadata, java.sql.Statement stmt) throws DBException
Load into the corresponding metadata all tables listed in TAP_SCHEMA.tables.
Note 1:
Schemas are searched in the given metadata by their ADQL name and case sensitively.
If they can not be found a DBException
is thrown.
Note 2:
If schemas are not supported by this DBMS connection, the DB name of the loaded
TAPTable
s is prefixed by the ADQL name of their respective schema.
Note 3: If the column table_index exists, table entries are retrieved ordered by ascending schema_name, then table_index, and finally table_name. If this column does not exist, table entries are retrieved ordered by ascending schema_name and then table_name.
tableDef
- Definition of the table TAP_SCHEMA.tables.metadata
- Metadata (containing already all schemas listed in TAP_SCHEMA.schemas).stmt
- Statement to use in order to interact with the database.loadColumns(TAPTable, List, Statement)
.DBException
- If a schema can not be found, or if any other error occurs while interacting with the database.protected java.util.Map<java.lang.String,TAPCoosys> loadCoosys(TAPTable tableDef, TAPMetadata metadata, java.sql.Statement stmt) throws DBException
tableDef
- Definition of the table TAP_SCHEMA.coosys.metadata
- Metadata in which the found coordinate systems will be inserted (see TAPMetadata.addCoosys(TAPCoosys)
).stmt
- Statement to use in order to interact with the database.TAPCoosys
).
note: this map is required by loadColumns(TAPTable, List, Map, Statement)
.DBException
- If any error occurs while interacting with the database.@Deprecated protected void loadColumns(TAPTable tableDef, java.util.List<TAPTable> lstTables, java.sql.Statement stmt) throws DBException
loadColumns(TAPTable, List, Map, Statement)
which has an additional parameter:
the list of declared coordinate systems.Load into the corresponding tables all columns listed in TAP_SCHEMA.columns.
Note:
Tables are searched in the given list by their ADQL name and case sensitively.
If they can not be found a DBException
is thrown.
Note 2: If the column column_index exists, column entries are retrieved ordered by ascending table_name, then column_index, and finally column_name. If this column does not exist, column entries are retrieved ordered by ascending table_name and then column_name.
tableDef
- Definition of the table TAP_SCHEMA.columns.lstTables
- List of all published tables (= all tables listed in TAP_SCHEMA.tables).stmt
- Statement to use in order to interact with the database.DBException
- If a table can not be found, or if any other error occurs while interacting with the database.protected void loadColumns(TAPTable tableDef, java.util.List<TAPTable> lstTables, java.util.Map<java.lang.String,TAPCoosys> mapCoosys, java.sql.Statement stmt) throws DBException
Load into the corresponding tables all columns listed in TAP_SCHEMA.columns.
Note:
Tables are searched in the given list by their ADQL name and case sensitively.
If they can not be found a DBException
is thrown.
Note 2: If the column column_index exists, column entries are retrieved ordered by ascending table_name, then column_index, and finally column_name. If this column does not exist, column entries are retrieved ordered by ascending table_name and then column_name.
tableDef
- Definition of the table TAP_SCHEMA.columns.lstTables
- List of all published tables (= all tables listed in TAP_SCHEMA.tables).mapCoosys
- List of all published coordinate systems (= all coordinates systems listed in TAP_SCHEMA.coosys).stmt
- Statement to use in order to interact with the database.DBException
- If a table can not be found, or if any other error occurs while interacting with the database.protected void loadKeys(TAPTable keysDef, TAPTable keyColumnsDef, java.util.List<TAPTable> lstTables, java.sql.Statement stmt) throws DBException
Load into the corresponding tables all keys listed in TAP_SCHEMA.keys and detailed in TAP_SCHEMA.key_columns.
Note 1:
Tables and columns are searched in the given list by their ADQL name and case sensitively.
If they can not be found a DBException
is thrown.
Note 2: Key entries are retrieved ordered by ascending key_id, then from_table and finally target_table. Key_Column entries are retrieved ordered by ascending from_column and then target_column.
keysDef
- Definition of the table TAP_SCHEMA.keys.keyColumnsDef
- Definition of the table TAP_SCHEMA.key_columns.lstTables
- List of all published tables (= all tables listed in TAP_SCHEMA.tables).stmt
- Statement to use in order to interact with the database.DBException
- If a table or a column can not be found, or if any other error occurs while interacting with the database.public void setTAPSchema(TAPMetadata metadata) throws DBCancelledException, DBException
This function is just calling the following functions:
mergeTAPSchemaDefs(TAPMetadata)
startTransaction()
resetTAPSchema(Statement, TAPTable[])
createTAPSchemaTable(TAPTable, Statement)
for each standard TAP_SCHEMA tablefillTAPSchema(TAPMetadata)
createTAPTableIndexes(TAPTable, Statement)
for each standard TA_SCHEMA tablecommit()
or rollback()
endTransaction()
Important note: If the connection does not support transactions, then there will be merely no transaction. Consequently, any failure (exception/error) will not clean the partial modifications done by this function.
setTAPSchema
in interface DBConnection
metadata
- List of all schemas, tables, columns and foreign keys to insert in the TAP_SCHEMA.DBCancelledException
- If DBConnection.cancel(boolean)
has been called during the processing.DBException
- If any error occurs while updating the database.DBConnection.setTAPSchema(tap.metadata.TAPMetadata)
protected TAPTable[] mergeTAPSchemaDefs(TAPMetadata metadata)
Merge the definition of TAP_SCHEMA tables given in parameter with the definition provided in the TAP standard.
The goal is to get in output the list of all standard TAP_SCHEMA tables. But it must take into account the customized definition given in parameter if there is one. Indeed, if a part of TAP_SCHEMA is not provided, it will be completed here by the definition provided in the TAP standard. And so, if the whole TAP_SCHEMA is not provided at all, the returned tables will be those of the IVOA standard.
Important note: If the TAP_SCHEMA definition is missing or incomplete in the given metadata, it will be added or completed automatically by this function with the definition provided in the IVOA TAP standard.
Note: Only the standard tables of TAP_SCHEMA are considered. The others are skipped (that's to say: never returned by this function ; however, they will stay in the given metadata).
Note: If schemas are not supported by this DBMS connection, the DB name of schemas is set to NULL and the DB name of tables is prefixed by the schema name.
metadata
- Metadata (with or without TAP_SCHEMA schema or some of its table). Must not be NULLgetCreationOrder(tap.metadata.TAPMetadata.STDTable)
).TAPMetadata.resolveStdTable(String)
,
TAPMetadata.getStdSchema(boolean)
,
TAPMetadata.getStdTable(STDTable)
protected void resetTAPSchema(java.sql.Statement stmt, TAPTable[] stdTables) throws java.sql.SQLException
Ensure the TAP_SCHEMA schema exists in the database AND it must especially drop all of its standard tables (schemas, tables, columns, keys and key_columns), if they exist.
Important note: If TAP_SCHEMA already exists and contains other tables than the standard ones, they will not be dropped and they will stay in place.
stmt
- The statement to use in order to interact with the database.stdTables
- List of all standard tables that must be (re-)created.
They will be used just to know the name of the standard tables that should be dropped here.java.sql.SQLException
- If any error occurs while querying or updating the database.protected void createTAPSchemaTable(TAPTable table, java.sql.Statement stmt) throws DBException, java.sql.SQLException
Create the specified standard TAP_SCHEMA tables into the database.
Important note: Only standard TAP_SCHEMA tables (schemas, tables, columns, keys and key_columns) can be created here. If the given table is not part of the schema TAP_SCHEMA (comparison done on the ADQL name case-sensitively) and is not a standard TAP_SCHEMA table (comparison done on the ADQL name case-sensitively), this function will do nothing and will throw an exception.
Note: An extra column is added in TAP_SCHEMA.schemas, TAP_SCHEMA.tables and TAP_SCHEMA.columns: "dbname". This column is particularly used when getting the TAP metadata from the database to alias some schema, table and/or column names in ADQL.
table
- Table to create.stmt
- Statement to use in order to interact with the database.DBException
- If the given table is not a standard TAP_SCHEMA table.java.sql.SQLException
- If any error occurs while querying or updating the database.protected void createTAPTableIndexes(TAPTable table, java.sql.Statement stmt) throws DBCancelledException, DBException, java.sql.SQLException
Create the DB indexes corresponding to the given TAP_SCHEMA table.
Important note: Only standard TAP_SCHEMA tables (schemas, tables, columns, keys and key_columns) can be created here. If the given table is not part of the schema TAP_SCHEMA (comparison done on the ADQL name case-sensitively) and is not a standard TAP_SCHEMA table (comparison done on the ADQL name case-sensitively), this function will do nothing and will throw an exception.
table
- Table whose indexes must be created here.stmt
- Statement to use in order to interact with the database.DBCancelledException
- If cancel(boolean)
has been called during the processing,DBException
- If the given table is not a standard TAP_SCHEMA table.java.sql.SQLException
- If any error occurs while querying or updating the database.protected void fillTAPSchema(TAPMetadata meta) throws java.sql.SQLException, DBCancelledException, DBException
Fill all the standard tables of TAP_SCHEMA (schemas, tables, columns, keys and key_columns).
This function just call the following functions:
meta
- All schemas and tables to list inside the TAP_SCHEMA tables.DBCancelledException
- If cancel(boolean)
has been called during the processing,DBException
- If rows can not be inserted because the SQL update query has failed.java.sql.SQLException
- If any other SQL exception occurs.public boolean addUploadedTable(TAPTable tableDef, TableIterator data) throws DBException, DataReadException
Important note:
Only tables uploaded by users can be created in the database. To ensure that, the schema name of this table MUST be TAPMetadata.STDSchema.UPLOADSCHEMA
("TAP_UPLOAD") in ADQL.
If it has another ADQL name, an exception will be thrown. Of course, the DB name of this schema MAY be different.
Important note:
This function may modify the given TAPTable
object if schemas are not supported by this connection.
In this case, this function will prefix the table's DB name by the schema's DB name directly inside the given
TAPTable
object. Then the DB name of the schema will be set to NULL.
Note: If the upload schema does not already exist in the database, it will be created.
addUploadedTable
in interface DBConnection
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 DBConnection.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).DBConnection.addUploadedTable(tap.metadata.TAPTable, tap.data.TableIterator)
,
checkUploadedTableDef(TAPTable)
protected int fillUploadedTable(TAPTable metaTable, TableIterator data) throws java.sql.SQLException, DBCancelledException, DBException, DataReadException
Fill the table uploaded by the user with the given data.
Note: Batch updates may be done here if its supported by the DBMS connection. In case of any failure while using this feature, it will be flagged as unsupported and one-by-one updates will be processed.
Note: This function proceeds to a formatting of TIMESTAMP and GEOMETRY (point, circle, box, polygon) values.
metaTable
- Description of the updated table.data
- Iterator over the rows to insert.DBCancelledException
- If cancel(boolean)
has been called during the processing,DBException
- If rows can not be inserted because the SQL update query has failed.java.sql.SQLException
- If any other SQL exception occurs.DataReadException
- If there is any error while reading the data from the given TableIterator
(and particularly if a limit - in byte or row - has been reached).public boolean dropUploadedTable(TAPTable tableDef) throws DBException
Important note:
Only tables uploaded by users can be dropped from the database. To ensure that, the schema name of this table MUST be TAPMetadata.STDSchema.UPLOADSCHEMA
("TAP_UPLOAD") in ADQL.
If it has another ADQL name, an exception will be thrown. Of course, the DB name of this schema MAY be different.
Important note:
This function may modify the given TAPTable
object if schemas are not supported by this connection.
In this case, this function will prefix the table's DB name by the schema's DB name directly inside the given
TAPTable
object. Then the DB name of the schema will be set to NULL.
Note: This implementation is able to drop only one uploaded table. So if this function finds more than one table matching to the given one, an exception will be thrown and no table will be dropped.
dropUploadedTable
in interface DBConnection
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.DBConnection.dropUploadedTable(tap.metadata.TAPTable)
,
checkUploadedTableDef(TAPTable)
protected void checkUploadedTableDef(TAPTable tableDef) throws DBException
Ensures that the given table MUST be inside the upload schema in ADQL.
Thus, the following cases are taken into account:
TAPMetadata.STDSchema.UPLOADSCHEMA
("TAP_UPLOAD") in ADQL.
If it has another ADQL name, an exception will be thrown. Of course, the DB name of this schema MAY be different.
TAPTable
object. Then the DB name of the schema will be set to NULL.
tableDef
- Definition of the table to create/drop.DBException
- If the given table is not in a schema
or if the ADQL name of this schema is not TAPMetadata.STDSchema.UPLOADSCHEMA
("TAP_UPLOAD").protected java.lang.String convertTypeToDB(DBType type)
Convert the given TAP type into the corresponding DBMS column type.
This function tries first the type conversion using the translator (JDBCTranslator.convertTypeToDB(DBType)
).
If it fails, a default conversion is done considering all the known types of the following DBMS:
PostgreSQL, SQLite, MySQL, Oracle and JavaDB/Derby.
type
- TAP type to convert.JDBCTranslator.convertTypeToDB(DBType)
,
defaultTypeConversion(DBType)
protected java.lang.String defaultTypeConversion(DBType datatype)
Get the DBMS compatible datatype corresponding to the given column DBType
.
Note 1: This function is able to generate a DB datatype compatible with the currently used DBMS. In this current implementation, only Postgresql, Oracle, SQLite, MySQL and Java DB/Derby have been considered. Most of the TAP types have been tested only with Postgresql and SQLite without any problem. If the DBMS you are using has not been considered, note that this function will return the TAP type expression by default.
Note 2: In case the given datatype is NULL or not managed here, the DBMS type corresponding to "VARCHAR" will be returned.
Note 3: The special TAP types POINT and REGION are converted into the DBMS type corresponding to "VARCHAR".
datatype
- Column TAP type.protected void startTransaction() throws DBException
Start a transaction.
Basically, if transactions are supported by this connection, the flag AutoCommit is just turned off.
It will be turned on again when endTransaction()
is called.
If transactions are not supported by this connection, nothing is done.
Important note: If any error interrupts the START TRANSACTION operation, transactions will be afterwards considered as not supported by this connection. So, subsequent call to this function (and any other transaction related function) will never do anything.
DBException
- If it is impossible to start a transaction though transactions are supported by this connection.
If these are not supported, this error can never be thrown.protected void commit() throws DBException
Commit the current transaction.
startTransaction()
must have been called before. If it's not the case the connection
may throw a SQLException
which will be transformed into a DBException
here.
If transactions are not supported by this connection, nothing is done.
Important note: If any error interrupts the COMMIT operation, transactions will be afterwards considered as not supported by this connection. So, subsequent call to this function (and any other transaction related function) will never do anything.
DBException
- If it is impossible to commit a transaction though transactions are supported by this connection..
If these are not supported, this error can never be thrown.protected final void rollback()
Rollback the current transaction. The success or the failure of the rollback operation is always logged (except if no logger is available).
startTransaction()
must have been called before. If it's not the case the connection
may throw a SQLException
which will be transformed into a DBException
here.
If transactions are not supported by this connection, nothing is done.
Important note: If any error interrupts the ROLLBACK operation, transactions will considered afterwards as not supported by this connection. So, subsequent call to this function (and any other transaction related function) will never do anything.
DBException
- If it is impossible to rollback a transaction though transactions are supported by this connection..
If these are not supported, this error can never be thrown.rollback(boolean)
protected void rollback(boolean log)
Rollback the current transaction.
startTransaction()
must have been called before. If it's not the case the connection
may throw a SQLException
which will be transformed into a DBException
here.
If transactions are not supported by this connection, nothing is done.
Important note: If any error interrupts the ROLLBACK operation, transactions will considered afterwards as not supported by this connection. So, subsequent call to this function (and any other transaction related function) will never do anything.
log
- true
to log the success/failure of the rollback operation,
false
to be quiet whatever happens.DBException
- If it is impossible to rollback a transaction though transactions are supported by this connection..
If these are not supported, this error can never be thrown.protected final void endTransaction()
End the current transaction. The success or the failure of the transaction ending operation is always logged (except if no logger is available).
Basically, if transactions are supported by this connection, the flag AutoCommit is just turned on.
If transactions are not supported by this connection, nothing is done.
Important note: If any error interrupts the END TRANSACTION operation, transactions will be afterwards considered as not supported by this connection. So, subsequent call to this function (and any other transaction related function) will never do anything.
DBException
- If it is impossible to end a transaction though transactions are supported by this connection.
If these are not supported, this error can never be thrown.endTransaction(boolean)
protected void endTransaction(boolean log)
End the current transaction.
Basically, if transactions are supported by this connection, the flag AutoCommit is just turned on.
If transactions are not supported by this connection, nothing is done.
Important note: If any error interrupts the END TRANSACTION operation, transactions will be afterwards considered as not supported by this connection. So, subsequent call to this function (and any other transaction related function) will never do anything.
log
- true
to log the success/failure of the transaction ending operation,
false
to be quiet whatever happens.DBException
- If it is impossible to end a transaction though transactions are supported by this connection.
If these are not supported, this error can never be thrown.protected final void close(java.sql.ResultSet rs)
Close silently the given ResultSet
.
If the given ResultSet
is NULL, nothing (even exception/error) happens.
If any SQLException
occurs during this operation, it is caught and just logged
(see TAPLog.logDB(uws.service.log.UWSLog.LogLevel, DBConnection, String, String, Throwable)
).
No error is thrown and nothing else is done.
rs
- ResultSet
to close.protected final void close(java.sql.Statement stmt)
Close silently the given Statement
.
If the given Statement
is NULL, nothing (even exception/error) happens.
The given statement is explicitly canceled by this function before being closed. Thus the corresponding DBMS process is ensured to be stopped. Of course, this cancellation is effective only if this operation is supported by the JDBC driver and the DBMS.
Important note: In case of cancellation, NO rollback is performed.
If any SQLException
occurs during this operation, it is caught and just logged
(see TAPLog.logDB(uws.service.log.UWSLog.LogLevel, DBConnection, String, String, Throwable)
).
No error is thrown and nothing else is done.
stmt
- Statement
to close.cancel(Statement, boolean)
protected final boolean toBoolean(java.lang.Object colValue)
Transform the given column value in a boolean value.
The following cases are taken into account in function of the given value's type:
Boolean
: the boolean value is returned as provided (but casted in boolean).Integer
: true is returned only if the integer value is strictly greater than 0, otherwise false is returned.colValue
- The column value to transform in boolean.protected final java.lang.String nullifyIfNeeded(java.lang.String dbValue)
dbValue
- Value to nullify if needed.protected int getTableSchemaIndexInMetadata()
DatabaseMetaData.getTables(String, String, String, String[])
.
The index returned by this function may be different from one DBMS from another depending on how it deals with schemas. For instance, in MySQL database, schemas are interpreted as catalogs (so the index would be 2 instead of 1).
protected java.sql.ResultSet getDBMetaSchemas(java.sql.DatabaseMetaData dbMeta) throws java.sql.SQLException
dbMeta
- Metadata of the database to investigate.java.sql.SQLException
- If any error occurs while querying the database
metadata.protected java.sql.ResultSet getDBMetaTables(java.sql.DatabaseMetaData dbMeta, java.lang.String schemaPattern, java.lang.String tablePattern) throws java.sql.SQLException
dbMeta
- Metadata of the database to investigate.schemaPattern
- Pattern matching the schema(s) name containing the
target tables.
If NULL, the table will be searched in all
schemas.tablePattern
- Pattern matching the name of the tables to list.java.sql.SQLException
- If any error occurs while querying the database
metadata.protected java.sql.ResultSet getDBMetaColumns(java.sql.DatabaseMetaData dbMeta, java.lang.String schemaPattern, java.lang.String tablePattern, java.lang.String columnPattern) throws java.sql.SQLException
dbMeta
- Metadata of the database to investigate.schemaPattern
- Pattern matching the schema(s) name containing the
target columns.
If NULL, the columns will be searched in all
schemas.tablePattern
- Pattern matching the table(s) name containing the
target columns.
If NULL, the columns will be searched in all
tables.columnPattern
- Pattern matching the name of the columns to list.java.sql.SQLException
- If any error occurs while querying the database
metadata.protected boolean isSchemaExisting(java.lang.String schemaName, java.sql.DatabaseMetaData dbMeta) throws java.sql.SQLException
Tell whether the specified schema exists in the database.
To do so, it is using the given DatabaseMetaData
object to query the database and list all existing schemas.
Note: This function is completely useless if the connection is not supporting schemas.
Note:
Test on the schema name is done considering the case sensitivity indicated by the translator
(see JDBCTranslator.isCaseSensitive(IdentifierField)
).
Note:
This functions is used by addUploadedTable(TAPTable, TableIterator)
and resetTAPSchema(Statement, TAPTable[])
.
schemaName
- DB name of the schema whose the existence must be checked.dbMeta
- Metadata about the database, and mainly the list of all existing schemas.java.sql.SQLException
- If any error occurs while interrogating the database about existing schema.protected boolean isTableExisting(java.lang.String schemaName, java.lang.String tableName, java.sql.DatabaseMetaData dbMeta) throws DBException, java.sql.SQLException
Tell whether the specified table exists in the database.
To do so, it is using the given DatabaseMetaData
object to query the database and list all existing tables.
Important note: If schemas are not supported by this connection but a schema name is even though provided in parameter, the table name will be prefixed by the schema name. The research will then be done with NULL as schema name and this prefixed table name.
Note:
Test on the schema name is done considering the case sensitivity indicated by the translator
(see JDBCTranslator.isCaseSensitive(IdentifierField)
).
Note:
This function is used by addUploadedTable(TAPTable, TableIterator)
and dropUploadedTable(TAPTable)
.
schemaName
- DB name of the schema in which the table to search is. If NULL, the table is expected in any schema but ONLY one MUST exist.tableName
- DB name of the table to search.dbMeta
- Metadata about the database, and mainly the list of all existing tables.java.sql.SQLException
- If any error occurs while interrogating the database about existing tables.DBException
protected boolean isColumnExisting(java.lang.String schemaName, java.lang.String tableName, java.lang.String columnName, java.sql.DatabaseMetaData dbMeta) throws DBException, java.sql.SQLException
Tell whether the specified column exists in the specified table of the database.
To do so, it is using the given DatabaseMetaData
object to query the database and list all existing columns.
Important note: If schemas are not supported by this connection but a schema name is even though provided in parameter, the table name will be prefixed by the schema name. The research will then be done with NULL as schema name and this prefixed table name.
Note:
Test on the schema name is done considering the case sensitivity indicated by the translator
(see JDBCTranslator.isCaseSensitive(IdentifierField)
).
Note:
This function is used by loadSchemas(TAPTable, TAPMetadata, Statement)
, loadTables(TAPTable, TAPMetadata, Statement)
and loadColumns(TAPTable, List, Statement)
.
schemaName
- DB name of the table schema. MAY BE NULLtableName
- DB name of the table containing the column to search. MAY BE NULLcolumnName
- DB name of the column to search.dbMeta
- Metadata about the database, and mainly the list of all existing tables.java.sql.SQLException
- If any error occurs while interrogating the database about existing columns.DBException
protected final TAPMetadata.STDTable isStdTable(java.lang.String dbTableName, TAPTable[] stdTables, boolean caseSensitive)
dbTableName
- DB (unqualified) table name.stdTables
- List of all tables to consider as the standard ones.caseSensitive
- Indicate whether the equality test must be done case sensitively or not.TAPMetadata.STDTable
if the specified table is a standard one,
NULL otherwise.TAPMetadata.resolveStdTable(String)
protected final void executeUpdate(java.sql.PreparedStatement stmt, int indRow) throws java.sql.SQLException, DBException
"Execute" the query update. This update must concern ONLY ONE ROW.
Note that the "execute" action will be different in function of whether batch update queries are supported or not by this connection:
PreparedStatement.addBatch()
will be called.
It means, the query will be appended in a list and will be executed only if
executeBatchUpdates(PreparedStatement, int)
is then called.
PreparedStatement.executeUpdate()
will merely be called.
Before returning, and only if batch update queries are not supported, this function is ensuring that exactly one row has been updated.
If it is not the case, a DBException
is thrown.
Important note:
If the function PreparedStatement.addBatch()
fails by throwing an SQLException
, batch updates
will be afterwards considered as not supported by this connection. Besides, if this row is the first one in a batch update (parameter indRow=1),
then, the error will just be logged and an PreparedStatement.executeUpdate()
will be tried. However, if the row is not the first one,
the error will be logged but also thrown as a DBException
. In both cases, a subsequent call to
executeBatchUpdates(PreparedStatement, int)
will have obviously no effect.
stmt
- PreparedStatement
in which the update query has been prepared.indRow
- Index of the row in the whole update process. It is used only for error management purpose.java.sql.SQLException
- If PreparedStatement.executeUpdate()
fails.DBException
- If PreparedStatement.addBatch()
fails and this update does not concern the first row, or if the number of updated rows is different from 1.protected final void executeBatchUpdates(java.sql.PreparedStatement stmt, int nbRows) throws DBException
Execute all batched queries.
To do so, Statement.executeBatch()
and then, if the first was successful, Statement.clearBatch()
is called.
Before returning, this function is ensuring that exactly the given number of rows has been updated.
If it is not the case, a DBException
is thrown.
Note: This function has no effect if batch queries are not supported.
Important note:
In case Statement.executeBatch()
fails by throwing an SQLException
,
batch update queries will be afterwards considered as not supported by this connection.
stmt
- PreparedStatement
in which the update query has been prepared.nbRows
- Number of rows that should be updated.DBException
- If Statement.executeBatch()
fails, or if the number of updated rows is different from the given one.protected final boolean equals(java.lang.String dbName, java.lang.String metaName, boolean caseSensitive)
Tell whether the given DB name is equals (case sensitively or not, in function of the given parameter)
to the given name coming from a TAPMetadata
object.
If at least one of the given name is NULL, false is returned.
Note: The comparison will be done in function of the specified case sensitivity BUT ALSO of the case supported and stored by the DBMS. For instance, if it has been specified a case insensitivity and that mixed case is not supported by unquoted identifier, the comparison must be done, surprisingly, by considering the case if unquoted identifiers are stored in lower or upper case. Thus, this special way to evaluate equality should be as closed as possible to the identifier storage and research policies of the used DBMS.
dbName
- Name provided by the database.metaName
- Name provided by a TAPMetadata
object.caseSensitive
- true if the equality test must be done case sensitively, false otherwise.public void setFetchSize(int size)
DBConnection
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 DBConnection.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.
setFetchSize
in interface DBConnection
size
- Blocks size (in number of rows) to fetch.