org.drizzle.jdbc.DrizzleConnection Maven / Gradle / Ivy
Show all versions of drizzle-jdbc Show documentation
/*
* Drizzle-JDBC
*
* Copyright (c) 2009-2011, Marcus Eriksson
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
* conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the driver nor the names of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.drizzle.jdbc;
import org.drizzle.jdbc.internal.SQLExceptionMapper;
import org.drizzle.jdbc.internal.common.BinlogDumpException;
import org.drizzle.jdbc.internal.common.DefaultParameterizedBatchHandlerFactory;
import org.drizzle.jdbc.internal.common.ParameterizedBatchHandlerFactory;
import org.drizzle.jdbc.internal.common.Protocol;
import org.drizzle.jdbc.internal.common.QueryException;
import org.drizzle.jdbc.internal.common.Utils;
import org.drizzle.jdbc.internal.common.packet.RawPacket;
import org.drizzle.jdbc.internal.common.query.QueryFactory;
import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
/**
* A JDBC Connection.
*
* User: marcuse Date: Jan 14, 2009 Time: 7:47:37 AM
*/
public final class DrizzleConnection
implements Connection, ReplicationConnection {
/**
* the protocol to communicate with.
*/
private final Protocol protocol;
/**
* save point count - to generate good names for the savepoints.
*/
private int savepointCount = 0;
/**
* the properties for the client.
*/
private final Properties clientInfoProperties;
/**
* a query factory.
*/
private final QueryFactory queryFactory;
private ParameterizedBatchHandlerFactory parameterizedBatchHandlerFactory;
/**
* Executor that keeps track of timeouts for statements
*
* Works having just one thread for this since it is not legal to have several executing queries on the same connection!
*/
private final ScheduledExecutorService timeoutExecutor = Executors.newSingleThreadScheduledExecutor();
/**
* Creates a new connection with a given protocol and query factory.
*
* @param protocol the protocol to use.
* @param queryFactory the query factory to use.
*/
public DrizzleConnection(final Protocol protocol, final QueryFactory queryFactory) {
this.protocol = protocol;
clientInfoProperties = new Properties();
this.queryFactory = queryFactory;
}
/**
* creates a new statement.
*
* @return a statement
* @throws SQLException if we cannot create the statement.
*/
public Statement createStatement() throws SQLException {
return new DrizzleStatement(protocol, this, queryFactory);
}
/**
* creates a new prepared statement. Only client side prepared statement emulation right now.
*
* @param sql the query.
* @return a prepared statement.
* @throws SQLException if there is a problem preparing the statement.
*/
public PreparedStatement prepareStatement(final String sql) throws SQLException {
if (parameterizedBatchHandlerFactory == null) {
this.parameterizedBatchHandlerFactory = new DefaultParameterizedBatchHandlerFactory();
}
final String strippedQuery = Utils.stripQuery(sql);
return new DrizzlePreparedStatement(protocol,
this,
strippedQuery,
queryFactory,
parameterizedBatchHandlerFactory.get(strippedQuery, protocol));
}
/**
* not implemented.
*
* @param sql unused
* @return nothing.
* @throws SQLException always since this is not implemented.
*/
public CallableStatement prepareCall(final String sql) throws SQLException {
throw SQLExceptionMapper.getFeatureNotSupportedException("Stored procedures not supported");
}
/**
* currently does nothing. //TODO: implement
*
* @param sql
* @return
* @throws SQLException
*/
public String nativeSQL(final String sql) throws SQLException {
return sql;
}
/**
* Sets whether this connection is auto commited.
*
* @param autoCommit if it should be auto commited.
* @throws SQLException if something goes wrong talking to the server.
*/
public void setAutoCommit(final boolean autoCommit) throws SQLException {
Statement stmt = createStatement();
String clause;
if(autoCommit) {
clause = "1";
} else {
clause = "0";
}
stmt.executeUpdate("set autocommit="+clause);
}
/**
* returns true if statements on this connection are auto commited.
*
* @return true if auto commit is on.
* @throws SQLException
*/
public boolean getAutoCommit() throws SQLException {
Statement stmt = createStatement();
ResultSet rs = stmt.executeQuery("select @@autocommit");
rs.next();
boolean autocommit = rs.getBoolean(1);
rs.close();
stmt.close();
return autocommit;
}
/**
* sends commit to the server.
*
* @throws SQLException if there is an error commiting.
*/
public void commit() throws SQLException {
try {
protocol.commit();
} catch (QueryException e) {
throw SQLExceptionMapper.get(e);
}
}
/**
* rolls back a transaction.
*
* @throws SQLException if there is an error rolling back.
*/
public void rollback() throws SQLException {
try {
protocol.rollback();
} catch (QueryException e) {
throw SQLExceptionMapper.get(e);
}
}
/**
* close the connection.
*
* @throws SQLException if there is a problem talking to the server.
*/
public void close() throws SQLException {
try {
this.timeoutExecutor.shutdown();
protocol.close();
} catch (QueryException e) {
throw SQLExceptionMapper.get(e);
}
}
/**
* checks if the connection is closed.
*
* @return true if the connection is closed
* @throws SQLException if the connection cannot be closed.
*/
public boolean isClosed() throws SQLException {
return protocol.isClosed();
}
/**
* returns the meta data about the database.
*
* @return meta data about the db.
* @throws SQLException if there is a problem creating the meta data.
*/
public DatabaseMetaData getMetaData() throws SQLException {
return new CommonDatabaseMetaData.Builder(protocol.getDatabaseType(), this).
url("jdbc:drizzle://" + protocol.getHost()
+ ":" + protocol.getPort()
+ "/" + protocol.getDatabase()).
username(protocol.getUsername()).
version(protocol.getServerVersion()).
databaseProductName(protocol.getDatabaseType().getDatabaseName()).
build();
}
/**
* Sets whether this connection is read only.
*
* @param readOnly true if it should be read only.
* @throws SQLException if there is a problem
*/
public void setReadOnly(final boolean readOnly) throws SQLException {
protocol.setReadonly(readOnly);
}
/**
* Retrieves whether this Connection
object is in read-only mode.
*
* @return true
if this Connection
object is read-only; false
otherwise
* @throws java.sql.SQLException SQLException if a database access error occurs or this method is called on a closed
* connection
*/
public boolean isReadOnly() throws SQLException {
return false;
}
/**
* Sets the given catalog name in order to select a subspace of this Connection
object's database in
* which to work.
*
* If the driver does not support catalogs, it will silently ignore this request.
*
* @param catalog the name of a catalog (subspace in this Connection
object's database) in which to
* work
* @throws java.sql.SQLException if a database access error occurs or this method is called on a closed connection
* @see #getCatalog
*/
public void setCatalog(final String catalog) throws SQLException {
// silently ignored since drizzle does not support catalogs
}
/**
* Retrieves this Connection
object's current catalog name.
*
* catalogs are not supported in drizzle
*
* TODO: Explain the wrapper interface to be able to change database
*
* @return the current catalog name or null
if there is none
* @throws java.sql.SQLException if a database access error occurs or this method is called on a closed connection
* @see #setCatalog
*/
public String getCatalog() throws SQLException {
return null;
}
/**
* Attempts to change the transaction isolation level for this Connection
object to the one given. The
* constants defined in the interface Connection
are the possible transaction isolation levels.
*
* Note: If this method is called during a transaction, the result is implementation-defined.
*
* @param level one of the following Connection
constants: Connection.TRANSACTION_READ_UNCOMMITTED
,
* Connection.TRANSACTION_READ_COMMITTED
, Connection.TRANSACTION_REPEATABLE_READ
,
* or Connection.TRANSACTION_SERIALIZABLE
. (Note that Connection.TRANSACTION_NONE
* cannot be used because it specifies that transactions are not supported.)
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed connection or
* the given parameter is not one of the Connection
constants
* @see java.sql.DatabaseMetaData#supportsTransactionIsolationLevel
* @see #getTransactionIsolation
*/
public void setTransactionIsolation(final int level) throws SQLException {
String query = "SET SESSION TRANSACTION ISOLATION LEVEL";
switch (level) {
case Connection.TRANSACTION_READ_UNCOMMITTED:
query += " READ UNCOMMITTED";
break;
case Connection.TRANSACTION_READ_COMMITTED:
query += " READ COMMITTED";
break;
case Connection.TRANSACTION_REPEATABLE_READ:
query += " REPEATABLE READ";
break;
case Connection.TRANSACTION_SERIALIZABLE:
query += " SERIALIZABLE";
break;
default:
throw SQLExceptionMapper.getSQLException("Unsupported transaction isolation level");
}
try {
protocol.executeQuery(queryFactory.createQuery(query));
} catch (QueryException e) {
throw SQLExceptionMapper.get(e);
}
}
/**
* Retrieves this Connection
object's current transaction isolation level.
*
* @return the current transaction isolation level, which will be one of the following constants:
* Connection.TRANSACTION_READ_UNCOMMITTED
, Connection.TRANSACTION_READ_COMMITTED
,
* Connection.TRANSACTION_REPEATABLE_READ
, Connection.TRANSACTION_SERIALIZABLE
, or
* Connection.TRANSACTION_NONE
.
* @throws java.sql.SQLException if a database access error occurs or this method is called on a closed connection
* @see #setTransactionIsolation
*/
public int getTransactionIsolation() throws SQLException {
final Statement stmt = createStatement();
try {
final ResultSet rs = stmt.executeQuery("SELECT @@tx_isolation");
rs.next();
final String response = rs.getString(1);
if (response.equals("REPEATABLE-READ")) {
return Connection.TRANSACTION_REPEATABLE_READ;
}
if (response.equals("READ-UNCOMMITTED")) {
return Connection.TRANSACTION_READ_UNCOMMITTED;
}
if (response.equals("READ-COMMITTED")) {
return Connection.TRANSACTION_READ_COMMITTED;
}
if (response.equals("SERIALIZABLE")) {
return Connection.TRANSACTION_SERIALIZABLE;
}
} finally {
stmt.close();
}
throw SQLExceptionMapper.getSQLException("Could not get transaction isolation level");
}
/**
* Not yet implemented: Protocol needs to store any warnings related to connections
*
*
* Retrieves the first warning reported by calls on this Connection
object. If there is more than one
* warning, subsequent warnings will be chained to the first one and can be retrieved by calling the method
* SQLWarning.getNextWarning
on the warning that was retrieved previously.
*
* This method may not be called on a closed connection; doing so will cause an SQLException
to be
* thrown.
*
* Note: Subsequent warnings will be chained to this SQLWarning.
*
* @return the first SQLWarning
object or null
if there are none
* @throws java.sql.SQLException if a database access error occurs or this method is called on a closed connection
* @see java.sql.SQLWarning
*/
public SQLWarning getWarnings() throws SQLException {
return null;
}
/**
* Clears all warnings reported for this Connection
object. After a call to this method, the method
* getWarnings
returns null
until a new warning is reported for this
* Connection
object.
*
* @throws java.sql.SQLException SQLException if a database access error occurs or this method is called on a closed
* connection
*/
public void clearWarnings() throws SQLException {
}
/**
* Creates a Statement
object that will generate ResultSet
objects with the given type and
* concurrency. This method is the same as the createStatement
method above, but it allows the default
* result set type and concurrency to be overridden. The holdability of the created result sets can be determined by
* calling {@link #getHoldability}.
*
* @param resultSetType a result set type; one of ResultSet.TYPE_FORWARD_ONLY
,
* ResultSet.TYPE_SCROLL_INSENSITIVE
, or ResultSet.TYPE_SCROLL_SENSITIVE
* @param resultSetConcurrency a concurrency type; one of ResultSet.CONCUR_READ_ONLY
or
* ResultSet.CONCUR_UPDATABLE
* @return a new Statement
object that will generate ResultSet
objects with the given type
* and concurrency
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed connection or
* the given parameters are not ResultSet
constants indicating type and
* concurrency
*/
public Statement createStatement(final int resultSetType, final int resultSetConcurrency) throws SQLException {
// for now resultSetType and resultSetConcurrency are ignored
// TODO: fix
return createStatement();
}
/**
* Creates a PreparedStatement
object that will generate ResultSet
objects with the given
* type and concurrency. This method is the same as the prepareStatement
method above, but it allows
* the default result set type and concurrency to be overridden. The holdability of the created result sets can be
* determined by calling {@link #getHoldability}.
*
* @param sql a String
object that is the SQL statement to be sent to the database;
* may contain one or more '?' IN parameters
* @param resultSetType a result set type; one of ResultSet.TYPE_FORWARD_ONLY
,
* ResultSet.TYPE_SCROLL_INSENSITIVE
, or ResultSet.TYPE_SCROLL_SENSITIVE
* @param resultSetConcurrency a concurrency type; one of ResultSet.CONCUR_READ_ONLY
or
* ResultSet.CONCUR_UPDATABLE
* @return a new PreparedStatement object containing the pre-compiled SQL statement that will produce
* ResultSet
objects with the given type and concurrency
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed connection or
* the given parameters are not ResultSet
constants indicating type and
* concurrency
*/
public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency)
throws SQLException {
// for now resultSetType and resultSetConcurrency are ignored
// TODO: fix
return prepareStatement(sql);
}
/**
* Creates a CallableStatement
object that will generate ResultSet
objects with the given
* type and concurrency. This method is the same as the prepareCall
method above, but it allows the
* default result set type and concurrency to be overridden. The holdability of the created result sets can be
* determined by calling {@link #getHoldability}.
*
* @param sql a String
object that is the SQL statement to be sent to the database;
* may contain on or more '?' parameters
* @param resultSetType a result set type; one of ResultSet.TYPE_FORWARD_ONLY
,
* ResultSet.TYPE_SCROLL_INSENSITIVE
, or ResultSet.TYPE_SCROLL_SENSITIVE
* @param resultSetConcurrency a concurrency type; one of ResultSet.CONCUR_READ_ONLY
or
* ResultSet.CONCUR_UPDATABLE
* @return a new CallableStatement
object containing the pre-compiled SQL statement that will produce
* ResultSet
objects with the given type and concurrency
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed connection or
* the given parameters are not ResultSet
constants indicating type and
* concurrency
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this method or this method is not supported for
* the specified result set type and result set concurrency.
*/
public CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException {
throw SQLExceptionMapper.getFeatureNotSupportedException("Stored procedures not supported");
}
/**
* Retrieves the Map
object associated with this Connection
object. Unless the application
* has added an entry, the type map returned will be empty.
*
* @return the java.util.Map
object associated with this Connection
object
* @throws java.sql.SQLException if a database access error occurs or this method is called on a closed connection
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this method
* @see #setTypeMap
* @since 1.2
*/
public Map> getTypeMap() throws SQLException {
throw SQLExceptionMapper.getFeatureNotSupportedException("Not yet supported");
}
/**
* Installs the given TypeMap
object as the type map for this Connection
object. The type
* map will be used for the custom mapping of SQL structured types and distinct types.
*
* @param map the java.util.Map
object to install as the replacement for this Connection
* object's default type map
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed connection or
* the given parameter is not a java.util.Map
object
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this method
* @see #getTypeMap
*/
public void setTypeMap(final Map> map) throws SQLException {
throw SQLExceptionMapper.getFeatureNotSupportedException("Not yet supported");
}
/**
* Changes the default holdability of ResultSet
objects created using this Connection
* object to the given holdability. The default holdability of ResultSet
objects can be be determined
* by invoking {@link java.sql.DatabaseMetaData#getResultSetHoldability}.
*
* @param holdability a ResultSet
holdability constant; one of ResultSet.HOLD_CURSORS_OVER_COMMIT
* or ResultSet.CLOSE_CURSORS_AT_COMMIT
* @throws java.sql.SQLException if a database access occurs, this method is called on a closed connection, or the
* given parameter is not a ResultSet
constant indicating holdability
* @throws java.sql.SQLFeatureNotSupportedException
* if the given holdability is not supported
* @see #getHoldability
* @see java.sql.DatabaseMetaData#getResultSetHoldability
* @see java.sql.ResultSet
* @since 1.4
*/
public void setHoldability(final int holdability) throws SQLException {
if (holdability != ResultSet.HOLD_CURSORS_OVER_COMMIT) {
throw SQLExceptionMapper.getFeatureNotSupportedException("Only holding cursors over commit is supported");
}
}
/**
* Retrieves the current holdability of ResultSet
objects created using this Connection
* object.
*
* @return the holdability, one of ResultSet.HOLD_CURSORS_OVER_COMMIT
or
* ResultSet.CLOSE_CURSORS_AT_COMMIT
* @throws java.sql.SQLException if a database access error occurs or this method is called on a closed connection
* @see #setHoldability
* @see java.sql.DatabaseMetaData#getResultSetHoldability
* @see java.sql.ResultSet
* @since 1.4
*/
public int getHoldability() throws SQLException {
return ResultSet.HOLD_CURSORS_OVER_COMMIT;
}
/**
* Creates an unnamed savepoint in the current transaction and returns the new Savepoint
object that
* represents it.
*
* if setSavepoint is invoked outside of an active transaction, a transaction will be started at this newly
* created savepoint.
*
* @return the new Savepoint
object
* @throws java.sql.SQLException if a database access error occurs, this method is called while participating in a
* distributed transaction, this method is called on a closed connection or this
* Connection
object is currently in auto-commit mode
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this method
* @see java.sql.Savepoint
* @since 1.4
*/
public Savepoint setSavepoint() throws SQLException {
return setSavepoint("unnamed");
}
/**
* Creates a savepoint with the given name in the current transaction and returns the new Savepoint
* object that represents it.
*
* if setSavepoint is invoked outside of an active transaction, a transaction will be started at this newly
* created savepoint.
*
* @param name a String
containing the name of the savepoint
* @return the new Savepoint
object
* @throws java.sql.SQLException if a database access error occurs, this method is called while participating in a
* distributed transaction, this method is called on a closed connection or this
* Connection
object is currently in auto-commit mode
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this method
* @see java.sql.Savepoint
* @since 1.4
*/
public Savepoint setSavepoint(final String name) throws SQLException {
final Savepoint drizzleSavepoint = new DrizzleSavepoint(name, savepointCount++);
try {
protocol.setSavepoint(drizzleSavepoint.toString());
} catch (QueryException e) {
throw SQLExceptionMapper.get(e);
}
return drizzleSavepoint;
}
/**
* Undoes all changes made after the given Savepoint
object was set.
*
* This method should be used only when auto-commit has been disabled.
*
* @param savepoint the Savepoint
object to roll back to
* @throws java.sql.SQLException if a database access error occurs, this method is called while participating in a
* distributed transaction, this method is called on a closed connection, the
* Savepoint
object is no longer valid, or this Connection
* object is currently in auto-commit mode
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this method
* @see java.sql.Savepoint
* @see #rollback
* @since 1.4
*/
public void rollback(final Savepoint savepoint) throws SQLException {
try {
protocol.rollback(savepoint.toString());
} catch (QueryException e) {
throw SQLExceptionMapper.get(e);
}
}
/**
* Removes the specified Savepoint
and subsequent Savepoint
objects from the current
* transaction. Any reference to the savepoint after it have been removed will cause an SQLException
to
* be thrown.
*
* @param savepoint the Savepoint
object to be removed
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed connection or
* the given Savepoint
object is not a valid savepoint in the current
* transaction
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this method
* @since 1.4
*/
public void releaseSavepoint(final Savepoint savepoint) throws SQLException {
try {
protocol.releaseSavepoint(savepoint.toString());
} catch (QueryException e) {
throw SQLExceptionMapper.get(e);
}
}
/**
* Creates a Statement
object that will generate ResultSet
objects with the given type,
* concurrency, and holdability. This method is the same as the createStatement
method above, but it
* allows the default result set type, concurrency, and holdability to be overridden.
*
* @param resultSetType one of the following ResultSet
constants: ResultSet.TYPE_FORWARD_ONLY
,
* ResultSet.TYPE_SCROLL_INSENSITIVE
, or ResultSet.TYPE_SCROLL_SENSITIVE
* @param resultSetConcurrency one of the following ResultSet
constants: ResultSet.CONCUR_READ_ONLY
* or ResultSet.CONCUR_UPDATABLE
* @param resultSetHoldability one of the following ResultSet
constants: ResultSet.HOLD_CURSORS_OVER_COMMIT
* or ResultSet.CLOSE_CURSORS_AT_COMMIT
* @return a new Statement
object that will generate ResultSet
objects with the given
* type, concurrency, and holdability
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed connection or
* the given parameters are not ResultSet
constants indicating type,
* concurrency, and holdability
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this method or this method is not supported for
* the specified result set type, result set holdability and result set concurrency.
* @see java.sql.ResultSet
* @since 1.4
*/
public Statement createStatement(final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability)
throws SQLException {
if (resultSetConcurrency != ResultSet.CONCUR_READ_ONLY) {
throw SQLExceptionMapper.getFeatureNotSupportedException("Only read-only result sets allowed");
}
if (resultSetHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT) {
throw SQLExceptionMapper.getFeatureNotSupportedException(
"Cursors are always kept when sending commit (they are only client-side)");
}
return createStatement();
}
/**
* Creates a PreparedStatement
object that will generate ResultSet
objects with the given
* type, concurrency, and holdability.
*
* This method is the same as the prepareStatement
method above, but it allows the default result set
* type, concurrency, and holdability to be overridden.
*
* @param sql a String
object that is the SQL statement to be sent to the database;
* may contain one or more '?' IN parameters
* @param resultSetType one of the following ResultSet
constants: ResultSet.TYPE_FORWARD_ONLY
,
* ResultSet.TYPE_SCROLL_INSENSITIVE
, or ResultSet.TYPE_SCROLL_SENSITIVE
* @param resultSetConcurrency one of the following ResultSet
constants: ResultSet.CONCUR_READ_ONLY
* or ResultSet.CONCUR_UPDATABLE
* @param resultSetHoldability one of the following ResultSet
constants: ResultSet.HOLD_CURSORS_OVER_COMMIT
* or ResultSet.CLOSE_CURSORS_AT_COMMIT
* @return a new PreparedStatement
object, containing the pre-compiled SQL statement, that will
* generate ResultSet
objects with the given type, concurrency, and holdability
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed connection or
* the given parameters are not ResultSet
constants indicating type,
* concurrency, and holdability
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this method or this method is not supported for
* the specified result set type, result set holdability and result set concurrency.
* @see java.sql.ResultSet
* @since 1.4
*/
public PreparedStatement prepareStatement(final String sql,
final int resultSetType,
final int resultSetConcurrency,
final int resultSetHoldability) throws SQLException {
if (resultSetConcurrency != ResultSet.CONCUR_READ_ONLY) {
throw SQLExceptionMapper.getFeatureNotSupportedException("Only read-only result sets allowed");
}
if (resultSetHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT) {
throw SQLExceptionMapper.getFeatureNotSupportedException(
"Cursors are always kept when sending commit (they are only client-side)");
}
// resultSetType is ignored since we always are scroll insensitive
return prepareStatement(sql);
}
/**
* Creates a CallableStatement
object that will generate ResultSet
objects with the given
* type and concurrency. This method is the same as the prepareCall
method above, but it allows the
* default result set type, result set concurrency type and holdability to be overridden.
*
* @param sql a String
object that is the SQL statement to be sent to the database;
* may contain on or more '?' parameters
* @param resultSetType one of the following ResultSet
constants: ResultSet.TYPE_FORWARD_ONLY
,
* ResultSet.TYPE_SCROLL_INSENSITIVE
, or ResultSet.TYPE_SCROLL_SENSITIVE
* @param resultSetConcurrency one of the following ResultSet
constants: ResultSet.CONCUR_READ_ONLY
* or ResultSet.CONCUR_UPDATABLE
* @param resultSetHoldability one of the following ResultSet
constants: ResultSet.HOLD_CURSORS_OVER_COMMIT
* or ResultSet.CLOSE_CURSORS_AT_COMMIT
* @return a new CallableStatement
object, containing the pre-compiled SQL statement, that will
* generate ResultSet
objects with the given type, concurrency, and holdability
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed connection or
* the given parameters are not ResultSet
constants indicating type,
* concurrency, and holdability
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this method or this method is not supported for
* the specified result set type, result set holdability and result set concurrency.
* @see java.sql.ResultSet
* @since 1.4
*/
public CallableStatement prepareCall(final String sql,
final int resultSetType,
final int resultSetConcurrency,
final int resultSetHoldability) throws SQLException {
throw SQLExceptionMapper.getFeatureNotSupportedException("Prepared statements are not supported");
}
/**
* Creates a default PreparedStatement
object that has the capability to retrieve auto-generated keys.
* The given constant tells the driver whether it should make auto-generated keys available for retrieval. This
* parameter is ignored if the SQL statement is not an INSERT
statement, or an SQL statement able to
* return auto-generated keys (the list of such statements is vendor-specific).
*
* Note: This method is optimized for handling parametric SQL statements that benefit from precompilation. If
* the driver supports precompilation, the method prepareStatement
will send the statement to the
* database for precompilation. Some drivers may not support precompilation. In this case, the statement may not be
* sent to the database until the PreparedStatement
object is executed. This has no direct effect on
* users; however, it does affect which methods throw certain SQLExceptions.
*
* Result sets created using the returned PreparedStatement
object will by default be type
* TYPE_FORWARD_ONLY
and have a concurrency level of CONCUR_READ_ONLY
. The holdability of
* the created result sets can be determined by calling {@link #getHoldability}.
*
* @param sql an SQL statement that may contain one or more '?' IN parameter placeholders
* @param autoGeneratedKeys a flag indicating whether auto-generated keys should be returned; one of
* Statement.RETURN_GENERATED_KEYS
or Statement.NO_GENERATED_KEYS
* @return a new PreparedStatement
object, containing the pre-compiled SQL statement, that will have
* the capability of returning auto-generated keys
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed connection or
* the given parameter is not a Statement
constant indicating whether
* auto-generated keys should be returned
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this method with a constant of
* Statement.RETURN_GENERATED_KEYS
* @since 1.4
*/
public PreparedStatement prepareStatement(final String sql, final int autoGeneratedKeys) throws SQLException {
// autoGeneratedKeys are ignored since we always receive them for free with drizzle
return prepareStatement(sql);
}
/**
* Creates a default PreparedStatement
object capable of returning the auto-generated keys designated
* by the given array. This array contains the indexes of the columns in the target table that contain the
* auto-generated keys that should be made available. The driver will ignore the array if the SQL statement is not
* an INSERT
statement, or an SQL statement able to return auto-generated keys (the list of such
* statements is vendor-specific).
*
* An SQL statement with or without IN parameters can be pre-compiled and stored in a PreparedStatement
* object. This object can then be used to efficiently execute this statement multiple times.
*
* Note: This method is optimized for handling parametric SQL statements that benefit from precompilation. If
* the driver supports precompilation, the method prepareStatement
will send the statement to the
* database for precompilation. Some drivers may not support precompilation. In this case, the statement may not be
* sent to the database until the PreparedStatement
object is executed. This has no direct effect on
* users; however, it does affect which methods throw certain SQLExceptions.
*
* Result sets created using the returned PreparedStatement
object will by default be type
* TYPE_FORWARD_ONLY
and have a concurrency level of CONCUR_READ_ONLY
. The holdability of
* the created result sets can be determined by calling {@link #getHoldability}.
*
* @param sql an SQL statement that may contain one or more '?' IN parameter placeholders
* @param columnIndexes an array of column indexes indicating the columns that should be returned from the inserted
* row or rows
* @return a new PreparedStatement
object, containing the pre-compiled statement, that is capable of
* returning the auto-generated keys designated by the given array of column indexes
* @throws java.sql.SQLException if a database access error occurs or this method is called on a closed connection
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this method
* @since 1.4
*/
public PreparedStatement prepareStatement(final String sql, final int[] columnIndexes) throws SQLException {
if (columnIndexes != null && columnIndexes.length == 1 && columnIndexes[0] == 1) {
return prepareStatement(sql);
}
throw SQLExceptionMapper.getSQLException("Only one auto generated key is supported, and it is on position 1");
}
/**
* Creates a default PreparedStatement
object capable of returning the auto-generated keys designated
* by the given array. This array contains the names of the columns in the target table that contain the
* auto-generated keys that should be returned. The driver will ignore the array if the SQL statement is not an
* INSERT
statement, or an SQL statement able to return auto-generated keys (the list of such
* statements is vendor-specific).
*
* An SQL statement with or without IN parameters can be pre-compiled and stored in a PreparedStatement
* object. This object can then be used to efficiently execute this statement multiple times.
*
* Note: This method is optimized for handling parametric SQL statements that benefit from precompilation. If
* the driver supports precompilation, the method prepareStatement
will send the statement to the
* database for precompilation. Some drivers may not support precompilation. In this case, the statement may not be
* sent to the database until the PreparedStatement
object is executed. This has no direct effect on
* users; however, it does affect which methods throw certain SQLExceptions.
*
* Result sets created using the returned PreparedStatement
object will by default be type
* TYPE_FORWARD_ONLY
and have a concurrency level of CONCUR_READ_ONLY
. The holdability of
* the created result sets can be determined by calling {@link #getHoldability}.
*
* @param sql an SQL statement that may contain one or more '?' IN parameter placeholders
* @param columnNames an array of column names indicating the columns that should be returned from the inserted row
* or rows
* @return a new PreparedStatement
object, containing the pre-compiled statement, that is capable of
* returning the auto-generated keys designated by the given array of column names
* @throws java.sql.SQLException if a database access error occurs or this method is called on a closed connection
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this method
* @since 1.4
*/
public PreparedStatement prepareStatement(final String sql, final String[] columnNames) throws SQLException {
if (columnNames != null && columnNames.length == 1 && columnNames[0].equals("insert_id")) {
return prepareStatement(sql);
}
throw SQLExceptionMapper.getSQLException("Only one auto generated key is supported, and it is called insert_id");
}
/**
* Constructs an object that implements the Clob
interface. The object returned initially contains no
* data. The setAsciiStream
, setCharacterStream
and setString
methods of the
* Clob
interface may be used to add data to the Clob
.
*
* @return An object that implements the Clob
interface
* @throws java.sql.SQLException if an object that implements the Clob
interface can not be
* constructed, this method is called on a closed connection or a database access
* error occurs.
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this data type
* @since 1.6
*/
public Clob createClob() throws SQLException {
throw SQLExceptionMapper.getFeatureNotSupportedException("Not yet supported");
}
/**
* Constructs an object that implements the Blob
interface. The object returned initially contains no
* data. The setBinaryStream
and setBytes
methods of the Blob
interface may
* be used to add data to the Blob
.
*
* @return An object that implements the Blob
interface
* @throws java.sql.SQLException if an object that implements the Blob
interface can not be
* constructed, this method is called on a closed connection or a database access
* error occurs.
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this data type
* @since 1.6
*/
public Blob createBlob() throws SQLException {
return new DrizzleBlob();
}
/**
* Constructs an object that implements the NClob
interface. The object returned initially contains no
* data. The setAsciiStream
, setCharacterStream
and setString
methods of the
* NClob
interface may be used to add data to the NClob
.
*
* @return An object that implements the NClob
interface
* @throws java.sql.SQLException if an object that implements the NClob
interface can not be
* constructed, this method is called on a closed connection or a database access
* error occurs.
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this data type
* @since 1.6
*/
public java.sql.NClob createNClob() throws SQLException {
throw SQLExceptionMapper.getFeatureNotSupportedException("NClobs not supported");
}
/**
* Constructs an object that implements the SQLXML
interface. The object returned initially contains no
* data. The createXmlStreamWriter
object and setString
method of the SQLXML
* interface may be used to add data to the SQLXML
object.
*
* @return An object that implements the SQLXML
interface
* @throws java.sql.SQLException if an object that implements the SQLXML
interface can not be
* constructed, this method is called on a closed connection or a database access
* error occurs.
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this data type
* @since 1.6
*/
public java.sql.SQLXML createSQLXML() throws SQLException {
throw SQLExceptionMapper.getFeatureNotSupportedException("Not supported");
}
/**
* Returns true if the connection has not been closed and is still valid. The driver shall submit a query on the
* connection or use some other mechanism that positively verifies the connection is still valid when this method is
* called.
*
* The query submitted by the driver to validate the connection shall be executed in the context of the current
* transaction.
*
* @param timeout - The time in seconds to wait for the database operation used to validate the
* connection to complete. If the timeout period expires before the operation completes, this method
* returns false. A value of 0 indicates a timeout is not applied to the database operation.
*
* @return true if the connection is valid, false otherwise
* @throws java.sql.SQLException if the value supplied for timeout
is less then 0
* @see java.sql.DatabaseMetaData#getClientInfoProperties
* @since 1.6
*
*/
public boolean isValid(final int timeout) throws SQLException {
try {
return protocol.ping();
} catch (QueryException e) {
throw SQLExceptionMapper.get(e);
}
}
/**
* Sets the value of the client info property specified by name to the value specified by value.
*
* Applications may use the DatabaseMetaData.getClientInfoProperties
method to determine the client
* info properties supported by the driver and the maximum length that may be specified for each property.
*
* The driver stores the value specified in a suitable location in the database. For example in a special register,
* session parameter, or system table column. For efficiency the driver may defer setting the value in the database
* until the next time a statement is executed or prepared. Other than storing the client information in the
* appropriate place in the database, these methods shall not alter the behavior of the connection in anyway. The
* values supplied to these methods are used for accounting, diagnostics and debugging purposes only.
*
* The driver shall generate a warning if the client info name specified is not recognized by the driver.
*
* If the value specified to this method is greater than the maximum length for the property the driver may either
* truncate the value and generate a warning or generate a SQLClientInfoException
. If the driver
* generates a SQLClientInfoException
, the value specified was not set on the connection.
*
* The following are standard client info properties. Drivers are not required to support these properties however
* if the driver supports a client info property that can be described by one of the standard properties, the
* standard property name should be used.
*
* - ApplicationName - The name of the application currently utilizing the connection
* - ClientUser - The name of the user that the application using the connection is performing
* work for. This may not be the same as the user name that was used in establishing the connection.
* - ClientHostname - The hostname of the computer the application using the connection is running
* on.
*
*
* @param name The name of the client info property to set
* @param value The value to set the client info property to. If the value is null, the current value of the
* specified property is cleared.
*
* @throws java.sql.SQLClientInfoException
* if the database server returns an error while setting the client info value on the database server or
* this method is called on a closed connection
*
* @since 1.6
*/
public void setClientInfo(final String name, final String value) throws java.sql.SQLClientInfoException {
this.clientInfoProperties.setProperty(name, value);
}
/**
* Sets the value of the connection's client info properties. The Properties
object contains the names
* and values of the client info properties to be set. The set of client info properties contained in the
* properties list replaces the current set of client info properties on the connection. If a property that is
* currently set on the connection is not present in the properties list, that property is cleared. Specifying an
* empty properties list will clear all of the properties on the connection. See setClientInfo (String,
* String)
for more information.
*
* If an error occurs in setting any of the client info properties, a SQLClientInfoException
is thrown.
* The SQLClientInfoException
contains information indicating which client info properties were not
* set. The state of the client information is unknown because some databases do not allow multiple client info
* properties to be set atomically. For those databases, one or more properties may have been set before the error
* occurred.
*
*
* @param properties the list of client info properties to set
*
* @throws java.sql.SQLClientInfoException
* if the database server returns an error while setting the clientInfo values on the database server or
* this method is called on a closed connection
*
* @see java.sql.Connection#setClientInfo(String, String) setClientInfo(String, String)
* @since 1.6
*
*/
public void setClientInfo(final Properties properties) throws java.sql.SQLClientInfoException {
// TODO: actually use these!
for (final String key : properties.stringPropertyNames()) {
this.clientInfoProperties.setProperty(key, properties.getProperty(key));
}
}
/**
* Returns the value of the client info property specified by name. This method may return null if the specified
* client info property has not been set and does not have a default value. This method will also return null if
* the specified client info property name is not supported by the driver.
*
* Applications may use the DatabaseMetaData.getClientInfoProperties
method to determine the client
* info properties supported by the driver.
*
*
* @param name The name of the client info property to retrieve
*
* @return The value of the client info property specified
*
* @throws java.sql.SQLException if the database server returns an error when fetching the client info value from
* the database or this method is called on a closed connection
*
* @see java.sql.DatabaseMetaData#getClientInfoProperties
* @since 1.6
*
*/
public String getClientInfo(final String name) throws SQLException {
return clientInfoProperties.getProperty(name);
}
/**
* Returns a list containing the name and current value of each client info property supported by the driver. The
* value of a client info property may be null if the property has not been set and does not have a default value.
*
*
* @return A Properties
object that contains the name and current value of each of the client info
* properties supported by the driver.
*
* @throws java.sql.SQLException if the database server returns an error when fetching the client info values from
* the database or this method is called on a closed connection
*
* @since 1.6
*/
public Properties getClientInfo() throws SQLException {
return clientInfoProperties;
}
/**
* Factory method for creating Array objects.
*
* Note: When createArrayOf
is used to create an array object that maps to a primitive data
* type, then it is implementation-defined whether the Array
object is an array of that primitive data
* type or an array of Object
.
*
* Note: The JDBC driver is responsible for mapping the elements Object
array to the default
* JDBC SQL type defined in java.sql.Types for the given class of Object
. The default mapping is
* specified in Appendix B of the JDBC specification. If the resulting JDBC type is not the appropriate type for
* the given typeName then it is implementation defined whether an SQLException
is thrown or the driver
* supports the resulting conversion.
*
* @param typeName the SQL name of the type the elements of the array map to. The typeName is a database-specific
* name which may be the name of a built-in type, a user-defined type or a standard SQL type
* supported by this database. This is the value returned by Array.getBaseTypeName
* @param elements the elements that populate the returned object
* @return an Array object whose elements map to the specified SQL type
* @throws java.sql.SQLException if a database error occurs, the JDBC type is not appropriate for the typeName and
* the conversion is not supported, the typeName is null or this method is called on a
* closed connection
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this data type
* @since 1.6
*/
public Array createArrayOf(final String typeName, final Object[] elements) throws SQLException {
throw SQLExceptionMapper.getFeatureNotSupportedException("Not yet supported");
}
/**
* Factory method for creating Struct objects.
*
* @param typeName the SQL type name of the SQL structured type that this Struct
object maps to. The
* typeName is the name of a user-defined type that has been defined for this database. It is the
* value returned by Struct.getSQLTypeName
.
* @param attributes the attributes that populate the returned object
* @return a Struct object that maps to the given SQL type and is populated with the given attributes
* @throws java.sql.SQLException if a database error occurs, the typeName is null or this method is called on a
* closed connection
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this data type
* @since 1.6
*/
public Struct createStruct(final String typeName, final Object[] attributes) throws SQLException {
throw SQLExceptionMapper.getFeatureNotSupportedException("Not yet supported");
}
/**
* Returns an object that implements the given interface to allow access to non-standard methods, or standard
* methods not exposed by the proxy.
*
* If the receiver implements the interface then the result is the receiver or a proxy for the receiver. If the
* receiver is a wrapper and the wrapped object implements the interface then the result is the wrapped object or a
* proxy for the wrapped object. Otherwise return the the result of calling unwrap
recursively on the
* wrapped object or a proxy for that result. If the receiver is not a wrapper and does not implement the interface,
* then an SQLException
is thrown.
*
* @param iface A Class defining an interface that the result must implement.
* @return an object that implements the interface. May be a proxy for the actual implementing object.
* @throws java.sql.SQLException If no object found that implements the interface
* @since 1.6
*/
public T unwrap(final Class iface) throws SQLException {
return iface.cast(this);
}
/**
* Returns true if this either implements the interface argument or is directly or indirectly a wrapper for an
* object that does. Returns false otherwise. If this implements the interface then return true, else if this is a
* wrapper then return the result of recursively calling isWrapperFor
on the wrapped object. If this
* does not implement the interface and is not a wrapper, return false. This method should be implemented as a
* low-cost operation compared to unwrap
so that callers can use this method to avoid expensive
* unwrap
calls that may fail. If this method returns true then calling unwrap
with the
* same argument should succeed.
*
* @param iface a Class defining an interface.
* @return true if this implements the interface or directly or indirectly wraps an object that does.
* @throws java.sql.SQLException if an error occurs while determining whether this is a wrapper for an object with
* the given interface.
* @since 1.6
*/
public boolean isWrapperFor(final Class> iface) throws SQLException {
return iface.isInstance(this);
}
/**
* returns the username for the connection.
*
* @return the username.
*/
public String getUsername() {
return protocol.getUsername();
}
/**
* returns the password for the connection.
*
* @return the password.
*/
public String getPassword() {
return protocol.getPassword();
}
/**
* returns the hostname for the connection.
*
* @return the hostname.
*/
public String getHostname() {
return protocol.getHost();
}
/**
* returns the port for the connection.
*
* @return the port
*/
public int getPort() {
return protocol.getPort();
}
/**
* returns the database.
*
* @return the database
*/
public String getDatabase() {
return protocol.getDatabase();
}
/**
* returns a list of binlog entries.
*
* @param position the position to start at
* @param logfile the log file to use
* @return a list of rawpackets from the server
* @throws SQLException if there is a problem talking to the server.
*/
public List startBinlogDump(final int position, final String logfile) throws SQLException {
try {
return this.protocol.startBinlogDump(position, logfile);
} catch (BinlogDumpException e) {
throw SQLExceptionMapper.getSQLException("Could not dump binlog", e);
}
}
public void setBatchQueryHandlerFactory(final ParameterizedBatchHandlerFactory batchHandlerFactory) {
this.parameterizedBatchHandlerFactory = batchHandlerFactory;
}
protected ScheduledExecutorService getTimeoutExecutor() {
return timeoutExecutor;
}
}