1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-15 19:21:59 +03:00

Third phase of restructuring to add jdbc3 support.

Modified Files:
 	jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java
 	jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java
 	jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java
 	jdbc/org/postgresql/jdbc1/DatabaseMetaData.java
 	jdbc/org/postgresql/jdbc1/Jdbc1Connection.java
 	jdbc/org/postgresql/jdbc1/Jdbc1ResultSet.java
 	jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java
 	jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java
 	jdbc/org/postgresql/jdbc2/Array.java
 	jdbc/org/postgresql/jdbc2/DatabaseMetaData.java
 	jdbc/org/postgresql/jdbc2/Jdbc2Connection.java
 	jdbc/org/postgresql/jdbc2/Jdbc2ResultSet.java
 Added Files:
 	jdbc/org/postgresql/jdbc1/Jdbc1CallableStatement.java
 	jdbc/org/postgresql/jdbc2/Jdbc2CallableStatement.java
 Removed Files:
 	jdbc/org/postgresql/jdbc1/CallableStatement.java
 	jdbc/org/postgresql/jdbc2/CallableStatement.java
 	jdbc/org/postgresql/jdbc2/UpdateableResultSet.java
This commit is contained in:
Barry Lind
2002-07-25 22:45:28 +00:00
parent 73eb2dfe77
commit 68c6eff945
17 changed files with 1873 additions and 3123 deletions

View File

