aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBarry Lind <barry@xythos.com>2002-07-25 22:45:28 +0000
committerBarry Lind <barry@xythos.com>2002-07-25 22:45:28 +0000
commit68c6eff9454caa57de1b807f58eade19997c9c14 (patch)
treec6824c5f608d8566bb3abe0a95e90e382d6c33ed /src
parent73eb2dfe77f5b08197a2d27557d72fcd229e2100 (diff)
downloadpostgresql-68c6eff9454caa57de1b807f58eade19997c9c14.tar.gz
postgresql-68c6eff9454caa57de1b807f58eade19997c9c14.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java5
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java13
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java404
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc1/CallableStatement.java322
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java24
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1CallableStatement.java14
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Connection.java12
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1ResultSet.java11
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java2065
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java61
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc2/Array.java2
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc2/CallableStatement.java604
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc2/DatabaseMetaData.java26
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2CallableStatement.java15
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Connection.java18
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2ResultSet.java11
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc2/UpdateableResultSet.java1389
17 files changed, 1873 insertions, 3123 deletions
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java
index 98aa33e5c91..f6d3807bb9a 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java
@@ -13,7 +13,7 @@ import org.postgresql.largeobject.LargeObjectManager;
import org.postgresql.util.*;
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Connection.java,v 1.1 2002/07/23 03:59:55 barry Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Connection.java,v 1.2 2002/07/25 22:45:27 barry Exp $
* This class defines methods of the jdbc1 specification. This class is
* extended by org.postgresql.jdbc2.AbstractJdbc2Connection which adds the jdbc2
* methods. The real Connection class (for jdbc1) is org.postgresql.jdbc1.Jdbc1Connection
@@ -359,8 +359,7 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec
// are common to all implementations (JDBC1 or 2), they are placed here.
// This should make it easy to maintain the two specifications.
-//BJL TODO this method shouldn't need to take a Connection since this can be used.
- public abstract java.sql.ResultSet getResultSet(java.sql.Statement stat, org.postgresql.Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException;
+ public abstract java.sql.ResultSet getResultSet(Statement statement, org.postgresql.Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException;
/*
* This adds a warning to the warning chain.
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java
index 5aa4f90298a..3bb278a8e9d 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java
@@ -13,15 +13,15 @@ import org.postgresql.largeobject.*;
import org.postgresql.util.PGbytea;
import org.postgresql.util.PSQLException;
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1ResultSet.java,v 1.1 2002/07/23 03:59:55 barry Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1ResultSet.java,v 1.2 2002/07/25 22:45:27 barry Exp $
* This class defines methods of the jdbc1 specification. This class is
* extended by org.postgresql.jdbc2.AbstractJdbc2ResultSet which adds the jdbc2
* methods. The real ResultSet class (for jdbc1) is org.postgresql.jdbc1.Jdbc1ResultSet
*/
public abstract class AbstractJdbc1ResultSet
{
-
protected Vector rows; // The results
+ protected Statement statement;
protected Field fields[]; // The field descriptions
protected String status; // Status of the result
protected boolean binaryCursor = false; // is the data binary or Strings
@@ -33,7 +33,7 @@ public abstract class AbstractJdbc1ResultSet
protected SQLWarning warnings = null; // The warning chain
protected boolean wasNullFlag = false; // the flag for wasNull()
- // We can chain multiple resultSets together - this points to
+ // We can chain multiple resultSets together - this points to
// next resultSet in the chain.
protected ResultSet next = null;
@@ -41,9 +41,10 @@ public abstract class AbstractJdbc1ResultSet
public byte[][] rowBuffer=null;
- public AbstractJdbc1ResultSet(org.postgresql.PGConnection conn, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor)
+ public AbstractJdbc1ResultSet(org.postgresql.PGConnection conn, Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor)
{
this.connection = conn;
+ this.statement = statement;
this.fields = fields;
this.rows = tuples;
this.status = status;
@@ -116,7 +117,7 @@ public abstract class AbstractJdbc1ResultSet
throw new PSQLException("postgresql.res.badbyte", s);
}
}
- return 0; // SQL NULL
+ return 0; // SQL NULL
}
public short getShort(int columnIndex) throws SQLException
@@ -134,7 +135,7 @@ public abstract class AbstractJdbc1ResultSet
throw new PSQLException("postgresql.res.badshort", s);
}
}
- return 0; // SQL NULL
+ return 0; // SQL NULL
}
public int getInt(int columnIndex) throws SQLException
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java
index 6b06cc873e0..96a50efa8fa 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java
@@ -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.
@@ -1215,6 +1243,291 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
}
/*
+ * 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.
* NB: This is identical to compileQuery() except instead of throwing
@@ -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");
+ }
+
}
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/CallableStatement.java b/src/interfaces/jdbc/org/postgresql/jdbc1/CallableStatement.java
deleted file mode 100644
index dab157f97b6..00000000000
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/CallableStatement.java
+++ /dev/null
@@ -1,322 +0,0 @@
-package org.postgresql.jdbc1;
-
-// IMPORTANT NOTE: This file implements the JDBC 1 version of the driver.
-// If you make any modifications to this file, you must make sure that the
-// changes are also made (if relevent) to the related JDBC 2 class in the
-// org.postgresql.jdbc2 package.
-
-import java.sql.*;
-import java.math.*;
-
-/*
- * CallableStatement is used to execute SQL stored procedures.
- *
- * <p>JDBC provides a stored procedure SQL escape that allows stored
- * procedures to be called in a standard way for all RDBMS's. 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 may be used for input, output or both.
- * Parameters are refered to sequentially, by number. The first parameter
- * is 1.
- *
- * {?= call <procedure-name>[<arg1>,<arg2>, ...]}
- * {call <procedure-name>[<arg1>,<arg2>, ...]}
- *
- *
- * <p>IN parameter values are set using the set methods inherited from
- * 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.
- *
- * <p>A Callable statement may return a ResultSet or multiple ResultSets.
- * Multiple ResultSets are handled using operations inherited from
- * Statement.
- *
- * <p>For maximum portability, a call's ResultSets and update counts should
- * be processed prior to getting the values of output parameters.
- *
- * @see Connection#prepareCall
- * @see ResultSet
- */
-
-public class CallableStatement extends Jdbc1PreparedStatement implements java.sql.CallableStatement
-{
- /*
- * @exception SQLException on failure
- */
- CallableStatement(Jdbc1Connection c, String q) throws SQLException
- {
- super(c, q);
- }
-
- /*
- * 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.
- *
- * @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
- {}
-
- /*
- * 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
- {}
-
- // Old api?
- //public boolean isNull(int parameterIndex) throws SQLException {
- //return true;
- //}
-
- /*
- * 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 false; // fake it for now
- }
-
- // Old api?
- //public String getChar(int parameterIndex) throws SQLException {
- //return 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
- {
- return null;
- }
- //public String getVarChar(int parameterIndex) throws SQLException {
- // return null;
- //}
-
- //public String getLongVarChar(int parameterIndex) throws SQLException {
- //return null;
- //}
-
- /*
- * 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
- {
- return false;
- }
-
- /*
- * 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
- {
- return 0;
- }
-
- /*
- * 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
- {
- return 0;
- }
-
- /*
- * 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
- {
- return 0;
- }
-
- /*
- * 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
- {
- return 0;
- }
-
- /*
- * 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
- {
- return (float) 0.0;
- }
-
- /*
- * 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
- {
- return 0.0;
- }
-
- /*
- * 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.
- */
- public BigDecimal getBigDecimal(int parameterIndex, int scale)
- throws SQLException
- {
- return null;
- }
-
- /*
- * 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
- {
- return null;
- }
-
- // New API (JPM) (getLongVarBinary)
- //public byte[] getBinaryStream(int parameterIndex) throws SQLException {
- //return null;
- //}
-
- /*
- * 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
- {
- return null;
- }
-
- /*
- * 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
- {
- return null;
- }
-
- /*
- * 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
- {
- return null;
- }
-
- //----------------------------------------------------------------------
- // Advanced features:
-
- // You can obtain a ParameterMetaData object to get information
- // about the parameters to this CallableStatement.
- //public DatabaseMetaData getMetaData() {
- //return null;
- //}
-
- // 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
- {
- return null;
- }
-}
-
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java b/src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java
index 747ee1f1ea4..bf81f78874d 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java
@@ -13,7 +13,7 @@ import org.postgresql.util.PSQLException;
/*
* This class provides information about the database as a whole.
*
- * $Id: DatabaseMetaData.java,v 1.48 2002/07/23 03:59:55 barry Exp $
+ * $Id: DatabaseMetaData.java,v 1.49 2002/07/25 22:45:28 barry Exp $
*
* <p>Many of the methods here return lists of information in ResultSets. You
* can use the normal ResultSet methods such as getString and getInt to
@@ -1549,7 +1549,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
v.addElement(tuple);
}
- return new Jdbc1ResultSet(connection, f, v, "OK", 1);
+ return connection.getResultSet(null, f, v, "OK", 1);
}
/*
@@ -1627,7 +1627,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
// add query loop here
- return new Jdbc1ResultSet(connection, f, v, "OK", 1);
+ return connection.getResultSet(null, f, v, "OK", 1);
}
/*
@@ -1762,7 +1762,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
v.addElement(tuple);
}
r.close();
- return new Jdbc1ResultSet(connection, f, v, "OK", 1);
+ return connection.getResultSet(null, f, v, "OK", 1);
}
// This array contains the valid values for the types argument
@@ -1809,7 +1809,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
f[0] = new Field(connection, "TABLE_SCHEM", iVarcharOid, 32);
tuple[0] = "".getBytes();
v.addElement(tuple);
- return new Jdbc1ResultSet(connection, f, v, "OK", 1);
+ return connection.getResultSet(null, f, v, "OK", 1);
}
/*
@@ -1854,7 +1854,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
tuple[0] = getTableTypes[i][0].getBytes();
v.addElement(tuple);
}
- return new Jdbc1ResultSet(connection, f, v, "OK", 1);
+ return connection.getResultSet(null, f, v, "OK", 1);
}
/*
@@ -2050,7 +2050,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
}
r.close();
- return new Jdbc1ResultSet(connection, f, v, "OK", 1);
+ return connection.getResultSet(null, f, v, "OK", 1);
}
/*
@@ -2113,7 +2113,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
//v.addElement(tuple);
}
- return new Jdbc1ResultSet(connection, f, v, "OK", 1);
+ return connection.getResultSet(null, f, v, "OK", 1);
}
/*
@@ -2203,7 +2203,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
f[6] = new Field(connection, "DECIMAL_DIGITS", iInt2Oid, 2);
f[7] = new Field(connection, "PSEUDO_COLUMN", iInt2Oid, 2);
- return new Jdbc1ResultSet(connection, f, v, "OK", 1);
+ return connection.getResultSet(null, f, v, "OK", 1);
}
/*
@@ -2413,7 +2413,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
while (hasMore);
}
- return new Jdbc1ResultSet(connection, f, tuples, "OK", 1);
+ return connection.getResultSet(null, f, tuples, "OK", 1);
}
/*
@@ -2692,7 +2692,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
v.addElement(tuple);
}
rs.close();
- return new Jdbc1ResultSet(connection, f, v, "OK", 1);
+ return connection.getResultSet(null, f, v, "OK", 1);
}
throw new PSQLException("postgresql.metadata.unavailable");
@@ -2832,7 +2832,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
}
}
- return new Jdbc1ResultSet(connection, f, v, "OK", 1);
+ return connection.getResultSet(null, f, v, "OK", 1);
}
}
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1CallableStatement.java b/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1CallableStatement.java
new file mode 100644
index 00000000000..7cd69103bd5
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1CallableStatement.java
@@ -0,0 +1,14 @@
+package org.postgresql.jdbc1;
+
+
+import java.sql.*;
+
+public class Jdbc1CallableStatement extends AbstractJdbc1Statement implements java.sql.CallableStatement
+{
+
+ public Jdbc1CallableStatement(Jdbc1Connection connection, String sql) throws SQLException
+ {
+ super(connection, sql);
+ }
+}
+
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Connection.java
index 249a41049b6..b67b07fde93 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Connection.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Connection.java
@@ -6,7 +6,7 @@ import java.sql.*;
import org.postgresql.Field;
import org.postgresql.util.PSQLException;
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1Connection.java,v 1.2 2002/07/24 22:08:40 barry Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1Connection.java,v 1.3 2002/07/25 22:45:28 barry Exp $
* This class implements the java.sql.Connection interface for JDBC1.
* However most of the implementation is really done in
* org.postgresql.jdbc1.AbstractJdbc1Connection
@@ -24,10 +24,9 @@ public class Jdbc1Connection extends org.postgresql.jdbc1.AbstractJdbc1Connectio
return new org.postgresql.jdbc1.Jdbc1PreparedStatement(this, sql);
}
-//BJL TODO - merge callable statement logic from jdbc2 to jdbc1
public java.sql.CallableStatement prepareCall(String sql) throws SQLException
{
- throw new PSQLException("postgresql.con.call");
+ return new org.postgresql.jdbc1.Jdbc1CallableStatement(this, sql);
}
public java.sql.DatabaseMetaData getMetaData() throws SQLException
@@ -39,7 +38,12 @@ public class Jdbc1Connection extends org.postgresql.jdbc1.AbstractJdbc1Connectio
public java.sql.ResultSet getResultSet(java.sql.Statement stat, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException
{
- return new Jdbc1ResultSet(this, fields, tuples, status, updateCount, insertOID, binaryCursor);
+ return new Jdbc1ResultSet(this, stat, fields, tuples, status, updateCount, insertOID, binaryCursor);
+ }
+
+ public java.sql.ResultSet getResultSet(java.sql.Statement stat, Field[] fields, Vector tuples, String status, int updateCount) throws SQLException
+ {
+ return new Jdbc1ResultSet(this, stat, fields, tuples, status, updateCount, 0, false);
}
}
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1ResultSet.java
index a959fef9d39..57850569ec8 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1ResultSet.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1ResultSet.java
@@ -5,7 +5,7 @@ import java.sql.*;
import java.util.Vector;
import org.postgresql.Field;
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1ResultSet.java,v 1.1 2002/07/23 03:59:55 barry Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1ResultSet.java,v 1.2 2002/07/25 22:45:28 barry Exp $
* This class implements the java.sql.ResultSet interface for JDBC1.
* However most of the implementation is really done in
* org.postgresql.jdbc1.AbstractJdbc1ResultSet
@@ -13,14 +13,9 @@ import org.postgresql.Field;
public class Jdbc1ResultSet extends org.postgresql.jdbc1.AbstractJdbc1ResultSet implements java.sql.ResultSet
{
- public Jdbc1ResultSet(Jdbc1Connection conn, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor)
+ public Jdbc1ResultSet(Jdbc1Connection conn, Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor)
{
- super(conn, fields, tuples, status, updateCount, insertOID, binaryCursor);
- }
-
- public Jdbc1ResultSet(Jdbc1Connection conn, Field[] fields, Vector tuples, String status, int updateCount)
- {
- super(conn, fields, tuples, status, updateCount, 0, false);
+ super(conn, statement, fields, tuples, status, updateCount, insertOID, binaryCursor);
}
public java.sql.ResultSetMetaData getMetaData() throws SQLException
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java
index d2c5ee07607..1a6379bf592 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java
@@ -6,747 +6,1348 @@ import java.io.*;
import java.sql.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
-import java.util.Vector;
+import java.util.*;
+import org.postgresql.Driver;
import org.postgresql.Field;
import org.postgresql.core.Encoding;
import org.postgresql.largeobject.*;
import org.postgresql.util.PGbytea;
import org.postgresql.util.PSQLException;
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2ResultSet.java,v 1.2 2002/07/24 22:08:42 barry Exp $
+
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2ResultSet.java,v 1.3 2002/07/25 22:45:28 barry Exp $
* This class defines methods of the jdbc2 specification. This class extends
* org.postgresql.jdbc1.AbstractJdbc1ResultSet which provides the jdbc1
* methods. The real Statement class (for jdbc2) is org.postgresql.jdbc2.Jdbc2ResultSet
*/
-public class AbstractJdbc2ResultSet extends org.postgresql.jdbc1.AbstractJdbc1ResultSet
-{
- protected Statement statement;
-
- protected String sqlQuery=null;
-
- public AbstractJdbc2ResultSet(org.postgresql.PGConnection conn, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor)
- {
- super(conn, fields, tuples, status, updateCount, insertOID, binaryCursor);
- }
-
- public java.net.URL getURL(int columnIndex) throws SQLException
- {
- return null;
- }
-
- public java.net.URL getURL(String columnName) throws SQLException
- {
- return null;
- }
-
- /*
- * Get the value of a column in the current row as a Java object
- *
- * <p>This method will return the value of the given column as a
- * Java object. The type of the Java object will be the default
- * Java Object type corresponding to the column's SQL type, following
- * the mapping specified in the JDBC specification.
- *
- * <p>This method may also be used to read database specific abstract
- * data types.
- *
- * @param columnIndex the first column is 1, the second is 2...
- * @return a Object holding the column value
- * @exception SQLException if a database access error occurs
- */
- public Object getObject(int columnIndex) throws SQLException
- {
- Field field;
-
- checkResultSet( columnIndex );
-
- wasNullFlag = (this_row[columnIndex - 1] == null);
- if (wasNullFlag)
- return null;
-
- field = fields[columnIndex - 1];
-
- // some fields can be null, mainly from those returned by MetaData methods
- if (field == null)
- {
- wasNullFlag = true;
- return null;
- }
-
- switch (field.getSQLType())
- {
- case Types.BIT:
- return getBoolean(columnIndex) ? Boolean.TRUE : Boolean.FALSE;
- case Types.SMALLINT:
- return new Short(getShort(columnIndex));
- case Types.INTEGER:
- return new Integer(getInt(columnIndex));
- case Types.BIGINT:
- return new Long(getLong(columnIndex));
- case Types.NUMERIC:
- return getBigDecimal
- (columnIndex, (field.getMod() == -1) ? -1 : ((field.getMod() - 4) & 0xffff));
- case Types.REAL:
- return new Float(getFloat(columnIndex));
- case Types.DOUBLE:
- return new Double(getDouble(columnIndex));
- case Types.CHAR:
- case Types.VARCHAR:
- return getString(columnIndex);
- case Types.DATE:
- return getDate(columnIndex);
- case Types.TIME:
- return getTime(columnIndex);
- case Types.TIMESTAMP:
- return getTimestamp(columnIndex);
- case Types.BINARY:
- case Types.VARBINARY:
- return getBytes(columnIndex);
- case Types.ARRAY:
- return getArray(columnIndex);
- default:
- String type = field.getPGType();
- // if the backend doesn't know the type then coerce to String
- if (type.equals("unknown"))
- {
- return getString(columnIndex);
- }
- else
- {
- return connection.getObject(field.getPGType(), getString(columnIndex));
- }
- }
- }
-
- public boolean absolute(int index) throws SQLException
- {
- // index is 1-based, but internally we use 0-based indices
- int internalIndex;
-
- if (index == 0)
- throw new SQLException("Cannot move to index of 0");
-
- final int rows_size = rows.size();
-
- //if index<0, count from the end of the result set, but check
- //to be sure that it is not beyond the first index
- if (index < 0)
- {
- if (index >= -rows_size)
- internalIndex = rows_size + index;
- else
- {
- beforeFirst();
- return false;
- }
- }
- else
- {
- //must be the case that index>0,
- //find the correct place, assuming that
- //the index is not too large
- if (index <= rows_size)
- internalIndex = index - 1;
- else
- {
- afterLast();
- return false;
- }
- }
-
- current_row = internalIndex;
- this_row = (byte [][])rows.elementAt(internalIndex);
- return true;
- }
-
- public void afterLast() throws SQLException
- {
- final int rows_size = rows.size();
- if (rows_size > 0)
- current_row = rows_size;
- }
-
- public void beforeFirst() throws SQLException
- {
- if (rows.size() > 0)
- current_row = -1;
- }
-
- public void cancelRowUpdates() throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public void deleteRow() throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public boolean first() throws SQLException
- {
- if (rows.size() <= 0)
- return false;
-
- current_row = 0;
- this_row = (byte [][])rows.elementAt(current_row);
-
- rowBuffer=new byte[this_row.length][];
- System.arraycopy(this_row,0,rowBuffer,0,this_row.length);
-
- return true;
- }
-
- public java.sql.Array getArray(String colName) throws SQLException
- {
- return getArray(findColumn(colName));
- }
-
- public java.sql.Array getArray(int i) throws SQLException
- {
- wasNullFlag = (this_row[i - 1] == null);
- if (wasNullFlag)
- return null;
-
- if (i < 1 || i > fields.length)
- throw new PSQLException("postgresql.res.colrange");
- return (java.sql.Array) new org.postgresql.jdbc2.Array( connection, i, fields[i - 1], (java.sql.ResultSet)this );
- }
-
- public java.math.BigDecimal getBigDecimal(int columnIndex) throws SQLException
- {
- return getBigDecimal(columnIndex, -1);
- }
-
- public java.math.BigDecimal getBigDecimal(String columnName) throws SQLException
- {
- return getBigDecimal(findColumn(columnName));
- }
-
- public Blob getBlob(String columnName) throws SQLException
- {
- return getBlob(findColumn(columnName));
- }
-
- public Blob getBlob(int i) throws SQLException
- {
- return new org.postgresql.largeobject.PGblob(connection, getInt(i));
- }
-
- public java.io.Reader getCharacterStream(String columnName) throws SQLException
- {
- return getCharacterStream(findColumn(columnName));
- }
-
- public java.io.Reader getCharacterStream(int i) throws SQLException
- {
- checkResultSet( i );
- wasNullFlag = (this_row[i - 1] == null);
- if (wasNullFlag)
- return null;
-
- if (((AbstractJdbc2Connection)connection).haveMinimumCompatibleVersion("7.2"))
- {
- //Version 7.2 supports AsciiStream for all the PG text types
- //As the spec/javadoc for this method indicate this is to be used for
- //large text values (i.e. LONGVARCHAR) PG doesn't have a separate
- //long string datatype, but with toast the text datatype is capable of
- //handling very large values. Thus the implementation ends up calling
- //getString() since there is no current way to stream the value from the server
- return new CharArrayReader(getString(i).toCharArray());
- }
- else
- {
- // In 7.1 Handle as BLOBS so return the LargeObject input stream
- Encoding encoding = connection.getEncoding();
- InputStream input = getBinaryStream(i);
- return encoding.getDecodingReader(input);
- }
- }
-
- public Clob getClob(String columnName) throws SQLException
- {
- return getClob(findColumn(columnName));
- }
-
- public Clob getClob(int i) throws SQLException
- {
- return new org.postgresql.largeobject.PGclob(connection, getInt(i));
- }
-
- public int getConcurrency() throws SQLException
- {
- // The standard ResultSet class will now return
- // CONCUR_READ_ONLY. A sub-class will overide this if the query was
- // updateable.
- return java.sql.ResultSet.CONCUR_READ_ONLY;
- }
-
- public java.sql.Date getDate(int i, java.util.Calendar cal) throws SQLException
- {
- // If I read the specs, this should use cal only if we don't
- // store the timezone, and if we do, then act just like getDate()?
- // for now...
- return getDate(i);
- }
-
- public Time getTime(int i, java.util.Calendar cal) throws SQLException
- {
- // If I read the specs, this should use cal only if we don't
- // store the timezone, and if we do, then act just like getTime()?
- // for now...
- return getTime(i);
- }
-
- public Timestamp getTimestamp(int i, java.util.Calendar cal) throws SQLException
- {
- // If I read the specs, this should use cal only if we don't
- // store the timezone, and if we do, then act just like getDate()?
- // for now...
- return getTimestamp(i);
- }
-
- public java.sql.Date getDate(String c, java.util.Calendar cal) throws SQLException
- {
- return getDate(findColumn(c), cal);
- }
-
- public Time getTime(String c, java.util.Calendar cal) throws SQLException
- {
- return getTime(findColumn(c), cal);
- }
-
- public Timestamp getTimestamp(String c, java.util.Calendar cal) throws SQLException
- {
- return getTimestamp(findColumn(c), cal);
- }
-
- public int getFetchDirection() throws SQLException
- {
- //PostgreSQL normally sends rows first->last
- return java.sql.ResultSet.FETCH_FORWARD;
- }
-
- public int getFetchSize() throws SQLException
- {
- // In this implementation we return the entire result set, so
- // here return the number of rows we have. Sub-classes can return a proper
- // value
- return rows.size();
- }
-
- public Object getObject(String columnName, java.util.Map map) throws SQLException
- {
- return getObject(findColumn(columnName), map);
- }
-
- /*
- * This checks against map for the type of column i, and if found returns
- * an object based on that mapping. The class must implement the SQLData
- * interface.
- */
- public Object getObject(int i, java.util.Map map) throws SQLException
- {
- throw org.postgresql.Driver.notImplemented();
- }
-
- public Ref getRef(String columnName) throws SQLException
- {
- return getRef(findColumn(columnName));
- }
-
- public Ref getRef(int i) throws SQLException
- {
- //The backend doesn't yet have SQL3 REF types
- throw new PSQLException("postgresql.psqlnotimp");
- }
-
- public int getRow() throws SQLException
- {
- final int rows_size = rows.size();
-
- if (current_row < 0 || current_row >= rows_size)
- return 0;
-
- return current_row + 1;
- }
-
- // This one needs some thought, as not all ResultSets come from a statement
- public Statement getStatement() throws SQLException
- {
- return statement;
- }
-
- public int getType() throws SQLException
- {
- // This implementation allows scrolling but is not able to
- // see any changes. Sub-classes may overide this to return a more
- // meaningful result.
- return java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE;
- }
-
- public void insertRow() throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public boolean isAfterLast() throws SQLException
- {
- final int rows_size = rows.size();
- return (current_row >= rows_size && rows_size > 0);
- }
-
- public boolean isBeforeFirst() throws SQLException
- {
- return (current_row < 0 && rows.size() > 0);
- }
-
- public boolean isFirst() throws SQLException
- {
- return (current_row == 0 && rows.size() >= 0);
- }
-
- public boolean isLast() throws SQLException
- {
- final int rows_size = rows.size();
- return (current_row == rows_size - 1 && rows_size > 0);
- }
-
- public boolean last() throws SQLException
- {
- final int rows_size = rows.size();
- if (rows_size <= 0)
- return false;
-
- current_row = rows_size - 1;
- this_row = (byte [][])rows.elementAt(current_row);
-
- rowBuffer=new byte[this_row.length][];
- System.arraycopy(this_row,0,rowBuffer,0,this_row.length);
-
- return true;
- }
-
- public void moveToCurrentRow() throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public void moveToInsertRow() throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public boolean previous() throws SQLException
- {
- if (--current_row < 0)
- return false;
- this_row = (byte [][])rows.elementAt(current_row);
- System.arraycopy(this_row,0,rowBuffer,0,this_row.length);
- return true;
- }
-
- public void refreshRow() throws SQLException
- {
- throw new PSQLException("postgresql.notsensitive");
- }
-
- public boolean relative(int rows) throws SQLException
- {
- //have to add 1 since absolute expects a 1-based index
- return absolute(current_row + 1 + rows);
- }
-
- public boolean rowDeleted() throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- return false; // javac complains about not returning a value!
- }
-
- public boolean rowInserted() throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- return false; // javac complains about not returning a value!
- }
-
- public boolean rowUpdated() throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- return false; // javac complains about not returning a value!
- }
-
- public void setFetchDirection(int direction) throws SQLException
- {
- throw new PSQLException("postgresql.psqlnotimp");
- }
-
- public void setFetchSize(int rows) throws SQLException
- {
- // Sub-classes should implement this as part of their cursor support
- throw org.postgresql.Driver.notImplemented();
- }
-
- public void updateAsciiStream(int columnIndex,
- java.io.InputStream x,
- int length
- ) throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public void updateAsciiStream(String columnName,
- java.io.InputStream x,
- int length
- ) throws SQLException
- {
- updateAsciiStream(findColumn(columnName), x, length);
- }
-
- public void updateBigDecimal(int columnIndex,
- java.math.BigDecimal x
- ) throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public void updateBigDecimal(String columnName,
- java.math.BigDecimal x
- ) throws SQLException
- {
- updateBigDecimal(findColumn(columnName), x);
- }
-
- public void updateBinaryStream(int columnIndex,
- java.io.InputStream x,
- int length
- ) throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public void updateBinaryStream(String columnName,
- java.io.InputStream x,
- int length
- ) throws SQLException
- {
- updateBinaryStream(findColumn(columnName), x, length);
- }
-
- public void updateBoolean(int columnIndex, boolean x) throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public void updateBoolean(String columnName, boolean x) throws SQLException
- {
- updateBoolean(findColumn(columnName), x);
- }
-
- public void updateByte(int columnIndex, byte x) throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public void updateByte(String columnName, byte x) throws SQLException
- {
- updateByte(findColumn(columnName), x);
- }
-
- public void updateBytes(String columnName, byte[] x) throws SQLException
- {
- updateBytes(findColumn(columnName), x);
- }
-
- public void updateBytes(int columnIndex, byte[] x) throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public void updateCharacterStream(int columnIndex,
- java.io.Reader x,
- int length
- ) throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public void updateCharacterStream(String columnName,
- java.io.Reader x,
- int length
- ) throws SQLException
- {
- updateCharacterStream(findColumn(columnName), x, length);
- }
-
- public void updateDate(int columnIndex, java.sql.Date x) throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public void updateDate(String columnName, java.sql.Date x) throws SQLException
- {
- updateDate(findColumn(columnName), x);
- }
-
- public void updateDouble(int columnIndex, double x) throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public void updateDouble(String columnName, double x) throws SQLException
- {
- updateDouble(findColumn(columnName), x);
- }
-
- public void updateFloat(int columnIndex, float x) throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public void updateFloat(String columnName, float x) throws SQLException
- {
- updateFloat(findColumn(columnName), x);
- }
-
- public void updateInt(int columnIndex, int x) throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public void updateInt(String columnName, int x) throws SQLException
- {
- updateInt(findColumn(columnName), x);
- }
-
- public void updateLong(int columnIndex, long x) throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public void updateLong(String columnName, long x) throws SQLException
- {
- updateLong(findColumn(columnName), x);
- }
-
- public void updateNull(int columnIndex) throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public void updateNull(String columnName) throws SQLException
- {
- updateNull(findColumn(columnName));
- }
-
- public void updateObject(int columnIndex, Object x) throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public void updateObject(String columnName, Object x) throws SQLException
- {
- updateObject(findColumn(columnName), x);
- }
-
- public void updateObject(int columnIndex, Object x, int scale) throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public void updateObject(String columnName, Object x, int scale) throws SQLException
- {
- updateObject(findColumn(columnName), x, scale);
- }
-
- public void updateRow() throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public void updateShort(int columnIndex, short x) throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public void updateShort(String columnName, short x) throws SQLException
- {
- updateShort(findColumn(columnName), x);
- }
-
- public void updateString(int columnIndex, String x) throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public void updateString(String columnName, String x) throws SQLException
- {
- updateString(findColumn(columnName), x);
- }
-
- public void updateTime(int columnIndex, Time x) throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public void updateTime(String columnName, Time x) throws SQLException
- {
- updateTime(findColumn(columnName), x);
- }
-
- public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException
- {
- // only sub-classes implement CONCUR_UPDATEABLE
- notUpdateable();
- }
-
- public void updateTimestamp(String columnName, Timestamp x) throws SQLException
- {
- updateTimestamp(findColumn(columnName), x);
- }
-
- // helper method. Throws an SQLException when an update is not possible
- public void notUpdateable() throws SQLException
- {
- throw new PSQLException("postgresql.noupdate");
- }
-
- /*
- * It's used currently by getStatement() but may also with the new core
- * package.
- */
- public void setStatement(Statement statement)
- {
- this.statement = statement;
- }
-
- public void setSQLQuery(String sqlQuery) {
- this.sqlQuery=sqlQuery;
- }
+public class AbstractJdbc2ResultSet extends org.postgresql.jdbc1.AbstractJdbc1ResultSet {
+ protected String sqlQuery = null;
+
+ //needed for updateable result set support
+ protected boolean updateable = false;
+ protected boolean doingUpdates = false;
+ protected boolean onInsertRow = false;
+ protected Hashtable updateValues = new Hashtable();
+ private boolean usingOID = false; // are we using the OID for the primary key?
+ private Vector primaryKeys; // list of primary keys
+ private int numKeys = 0;
+ private boolean singleTable = false;
+ protected String tableName = null;
+ protected PreparedStatement updateStatement = null;
+ protected PreparedStatement insertStatement = null;
+ protected PreparedStatement deleteStatement = null;
+ private PreparedStatement selectStatement = null;
+
+
+
+ public AbstractJdbc2ResultSet(org.postgresql.PGConnection conn, Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) {
+ super (conn, statement, fields, tuples, status, updateCount, insertOID, binaryCursor);
+ }
+
+ public java.net.URL getURL(int columnIndex) throws SQLException {
+ return null;
+ }
+
+
+ public java.net.URL getURL(String columnName) throws SQLException {
+ return null;
+ }
+
+
+ /*
+ * Get the value of a column in the current row as a Java object
+ *
+ * <p>This method will return the value of the given column as a
+ * Java object. The type of the Java object will be the default
+ * Java Object type corresponding to the column's SQL type, following
+ * the mapping specified in the JDBC specification.
+ *
+ * <p>This method may also be used to read database specific abstract
+ * data types.
+ *
+ * @param columnIndex the first column is 1, the second is 2...
+ * @return a Object holding the column value
+ * @exception SQLException if a database access error occurs
+ */
+ public Object getObject(int columnIndex) throws SQLException {
+ Field field;
+
+ checkResultSet( columnIndex );
+
+ wasNullFlag = (this_row[columnIndex - 1] == null);
+ if (wasNullFlag)
+ return null;
+
+ field = fields[columnIndex - 1];
+
+ // some fields can be null, mainly from those returned by MetaData methods
+ if (field == null) {
+ wasNullFlag = true;
+ return null;
+ }
+
+ switch (field.getSQLType()) {
+ case Types.BIT:
+ return getBoolean(columnIndex) ? Boolean.TRUE : Boolean.FALSE;
+
+ case Types.SMALLINT:
+ return new Short(getShort(columnIndex));
+
+ case Types.INTEGER:
+ return new Integer(getInt(columnIndex));
+
+ case Types.BIGINT:
+ return new Long(getLong(columnIndex));
+
+ case Types.NUMERIC:
+ return getBigDecimal
+ (columnIndex, (field.getMod() == -1) ? -1 : ((field.getMod() - 4) & 0xffff));
+
+ case Types.REAL:
+ return new Float(getFloat(columnIndex));
+
+ case Types.DOUBLE:
+ return new Double(getDouble(columnIndex));
+
+ case Types.CHAR:
+ case Types.VARCHAR:
+ return getString(columnIndex);
+
+ case Types.DATE:
+ return getDate(columnIndex);
+
+ case Types.TIME:
+ return getTime(columnIndex);
+
+ case Types.TIMESTAMP:
+ return getTimestamp(columnIndex);
+
+ case Types.BINARY:
+ case Types.VARBINARY:
+ return getBytes(columnIndex);
+
+ case Types.ARRAY:
+ return getArray(columnIndex);
+
+ default:
+ String type = field.getPGType();
+ // if the backend doesn't know the type then coerce to String
+ if (type.equals("unknown")) {
+ return getString(columnIndex);
+ }
+ else {
+ return connection.getObject(field.getPGType(), getString(columnIndex));
+ }
+ }
+ }
+
+
+ public boolean absolute(int index) throws SQLException {
+ // index is 1-based, but internally we use 0-based indices
+ int internalIndex;
+
+ if (index == 0)
+ throw new SQLException("Cannot move to index of 0");
+
+ final int rows_size = rows.size();
+
+ //if index<0, count from the end of the result set, but check
+ //to be sure that it is not beyond the first index
+ if (index < 0) {
+ if (index >= -rows_size)
+ internalIndex = rows_size + index;
+ else {
+ beforeFirst();
+ return false;
+ }
+ }
+ else {
+ //must be the case that index>0,
+ //find the correct place, assuming that
+ //the index is not too large
+ if (index <= rows_size)
+ internalIndex = index - 1;
+ else {
+ afterLast();
+ return false;
+ }
+ }
+
+ current_row = internalIndex;
+ this_row = (byte[][]) rows.elementAt(internalIndex);
+ return true;
+ }
+
+
+ public void afterLast() throws SQLException {
+ final int rows_size = rows.size();
+ if (rows_size > 0)
+ current_row = rows_size;
+ }
+
+
+ public void beforeFirst() throws SQLException {
+ if (rows.size() > 0)
+ current_row = -1;
+ }
+
+
+ public boolean first() throws SQLException {
+ if (rows.size() <= 0)
+ return false;
+
+ current_row = 0;
+ this_row = (byte[][]) rows.elementAt(current_row);
+
+ rowBuffer = new byte[this_row.length][];
+ System.arraycopy(this_row, 0, rowBuffer, 0, this_row.length);
+
+ return true;
+ }
+
+
+ public java.sql.Array getArray(String colName) throws SQLException {
+ return getArray(findColumn(colName));
+ }
+
+
+ public java.sql.Array getArray(int i) throws SQLException {
+ wasNullFlag = (this_row[i - 1] == null);
+ if (wasNullFlag)
+ return null;
+
+ if (i < 1 || i > fields.length)
+ throw new PSQLException("postgresql.res.colrange");
+ return (java.sql.Array) new org.postgresql.jdbc2.Array( connection, i, fields[i - 1], (java.sql.ResultSet) this );
+ }
+
+
+ public java.math.BigDecimal getBigDecimal(int columnIndex) throws SQLException {
+ return getBigDecimal(columnIndex, -1);
+ }
+
+
+ public java.math.BigDecimal getBigDecimal(String columnName) throws SQLException {
+ return getBigDecimal(findColumn(columnName));
+ }
+
+
+ public Blob getBlob(String columnName) throws SQLException {
+ return getBlob(findColumn(columnName));
+ }
+
+
+ public Blob getBlob(int i) throws SQLException {
+ return new org.postgresql.largeobject.PGblob(connection, getInt(i));
+ }
+
+
+ public java.io.Reader getCharacterStream(String columnName) throws SQLException {
+ return getCharacterStream(findColumn(columnName));
+ }
+
+
+ public java.io.Reader getCharacterStream(int i) throws SQLException {
+ checkResultSet( i );
+ wasNullFlag = (this_row[i - 1] == null);
+ if (wasNullFlag)
+ return null;
+
+ if (((AbstractJdbc2Connection) connection).haveMinimumCompatibleVersion("7.2")) {
+ //Version 7.2 supports AsciiStream for all the PG text types
+ //As the spec/javadoc for this method indicate this is to be used for
+ //large text values (i.e. LONGVARCHAR) PG doesn't have a separate
+ //long string datatype, but with toast the text datatype is capable of
+ //handling very large values. Thus the implementation ends up calling
+ //getString() since there is no current way to stream the value from the server
+ return new CharArrayReader(getString(i).toCharArray());
+ }
+ else {
+ // In 7.1 Handle as BLOBS so return the LargeObject input stream
+ Encoding encoding = connection.getEncoding();
+ InputStream input = getBinaryStream(i);
+ return encoding.getDecodingReader(input);
+ }
+ }
+
+
+ public Clob getClob(String columnName) throws SQLException {
+ return getClob(findColumn(columnName));
+ }
+
+
+ public Clob getClob(int i) throws SQLException {
+ return new org.postgresql.largeobject.PGclob(connection, getInt(i));
+ }
+
+
+ public int getConcurrency() throws SQLException {
+ if (statement == null)
+ return java.sql.ResultSet.CONCUR_READ_ONLY;
+ return statement.getResultSetConcurrency();
+ }
+
+
+ public java.sql.Date getDate(int i, java.util.Calendar cal) throws SQLException {
+ // If I read the specs, this should use cal only if we don't
+ // store the timezone, and if we do, then act just like getDate()?
+ // for now...
+ return getDate(i);
+ }
+
+
+ public Time getTime(int i, java.util.Calendar cal) throws SQLException {
+ // If I read the specs, this should use cal only if we don't
+ // store the timezone, and if we do, then act just like getTime()?
+ // for now...
+ return getTime(i);
+ }
+
+
+ public Timestamp getTimestamp(int i, java.util.Calendar cal) throws SQLException {
+ // If I read the specs, this should use cal only if we don't
+ // store the timezone, and if we do, then act just like getDate()?
+ // for now...
+ return getTimestamp(i);
+ }
+
+
+ public java.sql.Date getDate(String c, java.util.Calendar cal) throws SQLException {
+ return getDate(findColumn(c), cal);
+ }
+
+
+ public Time getTime(String c, java.util.Calendar cal) throws SQLException {
+ return getTime(findColumn(c), cal);
+ }
+
+
+ public Timestamp getTimestamp(String c, java.util.Calendar cal) throws SQLException {
+ return getTimestamp(findColumn(c), cal);
+ }
+
+
+ public int getFetchDirection() throws SQLException {
+ //PostgreSQL normally sends rows first->last
+ return java.sql.ResultSet.FETCH_FORWARD;
+ }
+
+
+ public int getFetchSize() throws SQLException {
+ // In this implementation we return the entire result set, so
+ // here return the number of rows we have. Sub-classes can return a proper
+ // value
+ return rows.size();
+ }
+
+
+ public Object getObject(String columnName, java.util.Map map) throws SQLException {
+ return getObject(findColumn(columnName), map);
+ }
+
+
+ /*
+ * This checks against map for the type of column i, and if found returns
+ * an object based on that mapping. The class must implement the SQLData
+ * interface.
+ */
+ public Object getObject(int i, java.util.Map map) throws SQLException {
+ throw org.postgresql.Driver.notImplemented();
+ }
+
+
+ public Ref getRef(String columnName) throws SQLException {
+ return getRef(findColumn(columnName));
+ }
+
+
+ public Ref getRef(int i) throws SQLException {
+ //The backend doesn't yet have SQL3 REF types
+ throw new PSQLException("postgresql.psqlnotimp");
+ }
+
+
+ public int getRow() throws SQLException {
+ final int rows_size = rows.size();
+
+ if (current_row < 0 || current_row >= rows_size)
+ return 0;
+
+ return current_row + 1;
+ }
+
+
+ // This one needs some thought, as not all ResultSets come from a statement
+ public Statement getStatement() throws SQLException {
+ return statement;
+ }
+
+
+ public int getType() throws SQLException {
+ // This implementation allows scrolling but is not able to
+ // see any changes. Sub-classes may overide this to return a more
+ // meaningful result.
+ return java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE;
+ }
+
+
+ public boolean isAfterLast() throws SQLException {
+ final int rows_size = rows.size();
+ return (current_row >= rows_size && rows_size > 0);
+ }
+
+
+ public boolean isBeforeFirst() throws SQLException {
+ return (current_row < 0 && rows.size() > 0);
+ }
+
+
+ public boolean isFirst() throws SQLException {
+ return (current_row == 0 && rows.size() >= 0);
+ }
+
+
+ public boolean isLast() throws SQLException {
+ final int rows_size = rows.size();
+ return (current_row == rows_size - 1 && rows_size > 0);
+ }
+
+
+ public boolean last() throws SQLException {
+ final int rows_size = rows.size();
+ if (rows_size <= 0)
+ return false;
+
+ current_row = rows_size - 1;
+ this_row = (byte[][]) rows.elementAt(current_row);
+
+ rowBuffer = new byte[this_row.length][];
+ System.arraycopy(this_row, 0, rowBuffer, 0, this_row.length);
+
+ return true;
+ }
+
+
+ public boolean previous() throws SQLException {
+ if (--current_row < 0)
+ return false;
+ this_row = (byte[][]) rows.elementAt(current_row);
+ System.arraycopy(this_row, 0, rowBuffer, 0, this_row.length);
+ return true;
+ }
+
+
+ public boolean relative(int rows) throws SQLException {
+ //have to add 1 since absolute expects a 1-based index
+ return absolute(current_row + 1 + rows);
+ }
+
+
+ public void setFetchDirection(int direction) throws SQLException {
+ throw new PSQLException("postgresql.psqlnotimp");
+ }
+
+
+ public void setFetchSize(int rows) throws SQLException {
+ // Sub-classes should implement this as part of their cursor support
+ throw org.postgresql.Driver.notImplemented();
+ }
+
+
+ public synchronized void cancelRowUpdates() throws SQLException {
+ if (doingUpdates) {
+ doingUpdates = false;
+
+ clearRowBuffer();
+ }
+ }
+
+
+ public synchronized void deleteRow() throws SQLException {
+ if ( !isUpdateable() ) {
+ throw new PSQLException( "postgresql.updateable.notupdateable" );
+ }
+
+ if (onInsertRow) {
+ throw new PSQLException( "postgresql.updateable.oninsertrow" );
+ }
+
+ if (rows.size() == 0) {
+ throw new PSQLException( "postgresql.updateable.emptydelete" );
+ }
+ if (isBeforeFirst()) {
+ throw new PSQLException( "postgresql.updateable.beforestartdelete" );
+ }
+ if (isAfterLast()) {
+ throw new PSQLException( "postgresql.updateable.afterlastdelete" );
+ }
+
+
+ int numKeys = primaryKeys.size();
+ if ( deleteStatement == null ) {
+
+
+ StringBuffer deleteSQL = new StringBuffer("DELETE FROM " ).append(tableName).append(" where " );
+
+ for ( int i = 0; i < numKeys; i++ ) {
+ deleteSQL.append( ((PrimaryKey) primaryKeys.get(i)).name ).append( " = ? " );
+ if ( i < numKeys - 1 ) {
+ deleteSQL.append( " and " );
+ }
+ }
+
+ deleteStatement = ((java.sql.Connection) connection).prepareStatement(deleteSQL.toString());
+ }
+ deleteStatement.clearParameters();
+
+ for ( int i = 0; i < numKeys; i++ ) {
+ deleteStatement.setObject(i + 1, ((PrimaryKey) primaryKeys.get(i)).getValue());
+ }
+
+
+ deleteStatement.executeUpdate();
+
+ rows.removeElementAt(current_row);
+ }
+
+
+ public synchronized void insertRow() throws SQLException {
+ if ( !isUpdateable() ) {
+ throw new PSQLException( "postgresql.updateable.notupdateable" );
+ }
+
+ if (!onInsertRow) {
+ throw new PSQLException( "postgresql.updateable.notoninsertrow" );
+ }
+ else {
+
+ // loop through the keys in the insertTable and create the sql statement
+ // we have to create the sql every time since the user could insert different
+ // columns each time
+
+ StringBuffer insertSQL = new StringBuffer("INSERT INTO ").append(tableName).append(" (");
+ StringBuffer paramSQL = new StringBuffer(") values (" );
+
+ Enumeration columnNames = updateValues.keys();
+ int numColumns = updateValues.size();
+
+ for ( int i = 0; columnNames.hasMoreElements(); i++ ) {
+ String columnName = (String) columnNames.nextElement();
+
+ insertSQL.append( columnName );
+ if ( i < numColumns - 1 ) {
+ insertSQL.append(", ");
+ paramSQL.append("?,");
+ }
+ else {
+ paramSQL.append("?)");
+ }
+
+ }
+
+ insertSQL.append(paramSQL.toString());
+ insertStatement = ((java.sql.Connection) connection).prepareStatement(insertSQL.toString());
+
+ Enumeration keys = updateValues.keys();
+
+ for ( int i = 1; keys.hasMoreElements(); i++) {
+ String key = (String) keys.nextElement();
+ insertStatement.setObject(i, updateValues.get( key ) );
+ }
+
+ insertStatement.executeUpdate();
+
+ if ( usingOID ) {
+ // we have to get the last inserted OID and put it in the resultset
+
+ long insertedOID = ((AbstractJdbc2Statement) insertStatement).getLastOID();
+
+ updateValues.put("oid", new Long(insertedOID) );
+
+ }
+
+ // update the underlying row to the new inserted data
+ updateRowBuffer();
+
+ rows.addElement(rowBuffer);
+
+ // we should now reflect the current data in this_row
+ // that way getXXX will get the newly inserted data
+ this_row = rowBuffer;
+
+ // need to clear this in case of another insert
+ clearRowBuffer();
+
+
+ }
+ }
+
+
+ public synchronized void moveToCurrentRow() throws SQLException {
+ if (!updateable) {
+ throw new PSQLException( "postgresql.updateable.notupdateable" );
+ }
+
+ this_row = (byte[][]) rows.elementAt(current_row);
+
+ rowBuffer = new byte[this_row.length][];
+ System.arraycopy(this_row, 0, rowBuffer, 0, this_row.length);
+
+ onInsertRow = false;
+ doingUpdates = false;
+ }
+
+
+ public synchronized void moveToInsertRow() throws SQLException {
+ if (!updateable) {
+ throw new PSQLException( "postgresql.updateable.notupdateable" );
+ }
+
+ if (insertStatement != null) {
+ insertStatement = null;
+ }
+
+
+ // make sure the underlying data is null
+ clearRowBuffer();
+
+ onInsertRow = true;
+ doingUpdates = false;
+
+ }
+
+
+ private synchronized void clearRowBuffer() throws SQLException {
+ // rowBuffer is the temporary storage for the row
+ rowBuffer = new byte[fields.length][];
+
+ // clear the updateValues hashTable for the next set of updates
+ updateValues.clear();
+
+ }
+
+
+ public boolean rowDeleted() throws SQLException {
+ // only sub-classes implement CONCURuPDATEABLE
+ throw Driver.notImplemented();
+ }
+
+
+ public boolean rowInserted() throws SQLException {
+ // only sub-classes implement CONCURuPDATEABLE
+ throw Driver.notImplemented();
+ }
+
+
+ public boolean rowUpdated() throws SQLException {
+ // only sub-classes implement CONCURuPDATEABLE
+ throw Driver.notImplemented();
+ }
+
+
+ public synchronized void updateAsciiStream(int columnIndex,
+ java.io.InputStream x,
+ int length
+ ) throws SQLException {
+
+ if ( !isUpdateable() ) {
+ throw new PSQLException( "postgresql.updateable.notupdateable" );
+ }
+
+ byte[] theData = null;
+
+ try {
+ x.read(theData, 0, length);
+ }
+ catch (NullPointerException ex ) {
+ throw new PSQLException("postgresql.updateable.inputstream");
+ }
+ catch (IOException ie) {
+ throw new PSQLException("postgresql.updateable.ioerror" + ie);
+ }
+
+ doingUpdates = !onInsertRow;
+
+ updateValues.put( fields[columnIndex - 1].getName(), theData );
+
+ }
+
+
+ public synchronized void updateBigDecimal(int columnIndex,
+ java.math.BigDecimal x )
+ throws SQLException {
+
+ if ( !isUpdateable() ) {
+ throw new PSQLException( "postgresql.updateable.notupdateable" );
+ }
+
+ doingUpdates = !onInsertRow;
+ updateValues.put( fields[columnIndex - 1].getName(), x );
+
+ }
+
+
+ public synchronized void updateBinaryStream(int columnIndex,
+ java.io.InputStream x,
+ int length
+ ) throws SQLException {
+
+ if ( !isUpdateable() ) {
+ throw new PSQLException( "postgresql.updateable.notupdateable" );
+ }
+
+ byte[] theData = null;
+
+ try {
+ x.read(theData, 0, length);
+
+ }
+ catch ( NullPointerException ex ) {
+ throw new PSQLException("postgresql.updateable.inputstream");
+ }
+ catch (IOException ie) {
+ throw new PSQLException("postgresql.updateable.ioerror" + ie);
+ }
+
+ doingUpdates = !onInsertRow;
+
+ updateValues.put( fields[columnIndex - 1].getName(), theData );
+
+ }
+
+
+ public synchronized void updateBoolean(int columnIndex, boolean x) throws SQLException {
+
+ if ( !isUpdateable() ) {
+ throw new PSQLException( "postgresql.updateable.notupdateable" );
+ }
+
+ if ( Driver.logDebug ) Driver.debug("updating boolean " + fields[columnIndex - 1].getName() + "=" + x);
+
+ doingUpdates = !onInsertRow;
+ updateValues.put( fields[columnIndex - 1].getName(), new Boolean(x) );
+
+ }
+
+
+ public synchronized void updateByte(int columnIndex, byte x) throws SQLException {
+ if ( !isUpdateable() ) {
+ throw new PSQLException( "postgresql.updateable.notupdateable" );
+ }
+
+ doingUpdates = true;
+ updateValues.put( fields[columnIndex - 1].getName(), String.valueOf(x) );
+ }
+
+
+ public synchronized void updateBytes(int columnIndex, byte[] x) throws SQLException {
+
+ if ( !isUpdateable() ) {
+ throw new PSQLException( "postgresql.updateable.notupdateable" );
+ }
+
+ doingUpdates = !onInsertRow;
+ updateValues.put( fields[columnIndex - 1].getName(), x );
+
+ }
+
+
+ public synchronized void updateCharacterStream(int columnIndex,
+ java.io.Reader x,
+ int length
+ ) throws SQLException {
+
+ if ( !isUpdateable() ) {
+ throw new PSQLException( "postgresql.updateable.notupdateable" );
+ }
+
+ char[] theData = null;
+
+ try {
+ x.read(theData, 0, length);
+
+ }
+ catch (NullPointerException ex) {
+ throw new PSQLException("postgresql.updateable.inputstream");
+ }
+ catch (IOException ie) {
+ throw new PSQLException("postgresql.updateable.ioerror" + ie);
+ }
+
+ doingUpdates = !onInsertRow;
+ updateValues.put( fields[columnIndex - 1].getName(), theData);
+
+ }
+
+
+ public synchronized void updateDate(int columnIndex, java.sql.Date x) throws SQLException {
+
+ if ( !isUpdateable() ) {
+ throw new PSQLException( "postgresql.updateable.notupdateable" );
+ }
+
+ doingUpdates = !onInsertRow;
+ updateValues.put( fields[columnIndex - 1].getName(), x );
+ }
+
+
+ public synchronized void updateDouble(int columnIndex, double x) throws SQLException {
+ if ( !isUpdateable() ) {
+ throw new PSQLException( "postgresql.updateable.notupdateable" );
+ }
+
+ if ( Driver.logDebug ) Driver.debug("updating double " + fields[columnIndex - 1].getName() + "=" + x);
+
+ doingUpdates = !onInsertRow;
+ updateValues.put( fields[columnIndex - 1].getName(), new Double(x) );
+
+ }
+
+
+ public synchronized void updateFloat(int columnIndex, float x) throws SQLException {
+ if ( !isUpdateable() ) {
+ throw new PSQLException( "postgresql.updateable.notupdateable" );
+ }
+
+ if ( Driver.logDebug ) Driver.debug("updating float " + fields[columnIndex - 1].getName() + "=" + x);
+
+ doingUpdates = !onInsertRow;
+
+ updateValues.put( fields[columnIndex - 1].getName(), new Float(x) );
+
+ }
+
+
+ public synchronized void updateInt(int columnIndex, int x) throws SQLException {
+ if ( !isUpdateable() ) {
+ throw new PSQLException( "postgresql.updateable.notupdateable" );
+ }
+
+ if ( Driver.logDebug ) Driver.debug("updating int " + fields[columnIndex - 1].getName() + "=" + x);
+
+ doingUpdates = !onInsertRow;
+ updateValues.put( fields[columnIndex - 1].getName(), new Integer(x) );
+
+ }
+
+
+ public synchronized void updateLong(int columnIndex, long x) throws SQLException {
+ if ( !isUpdateable() ) {
+ throw new PSQLException( "postgresql.updateable.notupdateable" );
+ }
+
+ if ( Driver.logDebug ) Driver.debug("updating long " + fields[columnIndex - 1].getName() + "=" + x);
+
+ doingUpdates = !onInsertRow;
+ updateValues.put( fields[columnIndex - 1].getName(), new Long(x) );
+
+ }
+
+
+ public synchronized void updateNull(int columnIndex) throws SQLException {
+ if ( !isUpdateable() ) {
+ throw new PSQLException( "postgresql.updateable.notupdateable" );
+ }
+
+ doingUpdates = !onInsertRow;
+ updateValues.put( fields[columnIndex - 1].getName(), null);
+
+
+ }
+
+
+ public synchronized void updateObject(int columnIndex, Object x) throws SQLException {
+ if ( !isUpdateable() ) {
+ throw new PSQLException( "postgresql.updateable.notupdateable" );
+ }
+
+ if ( Driver.logDebug ) Driver.debug("updating object " + fields[columnIndex - 1].getName() + " = " + x);
+
+ doingUpdates = !onInsertRow;
+ updateValues.put( fields[columnIndex - 1].getName(), x );
+ }
+
+
+ public synchronized void updateObject(int columnIndex, Object x, int scale) throws SQLException {
+ if ( !isUpdateable() ) {
+ throw new PSQLException( "postgresql.updateable.notupdateable" );
+ }
+
+ this.updateObject(columnIndex, x);
+
+ }
+
+
+ public void refreshRow() throws SQLException {
+ if ( !isUpdateable() ) {
+ throw new PSQLException( "postgresql.updateable.notupdateable" );
+ }
+
+ try {
+ StringBuffer selectSQL = new StringBuffer( "select ");
+
+ final int numColumns = java.lang.reflect.Array.getLength(fields);
+
+ for (int i = 0; i < numColumns; i++ ) {
+
+ selectSQL.append( fields[i].getName() );
+
+ if ( i < numColumns - 1 ) {
+
+ selectSQL.append(", ");
+ }
+
+ }
+ selectSQL.append(" from " ).append(tableName).append(" where ");
+
+ int numKeys = primaryKeys.size();
+
+ for ( int i = 0; i < numKeys; i++ ) {
+
+ PrimaryKey primaryKey = ((PrimaryKey) primaryKeys.get(i));
+ selectSQL.append(primaryKey.name).append("= ?");
+
+ if ( i < numKeys - 1 ) {
+ selectSQL.append(" and ");
+ }
+ }
+ if ( Driver.logDebug ) Driver.debug("selecting " + selectSQL.toString());
+ selectStatement = ((java.sql.Connection) connection).prepareStatement(selectSQL.toString());
+
+
+ for ( int j = 0, i = 1; j < numKeys; j++, i++) {
+ selectStatement.setObject( i, ((PrimaryKey) primaryKeys.get(j)).getValue() );
+ }
+
+ Jdbc2ResultSet rs = (Jdbc2ResultSet) selectStatement.executeQuery();
+
+ if ( rs.first() ) {
+ rowBuffer = rs.rowBuffer;
+ }
+
+ rows.setElementAt( rowBuffer, current_row );
+ if ( Driver.logDebug ) Driver.debug("done updates");
+
+ rs.close();
+ selectStatement.close();
+ selectStatement = null;
+
+ }
+ catch (Exception e) {
+ if ( Driver.logDebug ) Driver.debug(e.getClass().getName() + e);
+ throw new SQLException( e.getMessage() );
+ }
+
+ }
+
+
+ public synchronized void updateRow() throws SQLException {
+ if ( !isUpdateable() ) {
+ throw new PSQLException( "postgresql.updateable.notupdateable" );
+ }
+
+ if (doingUpdates) {
+
+ try {
+
+ StringBuffer updateSQL = new StringBuffer("UPDATE " + tableName + " SET ");
+
+ int numColumns = updateValues.size();
+ Enumeration columns = updateValues.keys();
+
+ for (int i = 0; columns.hasMoreElements(); i++ ) {
+
+ String column = (String) columns.nextElement();
+ updateSQL.append( column + "= ?");
+
+ if ( i < numColumns - 1 ) {
+
+ updateSQL.append(", ");
+ }
+
+ }
+ updateSQL.append( " WHERE " );
+
+ int numKeys = primaryKeys.size();
+
+ for ( int i = 0; i < numKeys; i++ ) {
+
+ PrimaryKey primaryKey = ((PrimaryKey) primaryKeys.get(i));
+ updateSQL.append(primaryKey.name).append("= ?");
+
+ if ( i < numKeys - 1 ) {
+ updateSQL.append(" and ");
+ }
+ }
+ if ( Driver.logDebug ) Driver.debug("updating " + updateSQL.toString());
+ updateStatement = ((java.sql.Connection) connection).prepareStatement(updateSQL.toString());
+
+ int i = 0;
+ Iterator iterator = updateValues.values().iterator();
+ for (; iterator.hasNext(); i++) {
+ updateStatement.setObject( i + 1, iterator.next() );
+
+ }
+ for ( int j = 0; j < numKeys; j++, i++) {
+ updateStatement.setObject( i + 1, ((PrimaryKey) primaryKeys.get(j)).getValue() );
+ }
+
+ updateStatement.executeUpdate();
+ updateStatement.close();
+
+ updateStatement = null;
+ updateRowBuffer();
+
+
+ if ( Driver.logDebug ) Driver.debug("copying data");
+ System.arraycopy(rowBuffer, 0, this_row, 0, rowBuffer.length);
+
+ rows.setElementAt( rowBuffer, current_row );
+ if ( Driver.logDebug ) Driver.debug("done updates");
+
+ doingUpdates = false;
+ }
+ catch (Exception e) {
+ if ( Driver.logDebug ) Driver.debug(e.getClass().getName() + e);
+ throw new SQLException( e.getMessage() );
+ }
+
+ }
+
+ }
+
+
+ public synchronized void updateShort(int columnIndex, short x) throws SQLException {
+ if ( Driver.logDebug ) Driver.debug("in update Short " + fields[columnIndex - 1].getName() + " = " + x);
+
+
+ doingUpdates = !onInsertRow;
+ updateValues.put( fields[columnIndex - 1].getName(), new Short(x) );
+
+ }
+
+
+ public synchronized void updateString(int columnIndex, String x) throws SQLException {
+ if ( Driver.logDebug ) Driver.debug("in update String " + fields[columnIndex - 1].getName() + " = " + x);
+
+ doingUpdates = !onInsertRow;
+ updateValues.put( fields[columnIndex - 1].getName(), x );
+
+ }
+
+
+ public synchronized void updateTime(int columnIndex, Time x) throws SQLException {
+ if ( Driver.logDebug ) Driver.debug("in update Time " + fields[columnIndex - 1].getName() + " = " + x);
+
+
+ doingUpdates = !onInsertRow;
+ updateValues.put( fields[columnIndex - 1].getName(), x );
+
+ }
+
+
+ public synchronized void updateTimestamp(int columnIndex, Timestamp x) throws SQLException {
+ if ( Driver.logDebug ) Driver.debug("updating Timestamp " + fields[columnIndex - 1].getName() + " = " + x);
+
+ doingUpdates = !onInsertRow;
+ updateValues.put( fields[columnIndex - 1].getName(), x );
+
+
+ }
+
+
+ public synchronized void updateNull(String columnName) throws SQLException {
+ updateNull(findColumn(columnName));
+ }
+
+
+ public synchronized void updateBoolean(String columnName, boolean x) throws SQLException {
+ updateBoolean(findColumn(columnName), x);
+ }
+
+
+ public synchronized void updateByte(String columnName, byte x) throws SQLException {
+ updateByte(findColumn(columnName), x);
+ }
+
+
+ public synchronized void updateShort(String columnName, short x) throws SQLException {
+ updateShort(findColumn(columnName), x);
+ }
+
+
+ public synchronized void updateInt(String columnName, int x) throws SQLException {
+ updateInt(findColumn(columnName), x);
+ }
+
+
+ public synchronized void updateLong(String columnName, long x) throws SQLException {
+ updateLong(findColumn(columnName), x);
+ }
+
+
+ public synchronized void updateFloat(String columnName, float x) throws SQLException {
+ updateFloat(findColumn(columnName), x);
+ }
+
+
+ public synchronized void updateDouble(String columnName, double x) throws SQLException {
+ updateDouble(findColumn(columnName), x);
+ }
+
+
+ public synchronized void updateBigDecimal(String columnName, BigDecimal x)
+ throws SQLException {
+ updateBigDecimal(findColumn(columnName), x);
+ }
+
+
+ public synchronized void updateString(String columnName, String x) throws SQLException {
+ updateString(findColumn(columnName), x);
+ }
+
+
+ public synchronized void updateBytes(String columnName, byte x[]) throws SQLException {
+ updateBytes(findColumn(columnName), x);
+ }
+
+
+ public synchronized void updateDate(String columnName, java.sql.Date x)
+ throws SQLException {
+ updateDate(findColumn(columnName), x);
+ }
+
+
+ public synchronized void updateTime(String columnName, java.sql.Time x)
+ throws SQLException {
+ updateTime(findColumn(columnName), x);
+ }
+
+
+ public synchronized void updateTimestamp(String columnName, java.sql.Timestamp x)
+ throws SQLException {
+ updateTimestamp(findColumn(columnName), x);
+ }
+
+
+ public synchronized void updateAsciiStream(
+ String columnName,
+ java.io.InputStream x,
+ int length)
+ throws SQLException {
+ updateAsciiStream(findColumn(columnName), x, length);
+ }
+
+
+ public synchronized void updateBinaryStream(
+ String columnName,
+ java.io.InputStream x,
+ int length)
+ throws SQLException {
+ updateBinaryStream(findColumn(columnName), x, length);
+ }
+
+
+ public synchronized void updateCharacterStream(
+ String columnName,
+ java.io.Reader reader,
+ int length)
+ throws SQLException {
+ updateCharacterStream(findColumn(columnName), reader, length);
+ }
+
+
+ public synchronized void updateObject(String columnName, Object x, int scale)
+ throws SQLException {
+ updateObject(findColumn(columnName), x);
+ }
+
+
+ public synchronized void updateObject(String columnName, Object x) throws SQLException {
+ updateObject(findColumn(columnName), x);
+ }
+
+
+ private int _findColumn( String columnName ) {
+ int i;
+
+ final int flen = fields.length;
+ for (i = 0; i < flen; ++i) {
+ if (fields[i].getName().equalsIgnoreCase(columnName)) {
+ return (i + 1);
+ }
+ }
+ return -1;
+ }
+
+
+ /**
+ * Is this ResultSet updateable?
+ */
+
+ boolean isUpdateable() throws SQLException {
+
+ if (updateable) return true;
+
+ if ( Driver.logDebug ) Driver.debug("checking if rs is updateable");
+
+ parseQuery();
+
+ if ( singleTable == false ) {
+ if ( Driver.logDebug ) Driver.debug("not a single table");
+ return false;
+ }
+
+ if ( Driver.logDebug ) Driver.debug("getting primary keys");
+
+ //
+ // Contains the primary key?
+ //
+
+ primaryKeys = new Vector();
+
+ // this is not stricty jdbc spec, but it will make things much faster if used
+ // the user has to select oid, * from table and then we will just use oid
+
+
+ usingOID = false;
+ int oidIndex = _findColumn( "oid" );
+ int i = 0;
+
+
+ // if we find the oid then just use it
+
+ if ( oidIndex > 0 ) {
+ i++;
+ primaryKeys.add( new PrimaryKey( oidIndex, "oid" ) );
+ usingOID = true;
+ }
+ else {
+ // otherwise go and get the primary keys and create a hashtable of keys
+ java.sql.ResultSet rs = ((java.sql.Connection) connection).getMetaData().getPrimaryKeys("", "", tableName);
+
+
+ for (; rs.next(); i++ ) {
+ String columnName = rs.getString(4); // get the columnName
+
+ int index = findColumn( columnName );
+
+ if ( index > 0 ) {
+ primaryKeys.add( new PrimaryKey(index, columnName ) ); // get the primary key information
+ }
+ }
+
+ rs.close();
+ }
+
+ numKeys = primaryKeys.size();
+
+ if ( Driver.logDebug ) Driver.debug( "no of keys=" + i );
+
+ if ( i < 1 ) {
+ throw new SQLException("No Primary Keys");
+ }
+
+ updateable = primaryKeys.size() > 0;
+
+ if ( Driver.logDebug ) Driver.debug( "checking primary key " + updateable );
+
+ return updateable;
+ }
+
+
+ public void parseQuery() {
+ StringTokenizer st = new StringTokenizer(sqlQuery, " \r\t");
+ boolean tableFound = false, tablesChecked = false;
+ String name = "";
+
+ singleTable = true;
+
+ while ( !tableFound && !tablesChecked && st.hasMoreTokens() ) {
+ name = st.nextToken();
+ if ( !tableFound ) {
+ if (name.toLowerCase().equals("from")) {
+ tableName = st.nextToken();
+ tableFound = true;
+ }
+ }
+ else {
+ tablesChecked = true;
+ // if the very next token is , then there are multiple tables
+ singleTable = !name.equalsIgnoreCase(",");
+ }
+ }
+ }
+
+
+ private void updateRowBuffer() throws SQLException {
+
+ Enumeration columns = updateValues.keys();
+
+ while ( columns.hasMoreElements() ) {
+ String columnName = (String) columns.nextElement();
+ int columnIndex = _findColumn( columnName ) - 1;
+
+ switch ( connection.getSQLType( fields[columnIndex].getPGType() ) ) {
+
+ case Types.DECIMAL:
+ case Types.BIGINT:
+ case Types.DOUBLE:
+ case Types.BIT:
+ case Types.VARCHAR:
+ case Types.DATE:
+ case Types.TIME:
+ case Types.TIMESTAMP:
+ case Types.SMALLINT:
+ case Types.FLOAT:
+ case Types.INTEGER:
+ case Types.CHAR:
+ case Types.NUMERIC:
+ case Types.REAL:
+ case Types.TINYINT:
+
+ try {
+ rowBuffer[columnIndex] = String.valueOf( updateValues.get( columnName ) ).getBytes(connection.getEncoding().name() );
+ }
+ catch ( UnsupportedEncodingException ex) {
+ throw new SQLException("Unsupported Encoding " + connection.getEncoding().name());
+ }
+
+ case Types.NULL:
+ continue;
+
+ default:
+ rowBuffer[columnIndex] = (byte[]) updateValues.get( columnName );
+ }
+
+ }
+ }
+
+
+ public void setStatement(Statement statement) {
+ this.statement = statement;
+ }
+
+
+ public void setSQLQuery(String sqlQuery) {
+ this.sqlQuery = sqlQuery;
+ }
+
+
+ private class PrimaryKey {
+ int index; // where in the result set is this primaryKey
+ String name; // what is the columnName of this primary Key
+
+ PrimaryKey( int index, String name) {
+ this.index = index;
+ this.name = name;
+ }
+ Object getValue() throws SQLException {
+ return getObject(index);
+ }
+ };
+
+
+
}
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java
index 47c2c779831..d8d16985ad1 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java
@@ -2,12 +2,13 @@ package org.postgresql.jdbc2;
import java.io.*;
+import java.math.*;
import java.sql.*;
import java.util.Vector;
import org.postgresql.largeobject.*;
import org.postgresql.util.PSQLException;
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Statement.java,v 1.2 2002/07/24 22:08:42 barry Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Statement.java,v 1.3 2002/07/25 22:45:28 barry Exp $
* This class defines methods of the jdbc2 specification. This class extends
* org.postgresql.jdbc1.AbstractJdbc1Statement which provides the jdbc1
* methods. The real Statement class (for jdbc2) is org.postgresql.jdbc2.Jdbc2Statement
@@ -46,7 +47,7 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra
{
boolean l_return = super.execute(sql);
//Now do the jdbc2 specific stuff
- //required for ResultSet.getStatement() to work
+ //required for ResultSet.getStatement() to work and updateable resultsets
((AbstractJdbc2ResultSet)result).setStatement((Statement)this);
// Added this so that the Updateable resultset knows the query that gave this
@@ -331,4 +332,60 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra
setTimestamp(i, new java.sql.Timestamp(cal.getTime().getTime()));
}
}
+
+ // ** JDBC 2 Extensions for CallableStatement**
+
+ public java.sql.Array getArray(int i) throws SQLException
+ {
+ throw org.postgresql.Driver.notImplemented();
+ }
+
+ public java.math.BigDecimal getBigDecimal(int parameterIndex) throws SQLException
+ {
+ checkIndex (parameterIndex, Types.NUMERIC, "BigDecimal");
+ return ((BigDecimal)callResult);
+ }
+
+ public Blob getBlob(int i) throws SQLException
+ {
+ throw org.postgresql.Driver.notImplemented();
+ }
+
+ public Clob getClob(int i) throws SQLException
+ {
+ throw org.postgresql.Driver.notImplemented();
+ }
+
+ public Object getObject(int i, java.util.Map map) throws SQLException
+ {
+ throw org.postgresql.Driver.notImplemented();
+ }
+
+ public Ref getRef(int i) throws SQLException
+ {
+ throw org.postgresql.Driver.notImplemented();
+ }
+
+ public java.sql.Date getDate(int i, java.util.Calendar cal) throws SQLException
+ {
+ throw org.postgresql.Driver.notImplemented();
+ }
+
+ public Time getTime(int i, java.util.Calendar cal) throws SQLException
+ {
+ throw org.postgresql.Driver.notImplemented();
+ }
+
+ public Timestamp getTimestamp(int i, java.util.Calendar cal) throws SQLException
+ {
+ throw org.postgresql.Driver.notImplemented();
+ }
+
+ // no custom types allowed yet..
+ public void registerOutParameter(int parameterIndex, int sqlType, String typeName) throws SQLException
+ {
+ throw org.postgresql.Driver.notImplemented();
+ }
+
+
}
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/Array.java b/src/interfaces/jdbc/org/postgresql/jdbc2/Array.java
index 2105802d66a..99cbf0ea8ce 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/Array.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/Array.java
@@ -340,7 +340,7 @@ public class Array implements java.sql.Array
default:
throw org.postgresql.Driver.notImplemented();
}
- return new Jdbc2ResultSet((org.postgresql.jdbc2.Jdbc2Connection)conn, fields, rows, "OK", 1 );
+ return ((Jdbc2Connection)conn).getResultSet(null, fields, rows, "OK", 1 );
}
public String toString()
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/CallableStatement.java b/src/interfaces/jdbc/org/postgresql/jdbc2/CallableStatement.java
deleted file mode 100644
index 51dd9b2c7f0..00000000000
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/CallableStatement.java
+++ /dev/null
@@ -1,604 +0,0 @@
-package org.postgresql.jdbc2;
-
-// IMPORTANT NOTE: This file implements the JDBC 2 version of the driver.
-// If you make any modifications to this file, you must make sure that the
-// changes are also made (if relevent) to the related JDBC 1 class in the
-// org.postgresql.jdbc1 package.
-
-import java.sql.*;
-import java.math.*;
-import org.postgresql.util.*;
-/*
- * CallableStatement is used to execute SQL stored procedures.
- *
- * <p>JDBC provides a stored procedure SQL escape that allows stored
- * procedures to be called in a standard way for all RDBMS's. 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 may be used for input, output or both.
- * Parameters are refered to sequentially, by number. The first parameter
- * is 1.
- *
- * {?= call <procedure-name>[<arg1>,<arg2>, ...]}
- * {call <procedure-name>[<arg1>,<arg2>, ...]}
- *
- *
- * <p>IN parameter values are set using the set methods inherited from
- * 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.
- *
- * <p>A Callable statement may return a ResultSet or multiple ResultSets.
- * Multiple ResultSets are handled using operations inherited from
- * Statement.
- *
- * <p>For maximum portability, a call's ResultSets and update counts should
- * be processed prior to getting the values of output parameters.
- *
- * @see Connection#prepareCall
- * @see ResultSet
- * @author Paul Bethe (implementer)
- */
-
-public class CallableStatement extends org.postgresql.jdbc2.Jdbc2PreparedStatement implements java.sql.CallableStatement
-{
- /*
- * @exception SQLException on failure
- */
- public CallableStatement(Jdbc2Connection c, String q) throws SQLException
- {
- super(c, q); // don't parse yet..
- }
-
-
- /**
- * allows this class to tweak the standard JDBC call !see Usage
- * -> and replace with the pgsql function syntax
- * ie. select <function ([params])> as RESULT;
- */
-
- protected void parseSqlStmt () throws SQLException {
- modifyJdbcCall ();
- super.parseSqlStmt ();
- }
- /**
- * 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 + ";";
- }
-
- // internals
- static final String JDBC_SYNTAX = "{[? =] call <some_function> ([? [,?]*]) }";
- static final String RESULT_COLUMN = "result";
- String originalSql = "";
- boolean isFunction;
- // functionReturnType contains the user supplied value to check
- // testReturn contains a modified version to make it easier to
- // check the getXXX methods..
- int functionReturnType;
- int testReturn;
- // returnTypeSet is true when a proper call to registerOutParameter has been made
- boolean returnTypeSet;
- Object result;
-
- /*
- * 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;
- }
-
- /**
- * allow calls to execute update
- * @return 1 if succesful call otherwise 0
- */
- public int executeUpdate() throws SQLException
- {
- java.sql.ResultSet rs = super.executeQuery (compileQuery());
- if (isFunction) {
- if (!rs.next ())
- throw new PSQLException ("postgresql.call.noreturnval");
- result = rs.getObject(1);
- int columnType = rs.getMetaData().getColumnType(1);
- if (columnType != functionReturnType)
- throw new PSQLException ("postgresql.call.wrongrtntype",
- new Object[]{
- getSqlTypeName (columnType), getSqlTypeName (functionReturnType) });
- }
- rs.close ();
- return 1;
- }
-
-
- /**
- * allow calls to execute update
- * @return true if succesful
- */
- public boolean execute() throws SQLException
- {
- return (executeUpdate() == 1);
- }
-
- /*
- * 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..
- }
-
- /*
- * override this method to check for set @ 1 when declared function..
- *
- * @param paramIndex the index into the inString
- * @param s a string to be stored
- * @exception SQLException if something goes wrong
- */
- protected void set(int paramIndex, String s) throws SQLException
- {
- if (paramIndex == 1 && isFunction) // need to registerOut instead
- throw new PSQLException ("postgresql.call.funcover");
- super.set (paramIndex, s); // else set as usual..
- }
-
- /*
- * Helper - this compiles the SQL query from the various parameters
- * This is identical to toString() except it throws an exception if a
- * parameter is unused.
- */
- protected synchronized String compileQuery()
- throws SQLException
- {
- 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..
- }
- return super.compileQuery ();
- }
-
- /*
- * 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 (result == 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)result;
- }
- //public String getVarChar(int parameterIndex) throws SQLException {
- // return null;
- //}
-
- //public String getLongVarChar(int parameterIndex) throws SQLException {
- //return null;
- //}
-
- /*
- * 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 (result == null) return false;
- return ((Boolean)result).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 (result == null) return 0;
- return (byte)((Integer)result).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 (result == null) return 0;
- return (short)((Integer)result).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 (result == null) return 0;
- return ((Integer)result).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 (result == null) return 0;
- return ((Long)result).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 (result == null) return 0;
- return ((Float)result).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 (result == null) return 0;
- return ((Double)result).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)result);
- }
-
- /*
- * 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 [])result);
- }
-
- // New API (JPM) (getLongVarBinary)
- //public byte[] getBinaryStream(int parameterIndex) throws SQLException {
- //return null;
- //}
-
- /*
- * 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)result;
- }
-
- /*
- * 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)result;
- }
-
- /*
- * 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)result;
- }
-
- //----------------------------------------------------------------------
- // Advanced features:
-
- // You can obtain a ParameterMetaData object to get information
- // about the parameters to this CallableStatement.
- //public DatabaseMetaData getMetaData() {
- //return null;
- //}
-
- // 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 result;
- }
-
- // ** JDBC 2 Extensions **
-
- public java.sql.Array getArray(int i) throws SQLException
- {
- throw org.postgresql.Driver.notImplemented();
- }
-
- public java.math.BigDecimal getBigDecimal(int parameterIndex) throws SQLException
- {
- checkIndex (parameterIndex, Types.NUMERIC, "BigDecimal");
- return ((BigDecimal)result);
- }
-
- public Blob getBlob(int i) throws SQLException
- {
- throw org.postgresql.Driver.notImplemented();
- }
-
- public Clob getClob(int i) throws SQLException
- {
- throw org.postgresql.Driver.notImplemented();
- }
-
- public Object getObject(int i, java.util.Map map) throws SQLException
- {
- throw org.postgresql.Driver.notImplemented();
- }
-
- public Ref getRef(int i) throws SQLException
- {
- throw org.postgresql.Driver.notImplemented();
- }
-
- public java.sql.Date getDate(int i, java.util.Calendar cal) throws SQLException
- {
- throw org.postgresql.Driver.notImplemented();
- }
-
- public Time getTime(int i, java.util.Calendar cal) throws SQLException
- {
- throw org.postgresql.Driver.notImplemented();
- }
-
- public Timestamp getTimestamp(int i, java.util.Calendar cal) throws SQLException
- {
- throw org.postgresql.Driver.notImplemented();
- }
-
- // no custom types allowed yet..
- public void registerOutParameter(int parameterIndex, int sqlType, String typeName) throws SQLException
- {
- throw org.postgresql.Driver.notImplemented();
- }
-
-
-
- /** helperfunction for the getXXX calls to check isFunction and index == 1
- */
- private void checkIndex (int parameterIndex, int type, String getName)
- throws SQLException {
- checkIndex (parameterIndex);
- if (type != this.testReturn)
- throw new PSQLException("postgresql.call.wrongget",
- new Object[]{getSqlTypeName (testReturn),
- getName,
- getSqlTypeName (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");
- }
-
- /** helper function for creating msg with type names
- * @param sqlType a java.sql.Types.XX constant
- * @return String which is the name of the constant..
- */
- private static String getSqlTypeName (int sqlType) {
- switch (sqlType)
- {
- case Types.BIT:
- return "BIT";
- case Types.SMALLINT:
- return "SMALLINT";
- case Types.INTEGER:
- return "INTEGER";
- case Types.BIGINT:
- return "BIGINT";
- case Types.NUMERIC:
- return "NUMERIC";
- case Types.REAL:
- return "REAL";
- case Types.DOUBLE:
- return "DOUBLE";
- case Types.FLOAT:
- return "FLOAT";
- case Types.CHAR:
- return "CHAR";
- case Types.VARCHAR:
- return "VARCHAR";
- case Types.DATE:
- return "DATE";
- case Types.TIME:
- return "TIME";
- case Types.TIMESTAMP:
- return "TIMESTAMP";
- case Types.BINARY:
- return "BINARY";
- case Types.VARBINARY:
- return "VARBINARY";
- default:
- return "UNKNOWN";
- }
- }
-}
-
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/DatabaseMetaData.java b/src/interfaces/jdbc/org/postgresql/jdbc2/DatabaseMetaData.java
index 77415d051d4..a1c8e22737b 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/DatabaseMetaData.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/DatabaseMetaData.java
@@ -15,7 +15,7 @@ import org.postgresql.util.PSQLException;
/*
* This class provides information about the database as a whole.
*
- * $Id: DatabaseMetaData.java,v 1.59 2002/07/23 03:59:55 barry Exp $
+ * $Id: DatabaseMetaData.java,v 1.60 2002/07/25 22:45:28 barry Exp $
*
* <p>Many of the methods here return lists of information in ResultSets. You
* can use the normal ResultSet methods such as getString and getInt to
@@ -1653,7 +1653,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
v.addElement(tuple);
}
- return new Jdbc2ResultSet(connection, f, v, "OK", 1);
+ return connection.getResultSet(null, f, v, "OK", 1);
}
/*
@@ -1731,7 +1731,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
// add query loop here
- return new Jdbc2ResultSet(connection, f, v, "OK", 1);
+ return connection.getResultSet(null, f, v, "OK", 1);
}
/*
@@ -1866,7 +1866,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
v.addElement(tuple);
}
r.close();
- return new Jdbc2ResultSet(connection, f, v, "OK", 1);
+ return connection.getResultSet(null, f, v, "OK", 1);
}
// This array contains the valid values for the types argument
@@ -1913,7 +1913,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
f[0] = new Field(connection, "TABLE_SCHEM", iVarcharOid, 32);
tuple[0] = "".getBytes();
v.addElement(tuple);
- return new Jdbc2ResultSet(connection, f, v, "OK", 1);
+ return connection.getResultSet(null, f, v, "OK", 1);
}
/*
@@ -1958,7 +1958,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
tuple[0] = getTableTypes[i][0].getBytes();
v.addElement(tuple);
}
- return new Jdbc2ResultSet(connection, f, v, "OK", 1);
+ return connection.getResultSet(null, f, v, "OK", 1);
}
/*
@@ -2154,7 +2154,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
}
r.close();
- return new Jdbc2ResultSet(connection, f, v, "OK", 1);
+ return connection.getResultSet(null, f, v, "OK", 1);
}
/*
@@ -2218,7 +2218,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
//v.addElement(tuple);
}
- return new Jdbc2ResultSet(connection, f, v, "OK", 1);
+ return connection.getResultSet(null, f, v, "OK", 1);
}
/*
@@ -2281,7 +2281,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
//v.addElement(tuple);
}
- return new Jdbc2ResultSet(connection, f, v, "OK", 1);
+ return connection.getResultSet(null, f, v, "OK", 1);
}
/*
@@ -2337,7 +2337,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
f[6] = new Field(connection, "DECIMAL_DIGITS", iInt2Oid, 2);
f[7] = new Field(connection, "PSEUDO_COLUMN", iInt2Oid, 2);
- return new Jdbc2ResultSet(connection, f, v, "OK", 1);
+ return connection.getResultSet(null, f, v, "OK", 1);
}
/*
@@ -2680,7 +2680,7 @@ WHERE
tuples.addElement(tuple);
}
- return new Jdbc2ResultSet(connection, f, tuples, "OK", 1);
+ return connection.getResultSet(null, f, tuples, "OK", 1);
}
/*
@@ -2959,7 +2959,7 @@ WHERE
v.addElement(tuple);
}
rs.close();
- return new Jdbc2ResultSet(connection, f, v, "OK", 1);
+ return connection.getResultSet(null, f, v, "OK", 1);
}
throw new PSQLException("postgresql.metadata.unavailable");
@@ -3097,7 +3097,7 @@ WHERE
}
}
- return new Jdbc2ResultSet(connection, f, v, "OK", 1);
+ return connection.getResultSet(null, f, v, "OK", 1);
}
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2CallableStatement.java b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2CallableStatement.java
new file mode 100644
index 00000000000..c8bc1b79073
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2CallableStatement.java
@@ -0,0 +1,15 @@
+package org.postgresql.jdbc2;
+
+
+import java.sql.*;
+
+public class Jdbc2CallableStatement extends AbstractJdbc2Statement implements java.sql.CallableStatement
+{
+
+ public Jdbc2CallableStatement(Jdbc2Connection connection, String sql) throws SQLException
+ {
+ super(connection, sql);
+ }
+
+}
+
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Connection.java
index 787b14e62af..b512355260c 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Connection.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Connection.java
@@ -3,9 +3,10 @@ package org.postgresql.jdbc2;
import java.sql.*;
import java.util.Vector;
+import java.util.Hashtable;
import org.postgresql.Field;
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2Connection.java,v 1.2 2002/07/24 22:08:42 barry Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2Connection.java,v 1.3 2002/07/25 22:45:28 barry Exp $
* This class implements the java.sql.Connection interface for JDBC2.
* However most of the implementation is really done in
* org.postgresql.jdbc2.AbstractJdbc2Connection or one of it's parents
@@ -32,7 +33,7 @@ public class Jdbc2Connection extends org.postgresql.jdbc2.AbstractJdbc2Connectio
public java.sql.CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
{
- org.postgresql.jdbc2.CallableStatement s = new org.postgresql.jdbc2.CallableStatement(this,sql);
+ Jdbc2CallableStatement s = new org.postgresql.jdbc2.Jdbc2CallableStatement(this,sql);
s.setResultSetType(resultSetType);
s.setResultSetConcurrency(resultSetConcurrency);
return s;
@@ -45,15 +46,14 @@ public class Jdbc2Connection extends org.postgresql.jdbc2.AbstractJdbc2Connectio
return metadata;
}
- public java.sql.ResultSet getResultSet(java.sql.Statement stat, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException
+ public java.sql.ResultSet getResultSet(Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException
{
- if (stat != null)
- {
- if (stat.getResultSetConcurrency() == java.sql.ResultSet.CONCUR_UPDATABLE)
- return new org.postgresql.jdbc2.UpdateableResultSet(this, fields, tuples, status, updateCount, insertOID, binaryCursor);
- }
+ return new Jdbc2ResultSet(this, statement, fields, tuples, status, updateCount, insertOID, binaryCursor);
+ }
- return new Jdbc2ResultSet(this, fields, tuples, status, updateCount, insertOID, binaryCursor);
+ public java.sql.ResultSet getResultSet(Statement statement, Field[] fields, Vector tuples, String status, int updateCount) throws SQLException
+ {
+ return new Jdbc2ResultSet(this, statement, fields, tuples, status, updateCount, 0, false);
}
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2ResultSet.java
index 7200cf549ad..e2c6ad7eea2 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2ResultSet.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2ResultSet.java
@@ -5,7 +5,7 @@ import java.sql.*;
import java.util.Vector;
import org.postgresql.Field;
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2ResultSet.java,v 1.1 2002/07/23 03:59:55 barry Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2ResultSet.java,v 1.2 2002/07/25 22:45:28 barry Exp $
* This class implements the java.sql.ResultSet interface for JDBC2.
* However most of the implementation is really done in
* org.postgresql.jdbc2.AbstractJdbc2ResultSet or one of it's parents
@@ -13,14 +13,9 @@ import org.postgresql.Field;
public class Jdbc2ResultSet extends org.postgresql.jdbc2.AbstractJdbc2ResultSet implements java.sql.ResultSet
{
- public Jdbc2ResultSet(Jdbc2Connection conn, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor)
+ public Jdbc2ResultSet(Jdbc2Connection conn, Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor)
{
- super(conn, fields, tuples, status, updateCount, insertOID, binaryCursor);
- }
-
- public Jdbc2ResultSet(Jdbc2Connection conn, Field[] fields, Vector tuples, String status, int updateCount)
- {
- super(conn, fields, tuples, status, updateCount, 0, false);
+ super(conn, statement, fields, tuples, status, updateCount, insertOID, binaryCursor);
}
public java.sql.ResultSetMetaData getMetaData() throws SQLException
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/UpdateableResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc2/UpdateableResultSet.java
deleted file mode 100644
index 6f6f67d8394..00000000000
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/UpdateableResultSet.java
+++ /dev/null
@@ -1,1389 +0,0 @@
-package org.postgresql.jdbc2;
-
-// IMPORTANT NOTE: This is the begining of supporting updateable ResultSets.
-//
-// This is because here we should be updateable, so any unimplemented methods
-// must say so.
-//
-// Also you'll notice that the String columnName based calls are not present.
-// They are not required as they are in the super class.
-//
-
-import java.lang.*;
-import java.io.*;
-import java.math.*;
-import java.text.*;
-import java.util.*;
-import java.sql.*;
-import org.postgresql.Field;
-import org.postgresql.largeobject.*;
-import org.postgresql.util.*;
-import org.postgresql.Driver;
-
-/*
- * @see ResultSet
- * @see ResultSetMetaData
- * @see java.sql.ResultSet
- */
-public class UpdateableResultSet extends org.postgresql.jdbc2.Jdbc2ResultSet
-{
-
-
- class PrimaryKey
- {
- int index; // where in the result set is this primaryKey
- String name; // what is the columnName of this primary Key
-
- PrimaryKey( int index, String name)
- {
- this.index = index;
- this.name = name;
- }
- Object getValue() throws SQLException
- {
- return getObject(index);
- }
- };
-
- private boolean usingOID = false; // are we using the OID for the primary key?
-
- private Vector primaryKeys; // list of primary keys
-
- private int numKeys = 0;
-
- private boolean singleTable = false;
-
- protected String tableName = null;
-
- /**
- * PreparedStatement used to delete data
- */
-
- protected java.sql.PreparedStatement updateStatement = null;
-
- /**
- * PreparedStatement used to insert data
- */
-
- protected java.sql.PreparedStatement insertStatement = null;
-
- /**
- * PreparedStatement used to delete data
- */
-
- protected java.sql.PreparedStatement deleteStatement = null;
-
-
- /**
- * PreparedStatement used to refresh data
- */
- private java.sql.PreparedStatement selectStatement = null;
-
-
- /**
- * Is this result set updateable?
- */
-
- protected boolean updateable = false;
-
- /**
- * Are we in the middle of doing updates to the current row?
- */
-
- protected boolean doingUpdates = false;
-
-
- /**
- * Are we on the insert row?
- */
-
- protected boolean onInsertRow = false;
-
-
- protected Hashtable updateValues = new Hashtable();
-
- // The Row Buffer will be used to cache updated rows..then we shall sync this with the rows vector
-
-
- /*
- * Create a new ResultSet - Note that we create ResultSets to
- * represent the results of everything.
- *
- * @param fields an array of Field objects (basically, the
- * ResultSet MetaData)
- * @param tuples Vector of the actual data
- * @param status the status string returned from the back end
- * @param updateCount the number of rows affected by the operation
- * @param cursor the positioned update/delete cursor name
- */
- public UpdateableResultSet(Jdbc2Connection conn, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor)
- {
- super(conn, fields, tuples, status, updateCount, insertOID, binaryCursor);
- }
-
- /**
- *
- * @throws SQLException
- */
- public synchronized void cancelRowUpdates() throws SQLException
- {
- if (doingUpdates)
- {
- doingUpdates = false;
-
- clearRowBuffer();
- }
- }
-
- /**
- *
- * @throws SQLException
- */
- public synchronized void deleteRow() throws SQLException
- {
- if ( !isUpdateable() )
- {
- throw new PSQLException( "postgresql.updateable.notupdateable" );
- }
-
- if (onInsertRow)
- {
- throw new PSQLException( "postgresql.updateable.oninsertrow" );
- }
-
- if (rows.size() == 0)
- {
- throw new PSQLException( "postgresql.updateable.emptydelete" );
- }
- if (isBeforeFirst())
- {
- throw new PSQLException( "postgresql.updateable.beforestartdelete" );
- }
- if (isAfterLast())
- {
- throw new PSQLException( "postgresql.updateable.afterlastdelete" );
- }
-
-
- int numKeys = primaryKeys.size();
- if ( deleteStatement == null )
- {
-
-
- StringBuffer deleteSQL= new StringBuffer("DELETE FROM " ).append(tableName).append(" where " );
-
- for ( int i=0; i < numKeys ; i++ )
- {
- deleteSQL.append( ((PrimaryKey)primaryKeys.get(i)).name ).append( " = ? " );
- if ( i < numKeys-1 )
- {
- deleteSQL.append( " and " );
- }
- }
-
- deleteStatement = ((java.sql.Connection)connection).prepareStatement(deleteSQL.toString());
- }
- deleteStatement.clearParameters();
-
- for ( int i =0; i < numKeys; i++ )
- {
- deleteStatement.setObject(i+1, ((PrimaryKey)primaryKeys.get(i)).getValue());
- }
-
-
- deleteStatement.executeUpdate();
-
- rows.removeElementAt(current_row);
- }
-
-
- /**
- *
- * @return
- * @throws SQLException
- */
- public int getConcurrency() throws SQLException
- {
- // New in 7.1 - The updateable ResultSet class will now return
- // CONCURuPDATEABLE.
- return CONCUR_UPDATABLE;
- }
-
- /**
- *
- * @throws SQLException
- */
-
- public synchronized void insertRow() throws SQLException
- {
- if ( !isUpdateable() )
- {
- throw new PSQLException( "postgresql.updateable.notupdateable" );
- }
-
- if (!onInsertRow)
- {
- throw new PSQLException( "postgresql.updateable.notoninsertrow" );
- }
- else
- {
-
- // loop through the keys in the insertTable and create the sql statement
- // we have to create the sql every time since the user could insert different
- // columns each time
-
- StringBuffer insertSQL=new StringBuffer("INSERT INTO ").append(tableName).append(" (");
- StringBuffer paramSQL = new StringBuffer(") values (" );
-
- Enumeration columnNames = updateValues.keys();
- int numColumns = updateValues.size();
-
- for ( int i=0; columnNames.hasMoreElements() ; i++ )
- {
- String columnName = (String)columnNames.nextElement();
-
- insertSQL.append( columnName );
- if ( i < numColumns - 1 )
- {
- insertSQL.append(", ");
- paramSQL.append("?,");
- }
- else
- {
- paramSQL.append("?)");
- }
-
- }
-
- insertSQL.append(paramSQL.toString());
- insertStatement = ((java.sql.Connection)connection).prepareStatement(insertSQL.toString());
-
- Enumeration keys = updateValues.keys();
-
- for( int i=1; keys.hasMoreElements() ; i++)
- {
- String key = (String)keys.nextElement();
- insertStatement.setObject(i, updateValues.get( key ) );
- }
-
- insertStatement.executeUpdate();
-
- if ( usingOID )
- {
- // we have to get the last inserted OID and put it in the resultset
-
- long insertedOID = ((AbstractJdbc2Statement)insertStatement).getLastOID();
-
- updateValues.put("oid", new Long(insertedOID) );
-
- }
-
- // update the underlying row to the new inserted data
- updateRowBuffer();
-
- rows.addElement(rowBuffer);
-
- // we should now reflect the current data in this_row
- // that way getXXX will get the newly inserted data
- this_row = rowBuffer;
-
- // need to clear this in case of another insert
- clearRowBuffer();
-
-
- }
- }
-
-
- /**
- *
- * @throws SQLException
- */
-
- public synchronized void moveToCurrentRow() throws SQLException
- {
- this_row = (byte [][])rows.elementAt(current_row);
-
- rowBuffer=new byte[this_row.length][];
- System.arraycopy(this_row,0,rowBuffer,0,this_row.length);
-
- onInsertRow = false;
- doingUpdates = false;
- }
-
- /**
- *
- * @throws SQLException
- */
- public synchronized void moveToInsertRow() throws SQLException
- {
- // only sub-classes implement CONCURuPDATEABLE
- if (!updateable)
- {
- throw new PSQLException( "postgresql.updateable.notupdateable" );
- }
-
- if (insertStatement != null)
- {
- insertStatement = null;
- }
-
-
- // make sure the underlying data is null
- clearRowBuffer();
-
- onInsertRow = true;
- doingUpdates = false;
-
- }
-
- /**
- *
- * @throws SQLException
- */
- private synchronized void clearRowBuffer() throws SQLException
- {
- // rowBuffer is the temporary storage for the row
- rowBuffer=new byte[fields.length][];
-
- // clear the updateValues hashTable for the next set of updates
- updateValues.clear();
-
- }
-
-
- /**
- *
- * @return
- * @throws SQLException
- */
- public boolean rowDeleted() throws SQLException
- {
- // only sub-classes implement CONCURuPDATEABLE
- throw Driver.notImplemented();
- }
-
- /**
- *
- * @return
- * @throws SQLException
- */
- public boolean rowInserted() throws SQLException
- {
- // only sub-classes implement CONCURuPDATEABLE
- throw Driver.notImplemented();
- }
-
- /**
- *
- * @return
- * @throws SQLException
- */
- public boolean rowUpdated() throws SQLException
- {
- // only sub-classes implement CONCURuPDATEABLE
- throw Driver.notImplemented();
- }
-
- /**
- *
- * @param columnIndex
- * @param x
- * @param length
- * @throws SQLException
- */
- public synchronized void updateAsciiStream(int columnIndex,
- java.io.InputStream x,
- int length
- ) throws SQLException
- {
-
- byte[] theData=null;
-
- try
- {
- x.read(theData,0,length);
- }
- catch (NullPointerException ex )
- {
- throw new PSQLException("postgresql.updateable.inputstream");
- }
- catch (IOException ie)
- {
- throw new PSQLException("postgresql.updateable.ioerror" + ie);
- }
-
- doingUpdates = !onInsertRow;
-
- updateValues.put( fields[columnIndex-1].getName(), theData );
-
- }
-
- /**
- *
- * @param columnIndex
- * @param x
- * @throws SQLException
- */
- public synchronized void updateBigDecimal(int columnIndex,
- java.math.BigDecimal x )
- throws SQLException
- {
-
- doingUpdates = !onInsertRow;
- updateValues.put( fields[columnIndex-1].getName(), x );
-
- }
-
- /**
- *
- * @param columnIndex
- * @param x
- * @param length
- * @throws SQLException
- */
- public synchronized void updateBinaryStream(int columnIndex,
- java.io.InputStream x,
- int length
- ) throws SQLException
- {
-
-
- byte[] theData=null;
-
- try {
- x.read(theData,0,length);
-
- }
- catch( NullPointerException ex )
- {
- throw new PSQLException("postgresql.updateable.inputstream");
- }
- catch (IOException ie)
- {
- throw new PSQLException("postgresql.updateable.ioerror" + ie);
- }
-
- doingUpdates = !onInsertRow;
-
- updateValues.put( fields[columnIndex-1].getName(), theData );
-
- }
-
- /**
- *
- * @param columnIndex
- * @param x
- * @throws SQLException
- */
- public synchronized void updateBoolean(int columnIndex, boolean x) throws SQLException
- {
-
- if ( Driver.logDebug ) Driver.debug("updating boolean "+fields[columnIndex-1].getName()+"="+x);
-
- doingUpdates = !onInsertRow;
- updateValues.put( fields[columnIndex-1].getName(), new Boolean(x) );
-
- }
-
- /**
- *
- * @param columnIndex
- * @param x
- * @throws SQLException
- */
- public synchronized void updateByte(int columnIndex, byte x) throws SQLException
- {
-
- doingUpdates = true;
- updateValues.put( fields[columnIndex-1].getName(), String.valueOf(x) );
- }
-
- /**
- *
- * @param columnIndex
- * @param x
- * @throws SQLException
- */
- public synchronized void updateBytes(int columnIndex, byte[] x) throws SQLException
- {
-
- doingUpdates = !onInsertRow;
- updateValues.put( fields[columnIndex-1].getName(), x );
-
- }
-
- /**
- *
- * @param columnIndex
- * @param x
- * @param length
- * @throws SQLException
- */
- public synchronized void updateCharacterStream(int columnIndex,
- java.io.Reader x,
- int length
- ) throws SQLException
- {
-
-
- char[] theData=null;
-
- try
- {
- x.read(theData,0,length);
-
- }
- catch (NullPointerException ex)
- {
- throw new PSQLException("postgresql.updateable.inputstream");
- }
- catch (IOException ie)
- {
- throw new PSQLException("postgresql.updateable.ioerror" + ie);
- }
-
- doingUpdates = !onInsertRow;
- updateValues.put( fields[columnIndex-1].getName(), theData);
-
- }
-
- public synchronized void updateDate(int columnIndex, java.sql.Date x) throws SQLException
- {
-
- doingUpdates = !onInsertRow;
- updateValues.put( fields[columnIndex-1].getName(), x );
- }
-
- public synchronized void updateDouble(int columnIndex, double x) throws SQLException
- {
- if ( Driver.logDebug ) Driver.debug("updating double "+fields[columnIndex-1].getName()+"="+x);
-
- doingUpdates = !onInsertRow;
- updateValues.put( fields[columnIndex-1].getName(), new Double(x) );
-
- }
-
- public synchronized void updateFloat(int columnIndex, float x) throws SQLException
- {
- if ( Driver.logDebug ) Driver.debug("updating float "+fields[columnIndex-1].getName()+"="+x);
-
- doingUpdates = !onInsertRow;
-
- updateValues.put( fields[columnIndex-1].getName(), new Float(x) );
-
- }
-
- public synchronized void updateInt(int columnIndex, int x) throws SQLException
- {
- if ( Driver.logDebug ) Driver.debug("updating int "+fields[columnIndex-1].getName()+"="+x);
-
- doingUpdates = !onInsertRow;
- updateValues.put( fields[columnIndex-1].getName(), new Integer(x) );
-
- }
-
- public synchronized void updateLong(int columnIndex, long x) throws SQLException
- {
- if ( Driver.logDebug ) Driver.debug("updating long "+fields[columnIndex-1].getName()+"="+x);
-
- doingUpdates = !onInsertRow;
- updateValues.put( fields[columnIndex-1].getName(), new Long(x) );
-
- }
-
- public synchronized void updateNull(int columnIndex) throws SQLException
- {
-
- doingUpdates = !onInsertRow;
- updateValues.put( fields[columnIndex-1].getName(), null);
-
-
- }
-
- public synchronized void updateObject(int columnIndex, Object x) throws SQLException
- {
-
-
- if ( Driver.logDebug ) Driver.debug("updating object " + fields[columnIndex-1].getName() + " = " + x);
-
- doingUpdates = !onInsertRow;
- updateValues.put( fields[columnIndex-1].getName(), x );
- }
-
- public synchronized void updateObject(int columnIndex, Object x, int scale) throws SQLException
- {
-
- this.updateObject(columnIndex, x);
-
- }
-
-
- public void refreshRow() throws SQLException
- {
- if ( !isUpdateable() )
- {
- throw new PSQLException( "postgresql.updateable.notupdateable" );
- }
-
- try
- {
- StringBuffer selectSQL = new StringBuffer( "select ");
-
- final int numColumns = java.lang.reflect.Array.getLength(fields);
-
- for (int i=0; i < numColumns ; i++ )
- {
-
- selectSQL.append( fields[i].getName() );
-
- if ( i < numColumns - 1 )
- {
-
- selectSQL.append(", ");
- }
-
- }
- selectSQL.append(" from " ).append(tableName).append(" where ");
-
- int numKeys = primaryKeys.size();
-
- for ( int i = 0; i < numKeys; i++ )
- {
-
- PrimaryKey primaryKey = ((PrimaryKey)primaryKeys.get(i));
- selectSQL.append(primaryKey.name).append("= ?");
-
- if ( i < numKeys -1 )
- {
- selectSQL.append(" and ");
- }
- }
- if ( Driver.logDebug ) Driver.debug("selecting "+ selectSQL.toString());
- selectStatement = ((java.sql.Connection)connection).prepareStatement(selectSQL.toString());
-
-
- for( int j=0, i=1; j < numKeys; j++, i++)
- {
- selectStatement.setObject( i, ((PrimaryKey)primaryKeys.get(j)).getValue() );
- }
-
- Jdbc2ResultSet rs = (Jdbc2ResultSet) selectStatement.executeQuery();
-
- if( rs.first() )
- {
- rowBuffer = rs.rowBuffer;
- }
-
- rows.setElementAt( rowBuffer, current_row );
- if ( Driver.logDebug ) Driver.debug("done updates");
-
- rs.close();
- selectStatement.close();
- selectStatement = null;
-
- }
- catch (Exception e)
- {
- if ( Driver.logDebug ) Driver.debug(e.getClass().getName()+e);
- throw new SQLException( e.getMessage() );
- }
-
- }
- /**
- *
- * @throws SQLException
- */
- public synchronized void updateRow() throws SQLException
- {
- if ( !isUpdateable() )
- {
- throw new PSQLException( "postgresql.updateable.notupdateable" );
- }
-
- if (doingUpdates)
- {
-
- try
- {
-
- StringBuffer updateSQL=new StringBuffer("UPDATE "+tableName+" SET ");
-
- int numColumns = updateValues.size();
- Enumeration columns = updateValues.keys();
-
- for (int i=0; columns.hasMoreElements() ; i++ )
- {
-
- String column = (String)columns.nextElement();
- updateSQL.append( column + "= ?");
-
- if ( i < numColumns - 1 )
- {
-
- updateSQL.append(", ");
- }
-
- }
- updateSQL.append( " WHERE " );
-
- int numKeys = primaryKeys.size();
-
- for ( int i = 0; i < numKeys; i++ )
- {
-
- PrimaryKey primaryKey = ((PrimaryKey)primaryKeys.get(i));
- updateSQL.append(primaryKey.name).append("= ?");
-
- if ( i < numKeys -1 )
- {
- updateSQL.append(" and ");
- }
- }
- if ( Driver.logDebug ) Driver.debug("updating "+updateSQL.toString());
- updateStatement = ((java.sql.Connection)connection).prepareStatement(updateSQL.toString());
-
- int i = 0;
- Iterator iterator = updateValues.values().iterator();
- for (; iterator.hasNext(); i++)
- {
- updateStatement.setObject( i+1, iterator.next() );
-
- }
- for( int j=0; j < numKeys; j++, i++)
- {
- updateStatement.setObject( i+1, ((PrimaryKey)primaryKeys.get(j)).getValue() );
- }
-
- updateStatement.executeUpdate();
- updateStatement.close();
-
- updateStatement = null;
- updateRowBuffer();
-
-
- if ( Driver.logDebug ) Driver.debug("copying data");
- System.arraycopy(rowBuffer,0,this_row,0,rowBuffer.length);
-
- rows.setElementAt( rowBuffer, current_row );
- if ( Driver.logDebug ) Driver.debug("done updates");
-
- doingUpdates = false;
- }
- catch(Exception e)
- {
- if ( Driver.logDebug ) Driver.debug(e.getClass().getName()+e);
- throw new SQLException( e.getMessage() );
- }
-
- }
-
- }
-
- public synchronized void updateShort(int columnIndex, short x) throws SQLException
- {
- if ( Driver.logDebug ) Driver.debug("in update Short "+fields[columnIndex-1].getName()+" = "+x);
-
-
- doingUpdates = !onInsertRow;
- updateValues.put( fields[columnIndex-1].getName(), new Short(x) );
-
- }
-
- public synchronized void updateString(int columnIndex, String x) throws SQLException
- {
- if ( Driver.logDebug ) Driver.debug("in update String "+fields[columnIndex-1].getName()+" = "+x);
-
- doingUpdates = !onInsertRow;
- updateValues.put( fields[columnIndex-1].getName(), x );
-
- }
-
- public synchronized void updateTime(int columnIndex, Time x) throws SQLException
- {
- if ( Driver.logDebug ) Driver.debug("in update Time "+fields[columnIndex-1].getName()+" = "+x);
-
-
- doingUpdates = !onInsertRow;
- updateValues.put( fields[columnIndex-1].getName(), x );
-
- }
-
- public synchronized void updateTimestamp(int columnIndex, Timestamp x) throws SQLException
- {
- if ( Driver.logDebug ) Driver.debug("updating Timestamp "+fields[columnIndex-1].getName()+" = "+x);
-
- doingUpdates = !onInsertRow;
- updateValues.put( fields[columnIndex-1].getName(), x );
-
-
- }
-
- public synchronized void updateNull(String columnName) throws SQLException
- {
- updateNull(findColumn(columnName));
- }
-
- /**
- * JDBC 2.0
- *
- * Update a column with a boolean value.
- *
- * The updateXXX() methods are used to update column values in the
- * current row, or the insert row. The updateXXX() methods do not
- * update the underlying database, instead the updateRow() or insertRow()
- * methods are called to update the database.
- *
- * @param columnName the name of the column
- * @param x the new column value
- * @exception SQLException if a database-access error occurs
- */
-
- public synchronized void updateBoolean(String columnName, boolean x) throws SQLException
- {
- updateBoolean(findColumn(columnName), x);
- }
-
- /**
- * JDBC 2.0
- *
- * Update a column with a byte value.
- *
- * The updateXXX() methods are used to update column values in the
- * current row, or the insert row. The updateXXX() methods do not
- * update the underlying database, instead the updateRow() or insertRow()
- * methods are called to update the database.
- *
- * @param columnName the name of the column
- * @param x the new column value
- * @exception SQLException if a database-access error occurs
- */
-
- public synchronized void updateByte(String columnName, byte x) throws SQLException
- {
- updateByte(findColumn(columnName), x);
- }
-
- /**
- * JDBC 2.0
- *
- * Update a column with a short value.
- *
- * The updateXXX() methods are used to update column values in the
- * current row, or the insert row. The updateXXX() methods do not
- * update the underlying database, instead the updateRow() or insertRow()
- * methods are called to update the database.
- *
- * @param columnName the name of the column
- * @param x the new column value
- * @exception SQLException if a database-access error occurs
- */
-
- public synchronized void updateShort(String columnName, short x) throws SQLException
- {
- updateShort(findColumn(columnName), x);
- }
-
- /**
- * JDBC 2.0
- *
- * Update a column with an integer value.
- *
- * The updateXXX() methods are used to update column values in the
- * current row, or the insert row. The updateXXX() methods do not
- * update the underlying database, instead the updateRow() or insertRow()
- * methods are called to update the database.
- *
- * @param columnName the name of the column
- * @param x the new column value
- * @exception SQLException if a database-access error occurs
- */
-
- public synchronized void updateInt(String columnName, int x) throws SQLException
- {
- updateInt(findColumn(columnName), x);
- }
-
- /**
- * JDBC 2.0
- *
- * Update a column with a long value.
- *
- * The updateXXX() methods are used to update column values in the
- * current row, or the insert row. The updateXXX() methods do not
- * update the underlying database, instead the updateRow() or insertRow()
- * methods are called to update the database.
- *
- * @param columnName the name of the column
- * @param x the new column value
- * @exception SQLException if a database-access error occurs
- */
-
- public synchronized void updateLong(String columnName, long x) throws SQLException
- {
- updateLong(findColumn(columnName), x);
- }
-
- /**
- * JDBC 2.0
- *
- * Update a column with a float value.
- *
- * The updateXXX() methods are used to update column values in the
- * current row, or the insert row. The updateXXX() methods do not
- * update the underlying database, instead the updateRow() or insertRow()
- * methods are called to update the database.
- *
- * @param columnName the name of the column
- * @param x the new column value
- * @exception SQLException if a database-access error occurs
- */
-
- public synchronized void updateFloat(String columnName, float x) throws SQLException
- {
- updateFloat(findColumn(columnName), x);
- }
-
- /**
- * JDBC 2.0
- *
- * Update a column with a double value.
- *
- * The updateXXX() methods are used to update column values in the
- * current row, or the insert row. The updateXXX() methods do not
- * update the underlying database, instead the updateRow() or insertRow()
- * methods are called to update the database.
- *
- * @param columnName the name of the column
- * @param x the new column value
- * @exception SQLException if a database-access error occurs
- */
-
- public synchronized void updateDouble(String columnName, double x) throws SQLException
- {
- updateDouble(findColumn(columnName), x);
- }
-
- /**
- * JDBC 2.0
- *
- * Update a column with a BigDecimal value.
- *
- * The updateXXX() methods are used to update column values in the
- * current row, or the insert row. The updateXXX() methods do not
- * update the underlying database, instead the updateRow() or insertRow()
- * methods are called to update the database.
- *
- * @param columnName the name of the column
- * @param x the new column value
- * @exception SQLException if a database-access error occurs
- */
-
- public synchronized void updateBigDecimal(String columnName, BigDecimal x)
- throws SQLException
- {
- updateBigDecimal(findColumn(columnName), x);
- }
-
- /**
- * JDBC 2.0
- *
- * Update a column with a String value.
- *
- * The updateXXX() methods are used to update column values in the
- * current row, or the insert row. The updateXXX() methods do not
- * update the underlying database, instead the updateRow() or insertRow()
- * methods are called to update the database.
- *
- * @param columnName the name of the column
- * @param x the new column value
- * @exception SQLException if a database-access error occurs
- */
-
- public synchronized void updateString(String columnName, String x) throws SQLException
- {
- updateString(findColumn(columnName), x);
- }
-
- /**
- * JDBC 2.0
- *
- * Update a column with a byte array value.
- *
- * The updateXXX() methods are used to update column values in the
- * current row, or the insert row. The updateXXX() methods do not
- * update the underlying database, instead the updateRow() or insertRow()
- * methods are called to update the database.
- *
- * @param columnName the name of the column
- * @param x the new column value
- * @exception SQLException if a database-access error occurs
- */
-
- public synchronized void updateBytes(String columnName, byte x[]) throws SQLException
- {
- updateBytes(findColumn(columnName), x);
- }
-
- /**
- * JDBC 2.0
- *
- * Update a column with a Date value.
- *
- * The updateXXX() methods are used to update column values in the
- * current row, or the insert row. The updateXXX() methods do not
- * update the underlying database, instead the updateRow() or insertRow()
- * methods are called to update the database.
- *
- * @param columnName the name of the column
- * @param x the new column value
- * @exception SQLException if a database-access error occurs
- */
-
- public synchronized void updateDate(String columnName, java.sql.Date x)
- throws SQLException
- {
- updateDate(findColumn(columnName), x);
- }
-
- /**
- * JDBC 2.0
- *
- * Update a column with a Time value.
- *
- * The updateXXX() methods are used to update column values in the
- * current row, or the insert row. The updateXXX() methods do not
- * update the underlying database, instead the updateRow() or insertRow()
- * methods are called to update the database.
- *
- * @param columnName the name of the column
- * @param x the new column value
- * @exception SQLException if a database-access error occurs
- */
-
- public synchronized void updateTime(String columnName, java.sql.Time x)
- throws SQLException
- {
- updateTime(findColumn(columnName), x);
- }
-
- /**
- * JDBC 2.0
- *
- * Update a column with a Timestamp value.
- *
- * The updateXXX() methods are used to update column values in the
- * current row, or the insert row. The updateXXX() methods do not
- * update the underlying database, instead the updateRow() or insertRow()
- * methods are called to update the database.
- *
- * @param columnName the name of the column
- * @param x the new column value
- * @exception SQLException if a database-access error occurs
- */
-
- public synchronized void updateTimestamp(String columnName, java.sql.Timestamp x)
- throws SQLException
- {
- updateTimestamp(findColumn(columnName), x);
- }
-
- /**
- * JDBC 2.0
- *
- * Update a column with an ascii stream value.
- *
- * The updateXXX() methods are used to update column values in the
- * current row, or the insert row. The updateXXX() methods do not
- * update the underlying database, instead the updateRow() or insertRow()
- * methods are called to update the database.
- *
- * @param columnName the name of the column
- * @param x the new column value
- * @param length of the stream
- * @exception SQLException if a database-access error occurs
- */
-
- public synchronized void updateAsciiStream(
- String columnName,
- java.io.InputStream x,
- int length)
- throws SQLException
- {
- updateAsciiStream(findColumn(columnName), x, length);
- }
-
- /**
- * JDBC 2.0
- *
- * Update a column with a binary stream value.
- *
- * The updateXXX() methods are used to update column values in the
- * current row, or the insert row. The updateXXX() methods do not
- * update the underlying database, instead the updateRow() or insertRow()
- * methods are called to update the database.
- *
- * @param columnName the name of the column
- * @param x the new column value
- * @param length of the stream
- * @exception SQLException if a database-access error occurs
- */
-
- public synchronized void updateBinaryStream(
- String columnName,
- java.io.InputStream x,
- int length)
- throws SQLException
- {
- updateBinaryStream(findColumn(columnName), x, length);
- }
-
- /**
- * JDBC 2.0
- *
- * Update a column with a character stream value.
- *
- * The updateXXX() methods are used to update column values in the
- * current row, or the insert row. The updateXXX() methods do not
- * update the underlying database, instead the updateRow() or insertRow()
- * methods are called to update the database.
- *
- * @param columnName the name of the column
- * @param x the new column value
- * @param length of the stream
- * @exception SQLException if a database-access error occurs
- */
-
- public synchronized void updateCharacterStream(
- String columnName,
- java.io.Reader reader,
- int length)
- throws SQLException
- {
- updateCharacterStream(findColumn(columnName), reader,length);
- }
-
- /**
- * JDBC 2.0
- *
- * Update a column with an Object value.
- *
- * The updateXXX() methods are used to update column values in the
- * current row, or the insert row. The updateXXX() methods do not
- * update the underlying database, instead the updateRow() or insertRow()
- * methods are called to update the database.
- *
- * @param columnName the name of the column
- * @param x the new column value
- * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
- * this is the number of digits after the decimal. For all other
- * types this value will be ignored.
- * @exception SQLException if a database-access error occurs
- */
-
- public synchronized void updateObject(String columnName, Object x, int scale)
- throws SQLException
- {
- updateObject(findColumn(columnName), x);
- }
-
- /**
- * JDBC 2.0
- *
- * Update a column with an Object value.
- *
- * The updateXXX() methods are used to update column values in the
- * current row, or the insert row. The updateXXX() methods do not
- * update the underlying database, instead the updateRow() or insertRow()
- * methods are called to update the database.
- *
- * @param columnName the name of the column
- * @param x the new column value
- * @exception SQLException if a database-access error occurs
- */
-
- public synchronized void updateObject(String columnName, Object x) throws SQLException
- {
- updateObject(findColumn(columnName), x);
- }
-
-
-
- private int _findColumn( String columnName )
- {
- int i;
-
- final int flen = fields.length;
- for (i = 0 ; i < flen; ++i)
- {
- if (fields[i].getName().equalsIgnoreCase(columnName))
- {
- return (i + 1);
- }
- }
- return -1;
- }
-
-
- /**
- * Is this ResultSet updateable?
- */
-
- boolean isUpdateable() throws SQLException
- {
-
- if (updateable) return true;
-
- if ( Driver.logDebug ) Driver.debug("checking if rs is updateable");
-
- parseQuery();
-
- if ( singleTable == false )
- {
- if ( Driver.logDebug ) Driver.debug("not a single table");
- return false;
- }
-
- if ( Driver.logDebug ) Driver.debug("getting primary keys");
-
- //
- // Contains the primary key?
- //
-
- primaryKeys = new Vector();
-
- // this is not stricty jdbc spec, but it will make things much faster if used
- // the user has to select oid, * from table and then we will just use oid
-
-
- usingOID = false;
- int oidIndex = _findColumn( "oid" );
- int i = 0;
-
-
- // if we find the oid then just use it
-
- if ( oidIndex > 0 )
- {
- i++;
- primaryKeys.add( new PrimaryKey( oidIndex, "oid" ) );
- usingOID = true;
- }
- else
- {
- // otherwise go and get the primary keys and create a hashtable of keys
- java.sql.ResultSet rs = ((java.sql.Connection)connection).getMetaData().getPrimaryKeys("","",tableName);
-
-
- for( ; rs.next(); i++ )
- {
- String columnName = rs.getString(4); // get the columnName
-
- int index = findColumn( columnName );
-
- if ( index > 0 )
- {
- primaryKeys.add( new PrimaryKey(index, columnName ) ); // get the primary key information
- }
- }
-
- rs.close();
- }
-
- numKeys = primaryKeys.size();
-
- if ( Driver.logDebug ) Driver.debug( "no of keys=" + i );
-
- if ( i < 1 )
- {
- throw new SQLException("No Primary Keys");
- }
-
- updateable = primaryKeys.size() > 0;
-
- if ( Driver.logDebug ) Driver.debug( "checking primary key " + updateable );
-
- return updateable;
- }
-
-
- /**
- *
- */
- public void parseQuery()
- {
- StringTokenizer st=new StringTokenizer(sqlQuery," \r\t");
- boolean tableFound=false, tablesChecked = false;
- String name="";
-
- singleTable = true;
-
- while ( !tableFound && !tablesChecked && st.hasMoreTokens() )
- {
- name=st.nextToken();
- if ( !tableFound )
- {
- if (name.toLowerCase().equals("from"))
- {
- tableName=st.nextToken();
- tableFound=true;
- }
- }
- else
- {
- tablesChecked = true;
- // if the very next token is , then there are multiple tables
- singleTable = !name.equalsIgnoreCase(",");
- }
- }
- }
-
-
- private void updateRowBuffer() throws SQLException
- {
-
- Enumeration columns = updateValues.keys();
-
- while( columns.hasMoreElements() )
- {
- String columnName = (String)columns.nextElement();
- int columnIndex = _findColumn( columnName ) - 1;
-
- switch ( connection.getSQLType( fields[columnIndex].getPGType() ) )
- {
-
- case Types.DECIMAL:
- case Types.BIGINT:
- case Types.DOUBLE:
- case Types.BIT:
- case Types.VARCHAR:
- case Types.DATE:
- case Types.TIME:
- case Types.TIMESTAMP:
- case Types.SMALLINT:
- case Types.FLOAT:
- case Types.INTEGER:
- case Types.CHAR:
- case Types.NUMERIC:
- case Types.REAL:
- case Types.TINYINT:
-
- try
- {
- rowBuffer[columnIndex] = String.valueOf( updateValues.get( columnName ) ).getBytes(connection.getEncoding().name() );
- }
- catch ( UnsupportedEncodingException ex)
- {
- throw new SQLException("Unsupported Encoding "+connection.getEncoding().name());
- }
- case Types.NULL:
- continue;
- default:
- rowBuffer[columnIndex] = (byte [])updateValues.get( columnName );
- }
-
- }
- }
-
-}
-