
org.drizzle.jdbc.DrizzleStatement 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.Protocol;
import org.drizzle.jdbc.internal.common.QueryException;
import org.drizzle.jdbc.internal.common.query.Query;
import org.drizzle.jdbc.internal.common.query.QueryFactory;
import org.drizzle.jdbc.internal.common.queryresults.ModifyQueryResult;
import org.drizzle.jdbc.internal.common.queryresults.QueryResult;
import org.drizzle.jdbc.internal.common.queryresults.ResultSetType;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Statement;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
/**
* A sql statement.
*
* User: marcuse Date: Jan 19, 2009 Time: 10:10:58 PM
*/
public class DrizzleStatement implements Statement {
/**
* the protocol used to talk to the server.
*/
private final Protocol protocol;
/**
* the result set produced by execute().
*/
private ResultSet resultSet;
/**
* how many rows were updated.
*/
private long updateCount;
/**
* the sql Connection object.
*/
private final DrizzleConnection connection;
/**
* The actual query result.
*/
private QueryResult queryResult;
/**
* are warnings cleared?
*/
private boolean warningsCleared;
/**
* creates queries.
*/
private final QueryFactory queryFactory;
private InputStream inputStream;
private int queryTimeout;
private ScheduledFuture> timoutFuture;
/**
* Creates a new Statement.
*
* @param protocol the protocol to use.
* @param connection the connection to return in getConnection.
* @param queryFactory the query factory to produce internal queries.
*/
public DrizzleStatement(final Protocol protocol,
final DrizzleConnection connection,
final QueryFactory queryFactory) {
this.protocol = protocol;
this.connection = connection;
this.queryFactory = queryFactory;
}
/**
* returns the protocol.
*
* @return the protocol used.
*/
public Protocol getProtocol() {
return protocol;
}
/**
* executes a select query.
*
* @param query the query to send to the server
* @return a result set
* @throws SQLException if something went wrong
*/
public ResultSet executeQuery(final String query) throws SQLException {
startTimer();
try {
if (queryResult != null) {
queryResult.close();
}
final Query queryToSend = queryFactory.createQuery(query);
queryResult = protocol.executeQuery(queryToSend);
warningsCleared = false;
return new DrizzleResultSet(queryResult, this, getProtocol());
} catch (QueryException e) {
throw SQLExceptionMapper.get(e);
} finally {
stopTimer();
}
}
protected void startTimer() {
if(this.queryTimeout > 0) {
this.timoutFuture = this.connection.getTimeoutExecutor().schedule(new Runnable() {
public void run() {
try {
getProtocol().timeOut();
} catch (QueryException e) {
throw new RuntimeException("Could not time out query.", e);
}
}
}, queryTimeout, TimeUnit.SECONDS);
}
}
protected void stopTimer() {
if(this.timoutFuture != null && !this.timoutFuture.isDone()) {
this.timoutFuture.cancel(true);
}
}
/**
* Executes an update.
*
* @param query the update query.
* @return update count
* @throws SQLException if the query could not be sent to server.
*/
public int executeUpdate(final String query) throws SQLException {
startTimer();
try {
if (queryResult != null) {
queryResult.close();
}
warningsCleared = false;
if(inputStream == null)
queryResult = protocol.executeQuery(queryFactory.createQuery(query));
else
queryResult = protocol.executeQuery(queryFactory.createQuery(query), inputStream);
return (int) ((ModifyQueryResult) queryResult).getUpdateCount();
} catch (QueryException e) {
throw SQLExceptionMapper.get(e);
}
finally
{
stopTimer();
if(inputStream != null)
{
try
{
inputStream.close();
}
catch (IOException e)
{
}
inputStream = null;
}
}
}
/**
* executes a query.
*
* @param query the query
* @return true if there was a result set, false otherwise.
* @throws SQLException
*/
public boolean execute(final String query) throws SQLException {
startTimer();
try {
if (queryResult != null) {
queryResult.close();
}
queryResult = protocol.executeQuery(queryFactory.createQuery(query));
if (queryResult.getResultSetType() == ResultSetType.SELECT) {
setResultSet(new DrizzleResultSet(queryResult, this, getProtocol()));
return true;
}
setUpdateCount(((ModifyQueryResult) queryResult).getUpdateCount());
return false;
} catch (QueryException e) {
throw SQLExceptionMapper.get(e);
} finally {
stopTimer();
}
}
public QueryFactory getQueryFactory() {
return queryFactory;
}
/**
* Releases this Statement
object's database and JDBC resources immediately instead of waiting for this
* to happen when it is automatically closed. It is generally good practice to release resources as soon as you are
* finished with them to avoid tying up database resources.
*
* Calling the method close
on a Statement
object that is already closed has no effect.
*
* Note:When a Statement
object is closed, its current ResultSet
object, if one
* exists, is also closed.
*
* @throws java.sql.SQLException if a database access error occurs
*/
public void close() throws SQLException {
if (queryResult != null) {
queryResult.close();
}
}
/**
* Retrieves the maximum number of bytes that can be returned for character and binary column values in a
* ResultSet
object produced by this Statement
object. This limit applies only to
* BINARY
, VARBINARY
, LONGVARBINARY
, CHAR
, VARCHAR
,
* NCHAR
, NVARCHAR
, LONGNVARCHAR
and LONGVARCHAR
columns. If
* the limit is exceeded, the excess data is silently discarded.
*
* @return the current column size limit for columns storing character and binary values; zero means there is no
* limit
* @throws java.sql.SQLException if a database access error occurs or this method is called on a closed
* Statement
* @see #setMaxFieldSize
*/
public int getMaxFieldSize() throws SQLException {
return 0;
}
/**
* Sets the limit for the maximum number of bytes that can be returned for character and binary column values in a
* ResultSet
object produced by this Statement
object.
*
* This limit applies only to BINARY
, VARBINARY
, LONGVARBINARY
,
* CHAR
, VARCHAR
, NCHAR
, NVARCHAR
, LONGNVARCHAR
and
* LONGVARCHAR
fields. If the limit is exceeded, the excess data is silently discarded. For maximum
* portability, use values greater than 256.
*
* @param max the new column size limit in bytes; zero means there is no limit
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed
* Statement
or the condition max >= 0 is not satisfied
* @see #getMaxFieldSize
*/
public void setMaxFieldSize(final int max) throws SQLException {
//we dont support max field sizes
}
/**
* Retrieves the maximum number of rows that a ResultSet
object produced by this Statement
* object can contain. If this limit is exceeded, the excess rows are silently dropped.
*
* @return the current maximum number of rows for a ResultSet
object produced by this
* Statement
object; zero means there is no limit
* @throws java.sql.SQLException if a database access error occurs or this method is called on a closed
* Statement
* @see #setMaxRows
*/
public int getMaxRows() throws SQLException {
return 0; // 0 = no limit
}
/**
* Sets the limit for the maximum number of rows that any ResultSet
object generated by this
* Statement
object can contain to the given number. If the limit is exceeded, the excess rows are
* silently dropped.
*
* @param max the new max rows limit; zero means there is no limit
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed
* Statement
or the condition max >= 0 is not satisfied
* @see #getMaxRows
*/
public void setMaxRows(final int max) throws SQLException {
//we dont support this (yet?)
}
/**
* Sets escape processing on or off. If escape scanning is on (the default), the driver will do escape substitution
* before sending the SQL statement to the database.
*
* Note: Since prepared statements have usually been parsed prior to making this call, disabling escape processing
* for PreparedStatements
objects will have no effect.
*
* @param enable true
to enable escape processing; false
to disable it
* @throws java.sql.SQLException if a database access error occurs or this method is called on a closed
* Statement
*/
public void setEscapeProcessing(final boolean enable) throws SQLException {
//TODO: check jdbc4 docs for more info
}
/**
* Retrieves the number of seconds the driver will wait for a Statement
object to execute. If the limit
* is exceeded, a SQLException
is thrown.
*
* @return the current query timeout limit in seconds; zero means there is no limit
* @throws java.sql.SQLException if a database access error occurs or this method is called on a closed
* Statement
* @see #setQueryTimeout
*/
public int getQueryTimeout() throws SQLException {
return queryTimeout;
}
/**
* Sets the number of seconds the driver will wait for a Statement
object to execute to the given
* number of seconds. If the limit is exceeded, an SQLException
is thrown. A JDBC driver must apply
* this limit to the execute
, executeQuery
and executeUpdate
methods. JDBC
* driver implementations may also apply this limit to ResultSet
methods (consult your driver vendor
* documentation for details).
*
* @param seconds the new query timeout limit in seconds; zero means there is no limit
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed
* Statement
or the condition seconds >= 0 is not satisfied
* @see #getQueryTimeout
*/
public void setQueryTimeout(final int seconds) throws SQLException {
this.queryTimeout = seconds;
}
/**
* Cancels this Statement
object if both the DBMS and driver support aborting an SQL statement. This
* method can be used by one thread to cancel a statement that is being executed by another thread.
*
* @throws java.sql.SQLException if a database access error occurs or this method is called on a closed
* Statement
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this method
*/
public void cancel() throws SQLException {
try {
protocol.cancelCurrentQuery();
} catch (QueryException e) {
throw SQLExceptionMapper.get(e);
}
}
/**
* Retrieves the first warning reported by calls on this Statement
object. Subsequent
* Statement
object warnings will be chained to this SQLWarning
object.
*
* The warning chain is automatically cleared each time a statement is (re)executed. This method may not be
* called on a closed Statement
object; doing so will cause an SQLException
to be thrown.
*
* Note: If you are processing a ResultSet
object, any warnings associated with reads on that
* ResultSet
object will be chained on it rather than on the Statement
object that
* produced it.
*
* @return the first SQLWarning
object or null
if there are no warnings
* @throws java.sql.SQLException if a database access error occurs or this method is called on a closed
* Statement
*/
public SQLWarning getWarnings() throws SQLException {
if (!warningsCleared && queryResult != null && queryResult.getWarnings() > 0) {
return new SQLWarning(queryResult.getMessage());
}
return null;
}
/**
* Clears all the warnings reported on this Statement
object. After a call to this method, the method
* getWarnings
will return null
until a new warning is reported for this
* Statement
object.
*
* @throws java.sql.SQLException if a database access error occurs or this method is called on a closed
* Statement
*/
public void clearWarnings() throws SQLException {
warningsCleared = true;
}
/**
* Sets the SQL cursor name to the given String
, which will be used by subsequent
* Statement
object execute
methods. This name can then be used in SQL positioned update
* or delete statements to identify the current row in the ResultSet
object generated by this
* statement. If the database does not support positioned update/delete, this method is a noop. To insure that a
* cursor has the proper isolation level to support updates, the cursor's SELECT
statement should have
* the form SELECT FOR UPDATE
. If FOR UPDATE
is not present, positioned updates may
* fail.
*
* Note: By definition, the execution of positioned updates and deletes must be done by a different
* Statement
object than the one that generated the ResultSet
object being used for
* positioning. Also, cursor names must be unique within a connection.
*
* @param name the new cursor name, which must be unique within a connection
* @throws java.sql.SQLException if a database access error occurs or this method is called on a closed
* Statement
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this method
*/
public void setCursorName(final String name) throws SQLException {
throw SQLExceptionMapper.getFeatureNotSupportedException("Cursors are not supported");
}
/**
* gets the connection that created this statement
*
* @return the connection
* @throws SQLException
*/
public Connection getConnection() throws SQLException {
return this.connection;
}
/**
* Moves to this Statement
object's next result, deals with any current ResultSet
* object(s) according to the instructions specified by the given flag, and returns true
if the next
* result is a ResultSet
object.
*
* There are no more results when the following is true:
// stmt is a Statement object
* ((stmt.getMoreResults(current) == false) && (stmt.getUpdateCount() == -1))
*
* @param current one of the following Statement
constants indicating what should happen to current
* ResultSet
objects obtained using the method getResultSet
:
* Statement.CLOSE_CURRENT_RESULT
, Statement.KEEP_CURRENT_RESULT
, or
* Statement.CLOSE_ALL_RESULTS
* @return true
if the next result is a ResultSet
object; false
if it is an
* update count or there are no more results
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed
* Statement
or the argument supplied is not one of the following:
* Statement.CLOSE_CURRENT_RESULT
, Statement.KEEP_CURRENT_RESULT
* or Statement.CLOSE_ALL_RESULTS
* @throws java.sql.SQLFeatureNotSupportedException
* if DatabaseMetaData.supportsMultipleOpenResults
returns
* false
and either Statement.KEEP_CURRENT_RESULT
or
* Statement.CLOSE_ALL_RESULTS
are supplied as the argument.
* @see #execute
* @since 1.4
*/
public boolean getMoreResults(final int current) throws SQLException {
return getMoreResults();
}
/**
* Retrieves any auto-generated keys created as a result of executing this Statement
object. If this
* Statement
object did not generate any keys, an empty ResultSet
object is returned.
*
* Note:If the columns which represent the auto-generated keys were not specified, the JDBC driver
* implementation will determine the columns which best represent the auto-generated keys.
*
* @return a ResultSet
object containing the auto-generated key(s) generated by the execution of this
* Statement
object
* @throws java.sql.SQLException if a database access error occurs or this method is called on a closed
* Statement
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this method
* @since 1.4
*/
public ResultSet getGeneratedKeys() throws SQLException {
if (queryResult != null && queryResult.getResultSetType() == ResultSetType.MODIFY) {
final QueryResult genRes = ((ModifyQueryResult) queryResult).getGeneratedKeysResult();
return new DrizzleResultSet(genRes, this, getProtocol());
}
return DrizzleResultSet.EMPTY;
}
/**
* Executes the given SQL statement and signals the driver with the given flag about whether the auto-generated keys
* produced by this Statement
object should be made available for retrieval. The driver will ignore
* the flag 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).
*
* @param sql an SQL Data Manipulation Language (DML) statement, such as INSERT
,
* UPDATE
or DELETE
; or an SQL statement that returns nothing,
* such as a DDL statement.
* @param autoGeneratedKeys a flag indicating whether auto-generated keys should be made available for retrieval;
* one of the following constants: Statement.RETURN_GENERATED_KEYS
* Statement.NO_GENERATED_KEYS
* @return either (1) the row count for SQL Data Manipulation Language (DML) statements or (2) 0 for SQL statements
* that return nothing
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed
* Statement
, the given SQL statement returns a ResultSet
* object, or the given constant is not one of those allowed
* @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 int executeUpdate(final String sql, final int autoGeneratedKeys) throws SQLException {
return executeUpdate(sql);
}
/**
* Executes the given SQL statement and signals the driver that the auto-generated keys indicated in the given array
* should be made available for retrieval. 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).
*
* @param sql an SQL Data Manipulation Language (DML) statement, such as INSERT
,
* UPDATE
or DELETE
; or an SQL statement that returns nothing, such
* as a DDL statement.
* @param columnIndexes an array of column indexes indicating the columns that should be returned from the inserted
* row
* @return either (1) the row count for SQL Data Manipulation Language (DML) statements or (2) 0 for SQL statements
* that return nothing
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed
* Statement
, the SQL statement returns a ResultSet
object,
* or the second argument supplied to this method is not an int
array
* whose elements are valid column indexes
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this method
* @since 1.4
*/
public int executeUpdate(final String sql, final int[] columnIndexes) throws SQLException {
throw SQLExceptionMapper.getFeatureNotSupportedException("Not supported");
}
/**
* Executes the given SQL statement and signals the driver that the auto-generated keys indicated in the given array
* should be made available for retrieval. This array contains the names 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).
*
* @param sql an SQL Data Manipulation Language (DML) statement, such as INSERT
,
* UPDATE
or DELETE
; or an SQL statement that returns nothing, such as
* a DDL statement.
* @param columnNames an array of the names of the columns that should be returned from the inserted row
* @return either the row count for INSERT
, UPDATE
, or DELETE
statements, or
* 0 for SQL statements that return nothing
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed
* Statement
, the SQL statement returns a ResultSet
object,
* or the second argument supplied to this method is not a String
array
* whose elements are valid column names
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this method
* @since 1.4
*/
public int executeUpdate(final String sql, final String[] columnNames) throws SQLException {
throw SQLExceptionMapper.getFeatureNotSupportedException("Not supported");
}
/**
* Executes the given SQL statement, which may return multiple results, and signals the driver that any
* auto-generated keys should be made available for retrieval. The driver will ignore this signal 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).
*
* In some (uncommon) situations, a single SQL statement may return multiple result sets and/or update counts.
* Normally you can ignore this unless you are (1) executing a stored procedure that you know may return multiple
* results or (2) you are dynamically executing an unknown SQL string.
*
* The execute
method executes an SQL statement and indicates the form of the first result. You must
* then use the methods getResultSet
or getUpdateCount
to retrieve the result, and
* getMoreResults
to move to any subsequent result(s).
*
* @param sql any SQL statement
* @param autoGeneratedKeys a constant indicating whether auto-generated keys should be made available for retrieval
* using the method getGeneratedKeys
; one of the following constants:
* Statement.RETURN_GENERATED_KEYS
or Statement.NO_GENERATED_KEYS
* @return true
if the first result is a ResultSet
object; false
if it is an
* update count or there are no results
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed
* Statement
or the second parameter supplied to this method is not
* Statement.RETURN_GENERATED_KEYS
or Statement.NO_GENERATED_KEYS
.
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this method with a constant of
* Statement.RETURN_GENERATED_KEYS
* @see #getResultSet
* @see #getUpdateCount
* @see #getMoreResults
* @see #getGeneratedKeys
* @since 1.4
*/
public boolean execute(final String sql, final int autoGeneratedKeys) throws SQLException {
return execute(sql); // auto generated keys are always available
}
/**
* Executes the given SQL statement, which may return multiple results, and signals the driver that the
* auto-generated keys indicated in the given array should be made available for retrieval. 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).
*
* Under some (uncommon) situations, a single SQL statement may return multiple result sets and/or update counts.
* Normally you can ignore this unless you are (1) executing a stored procedure that you know may return multiple
* results or (2) you are dynamically executing an unknown SQL string.
*
* The execute
method executes an SQL statement and indicates the form of the first result. You must
* then use the methods getResultSet
or getUpdateCount
to retrieve the result, and
* getMoreResults
to move to any subsequent result(s).
*
* @param sql any SQL statement
* @param columnIndexes an array of the indexes of the columns in the inserted row that should be made available
* for retrieval by a call to the method getGeneratedKeys
* @return true
if the first result is a ResultSet
object; false
if it is an
* update count or there are no results
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed
* Statement
or the elements in the int
array passed to this
* method are not valid column indexes
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this method
* @see #getResultSet
* @see #getUpdateCount
* @see #getMoreResults
* @since 1.4
*/
public boolean execute(final String sql, final int[] columnIndexes) throws SQLException {
throw SQLExceptionMapper.getFeatureNotSupportedException("Not supported");
}
/**
* Executes the given SQL statement, which may return multiple results, and signals the driver that the
* auto-generated keys indicated in the given array should be made available for retrieval. This array contains the
* names 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).
*
* In some (uncommon) situations, a single SQL statement may return multiple result sets and/or update counts.
* Normally you can ignore this unless you are (1) executing a stored procedure that you know may return multiple
* results or (2) you are dynamically executing an unknown SQL string.
*
* The execute
method executes an SQL statement and indicates the form of the first result. You must
* then use the methods getResultSet
or getUpdateCount
to retrieve the result, and
* getMoreResults
to move to any subsequent result(s).
*
* @param sql any SQL statement
* @param columnNames an array of the names of the columns in the inserted row that should be made available for
* retrieval by a call to the method getGeneratedKeys
* @return true
if the next result is a ResultSet
object; false
if it is an
* update count or there are no more results
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed
* Statement
or the elements of the String
array passed to
* this method are not valid column names
* @throws java.sql.SQLFeatureNotSupportedException
* if the JDBC driver does not support this method
* @see #getResultSet
* @see #getUpdateCount
* @see #getMoreResults
* @see #getGeneratedKeys
* @since 1.4
*/
public boolean execute(final String sql, final String[] columnNames) throws SQLException {
throw SQLExceptionMapper.getFeatureNotSupportedException("Not supported");
}
/**
* Retrieves the result set holdability for ResultSet
objects generated by this Statement
* object.
*
* @return either 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
* Statement
* @since 1.4
*/
public int getResultSetHoldability() throws SQLException {
return ResultSet.HOLD_CURSORS_OVER_COMMIT;
}
/**
* Retrieves whether this Statement
object has been closed. A Statement
is closed if the
* method close has been called on it, or if it is automatically closed.
*
* @return true if this Statement
object is closed; false if it is still open
* @throws java.sql.SQLException if a database access error occurs
* @since 1.6
*/
public boolean isClosed() throws SQLException {
return false;
}
/**
* Requests that a Statement
be pooled or not pooled. The value specified is a hint to the statement
* pool implementation indicating whether the applicaiton wants the statement to be pooled. It is up to the
* statement pool manager as to whether the hint is used.
*
* The poolable value of a statement is applicable to both internal statement caches implemented by the driver and
* external statement caches implemented by application servers and other applications.
*
* By default, a Statement
is not poolable when created, and a PreparedStatement
and
* CallableStatement
are poolable when created.
*
*
* @param poolable requests that the statement be pooled if true and that the statement not be pooled if false
*
* @throws java.sql.SQLException if this method is called on a closed Statement
*
* @since 1.6
*/
public void setPoolable(final boolean poolable) throws SQLException {
}
/**
* Returns a value indicating whether the Statement
is poolable or not.
*
*
* @return true
if the Statement
is poolable; false
otherwise
*
* @throws java.sql.SQLException if this method is called on a closed Statement
*
* @see java.sql.Statement#setPoolable(boolean) setPoolable(boolean)
* @since 1.6
*
*/
public boolean isPoolable() throws SQLException {
return false;
}
public ResultSet getResultSet() throws SQLException {
return resultSet;
}
public int getUpdateCount() throws SQLException {
if(queryResult != null && queryResult.getResultSetType() == ResultSetType.SELECT) {
return -1;
}
return (int)updateCount;
}
/**
* Moves to this Statement
object's next result, returns true
if it is a
* ResultSet
object, and implicitly closes any current ResultSet
object(s) obtained with
* the method getResultSet
.
*
* There are no more results when the following is true:
// stmt is a Statement object
* ((stmt.getMoreResults() == false) && (stmt.getUpdateCount() == -1))
*
* @return true
if the next result is a ResultSet
object; false
if it is an
* update count or there are no more results
* @throws java.sql.SQLException if a database access error occurs or this method is called on a closed
* Statement
* @see #execute
*/
public boolean getMoreResults() throws SQLException {
startTimer();
try {
if (queryResult != null) {
queryResult.close();
}
queryResult = protocol.getMoreResults();
if(queryResult == null) {
this.resultSet=null;
setUpdateCount(-1);
return false;
}
warningsCleared = false;
if (queryResult.getResultSetType() == ResultSetType.SELECT) {
setResultSet(new DrizzleResultSet(queryResult, this, getProtocol()));
return true;
}
setUpdateCount((int)((ModifyQueryResult) queryResult).getUpdateCount());
return false;
} catch (QueryException e) {
throw SQLExceptionMapper.get(e);
} finally {
stopTimer();
}
}
/**
* Gives the driver a hint as to the direction in which rows will be processed in ResultSet
objects
* created using this Statement
object. The default value is ResultSet.FETCH_FORWARD
.
*
* Note that this method sets the default fetch direction for result sets generated by this Statement
* object. Each result set has its own methods for getting and setting its own fetch direction.
*
* @param direction the initial direction for processing rows
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed
* Statement
or the given direction is not one of
* ResultSet.FETCH_FORWARD
, ResultSet.FETCH_REVERSE
, or
* ResultSet.FETCH_UNKNOWN
* @see #getFetchDirection
* @since 1.2
*/
public void setFetchDirection(final int direction) throws SQLException {
}
/**
* Retrieves the direction for fetching rows from database tables that is the default for result sets generated from
* this Statement
object. If this Statement
object has not set a fetch direction by
* calling the method setFetchDirection
, the return value is implementation-specific.
*
* @return the default fetch direction for result sets generated from this Statement
object
* @throws java.sql.SQLException if a database access error occurs or this method is called on a closed
* Statement
* @see #setFetchDirection
* @since 1.2
*/
public int getFetchDirection() throws SQLException {
return ResultSet.FETCH_FORWARD;
}
/**
* Gives the JDBC driver a hint as to the number of rows that should be fetched from the database when more rows are
* needed for ResultSet
objects genrated by this Statement
. If the value specified is
* zero, then the hint is ignored. The default value is zero.
*
* @param rows the number of rows to fetch
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed
* Statement
or the condition rows >= 0
is not satisfied.
* @see #getFetchSize
* @since 1.2
*/
public void setFetchSize(final int rows) throws SQLException {
}
/**
* Retrieves the number of result set rows that is the default fetch size for ResultSet
objects
* generated from this Statement
object. If this Statement
object has not set a fetch size
* by calling the method setFetchSize
, the return value is implementation-specific.
*
* @return the default fetch size for result sets generated from this Statement
object
* @throws java.sql.SQLException if a database access error occurs or this method is called on a closed
* Statement
* @see #setFetchSize
* @since 1.2
*/
public int getFetchSize() throws SQLException {
return 0;
}
/**
* Retrieves the result set concurrency for ResultSet
objects generated by this Statement
* object.
*
* @return either ResultSet.CONCUR_READ_ONLY
or ResultSet.CONCUR_UPDATABLE
* @throws java.sql.SQLException if a database access error occurs or this method is called on a closed
* Statement
* @since 1.2
*/
public int getResultSetConcurrency() throws SQLException {
return ResultSet.CONCUR_READ_ONLY;
}
/**
* Retrieves the result set type for ResultSet
objects generated by this Statement
* object.
*
* @return one of ResultSet.TYPE_FORWARD_ONLY
, ResultSet.TYPE_SCROLL_INSENSITIVE
, or
* ResultSet.TYPE_SCROLL_SENSITIVE
* @throws java.sql.SQLException if a database access error occurs or this method is called on a closed
* Statement
* @since 1.2
*/
public int getResultSetType() throws SQLException {
// TODO: this will change when the async protocol is implemented
return ResultSet.TYPE_SCROLL_INSENSITIVE;
}
/**
* Adds the given SQL command to the current list of commmands for this Statement
object. The commands
* in this list can be executed as a batch by calling the method executeBatch
.
*
*
* @param sql typically this is a SQL INSERT
or UPDATE
statement
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed
* Statement
or the driver does not support batch updates
* @see #executeBatch
* @see java.sql.DatabaseMetaData#supportsBatchUpdates
* @since 1.2
*/
public void addBatch(final String sql) throws SQLException {
this.protocol.addToBatch(queryFactory.createQuery(sql));
}
public void addBatch(final byte[] sql) throws SQLException {
this.protocol.addToBatch(queryFactory.createQuery(sql));
}
/**
* Empties this Statement
object's current list of SQL commands.
*
*
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed
* Statement
or the driver does not support batch updates
* @see #addBatch
* @see java.sql.DatabaseMetaData#supportsBatchUpdates
* @since 1.2
*/
public void clearBatch() throws SQLException {
this.protocol.clearBatch();
}
/**
* Submits a batch of commands to the database for execution and if all commands execute successfully, returns an
* array of update counts. The int
elements of the array that is returned are ordered to correspond to
* the commands in the batch, which are ordered according to the order in which they were added to the batch. The
* elements in the array returned by the method executeBatch
may be one of the following: - A
* number greater than or equal to zero -- indicates that the command was processed successfully and is an update
* count giving the number of rows in the database that were affected by the command's execution
- A value of
*
SUCCESS_NO_INFO
-- indicates that the command was processed successfully but that the number of rows
* affected is unknown
*
* If one of the commands in a batch update fails to execute properly, this method throws a
* BatchUpdateException
, and a JDBC driver may or may not continue to process the remaining commands in
* the batch. However, the driver's behavior must be consistent with a particular DBMS, either always continuing to
* process commands or never continuing to process commands. If the driver continues processing after a failure,
* the array returned by the method BatchUpdateException.getUpdateCounts
will contain as many elements
* as there are commands in the batch, and at least one of the elements will be the following:
*
* - A value of
EXECUTE_FAILED
-- indicates that the command failed to execute successfully and
* occurs only if a driver continues to process commands after a command fails
*
* The possible implementations and return values have been modified in the Java 2 SDK, Standard Edition, version
* 1.3 to accommodate the option of continuing to proccess commands in a batch update after a
* BatchUpdateException
obejct has been thrown.
*
* @return an array of update counts containing one element for each command in the batch. The elements of the
* array are ordered according to the order in which commands were added to the batch.
* @throws java.sql.SQLException if a database access error occurs, this method is called on a closed
* Statement
or the driver does not support batch statements. Throws
* {@link java.sql.BatchUpdateException} (a subclass of SQLException
) if
* one of the commands sent to the database fails to execute properly or attempts to
* return a result set.
* @see #addBatch
* @see java.sql.DatabaseMetaData#supportsBatchUpdates
* @since 1.3
*/
public int[] executeBatch() throws SQLException {
try {
final List queryRes = protocol.executeBatch();
final int[] retVals = new int[queryRes.size()];
int i = 0;
for (final QueryResult qr : queryRes) {
if (qr.getResultSetType() == ResultSetType.MODIFY) {
retVals[i++] =
(int) ((ModifyQueryResult) qr).getUpdateCount(); //TODO: this needs to be handled according to javadoc
} else {
retVals[i++] = SUCCESS_NO_INFO;
}
}
return retVals;
} catch (QueryException e) {
throw SQLExceptionMapper.get(e);
}
}
/**
* 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 null;
}
/**
* 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 false;
}
protected void setResultSet(final DrizzleResultSet drizzleResultSet) {
this.resultSet = drizzleResultSet;
}
protected void setUpdateCount(final long updateCount) {
this.updateCount = updateCount;
}
/**
* returns the query result.
*
* @return the queryresult
*/
protected QueryResult getQueryResult() {
return queryResult;
}
/**
* sets the current query result
*
* @param result
*/
protected void setQueryResult(final QueryResult result) {
this.queryResult = result;
}
public void setLocalInfileInputStream(InputStream is)
{
this.inputStream = is;
}
/**
* Indicates whether the statement is auto-closed when no result sets are
* remain open.
*
* @return True or false.
*/
public boolean isCloseOnCompletion() throws SQLException {
return false;
}
public void closeOnCompletion() throws SQLException {
throw SQLExceptionMapper.getFeatureNotSupportedException("Statement closeOnCompletion");
}
}