client-java.sources.src.main.org.firebirdsql.jdbc.AbstractCallableStatement Maven / Gradle / Ivy
/*
* Firebird Open Source J2ee connector - jdbc driver
*
* Distributable under LGPL license.
* You may obtain a copy of the License at http://www.gnu.org/copyleft/lgpl.html
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* LGPL License for more details.
*
* This file was created by members of the firebird development team.
* All individual contributions remain the Copyright (C) of those
* individuals. Contributors to this file are either listed here or
* can be obtained from a CVS history command.
*
* All rights reserved.
*/
package org.firebirdsql.jdbc;
import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.sql.*;
import java.util.*;
import org.firebirdsql.gds.DatabaseParameterBuffer;
import org.firebirdsql.gds.GDSException;
import org.firebirdsql.gds.impl.DatabaseParameterBufferExtension;
import org.firebirdsql.gds.impl.GDSHelper;
import org.firebirdsql.jdbc.field.FBField;
import org.firebirdsql.jdbc.field.TypeConvertionException;
/**
* The interface used to execute SQL
* stored procedures. JDBC provides a stored procedure
* SQL escape syntax that allows stored procedures to be called in a standard
* way for all RDBMSs. This escape syntax has one form that includes
* a result parameter and one that does not. If used, the result
* parameter must be registered as an OUT parameter. The other parameters
* can be used for input, output or both. Parameters are referred to
* sequentially, by number, with the first parameter being 1.
*
*
* {?= call <procedure-name>[<arg1>,<arg2>, ...]}
* {call <procedure-name>[<arg1>,<arg2>, ...]}
*
*
* IN parameter values are set using the set methods inherited from
* {@link PreparedStatement}. The type of all OUT parameters must be
* registered prior to executing the stored procedure; their values
* are retrieved after execution via the get
methods provided here.
*
* A CallableStatement
can return one {@link ResultSet} or
* multiple ResultSet
objects. Multiple
* ResultSet
objects are handled using operations
* inherited from {@link Statement}.
*
* For maximum portability, a call's ResultSet
objects and
* update counts should be processed prior to getting the values of output
* parameters.
*
* Methods that are new in the JDBC 2.0 API are marked "Since 1.2."
*
* Note: Escape syntax currently is not supported. Please use native
* Firebird procedure call syntax:
*
* EXECUTE PROCEDURE (param1, ...);
*
*
* @see Connection#prepareCall
* @see ResultSet
*
* @author David Jencks
* @author Roman Rokytskyy
* @author Steven Jardine
*/
public abstract class AbstractCallableStatement
extends AbstractPreparedStatement
implements CallableStatement, FirebirdCallableStatement
{
static final String NATIVE_CALL_COMMAND = "EXECUTE PROCEDURE";
static final String NATIVE_SELECT_COMMAND = "SELECT * FROM";
private ResultSet currentRs;
protected boolean selectableProcedure;
protected FBProcedureCall procedureCall;
protected AbstractCallableStatement(GDSHelper c, String sql, int rsType,
int rsConcurrency, int rsHoldability,
FBObjectListener.StatementListener statementListener,
FBObjectListener.BlobListener blobListener)
throws SQLException {
super(c, rsType, rsConcurrency, rsHoldability, statementListener, blobListener);
DatabaseParameterBuffer dpb = c.getDatabaseParameterBuffer();
int mode = FBEscapedParser.USE_BUILT_IN;
if (dpb.hasArgument(DatabaseParameterBufferExtension.USE_STANDARD_UDF))
mode = FBEscapedParser.USE_STANDARD_UDF;
FBEscapedCallParser parser = new FBEscapedCallParser(mode);
// here statement is parsed twicel, once in c.nativeSQL(...)
// and second time in parser.parseCall(...)... not nice, maybe
// in the future should be fixed by calling FBEscapedParser for
// each parameter in FBEscapedCallParser class
procedureCall = parser.parseCall(nativeSQL(sql));
}
private ArrayList batchList = new ArrayList();
public void addBatch() throws SQLException {
batchList.add(procedureCall.clone());
}
public void clearBatch() throws SQLException {
batchList.clear();
}
public int[] executeBatch() throws SQLException {
Object syncObject = getSynchronizationObject();
synchronized (syncObject) {
boolean success = false;
try {
notifyStatementStarted();
ArrayList results = new ArrayList(batchList.size());
Iterator iterator = batchList.iterator();
try {
while (iterator.hasNext()) {
procedureCall = (FBProcedureCall)iterator.next();
try {
prepareFixedStatement(procedureCall
.getSQL(selectableProcedure), true);
if (internalExecute(!selectableProcedure))
throw new BatchUpdateException(toArray(results));
results.add(new Integer(getUpdateCount()));
} catch (GDSException ex) {
throw new BatchUpdateException(ex.getMessage(), "", ex.getFbErrorCode(),
toArray(results));
}
}
success = true;
return toArray(results);
} finally {
clearBatch();
}
} finally {
notifyStatementCompleted(success);
}
}
}
/* (non-Javadoc)
* @see org.firebirdsql.jdbc.FirebirdCallableStatement#setSelectableProcedure(boolean)
*/
public void setSelectableProcedure(boolean selectableProcedure) {
this.selectableProcedure = selectableProcedure;
}
/**
* Set required types for output parameters.
*
* @throws SQLException if something went wrong.
*/
protected void setRequiredTypes() throws SQLException {
FBResultSet resultSet = (FBResultSet)getCurrentResultSet();
Iterator iter = procedureCall.getOutputParams().iterator();
while(iter.hasNext()) {
FBProcedureParam param = (FBProcedureParam)iter.next();
if (param == null)
continue;
FBField field = resultSet.getField(
procedureCall.mapOutParamIndexToPosition(param.getIndex()),
false);
field.setRequiredType(param.getType());
}
}
/**
* We allow multiple calls to this method without re-preparing the statement.
* This is an workaround to the issue that the statement is actually prepared
* only after all OUT parameters are registered.
*/
protected void prepareFixedStatement(String sql, boolean describeBind)
throws GDSException, SQLException {
if (fixedStmt != null)
return;
super.prepareFixedStatement(sql, describeBind);
}
/**
* Since we deferred the statement preparation until all OUT params are
* registered, we ensure that the statement is prepared before the meta
* data for the callable statement is obtained.
*/
public ResultSetMetaData getMetaData() throws SQLException {
statementListener.executionStarted(this);
Object syncObject = getSynchronizationObject();
synchronized(syncObject) {
try {
prepareFixedStatement(procedureCall.getSQL(selectableProcedure), true);
} catch (GDSException ge) {
throw new FBSQLException(ge);
}
}
return super.getMetaData();
}
/**
* Executes an execute stored procedure.
* Some prepared statements return multiple results; the execute
* method handles these complex statements as well as the simpler
* form of statements handled by the methods executeQuery
* and executeUpdate
.
*
* @exception SQLException if a database access error occurs
* @see Statement#execute
*/
public boolean execute() throws SQLException {
boolean hasResultSet = false;
Object syncObject = getSynchronizationObject();
synchronized (syncObject) {
notifyStatementStarted();
try {
try {
currentRs = null;
prepareFixedStatement(procedureCall
.getSQL(selectableProcedure), true);
hasResultSet = internalExecute(!selectableProcedure);
if (hasResultSet) setRequiredTypes();
} catch (GDSException ge) {
throw new FBSQLException(ge);
} // end of try-catch-finally
} finally {
if (!hasResultSet) notifyStatementCompleted();
}
return hasResultSet;
}
}
/**
* Execute query. This method prepares statement before execution. Rest of
* the processing is done by superclass.
*/
public ResultSet executeQuery() throws SQLException {
Object syncObject = getSynchronizationObject();
synchronized(syncObject) {
notifyStatementStarted();
try {
currentRs = null;
prepareFixedStatement(procedureCall.getSQL(selectableProcedure), true);
if (!internalExecute(!selectableProcedure))
throw new FBSQLException(
"No resultset for sql",
FBSQLException.SQL_STATE_NO_RESULT_SET);
getResultSet();
setRequiredTypes();
return getCurrentResultSet();
} catch(GDSException ex) {
throw new FBSQLException(ex);
}
}
}
/**
* Execute query. This method prepares statement before execution. Rest of
* the processing is done by superclass.
*/
public int executeUpdate() throws SQLException {
Object syncObject = getSynchronizationObject();
synchronized (syncObject) {
try {
notifyStatementStarted();
try {
currentRs = null;
prepareFixedStatement(procedureCall
.getSQL(selectableProcedure), true);
/*
* // R.Rokytskyy: JDBC CTS suite uses executeUpdate() //
* together with output parameters, therefore we cannot //
* throw exception if we want to pass the test suite
*
* if (internalExecute(true)) throw new FBSQLException(
* "Update statement returned results.");
*/
boolean hasResults = internalExecute(!selectableProcedure);
if (hasResults) {
setRequiredTypes();
}
return getUpdateCount();
} catch (GDSException ex) {
throw new FBSQLException(ex);
}
} finally {
notifyStatementCompleted();
}
}
}
/**
* Execute statement internally. This method sets cached parameters. Rest of
* the processing is done by superclass.
*/
protected boolean internalExecute(boolean sendOutParams)
throws SQLException {
int counter = 0;
List inputParams = procedureCall.getInputParams();
Iterator iter = inputParams.iterator();
while(iter.hasNext()) {
FBProcedureParam param = (FBProcedureParam)iter.next();
if (param != null && param.isParam()) {
counter++;
Object value = param.getValue();
FBField field = getField(counter);
if (value == null)
field.setNull();
else
if (value instanceof WrapperWithCalendar) {
Object obj = ((WrapperWithCalendar)value).getValue();
if (obj == null) {
field.setNull();
} else {
Calendar cal = ((WrapperWithCalendar)value).getCalendar();
if (obj instanceof Timestamp)
field.setTimestamp((Timestamp)obj, cal);
else
if (obj instanceof java.sql.Date)
field.setDate((java.sql.Date)obj, cal);
else
if (obj instanceof Time)
field.setTime((Time)obj, cal);
else
throw new TypeConvertionException(
"Cannot convert type " +
obj.getClass().getName());
}
} else
if (value instanceof WrapperWithInt) {
Object obj = ((WrapperWithInt)value).getValue();
if (obj == null) {
field.setNull();
} else {
int intValue = ((WrapperWithInt)value).getIntValue();
if (obj instanceof InputStream)
field.setBinaryStream((InputStream)obj, intValue);
else
if (obj instanceof Reader)
field.setCharacterStream((Reader)obj, intValue);
else
throw new TypeConvertionException(
"Cannot convert type " +
obj.getClass().getName());
}
} else
field.setObject(value);
isParamSet[counter - 1] = true;
}
}
return super.internalExecute(sendOutParams);
}
/**
* Registers the OUT parameter in ordinal position
* parameterIndex
to the JDBC type
* sqlType
. All OUT parameters must be registered
* before a stored procedure is executed.
*
* The JDBC type specified by sqlType
for an OUT
* parameter determines the Java type that must be used
* in the get
method to read the value of that parameter.
*
* If the JDBC type expected to be returned to this output parameter
* is specific to this particular database, sqlType
* should be java.sql.Types.OTHER
. The method
* {@link #getObject} retrieves the value.
* @param parameterIndex the first parameter is 1, the second is 2,
* and so on
* @param sqlType the JDBC type code defined by java.sql.Types
.
* If the parameter is of JDBC type NUMERIC
* or DECIMAL
, the version of
* registerOutParameter
that accepts a scale value
* should be used.
* @exception SQLException if a database access error occurs
* @see Types
*/
public void registerOutParameter(int parameterIndex, int sqlType)
throws SQLException
{
procedureCall.registerOutParam(parameterIndex, sqlType);
}
/**
* Registers the parameter in ordinal position
* parameterIndex
to be of JDBC type
* sqlType
. This method must be called
* before a stored procedure is executed.
*
* The JDBC type specified by sqlType
for an OUT
* parameter determines the Java type that must be used
* in the get
method to read the value of that parameter.
*
* This version of registerOutParameter
should be
* used when the parameter is of JDBC type NUMERIC
* or DECIMAL
.
* @param parameterIndex the first parameter is 1, the second is 2,
* and so on
* @param sqlType SQL type code defined by java.sql.Types
.
* @param scale the desired number of digits to the right of the
* decimal point. It must be greater than or equal to zero.
* @exception SQLException if a database access error occurs
* @see Types
*/
public void registerOutParameter(int parameterIndex, int sqlType, int scale)
throws SQLException
{
procedureCall.registerOutParam(parameterIndex, sqlType);
}
/**
* Indicates whether or not the last OUT parameter read had the value of
* SQL NULL
. Note that this method should be called only after
* calling a getXXX
method; otherwise, there is no value to use in
* determining whether it is null
or not.
* @return true
if the last parameter read was SQL
* NULL
; false
otherwise
* @exception SQLException if a database access error occurs
*/
public boolean wasNull() throws SQLException {
assertHasData(getCurrentResultSet());
return getCurrentResultSet().wasNull();
}
/**
* Retrieves the value of a JDBC CHAR
, VARCHAR
,
* or LONGVARCHAR
parameter as a String
in
* the Java programming language.
*
* For the fixed-length type JDBC CHAR
,
* the String
object
* returned has exactly the same value the JDBC
* CHAR
value had in the
* database, including any padding added by the database.
* @param parameterIndex the first parameter is 1, the second is 2,
* and so on
* @return the parameter value. If the value is SQL NULL
, the result
* is null
.
* @exception SQLException if a database access error occurs
*/
public String getString(int parameterIndex) throws SQLException {
assertHasData(getCurrentResultSet());
parameterIndex = procedureCall.mapOutParamIndexToPosition(parameterIndex);
return getCurrentResultSet().getString(parameterIndex);
}
/**
* Gets the value of a JDBC BIT
parameter as a boolean
* in the Java programming language.
* @param parameterIndex the first parameter is 1, the second is 2,
* and so on
* @return the parameter value. If the value is SQL NULL
, the result
* is false
.
* @exception SQLException if a database access error occurs
*/
public boolean getBoolean(int parameterIndex) throws SQLException {
assertHasData(getCurrentResultSet());
parameterIndex = procedureCall.mapOutParamIndexToPosition(parameterIndex);
return getCurrentResultSet().getBoolean(parameterIndex);
}
/**
* Gets the value of a JDBC TINYINT
parameter as a byte
* in the Java programming language.
* @param parameterIndex the first parameter is 1, the second is 2,
* and so on
* @return the parameter value. If the value is SQL NULL
, the result
* is 0.
* @exception SQLException if a database access error occurs
*/
public byte getByte(int parameterIndex) throws SQLException {
assertHasData(getCurrentResultSet());
parameterIndex = procedureCall.mapOutParamIndexToPosition(parameterIndex);
return getCurrentResultSet().getByte(parameterIndex);
}
/**
* Gets the value of a JDBC SMALLINT
parameter as a short
* in the Java programming language.
* @param parameterIndex the first parameter is 1, the second is 2,
* and so on
* @return the parameter value. If the value is SQL NULL
, the result
* is 0.
* @exception SQLException if a database access error occurs
*/
public short getShort(int parameterIndex) throws SQLException {
assertHasData(getCurrentResultSet());
parameterIndex = procedureCall.mapOutParamIndexToPosition(parameterIndex);
return getCurrentResultSet().getShort(parameterIndex);
}
/**
* Gets the value of a JDBC INTEGER
parameter as an int
* in the Java programming language.
* @param parameterIndex the first parameter is 1, the second is 2,
* and so on
* @return the parameter value. If the value is SQL NULL
, the result
* is 0.
* @exception SQLException if a database access error occurs
*/
public int getInt(int parameterIndex) throws SQLException {
assertHasData(getCurrentResultSet());
parameterIndex = procedureCall.mapOutParamIndexToPosition(parameterIndex);
return getCurrentResultSet().getInt(parameterIndex);
}
/**
* Gets the value of a JDBC BIGINT
parameter as a long
* in the Java programming language.
* @param parameterIndex the first parameter is 1, the second is 2,
* and so on
* @return the parameter value. If the value is SQL NULL
, the result
* is 0.
* @exception SQLException if a database access error occurs
*/
public long getLong(int parameterIndex) throws SQLException {
assertHasData(getCurrentResultSet());
parameterIndex = procedureCall.mapOutParamIndexToPosition(parameterIndex);
return getCurrentResultSet().getLong(parameterIndex);
}
/**
* Gets the value of a JDBC FLOAT
parameter as a float
* in the Java programming language.
* @param parameterIndex the first parameter is 1, the second is 2,
* and so on
* @return the parameter value. If the value is SQL NULL
, the result
* is 0.
* @exception SQLException if a database access error occurs
*/
public float getFloat(int parameterIndex) throws SQLException {
assertHasData(getCurrentResultSet());
parameterIndex = procedureCall.mapOutParamIndexToPosition(parameterIndex);
return getCurrentResultSet().getFloat(parameterIndex);
}
/**
* Gets the value of a JDBC DOUBLE
parameter as a double
* in the Java programming language.
* @param parameterIndex the first parameter is 1, the second is 2,
* and so on
* @return the parameter value. If the value is SQL NULL
, the result
* is 0.
* @exception SQLException if a database access error occurs
*/
public double getDouble(int parameterIndex) throws SQLException {
assertHasData(getCurrentResultSet());
parameterIndex = procedureCall.mapOutParamIndexToPosition(parameterIndex);
return getCurrentResultSet().getDouble(parameterIndex);
}
/**
* Gets the value of a JDBC NUMERIC
parameter as a
* java.math.BigDecimal
object with scale digits to
* the right of the decimal point.
* @param parameterIndex the first parameter is 1, the second is 2,
* and so on
* @param scale the number of digits to the right of the decimal point
* @return the parameter value. If the value is SQL NULL
, the result is
* null
.
* @exception SQLException if a database access error occurs
* @deprecated
*/
public BigDecimal getBigDecimal(int parameterIndex, int scale)
throws SQLException
{
assertHasData(getCurrentResultSet());
parameterIndex = procedureCall.mapOutParamIndexToPosition(parameterIndex);
return getCurrentResultSet().getBigDecimal(parameterIndex, scale);
}
/**
* Gets the value of a JDBC BINARY
or VARBINARY
* parameter as an array of byte
values in the Java
* programming language.
* @param parameterIndex the first parameter is 1, the second is 2,
* and so on
* @return the parameter value. If the value is SQL NULL
, the result is
* null
.
* @exception SQLException if a database access error occurs
*/
public byte[] getBytes(int parameterIndex) throws SQLException {
assertHasData(getCurrentResultSet());
parameterIndex = procedureCall.mapOutParamIndexToPosition(parameterIndex);
return getCurrentResultSet().getBytes(parameterIndex);
}
/**
* Gets the value of a JDBC DATE
parameter as a
* java.sql.Date
object.
* @param parameterIndex the first parameter is 1, the second is 2,
* and so on
* @return the parameter value. If the value is SQL NULL
, the result
* is null
.
* @exception SQLException if a database access error occurs
*/
public java.sql.Date getDate(int parameterIndex) throws SQLException {
assertHasData(getCurrentResultSet());
parameterIndex = procedureCall.mapOutParamIndexToPosition(parameterIndex);
return getCurrentResultSet().getDate(parameterIndex);
}
/**
* Get the value of a JDBC TIME
parameter as a
* java.sql.Time
object.
* @param parameterIndex the first parameter is 1, the second is 2,
* and so on
* @return the parameter value. If the value is SQL NULL
, the result
* is null
.
* @exception SQLException if a database access error occurs
*/
public Time getTime(int parameterIndex) throws SQLException {
assertHasData(getCurrentResultSet());
parameterIndex = procedureCall.mapOutParamIndexToPosition(parameterIndex);
return getCurrentResultSet().getTime(parameterIndex);
}
/**
* Gets the value of a JDBC TIMESTAMP
parameter as a
* java.sql.Timestamp
object.
* @param parameterIndex the first parameter is 1, the second is 2,
* and so on
* @return the parameter value. If the value is SQL NULL
, the result
* is null
.
* @exception SQLException if a database access error occurs
*/
public Timestamp getTimestamp(int parameterIndex)
throws SQLException
{
assertHasData(getCurrentResultSet());
parameterIndex = procedureCall.mapOutParamIndexToPosition(parameterIndex);
return getCurrentResultSet().getTimestamp(parameterIndex);
}
//----------------------------------------------------------------------
// Advanced features:
/**
* Gets the value of a parameter as an Object
in the Java
* programming language.
*
* This method returns a Java object whose type corresponds to the JDBC
* type that was registered for this parameter using the method
* registerOutParameter
. By registering the target JDBC
* type as java.sql.Types.OTHER
, this method can be used
* to read database-specific abstract data types.
* @param parameterIndex the first parameter is 1, the second is 2,
* and so on
* @return A java.lang.Object
holding the OUT parameter value.
* @exception SQLException if a database access error occurs
* @see Types
*/
public Object getObject(int parameterIndex) throws SQLException {
assertHasData(getCurrentResultSet());
parameterIndex = procedureCall.mapOutParamIndexToPosition(parameterIndex);
return getCurrentResultSet().getObject(parameterIndex);
}
//--------------------------JDBC 2.0-----------------------------
/**
*
* Gets the value of a JDBC NUMERIC
parameter as a
* java.math.BigDecimal
object with as many digits to the
* right of the decimal point as the value contains.
* @param parameterIndex the first parameter is 1, the second is 2,
* and so on
* @return the parameter value in full precision. If the value is
* SQL NULL
, the result is null
.
* @exception SQLException if a database access error occurs
* @since 1.2
* @see What Is in the JDBC 2.0 API
*/
public BigDecimal getBigDecimal(int parameterIndex) throws SQLException {
assertHasData(getCurrentResultSet());
parameterIndex = procedureCall.mapOutParamIndexToPosition(parameterIndex);
return getCurrentResultSet().getBigDecimal(parameterIndex);
}
/**
*
* Returns an object representing the value of OUT parameter
* i
and uses map
for the custom
* mapping of the parameter value.
*
* This method returns a Java object whose type corresponds to the
* JDBC type that was registered for this parameter using the method
* registerOutParameter
. By registering the target
* JDBC type as java.sql.Types.OTHER
, this method can
* be used to read database-specific abstract data types.
* @param parameterIndex the first parameter is 1, the second is 2, and so on
* @param map the mapping from SQL type names to Java classes
* @return a java.lang.Object
holding the OUT parameter value
* @exception SQLException if a database access error occurs
* @since 1.2
* @see What Is in the JDBC 2.0 API
*/
public Object getObject(int parameterIndex, Map map) throws SQLException {
assertHasData(getCurrentResultSet());
parameterIndex = procedureCall.mapOutParamIndexToPosition(parameterIndex);
return getCurrentResultSet().getObject(parameterIndex, map);
}
/**
*
* Gets the value of a JDBC REF(<structured-type>)
* parameter as a {@link Ref} object in the Java programming language.
* @param parameterIndex the first parameter is 1, the second is 2,
* and so on
* @return the parameter value as a Ref
object in the
* Java programming language. If the value was SQL NULL
, the value
* null
is returned.
* @exception SQLException if a database access error occurs
* @since 1.2
* @see What Is in the JDBC 2.0 API
*/
public Ref getRef (int parameterIndex) throws SQLException {
assertHasData(getCurrentResultSet());
parameterIndex = procedureCall.mapOutParamIndexToPosition(parameterIndex);
return getCurrentResultSet().getRef(parameterIndex);
}
/**
*
* Gets the value of a JDBC BLOB
parameter as a
* {@link Blob} object in the Java programming language.
* @param parameterIndex the first parameter is 1, the second is 2, and so on
* @return the parameter value as a Blob
object in the
* Java programming language. If the value was SQL NULL
, the value
* null
is returned.
* @exception SQLException if a database access error occurs
* @since 1.2
* @see What Is in the JDBC 2.0 API
*/
public Blob getBlob (int parameterIndex) throws SQLException {
assertHasData(getCurrentResultSet());
parameterIndex = procedureCall.mapOutParamIndexToPosition(parameterIndex);
return getCurrentResultSet().getBlob(parameterIndex);
}
/**
*
* Gets the value of a JDBC CLOB
parameter as a
* Clob
object in the Java programming language.
* @param parameterIndex the first parameter is 1, the second is 2, and
* so on
* @return the parameter value as a Clob
object in the
* Java programming language. If the value was SQL NULL
, the
* value null
is returned.
* @exception SQLException if a database access error occurs
* @since 1.2
* @see What Is in the JDBC 2.0 API
*/
public Clob getClob (int parameterIndex) throws SQLException {
assertHasData(getCurrentResultSet());
parameterIndex = procedureCall.mapOutParamIndexToPosition(parameterIndex);
return getCurrentResultSet().getClob(parameterIndex);
}
/**
*
* Gets the value of a JDBC ARRAY
parameter as an
* {@link Array} object in the Java programming language.
* @param parameterIndex the first parameter is 1, the second is 2, and
* so on
* @return the parameter value as an Array
object in
* the Java programming language. If the value was SQL NULL
, the
* value null
is returned.
* @exception SQLException if a database access error occurs
* @since 1.2
* @see What Is in the JDBC 2.0 API
*/
public Array getArray (int parameterIndex) throws SQLException {
assertHasData(getCurrentResultSet());
parameterIndex = procedureCall.mapOutParamIndexToPosition(parameterIndex);
return getCurrentResultSet().getArray(parameterIndex);
}
/**
* Gets the value of a JDBC DATE
parameter as a
* java.sql.Date
object, using
* the given Calendar
object
* to construct the date.
* With a Calendar
object, the driver
* can calculate the date taking into account a custom timezone and locale.
* If no Calendar
object is specified, the driver uses the
* default timezone and locale.
*
* @param parameterIndex the first parameter is 1, the second is 2,
* and so on
* @param cal the Calendar
object the driver will use
* to construct the date
* @return the parameter value. If the value is SQL NULL
, the result is
* null
.
* @exception SQLException if a database access error occurs
*/
public java.sql.Date getDate(int parameterIndex, Calendar cal)
throws SQLException
{
assertHasData(getCurrentResultSet());
parameterIndex = procedureCall.mapOutParamIndexToPosition(parameterIndex);
return getCurrentResultSet().getDate(parameterIndex, cal);
}
/**
* Gets the value of a JDBC TIME
parameter as a
* java.sql.Time
object, using
* the given Calendar
object
* to construct the time.
* With a Calendar
object, the driver
* can calculate the time taking into account a custom timezone and locale.
* If no Calendar
object is specified, the driver uses the
* default timezone and locale.
*
* @param parameterIndex the first parameter is 1, the second is 2,
* and so on
* @param cal the Calendar
object the driver will use
* to construct the time
* @return the parameter value; if the value is SQL NULL
, the result is
* null
.
* @exception SQLException if a database access error occurs
*/
public Time getTime(int parameterIndex, Calendar cal)
throws SQLException
{
assertHasData(getCurrentResultSet());
parameterIndex = procedureCall.mapOutParamIndexToPosition(parameterIndex);
return getCurrentResultSet().getTime(parameterIndex, cal);
}
/**
* Gets the value of a JDBC TIMESTAMP
parameter as a
* java.sql.Timestamp
object, using
* the given Calendar
object to construct
* the Timestamp
object.
* With a Calendar
object, the driver
* can calculate the timestamp taking into account a custom timezone and locale.
* If no Calendar
object is specified, the driver uses the
* default timezone and locale.
*
*
* @param parameterIndex the first parameter is 1, the second is 2,
* and so on
* @param cal the Calendar
object the driver will use
* to construct the timestamp
* @return the parameter value. If the value is SQL NULL
, the result is
* null
.
* @exception SQLException if a database access error occurs
*/
public Timestamp getTimestamp(int parameterIndex, Calendar cal)
throws SQLException
{
assertHasData(getCurrentResultSet());
parameterIndex = procedureCall.mapOutParamIndexToPosition(parameterIndex);
return getCurrentResultSet().getTimestamp(parameterIndex, cal);
}
//--------------------------JDBC 3.0-----------------------------
/**
* Asserts if the current statement has data to return. It checks if the
* result set has a row with data.
*
* @param rs result set to test
* @throws java.sql.SQLException when the result set has no data.
*/
protected void assertHasData(ResultSet rs) throws SQLException {
// check if we have a row, and try to move to the first position.
if (rs.getRow() == 0)
rs.next();
else
return;
// check if we still have no row and throw an exception in this case.
if (rs.getRow() == 0)
throw new FBSQLException(
"Current statement has not data to return.",
FBSQLException.SQL_STATE_NO_RESULT_SET);
}
//this method doesn't give an exception if it is called twice.
public ResultSet getCurrentResultSet() throws SQLException {
if (currentRs == null)
currentRs = super.getResultSet();
return currentRs;
}
// protected void cacheResultSet() throws SQLException {
//
// if (currentRs != null)
// throw new FBDriverConsistencyCheckException(
// "Trying to cache result set before closing exitsing one.");
//
// currentRs = getCachedResultSet(false);
// }
/**
* Returns the current result as a ResultSet
object.
* This method should be called only once per result.
* Calling this method twice with autocommit on and used will probably
* throw an inappropriate or uninformative exception.
*
* @return the current result as a ResultSet
object;
* null
if the result is an update count or there are no more results
* @exception SQLException if a database access error occurs
* @see #execute
*/
public ResultSet getResultSet() throws SQLException {
return getCurrentResultSet();
}
public void setArray(int i, Array x) throws SQLException {
procedureCall.getInputParam(i).setValue(x);
}
public void setAsciiStream(int parameterIndex, InputStream x, int length)
throws SQLException {
setBinaryStream(parameterIndex, x, length);
}
public void setBigDecimal(int parameterIndex, BigDecimal x)
throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(x);
}
public void setBinaryStream(int parameterIndex, InputStream inputStream,
int length) throws SQLException
{
procedureCall.getInputParam(parameterIndex).setValue(
new WrapperWithInt(inputStream, length));
}
public void setBlob(int parameterIndex, Blob blob) throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(blob);
}
public void setBoolean(int parameterIndex, boolean x) throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(new Boolean(x));
}
public void setByte(int parameterIndex, byte x) throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(new Byte(x));
}
public void setBytes(int parameterIndex, byte[] x) throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(x);
}
public void setCharacterStream(int parameterIndex, Reader reader,
int length) throws SQLException
{
procedureCall.getInputParam(parameterIndex).setValue(
new WrapperWithInt(reader, length));
}
public void setClob(int parameterIndex, Clob x) throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(x);
}
public void setDate(int parameterIndex, java.sql.Date x, Calendar cal)
throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(
new WrapperWithCalendar(x, cal));
}
public void setDate(int parameterIndex, java.sql.Date x) throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(x);
}
public void setDouble(int parameterIndex, double x) throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(new Double(x));
}
public void setFloat(int parameterIndex, float x) throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(new Float(x));
}
public void setInt(int parameterIndex, int x) throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(new Integer(x));
}
public void setLong(int parameterIndex, long x) throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(new Long(x));
}
public void setNull(int parameterIndex, int sqlType, String typeName)
throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(null);
}
public void setNull(int parameterIndex, int sqlType) throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(null);
}
public void setObject(int parameterIndex, Object x, int targetSqlType,
int scale) throws SQLException
{
procedureCall.getInputParam(parameterIndex).setValue(x);
}
public void setObject(int parameterIndex, Object x, int targetSqlType)
throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(x);
}
public void setObject(int parameterIndex, Object x) throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(x);
}
public void setRef(int parameterIndex, Ref x) throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(x);
}
public void setShort(int parameterIndex, short x) throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(new Short(x));
}
public void setString(int parameterIndex, String x) throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(x);
}
public void setTime(int parameterIndex, Time x, Calendar cal)
throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(
new WrapperWithCalendar(x, cal));
}
public void setTime(int parameterIndex, Time x) throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(x);
}
public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal)
throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(
new WrapperWithCalendar(x, cal));
}
public void setTimestamp(int parameterIndex, Timestamp x)
throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(x);
}
public void setUnicodeStream(int parameterIndex, InputStream x, int length)
throws SQLException {
procedureCall.getInputParam(parameterIndex).setValue(x);
}
private static class WrapperWithCalendar {
private Object value;
private Calendar c;
private WrapperWithCalendar(Object value, Calendar c) {
this.value = value;
this.c = c;
}
private Object getValue() {
return value;
}
private Calendar getCalendar() {
return c;
}
}
private static class WrapperWithInt {
private Object value;
private int intValue;
private WrapperWithInt(Object value, int intValue) {
this.value = value;
this.intValue = intValue;
}
private Object getValue() {
return value;
}
private int getIntValue() {
return intValue;
}
}
}