@ -8,7 +8,7 @@ import java.util.Vector;
import org.postgresql.largeobject.*;
import org.postgresql.util.*;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.2 2002/07/24 22:08:39 barry Exp $
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.3 2002/07/25 22:45:27 barry Exp $
* This class defines methods of the jdbc1 specification. This class is
* extended by org.postgresql.jdbc2.AbstractJdbc2Statement which adds the jdbc2
* methods. The real Statement class (for jdbc1) is org.postgresql.jdbc1.Jdbc1Statement
@ -47,6 +47,20 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
protected String[] templateStrings;
protected String[] inStrings;
//Used by the callablestatement style methods
private static final String JDBC_SYNTAX = "{[? =] call <some_function> ([? [,?]*]) }";
private static final String RESULT_COLUMN = "result";
private String originalSql = "";
private boolean isFunction;
// functionReturnType contains the user supplied value to check
// testReturn contains a modified version to make it easier to
// check the getXXX methods..
private int functionReturnType;
private int testReturn;
// returnTypeSet is true when a proper call to registerOutParameter has been made
private boolean returnTypeSet;
protected Object callResult;
public AbstractJdbc1Statement (AbstractJdbc1Connection connection)
@ -62,6 +76,10 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
}
protected void parseSqlStmt () throws SQLException {
if (this instanceof CallableStatement) {
modifyJdbcCall();
}
Vector v = new Vector();
boolean inQuotes = false;
int lastParmEnd = 0, i;
@ -179,7 +197,23 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
// New in 7.1, pass Statement so that ExecSQL can customise to it
result = ((AbstractJdbc1Connection)connection).ExecSQL(sql, (java.sql.Statement)this);
return (result != null && ((AbstractJdbc1ResultSet)result).reallyResultSet());
//If we are executing a callable statement function set the return data
if (isFunction) {
if (!((AbstractJdbc1ResultSet)result).reallyResultSet())
throw new PSQLException("postgresql.call.noreturnval");
if (!result.next ())
throw new PSQLException ("postgresql.call.noreturnval");
callResult = result.getObject(1);
int columnType = result.getMetaData().getColumnType(1);
if (columnType != functionReturnType)
throw new PSQLException ("postgresql.call.wrongrtntype",
new Object[]{
"java.sql.Types=" + columnType, "java.sql.Types="+functionReturnType });
result.close ();
return true;
} else {
return (result != null && ((AbstractJdbc1ResultSet)result).reallyResultSet());
}
}
/*
@ -233,6 +267,8 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
{
if (result == null)
return -1;
if (isFunction)
return 1;
if (((AbstractJdbc1ResultSet)result).reallyResultSet())
return -1;
return ((AbstractJdbc1ResultSet)result).getResultCount();
@ -253,14 +289,6 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
/*
* Returns the status message from the current Result.<p>
* This is used internally by the driver.
@ -1214,6 +1242,291 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
setSerialize(parameterIndex, connection.storeObject(x), x.getClass().getName() );
}
/*
* Before executing a stored procedure call you must explicitly
* call registerOutParameter to register the java.sql.Type of each
* out parameter.
*
* <p>Note: When reading the value of an out parameter, you must use
* the getXXX method whose Java type XXX corresponds to the
* parameter's registered SQL type.
*
* ONLY 1 RETURN PARAMETER if {?= call ..} syntax is used
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @param sqlType SQL type code defined by java.sql.Types; for
* parameters of type Numeric or Decimal use the version of
* registerOutParameter that accepts a scale value
* @exception SQLException if a database-access error occurs.
*/
public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException
{
if (parameterIndex != 1)
throw new PSQLException ("postgresql.call.noinout");
if (!isFunction)
throw new PSQLException ("postgresql.call.procasfunc", originalSql);
// functionReturnType contains the user supplied value to check
// testReturn contains a modified version to make it easier to
// check the getXXX methods..
functionReturnType = sqlType;
testReturn = sqlType;
if (functionReturnType == Types.CHAR ||
functionReturnType == Types.LONGVARCHAR)
testReturn = Types.VARCHAR;
else if (functionReturnType == Types.FLOAT)
testReturn = Types.REAL; // changes to streamline later error checking
returnTypeSet = true;
}
/*
* You must also specify the scale for numeric/decimal types:
*
* <p>Note: When reading the value of an out parameter, you must use
* the getXXX method whose Java type XXX corresponds to the
* parameter's registered SQL type.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @param sqlType use either java.sql.Type.NUMERIC or java.sql.Type.DECIMAL
* @param scale a value greater than or equal to zero representing the
* desired number of digits to the right of the decimal point
* @exception SQLException if a database-access error occurs.
*/
public void registerOutParameter(int parameterIndex, int sqlType,
int scale) throws SQLException
{
registerOutParameter (parameterIndex, sqlType); // ignore for now..
}
/*
* An OUT parameter may have the value of SQL NULL; wasNull
* reports whether the last value read has this special value.
*
* <p>Note: You must first call getXXX on a parameter to read its
* value and then call wasNull() to see if the value was SQL NULL.
* @return true if the last parameter read was SQL NULL
* @exception SQLException if a database-access error occurs.
*/
public boolean wasNull() throws SQLException
{
// check to see if the last access threw an exception
return (callResult == null);
}
/*
* Get the value of a CHAR, VARCHAR, or LONGVARCHAR parameter as a
* Java String.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @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
{
checkIndex (parameterIndex, Types.VARCHAR, "String");
return (String)callResult;
}
/*
* Get the value of a BIT parameter as a Java boolean.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @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
{
checkIndex (parameterIndex, Types.BIT, "Boolean");
if (callResult == null) return false;
return ((Boolean)callResult).booleanValue ();
}
/*
* Get the value of a TINYINT parameter as a Java byte.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @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
{
checkIndex (parameterIndex, Types.TINYINT, "Byte");
if (callResult == null) return 0;
return (byte)((Integer)callResult).intValue ();
}
/*
* Get the value of a SMALLINT parameter as a Java short.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @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
{
checkIndex (parameterIndex, Types.SMALLINT, "Short");
if (callResult == null) return 0;
return (short)((Integer)callResult).intValue ();
}
/*
* Get the value of an INTEGER parameter as a Java int.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @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
{
checkIndex (parameterIndex, Types.INTEGER, "Int");
if (callResult == null) return 0;
return ((Integer)callResult).intValue ();
}
/*
* Get the value of a BIGINT parameter as a Java long.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @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
{
checkIndex (parameterIndex, Types.BIGINT, "Long");
if (callResult == null) return 0;
return ((Long)callResult).longValue ();
}
/*
* Get the value of a FLOAT parameter as a Java float.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @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
{
checkIndex (parameterIndex, Types.REAL, "Float");
if (callResult == null) return 0;
return ((Float)callResult).floatValue ();
}
/*
* Get the value of a DOUBLE parameter as a Java double.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @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
{
checkIndex (parameterIndex, Types.DOUBLE, "Double");
if (callResult == null) return 0;
return ((Double)callResult).doubleValue ();
}
/*
* Get the value of a NUMERIC parameter as a java.math.BigDecimal
* object.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @param scale a value greater than or equal to zero representing the
* desired 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 in Java2.0
*/
public BigDecimal getBigDecimal(int parameterIndex, int scale)
throws SQLException
{
checkIndex (parameterIndex, Types.NUMERIC, "BigDecimal");
return ((BigDecimal)callResult);
}
/*
* Get the value of a SQL BINARY or VARBINARY parameter as a Java
* byte[]
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @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
{
checkIndex (parameterIndex, Types.VARBINARY, "Bytes");
return ((byte [])callResult);
}
/*
* Get the value of a SQL DATE parameter as a java.sql.Date object
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @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
{
checkIndex (parameterIndex, Types.DATE, "Date");
return (java.sql.Date)callResult;
}
/*
* Get the value of a SQL TIME parameter as a java.sql.Time object.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @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.Time getTime(int parameterIndex) throws SQLException
{
checkIndex (parameterIndex, Types.TIME, "Time");
return (java.sql.Time)callResult;
}
/*
* Get the value of a SQL TIMESTAMP parameter as a java.sql.Timestamp object.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @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.Timestamp getTimestamp(int parameterIndex)
throws SQLException
{
checkIndex (parameterIndex, Types.TIMESTAMP, "Timestamp");
return (java.sql.Timestamp)callResult;
}
// getObject returns a Java object for the parameter.
// See the JDBC spec's "Dynamic Programming" chapter for details.
/*
* Get the value of a parameter as a Java object.
*
* <p>This method returns a Java object whose type coresponds to the
* SQL type that was registered for this parameter using
* registerOutParameter.
*
* <P>Note that this method may be used to read datatabase-specific,
* abstract data types. This is done by specifying a targetSqlType
* of java.sql.types.OTHER, which allows the driver to return a
* database-specific Java type.
*
* <p>See the JDBC spec's "Dynamic Programming" chapter for details.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @return A java.lang.Object holding the OUT parameter value.
* @exception SQLException if a database-access error occurs.
*/
public Object getObject(int parameterIndex)
throws SQLException
{
checkIndex (parameterIndex);
return callResult;
}
/*
* Returns the SQL statement with the current template values
* substituted.
@ -1253,6 +1566,8 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
{
if (paramIndex < 1 || paramIndex > inStrings.length)
throw new PSQLException("postgresql.prep.range");
if (paramIndex == 1 && isFunction) // need to registerOut instead
throw new PSQLException ("postgresql.call.funcover");
inStrings[paramIndex - 1] = s;
}
@ -1267,6 +1582,13 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
sbuf.setLength(0);
int i;
if (isFunction && !returnTypeSet)
throw new PSQLException("postgresql.call.noreturntype");
if (isFunction) { // set entry 1 to dummy entry..
inStrings[0] = ""; // dummy entry which ensured that no one overrode
// and calls to setXXX (2,..) really went to first arg in a function call..
}
for (i = 0 ; i < inStrings.length ; ++i)
{
if (inStrings[i] == null)
@ -1299,5 +1621,67 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
set(parameterIndex, Long.toString(x) + "::" + tablename );
}
/**
* this method will turn a string of the form
* {? = call <some_function> (?, [?,..]) }
* into the PostgreSQL format which is
* select <some_function> (?, [?, ...]) as result
*
*/
private void modifyJdbcCall() throws SQLException {
// syntax checking is not complete only a few basics :(
originalSql = sql; // save for error msgs..
int index = sql.indexOf ("="); // is implied func or proc?
boolean isValid = true;
if (index != -1) {
isFunction = true;
isValid = sql.indexOf ("?") < index; // ? before =
}
sql = sql.trim ();
if (sql.startsWith ("{") && sql.endsWith ("}")) {
sql = sql.substring (1, sql.length() -1);
} else isValid = false;
index = sql.indexOf ("call");
if (index == -1 || !isValid)
throw new PSQLException ("postgresql.call.malformed",
new Object[]{sql, JDBC_SYNTAX});
sql = sql.replace ('{', ' '); // replace these characters
sql = sql.replace ('}', ' ');
sql = sql.replace (';', ' ');
// this removes the 'call' string and also puts a hidden '?'
// at the front of the line for functions, this will
// allow the registerOutParameter to work correctly
// because in the source sql there was one more ? for the return
// value that is not needed by the postgres syntax. But to make
// sure that the parameter numbers are the same as in the original
// sql we add a dummy parameter in this case
sql = (isFunction ? "?" : "") + sql.substring (index + 4);
sql = "select " + sql + " as " + RESULT_COLUMN + ";";
}
/** helperfunction for the getXXX calls to check isFunction and index == 1
*/
protected void checkIndex (int parameterIndex, int type, String getName)
throws SQLException {
checkIndex (parameterIndex);
if (type != this.testReturn)
throw new PSQLException("postgresql.call.wrongget",
new Object[]{"java.sql.Types="+testReturn,
getName,
"java.sql.Types="+type});
}
/** helperfunction for the getXXX calls to check isFunction and index == 1
* @param parameterIndex index of getXXX (index)
* check to make sure is a function and index == 1
*/
private void checkIndex (int parameterIndex) throws SQLException {
if (!isFunction)
throw new PSQLException("postgresql.call.noreturntype");
if (parameterIndex != 1)
throw new PSQLException("postgresql.call.noinout");
}
}