📄 preparedstatement_base.java
字号:
//
// Copyright 1998,1999 CDS Networks, Inc., Medford Oregon
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. 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.
// 3. All advertising materials mentioning features or use of this software
// must display the following acknowledgement:
// This product includes software developed by CDS Networks, Inc.
// 4. The name of CDS Networks, Inc. may not be used to endorse or promote
// products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY CDS NETWORKS, INC. ``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 CDS NETWORKS, INC. 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 net.sourceforge.jtds.jdbc;
import java.math.BigDecimal;
import java.sql.*;
import java.util.Map;
/**
* A SQL statement is pre-compiled and stored in a PreparedStatement object.
* This object can then be used to efficiently execute this statement multiple
* times.
* <p>
* <B>Note:</B> The setXXX methods for setting IN parameter values must specify
* types that are compatible with the defined SQL type of the input parameter.
* For instance, if the IN parameter has SQL type Integer then setInt should be
* used.
* <p>
* If arbitrary parameter type conversions are required then the setObject
* method should be used with a target SQL type.
*
* @author Craig Spannring
* @author The FreeTDS project
* @author Alin Sinpalean
* @version $Id: PreparedStatement_base.java,v 1.3 2002/10/18 15:21:07 alin_sinpalean Exp $
* @see Connection#prepareStatement
* @see ResultSet
*/
public class PreparedStatement_base extends TdsStatement implements PreparedStatementHelper, java.sql.PreparedStatement
{
public final static String cvsVersion = "$Id: PreparedStatement_base.java,v 1.3 2002/10/18 15:21:07 alin_sinpalean Exp $";
String rawQueryString = null;
ParameterListItem[] parameterList = null;
static Map typemap = null;
public PreparedStatement_base(TdsConnection conn_, String sql) throws SQLException
{
this( conn_, sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY );
}
public PreparedStatement_base(TdsConnection conn_, String sql, int type, int concurrency ) throws SQLException
{
super( conn_, type, concurrency );
rawQueryString = conn_.nativeSQL(sql);
int i;
int numberOfParameters = ParameterUtils.countParameters( rawQueryString );
parameterList = new ParameterListItem[numberOfParameters];
for ( i = 0; i < numberOfParameters; i++ )
parameterList[i] = new ParameterListItem();
}
protected void NotImplemented() throws java.sql.SQLException
{
throw new SQLException( "Not Implemented" );
}
/**
* In general, parameter values remain in force for repeated use of a
* Statement. Setting a parameter value automatically clears its previous
* value. However, in some cases it is useful to immediately release the
* resources used by the current parameter values; this can be done by
* calling clearParameters.
*
* @exception SQLException if a database-access error occurs.
*/
public void clearParameters() throws SQLException
{
int i;
for ( i = 0; i < parameterList.length; i++ ) {
parameterList[i].clear();
}
}
public boolean execute() throws SQLException
{
Tds tds = getTds(false);
return execute( tds );
}
/**
* Some prepared statements return multiple results; the execute method
* handles these complex statements as well as the simpler form of
* statements handled by executeQuery and executeUpdate.
*
*@exception SQLException if a database-access error occurs.
*@see Statement#execute
*/
public boolean execute( Tds tds ) throws SQLException
{
//
// TDS can handle prepared statements by creating a temporary
// procedure. Since procedure must have the datatype specified
// in the procedure declaration we will have to defer creating
// the actual procedure until the statement is executed. By
// that time we know all the types of all of the parameters.
//
Procedure procedure = null;
boolean result = false;
// SAfe No need for this either. We'll have to consume all input, nut
// just the last ResultSet (if one exists).
// closeResults(false);
// SAfe No need for this. getMoreResults sets it to -1 at start, anyway
// updateCount = -2;
// First make sure the caller has filled in all the parameters.
ParameterUtils.verifyThatParametersAreSet( parameterList );
// Find a stored procedure that is compatible with this set of parameters if one exists.
procedure = findCompatibleStoredProcedure( tds, rawQueryString );
// now look in tds
// if we don't have a suitable match then create a new temporary stored procedure
if( procedure == null )
{
// Create the stored procedure
procedure = new Procedure( rawQueryString, tds.getUniqueProcedureName(), parameterList, tds );
// SAfe Submit it to the SQL Server before adding it to the cache or procedures of transaction list.
// Otherwise, if submitProcedure fails (e.g. because of a syntax error) it will be in our procedure
// cache, but not on the server.
submitProcedure( tds, procedure );
// store it in the procedureCache
tds.procedureCache.put( rawQueryString, procedure );
// MJH Only record the proc name in proceduresOfTra if in manual commit mode
if( !getConnection().getAutoCommit() ) // MJH
tds.proceduresOfTra.add( procedure );
}
result = internalExecuteCall(procedure.getProcedureName(), procedure.getParameterList(), parameterList, tds,
warningChain);
return result;
}
private Procedure findCompatibleStoredProcedure( Tds tds, String rawQueryString )
{
return (Procedure)tds.procedureCache.get(rawQueryString);
}
private void submitProcedure( Tds tds, Procedure proc )
throws SQLException
{
String sql = proc.getPreparedSqlString();
tds.submitProcedure( sql, warningChain );
}
/**
* A prepared SQL query is executed and its ResultSet is returned.
*
* @return a ResultSet that contains the data produced by the query; never null
* @exception SQLException if a database-access error occurs.
*/
public java.sql.ResultSet executeQuery() throws SQLException
{
// closeResults(false);
Tds tds = getTds(false);
if( !execute(tds) )
{
skipToEnd();
releaseTds();
throw new SQLException( "Was expecting a result set" );
}
return results;
}
/**
* Execute a SQL INSERT, UPDATE or DELETE statement. In addition, SQL
* statements that return nothing such as SQL DDL statements can be
* executed.
*
*@return either the row count for INSERT, UPDATE or
* DELETE; or 0 for SQL statements that return nothing
*@exception SQLException if a database-access error occurs.
*/
public int executeUpdate() throws SQLException
{
// closeResults(false);
Tds tds = getTds(false);
if ( execute( tds ) ) {
skipToEnd();
releaseTds();
throw new SQLException( "executeUpdate can't return a result set" );
}
else {
int res = getUpdateCount();
releaseTds();
return res;
}
}
/**
* When a very large ASCII value is input to a LONGVARCHAR parameter, it
* may be more practical to send it via a java.io.InputStream. JDBC will
* read the data from the stream as needed, until it reaches end-of-file.
* The JDBC driver will do any necessary conversion from ASCII to the
* database char format. <P>
*
* <B>Note:</B> This stream object can either be a standard Java stream
* object or your own subclass that implements the standard interface.
*
*@param parameterIndex the first parameter is 1, the second is 2, ...
*@param x the java input stream which contains the ASCII
* parameter value
*@param length the number of bytes in the stream
*@exception SQLException if a database-access error occurs.
*/
public void setAsciiStream( int parameterIndex,
java.io.InputStream x,
int length )
throws SQLException
{
NotImplemented();
}
/**
* Set a parameter to a java.lang.BigDecimal value. The driver converts
* this to a SQL NUMERIC value when it sends it to the database.
*
*@param parameterIndex the first parameter is 1, the second is 2, ...
*@param x the parameter value
*@exception SQLException if a database-access error occurs.
*/
public void setBigDecimal( int parameterIndex, BigDecimal x ) throws SQLException
{
setParam( parameterIndex, x, java.sql.Types.DECIMAL, -1 );
}
/**
* When a very large binary value is input to a LONGVARBINARY parameter, it
* may be more practical to send it via a java.io.InputStream. JDBC will
* read the data from the stream as needed, until it reaches end-of-file.
* <P>
*
* <B>Note:</B> This stream object can either be a standard Java stream
* object or your own subclass that implements the standard interface.
*
*@param parameterIndex the first parameter is 1, the second is 2, ...
*@param x the java input stream which contains the binary
* parameter value
*@param length the number of bytes in the stream
*@exception SQLException if a database-access error occurs.
*/
public void setBinaryStream( int parameterIndex,
java.io.InputStream x,
int length )
throws SQLException
{
if ( length == 0 ) {
setBytes( parameterIndex, null );
}
byte[] bs = new byte[length];
int actlen;
try {
actlen = x.read( bs );
}
catch ( java.io.IOException e ) {
SQLException newE = new SQLException( "setBinaryStream: IO-Exception occured reading Stream" + e.toString() );
throw newE;
}
if ( actlen != length ) {
throw new SQLException( "SetBinaryStream parameterized Length: " + Integer.toString( length ) + " got length: " + Integer.toString( actlen ) );
}
else {
try {
actlen = x.read( bs );
}
catch ( java.io.IOException e ) {
SQLException newE = new SQLException( "setBinaryStream: IO-Exception occured reading Stream" + e.toString() );
throw newE;
}
if ( actlen != -1 ) {
throw new SQLException( "SetBinaryStream parameterized Length: " + Integer.toString( length ) + " got more than that " );
}
}
this.setBytes( parameterIndex, bs );
}
/**
* Set a parameter to a Java boolean value. The driver converts this to a
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -