? AbstractJdbc1Statement-backup.txt
? build
? build.properties
? jars
? pat-2002-12-30.patch
? pat-2003-01-02.diff
? org/postgresql/Driver.java
? org/postgresql/PGResultSet.java
Index: build.xml
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/build.xml,v
retrieving revision 1.31
diff -u -w -r1.31 build.xml
--- build.xml	2002/12/11 12:27:47	1.31
+++ build.xml	2003/01/02 15:14:48
@@ -25,6 +25,36 @@
 
   <property file="build.properties"/>
 
+  <target name="targets">
+    <echo>
+    -- Some help upon the targets possible
+
+    -- Normally used targets
+    all               -- default task, calls the jar task.
+    jar               -- builds the jars.
+    compile           -- compiles everything.
+    install           -- copies the jars to the ${install.directory}, if set.
+    uninstall         -- deletes the jars in the above mentioned directory.
+    clean             -- cleans up build/, lib/ and the Driver.java.
+    clean_all         -- mrproper-clean, deletes build.properties, too.
+
+    -- kind of internal targets
+    check_versions    -- checks jvm and JDBC versions installed.
+    check_driver      -- checks wether Driver.java needs to be rebuilt.
+    driver            -- builds Driver.java.
+    prepare           -- prepares build and lib directory.
+    examples          -- compiles examples in example/ directory.
+    corba             -- compiles examples in example/corba directory.
+
+    -- Testing: To test the driver yourself, create a database test
+    -- and a user test with password "password" first!
+    test              -- executes testjdbc2, testjdbc2optional and testjdbc3.
+    testjdbc2         -- executes the JDBC2 edition tests.
+    testjdbc2optional -- extended JDBC2 tests for the optional package.
+    testjdbc3         -- further testing of JDBC3 parts.
+    </echo>
+  </target>
+
   <!--
     This is a simpler method than utils.CheckVersion
     It defaults to jdbc1, but builds jdbc2 if the java.lang.Byte class is
@@ -104,6 +134,27 @@
   <!-- This is the core of the driver.  It is common for all three versions. -->
   <target name="compile" depends="prepare,check_versions,driver">
     <javac srcdir="${srcdir}" destdir="${builddir}" debug="${debug}">
+      <include name="${package}/*"/>
+      <include name="${package}/core/*"/>
+      <include name="${package}/fastpath/*"/>
+      <include name="${package}/geometric/*"/>
+      <include name="${package}/largeobject/*"/>
+      <include name="${package}/util/*"/>
+
+      <include name="${package}/jdbc1/*" if="jdbc1"/>
+      <include name="${package}/jdbc1/Abstract*" if="jdbc2"/>
+      <include name="${package}/jdbc1/Abstract*" if="jdbc3"/>
+
+      <include name="${package}/jdbc2/*" if="jdbc2"/>
+      <include name="${package}/jdbc2/Abstract*" if="jdbc3"/>
+      <include name="${package}/jdbc2/*Exception.java" if="jdbc3"/>
+
+      <include name="${package}/jdbc2/optional/*" if="datasource"/>
+
+      <include name="${package}/jdbc3/*" if="jdbc3"/>
+
+
+      <!--
       <include name="${package}/**" />
 
       <exclude name="${package}/jdbc1/**" unless="jdbc1"/>
@@ -112,6 +163,7 @@
 
       <exclude name="${package}/jdbc2/optional/**" unless="jdbc2" />
       <exclude name="${package}/jdbc2/optional/**" unless="datasource" />
+      -->
 
       <exclude name="${package}/test/**"/>
     </javac>
Index: org/postgresql/PGConnection.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/PGConnection.java,v
retrieving revision 1.3
diff -u -w -r1.3 PGConnection.java
--- org/postgresql/PGConnection.java	2002/09/06 21:23:05	1.3
+++ org/postgresql/PGConnection.java	2003/01/02 15:14:50
@@ -77,5 +77,15 @@
 	public PGNotification[] getNotifications();
 
 
+
+
+	// Added by Nic.
+
+	/** Create a result set for the specified statement.
+	 * This is the factory method provided by the various
+	 * version specific implementations of the JDBC connection
+	 * classes.
+	 */
+	public java.sql.ResultSet createResultSet (java.sql.Statement statement);
 }
 
Index: org/postgresql/core/QueryExecutor.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java,v
retrieving revision 1.17
diff -u -w -r1.17 QueryExecutor.java
--- org/postgresql/core/QueryExecutor.java	2002/11/14 05:35:45	1.17
+++ org/postgresql/core/QueryExecutor.java	2003/01/02 15:14:50
@@ -18,13 +18,57 @@
 
 public class QueryExecutor
 {
+	/** nic version - statically sets up the QE correctly.
+	 */
+	public static void execute (String[] p_sqlFrags,
+				    Object[] p_binds,
+				    java.sql.Statement statement,
+				    java.sql.ResultSet rs,
+				    PG_Stream pg_stream,
+				    java.sql.Connection con)
+	throws SQLException
+	{
+		QueryExecutor qe = new QueryExecutor();
+		// I think this should be a PGConnection and we should move
+		// everything we need for that from AbstractJdbc1... into PGConnection.
+		qe.connection = (org.postgresql.jdbc1.AbstractJdbc1Connection)con;
+		qe.m_sqlFrags = p_sqlFrags;
+		qe.m_binds = p_binds;
+		qe.statement = statement;
+		// Nic says: connection should wrap pg_stream.
+		qe.pg_stream = pg_stream;
+		if (statement != null)
+			qe.maxRows = statement.getMaxRows();
+		else
+			qe.maxRows = 0;
+		// The result set.
+		qe.rs = rs;
+		qe.execute();
+	}
+
+	// This is the result set used to wrap the results.
+	// The type of this is whatever is passed into the static above.
+	private java.sql.ResultSet rs;
 
-	private final String[] m_sqlFrags;
-	private final Object[] m_binds;
-	private final java.sql.Statement statement;
-	private final PG_Stream pg_stream;
-	private final org.postgresql.jdbc1.AbstractJdbc1Connection connection;
+	// cons for the static above.
+	private QueryExecutor ()
+	{
+	}
 
+
+
+
+	/*** pre-nic implementation   ***/
+
+
+	/// Nic has removed the final from ALL of these (to facilitate static method).
+	private String[] m_sqlFrags;
+	private Object[] m_binds;
+	private java.sql.Statement statement;
+	private PG_Stream pg_stream;
+	private org.postgresql.jdbc1.AbstractJdbc1Connection connection;
+
+
 	public QueryExecutor(String[] p_sqlFrags, Object[] p_binds,
 						 java.sql.Statement statement,
 						 PG_Stream pg_stream,
@@ -43,6 +87,7 @@
 			maxRows = 0;
 	}
 
+
 	private Field[] fields = null;
 	private Vector tuples = new Vector();
 	private boolean binaryCursor = false;
@@ -51,8 +96,10 @@
 	private long insert_oid = 0;
 	private int maxRows;
 
+
 	/*
 	 * Execute a query on the backend.
+	 *
 	 */
 	public java.sql.ResultSet execute() throws SQLException
 	{
@@ -129,8 +176,13 @@
 			// did we get an error during this query?
 			if ( errorMessage != null )
 				throw new SQLException( errorMessage.toString() );
+
 
-			return connection.getResultSet(statement, fields, tuples, status, update_count, insert_oid, binaryCursor);
+			// Nic changes.
+			PGResultSet resSet = ((PGResultSet)rs);
+			//  System.out.println(getClass().getName() + " resSet=" + resSet);
+			resSet.init(fields, tuples, status, update_count, insert_oid, binaryCursor);
+			return rs;
 		}
 	}
 
Index: org/postgresql/jdbc1/AbstractJdbc1Connection.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java,v
retrieving revision 1.13
diff -u -w -r1.13 AbstractJdbc1Connection.java
--- org/postgresql/jdbc1/AbstractJdbc1Connection.java	2002/11/14 05:35:45	1.13
+++ org/postgresql/jdbc1/AbstractJdbc1Connection.java	2003/01/02 15:14:51
@@ -84,7 +84,17 @@
 
 	public abstract java.sql.Statement createStatement() throws SQLException;
 
+   final Object[] nullarr = new Object[0];
 
+   // some defaults for statements
+   public int defaultFetchSize = 0;       // do not fetch by default. Use defaultFetchSize=xx in URL to change.
+   public boolean forceFetchSize = false;  // do not allow programmatic fetch size alteration. Use forceFetchSize in URL to change.
+   public boolean explicitCloseCursors = false; // explicitly close cursors on ResultSet close (needs another roundtrip).
+   // These two properties make a conjunction of the preparing policy:
+   // ALL means ..Always to true, never means ...Never to true.
+   // This is the fastest way to distinguish if or if not to prepare.
+   public boolean useServerPrepareAlways = false;
+   public boolean useServerPrepareNever = false;
 	/*
 	 * This method actually opens the connection. It is called by Driver.
 	 *
@@ -100,6 +110,7 @@
 	{
 		firstWarning = null;
 
+      //info.list(System.out);
 		// Throw an exception if the user or password properties are missing
 		// This occasionally occurs when the client uses the properties version
 		// of getConnection(), and is a common question on the email lists
@@ -350,9 +361,10 @@
 		// Set datestyle and fetch db encoding in a single call, to avoid making
 		// more than one round trip to the backend during connection startup.
 
-		java.sql.ResultSet resultSet =
-			ExecSQL("set datestyle to 'ISO'; select version(), " + encodingQuery + ";");
 
+      java.sql.ResultSet resultSet
+         = doQuery("set datestyle to 'ISO'; select version(), " + encodingQuery + ";");
+
 		if (! resultSet.next())
 		{
 			throw new PSQLException("postgresql.con.failed", "failed getting backend encoding");
@@ -373,7 +385,7 @@
 		if (haveMinimumServerVersion("7.3")) 
 		{
 			java.sql.ResultSet acRset =
-				ExecSQL("set client_encoding = 'UNICODE'; show autocommit");
+            doQuery("set client_encoding = 'UNICODE'; show autocommit");
 
 			//set encoding to be unicode
 			encoding = Encoding.getEncoding("UNICODE", null);
@@ -388,7 +400,7 @@
 			//to make the setting permanent
 			if (acRset.getString(1).equals("off"))
 			{
-				ExecSQL("set autocommit = on; commit;");
+            doQuery("set autocommit = on; commit;");
 			}
 		}
 
@@ -397,8 +409,39 @@
 
 		// Mark the connection as ok, and cleanup
 		PG_STATUS = CONNECTION_OK;
+
+      // Apply defaults. We have to do that at that rather late point to get
+      // information about version of backend etc.
+      // Set default Statement parameters
+      if (info.containsKey("defaultFetchSize"))
+      {
+         defaultFetchSize=new Integer(info.getProperty("defaultFetchSize")).intValue();
+      }
+      if (info.containsKey("forceFetchSize"))
+      {
+         forceFetchSize=new Boolean(info.getProperty("forceFetchSize")).booleanValue();
+      }
+      if (info.containsKey("explicitCloseCursors"))
+      {
+         explicitCloseCursors=new Boolean(info.getProperty("explicitCloseCursors")).booleanValue();
+      }
+      if (info.containsKey("useServerPrepare"))
+      {
+         if (haveMinimumServerVersion("7.3")) { // only >=7.3 can do this.
+            String s=info.getProperty("useServerPrepare").toLowerCase();
+            if (s.equals("always"))
+               useServerPrepareAlways=true;
+            else if (s.equals("never"))
+               useServerPrepareNever=true;
+         }
+         else // <7.3 servers aren't capable of preparing at all.
+         {
+            useServerPrepareNever=true;
+         }
 	}
 
+   }
+
 
 	/*
 	 * Return the instance of org.postgresql.Driver
@@ -409,13 +452,6 @@
 		return this_driver;
 	}
 
-	// These methods used to be in the main Connection implementation. As they
-	// are common to all implementations (JDBC1 or 2), they are placed here.
-	// This should make it easy to maintain the two specifications.
-
-	public abstract java.sql.ResultSet getResultSet(Statement statement, 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) throws SQLException;
 
 	/*
 	 * This adds a warning to the warning chain.
@@ -445,64 +481,51 @@
 		//}
 	}
 
-	/*
-	 * Send a query to the backend.  Returns one of the ResultSet
-	 * objects.
-	 *
-	 * <B>Note:</B> there does not seem to be any method currently
-	 * in existance to return the update count.
-	 *
-	 * @param sql the SQL statement to be executed
-	 * @return a ResultSet holding the results
-	 * @exception SQLException if a database error occurs
+   /** Simple query execution.
 	 */
-	public java.sql.ResultSet ExecSQL(String sql) throws SQLException
+   public java.sql.ResultSet doQuery (String s, java.sql.Statement stat, java.sql.ResultSet rs) throws SQLException
 	{
-		return ExecSQL(sql, null);
+      execSQL(new String[] { s }, nullarr, stat, rs);
+      return rs;
 	}
 
-	/*
-	 * Send a query to the backend.  Returns one of the ResultSet
-	 * objects.
-	 *
-	 * <B>Note:</B> there does not seem to be any method currently
-	 * in existance to return the update count.
-	 *
-	 * @param sql the SQL statement to be executed
-	 * @param stat The Statement associated with this query (may be null)
-	 * @return a ResultSet holding the results
-	 * @exception SQLException if a database error occurs
-	 */
-	public java.sql.ResultSet ExecSQL(String sql, java.sql.Statement stat) throws SQLException
-	{
-		if (isClosed())
+   public java.sql.ResultSet doQuery (String s, java.sql.Statement stat) throws SQLException
 		{
-			throw new PSQLException("postgresql.con.closed");
+      java.sql.ResultSet rs = createResultSet(stat);
+      return doQuery(s,stat,rs);
 		}
-		return new QueryExecutor(new String[] {sql}, EMPTY_OBJECT_ARRAY, stat, pg_stream, (java.sql.Connection)this).execute();
+
+   public java.sql.ResultSet doQuery (String s) throws SQLException
+   {
+      java.sql.Statement stat = createStatement();
+      java.sql.ResultSet rs = createResultSet(stat);
+      return doQuery(s,stat,rs);
 	}
-	private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
 
-	/*
-	 * Send a query to the backend.  Returns one of the ResultSet
-	 * objects.
-	 *
-	 * <B>Note:</B> there does not seem to be any method currently
-	 * in existance to return the update count.
+   /** Advanced query execution.
 	 *
 	 * @param p_sqlFragmentss the SQL statement parts to be executed
 	 * @param p_binds the SQL bind values
-	 * @param stat The Statement associated with this query (may be null)
-	 * @return a ResultSet holding the results
+    * @param stat the statement associated with this query.
+    * @param rs the ResultSet which will be initied for the results.
 	 * @exception SQLException if a database error occurs
 	 */
-	public java.sql.ResultSet ExecSQL(String[] p_sqlFragments, Object[] p_binds, java.sql.Statement stat) throws SQLException
+   public void execSQL(String[] p_sqlFragments,
+             Object[] p_binds,
+             java.sql.Statement stat,
+             java.sql.ResultSet rs)
+      throws SQLException
 	{
 		if (isClosed())
 		{
 			throw new PSQLException("postgresql.con.closed");
 		}
-		return new QueryExecutor(p_sqlFragments, p_binds, stat, pg_stream, (java.sql.Connection)this).execute();
+      QueryExecutor.execute(p_sqlFragments,
+                  p_binds,
+                  stat,
+                  rs,
+                  pg_stream,
+                  (java.sql.Connection)this);
 	}
 
 	/*
@@ -939,27 +962,27 @@
                 //We do the select to ensure a transaction is in process
 				//before we do the commit to avoid warning messages
 				//from issuing a commit without a transaction in process
-				ExecSQL("select 1; commit; set autocommit = on;");
+            doQuery("select 1; commit; set autocommit = on;");
 			}
 			else
 			{
-				ExecSQL("end");				
+            doQuery("end");
 			}
 		}
 		else
 		{
 			if (haveMinimumServerVersion("7.3"))
 			{
-				ExecSQL("set autocommit = off; " + getIsolationLevelSQL());
+            doQuery("set autocommit = off; " + getIsolationLevelSQL());
 			}
 			else if (haveMinimumServerVersion("7.1"))
 			{
-				ExecSQL("begin;" + getIsolationLevelSQL());
+            doQuery("begin;" + getIsolationLevelSQL());
 			}
 			else
 			{
-				ExecSQL("begin");
-				ExecSQL(getIsolationLevelSQL());
+            doQuery("begin");
+            doQuery(getIsolationLevelSQL());
 			}
 		}
 		this.autoCommit = autoCommit;
@@ -993,17 +1016,17 @@
 			return ;
 		if (haveMinimumServerVersion("7.3"))
 		{
-			ExecSQL("commit; " + getIsolationLevelSQL());
+         doQuery("commit; " + getIsolationLevelSQL());
 		}
 		else if (haveMinimumServerVersion("7.1"))
 		{
-			ExecSQL("commit;begin;" + getIsolationLevelSQL());
+         doQuery("commit;begin;" + getIsolationLevelSQL());
 		}
 		else
 		{
-			ExecSQL("commit");
-			ExecSQL("begin");
-			ExecSQL(getIsolationLevelSQL());
+         doQuery("commit");
+         doQuery("begin");
+         doQuery(getIsolationLevelSQL());
 		}
 	}
 
@@ -1024,17 +1047,17 @@
 			//we don't automatically start a transaction 
 			//but let the server functionality automatically start
 			//one when the first statement is executed
-			ExecSQL("rollback; " + getIsolationLevelSQL());
+         doQuery("rollback; " + getIsolationLevelSQL());
 		}
 		else if (haveMinimumServerVersion("7.1"))
 		{
-			ExecSQL("rollback; begin;" + getIsolationLevelSQL());
+         doQuery("rollback; begin;" + getIsolationLevelSQL());
 		}
 		else
 		{
-			ExecSQL("rollback");
-			ExecSQL("begin");
-			ExecSQL(getIsolationLevelSQL());
+         doQuery("rollback");
+         doQuery("begin");
+         doQuery(getIsolationLevelSQL());
 		}
 	}
 
@@ -1049,14 +1072,14 @@
 		String sql = "show transaction isolation level";
 		String level = null;
 		if (haveMinimumServerVersion("7.3")) {
-			ResultSet rs = ExecSQL(sql);
+         ResultSet rs = doQuery(sql);
 			if (rs.next()) {
 				level = rs.getString(1);
 			}
 			rs.close();
 		} else {
 			clearWarnings();
-			ExecSQL(sql);
+         doQuery(sql);
 			SQLWarning warning = getWarnings();
 			if (warning != null)
 			{
@@ -1121,7 +1144,7 @@
 											new Integer(isolationLevel));
 			}
 		}
-		ExecSQL(isolationLevelSQL);
+      doQuery(isolationLevelSQL);
 	}
 
 	/*
@@ -1264,7 +1287,7 @@
 				} else {
 					sql = "SELECT typname FROM pg_type WHERE oid = " +oid;
 				}
-				ResultSet result = ExecSQL(sql);
+            ResultSet result = doQuery(sql);
 				if (((AbstractJdbc1ResultSet)result).getColumnCount() != 1 || ((AbstractJdbc1ResultSet)result).getTupleCount() != 1) {
 					throw new PSQLException("postgresql.unexpected");
 				}
@@ -1305,7 +1328,7 @@
 				} else {
 					sql = "SELECT oid FROM pg_type WHERE typname='" + typeName + "'";
 				}
-				ResultSet result = ExecSQL(sql);
+            ResultSet result = doQuery(sql);
 				if (((AbstractJdbc1ResultSet)result).getColumnCount() != 1 || ((AbstractJdbc1ResultSet)result).getTupleCount() != 1)
 					throw new PSQLException("postgresql.unexpected");
 				result.next();
Index: org/postgresql/jdbc1/AbstractJdbc1DatabaseMetaData.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1DatabaseMetaData.java,v
retrieving revision 1.14
diff -u -w -r1.14 AbstractJdbc1DatabaseMetaData.java
--- org/postgresql/jdbc1/AbstractJdbc1DatabaseMetaData.java	2002/12/20 13:15:53	1.14
+++ org/postgresql/jdbc1/AbstractJdbc1DatabaseMetaData.java	2003/01/02 15:14:53
@@ -1915,7 +1915,9 @@
 		}
 		rs.close();
 
-		return connection.getResultSet(null, f, v, "OK", 1);
+		java.sql.ResultSet retRs = connection.createResultSet(connection.createStatement());
+		((AbstractJdbc1ResultSet)retRs).init(f, v, "OK", 1, 0, false);
+		return retRs;
 	}
 
 	/*
@@ -2206,7 +2208,10 @@
 			tuple[0] = types[i].getBytes();
 			v.addElement(tuple);
 		}
-		return connection.getResultSet(null, f, v, "OK", 1);
+
+		java.sql.ResultSet retRs = connection.createResultSet(connection.createStatement());
+		((AbstractJdbc1ResultSet)retRs).init(f, v, "OK", 1, 0, false);
+		return retRs;
 	}
 
 	/*
@@ -2380,7 +2385,9 @@
 		}
 		rs.close();
 
-		return connection.getResultSet(null, f, v, "OK", 1);
+		java.sql.ResultSet retRs = connection.createResultSet(connection.createStatement());
+		((AbstractJdbc1ResultSet)retRs).init(f, v, "OK", 1, 0, false);
+		return retRs;
 	}
 
 	/*
@@ -2492,7 +2499,10 @@
 			}
 		}
 		rs.close();
-		return connection.getResultSet(null, f, v, "OK", 1);
+
+		java.sql.ResultSet retRs = connection.createResultSet(connection.createStatement());
+		((AbstractJdbc1ResultSet)retRs).init(f, v, "OK", 1, 0, false);
+		return retRs;
 	}
 
 	/*
@@ -2594,7 +2604,9 @@
 		}
 		rs.close();
 
-		return connection.getResultSet(null, f, v, "OK", 1);
+		java.sql.ResultSet retRs = connection.createResultSet(connection.createStatement());
+		((AbstractJdbc1ResultSet)retRs).init(f, v, "OK", 1, 0, false);
+		return retRs;
 	}
 
 	private static void sortStringArray(String s[]) {
@@ -2787,7 +2799,10 @@
 			tuple[7] = Integer.toString(java.sql.DatabaseMetaData.bestRowNotPseudo).getBytes();
 			v.addElement(tuple);
 		}
-		return connection.getResultSet(null, f, v, "OK", 1);
+
+		java.sql.ResultSet retRs = connection.createResultSet(connection.createStatement());
+		((AbstractJdbc1ResultSet)retRs).init(f, v, "OK", 1, 0, false);
+		return retRs;
 	}
 
 	/*
@@ -2857,7 +2872,9 @@
 		/* Perhaps we should check that the given
 		 * catalog.schema.table actually exists. -KJ
 		 */
-		return connection.getResultSet(null, f, v, "OK", 1);
+		java.sql.ResultSet retRs = connection.createResultSet(connection.createStatement());
+		((AbstractJdbc1ResultSet)retRs).init(f, v, "OK", 1, 0, false);
+		return retRs;
 	}
 
 	/*
@@ -3209,7 +3226,9 @@
 			tuples.addElement(tuple);
 		}
 
-		return connection.getResultSet(null, f, tuples, "OK", 1);
+		java.sql.ResultSet retRs = connection.createResultSet(connection.createStatement());
+		((AbstractJdbc1ResultSet)retRs).init(f, tuples, "OK", 1, 0, false);
+		return retRs;
 	}
 
 	/*
@@ -3494,7 +3513,10 @@
 			v.addElement(tuple);
 		}
 		rs.close();
-		return connection.getResultSet(null, f, v, "OK", 1);
+
+		java.sql.ResultSet retRs = connection.createResultSet(connection.createStatement());
+		((AbstractJdbc1ResultSet)retRs).init(f, v, "OK", 1, 0, false);
+		return retRs;
 	}
 
 	/*
Index: org/postgresql/jdbc1/AbstractJdbc1ResultSet.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java,v
retrieving revision 1.7
diff -u -w -r1.7 AbstractJdbc1ResultSet.java
--- org/postgresql/jdbc1/AbstractJdbc1ResultSet.java	2002/10/19 22:10:36	1.7
+++ org/postgresql/jdbc1/AbstractJdbc1ResultSet.java	2003/01/02 15:14:53
@@ -18,7 +18,7 @@
  * 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
+public abstract class AbstractJdbc1ResultSet implements org.postgresql.PGResultSet
 {
 
 	protected Vector rows;			// The results
@@ -42,7 +42,13 @@
 	public byte[][] rowBuffer = null;
 
 
-	public AbstractJdbc1ResultSet(org.postgresql.PGConnection conn, Statement statement, 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;
@@ -50,25 +56,114 @@
 		this.rows = tuples;
 		this.status = status;
 		this.updateCount = updateCount;
+
+      System.out.println(getClass().getName() + " updateCount = " + updateCount);
+
+      this.insertOID = insertOID;
+      this.this_row = null;
+      this.current_row = -1;
+      this.binaryCursor = binaryCursor;
+   }
+
+
+   /*** nic constructor: called by superclass which is called from Jdbc1Connection.createResultSet ***/
+   public AbstractJdbc1ResultSet(org.postgresql.PGConnection conn,
+                  Statement statement)
+   {
+      this.connection = conn;
+      this.statement = statement;
+   }
+
+   /*** nic initializer. ***/
+   public void init (Field[] fields, Vector tuples, String status,
+           int updateCount, long insertOID, boolean binaryCursor)
+   {
+      this.fields = fields;
+
+      // on a reinit the size of this indicates how many we pulled
+      // back. If it's 0 then the res set has ended.
+      this.rows = tuples;
+      this.status = status;
+      this.updateCount = updateCount;
 		this.insertOID = insertOID;
 		this.this_row = null;
 		this.current_row = -1;
 		this.binaryCursor = binaryCursor;
 	}
 
+   public boolean isCursored()
+   {
+      return (((AbstractJdbc1Statement)statement).m_cursorName!=null);
+   }
+
+   public String getCursorName()
+   {
+      return (((AbstractJdbc1Statement)statement).m_cursorName);
+   }
+
+   public void closeCursor() throws SQLException
+   {
+      // do we really need this? It's another roundtrip to the database...
+      // if one thinks it needed, then here's the way to add it.
+      /*
+      if (isCursored())
+      {
+         ((AbstractJdbc1Connection)connection).doQuery(
+            new StringBuffer("CLOSE ").append(getCursorName()).toString());
+         ((AbstractJdbc1Statement)statement).m_cursorName=null;
+      }
+      */
+   }
+
+   public int getFetchSize()
+   {
+      return (((AbstractJdbc1Statement)statement).m_fetchSize);
+   }
+
 
+   // This slightly altered by nic.
 	public boolean next() throws SQLException
 	{
 		if (rows == null)
 			throw new PSQLException("postgresql.con.closed");
 
 		if (++current_row >= rows.size())
+      {
+         if (!isCursored())
+         {
+            return false; // we do not fetch by cursor, so this is the end...
+         }
+         // Smart optimization: If the rows.size() is smaller than the
+         // last fetch did end by not filling up completely -> we are at the end.
+         // So we do not need another roundtrip to the database.
+         if (rows.size()<getFetchSize())
+         {
+            return false;
+         }
+         // Use the ref to the statement to get
+         // the details we need to do another cursor
+         // query - it will use reinit() to repopulate this
+         // with the right data.
+         // We can safely throw the return value away, it reinits "this".
+         ((AbstractJdbc1Connection)connection).doQuery(
+            new StringBuffer("FETCH FORWARD ").append(getFetchSize())
+                  .append(" FROM ").append(getCursorName()).toString(),
+            statement, (java.sql.ResultSet)this);
+         if (rows.size() == 0)
+         {
+            // rows are still empty. So no data anymore...
 			return false;
+         }
+
+         // New data arrived. Reset the counter and let it go on...
+         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);
+      //rowBuffer = new byte[this_row.length][];
+      //System.arraycopy(this_row, 0, rowBuffer, 0, this_row.length);
+      rowBuffer=this_row;
 		return true;
 	}
 
@@ -79,6 +174,9 @@
 		{
 			rows = null;
 		}
+      // if it was cursored, we should the server side cursor as well.
+      // Note: this RS shouldn't be used after this call!
+      closeCursor();
 	}
 
 	public boolean wasNull() throws SQLException
@@ -431,10 +529,6 @@
 			this.warnings = warnings;
 	}
 
-	public String getCursorName() throws SQLException
-	{
-		return ((AbstractJdbc1Connection)connection).getCursorName();
-	}
 
 	/*
 	 * Get the value of a column in the current row as a Java object
Index: org/postgresql/jdbc1/AbstractJdbc1Statement.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java,v
retrieving revision 1.14
diff -u -w -r1.14 AbstractJdbc1Statement.java
--- org/postgresql/jdbc1/AbstractJdbc1Statement.java	2002/11/20 07:34:32	1.14
+++ org/postgresql/jdbc1/AbstractJdbc1Statement.java	2003/01/02 15:14:54
@@ -15,6 +15,8 @@
  */
 public abstract class AbstractJdbc1Statement implements org.postgresql.PGStatement
 {
+   // utility: an object[0] we need sometimes
+   final Object[] nullarr = new Object[0];
 
 	// The connection who created us
 	protected AbstractJdbc1Connection connection;
@@ -49,8 +51,10 @@
 	protected Object[] m_binds = new Object[0];
 	protected String[] m_bindTypes = new String[0];
 	private String m_statementName = null;
-	private boolean m_useServerPrepare = false;
+   protected String m_cursorName = null;
+   protected boolean m_useServerPrepare = false;
 	private static int m_preparedCount = 1;
+   protected int m_fetchSize = 0;
 
 	//Used by the callablestatement style methods
 	private static final String JDBC_SYNTAX = "{[? =] call <some_function> ([? [,?]*]) }";
@@ -71,14 +75,21 @@
 	public AbstractJdbc1Statement (AbstractJdbc1Connection connection)
 	{
 		this.connection = connection;
+      initDefaults();
 	}
 
 	public AbstractJdbc1Statement (AbstractJdbc1Connection connection, String p_sql) throws SQLException
 	{
 		this.connection = connection;
+      initDefaults();
 		parseSqlStmt(p_sql);  // this allows Callable stmt to override
 	}
 
+   public void initDefaults()
+   {
+      m_fetchSize=((AbstractJdbc1Connection) connection).defaultFetchSize;
+   }
+
 	protected void parseSqlStmt (String p_sql) throws SQLException
 	{
 		String l_sql = p_sql;
@@ -117,6 +128,31 @@
 
 	}
 
+   protected void resetSqlFragments() throws SQLException
+   {
+      //If we have already created a server prepared statement, we need
+      //to deallocate the existing one
+      if (m_statementName != null) {
+         ((AbstractJdbc1Connection)connection).doQuery("DEALLOCATE " + m_statementName);
+         m_statementName = null;
+         m_sqlFragments = null;
+         m_origSqlFragments = null;
+         m_executeSqlFragments = null;
+      }
+   }
+
+   /** small utility routine used for setting the m_sqlFragments
+    *  property to a new value. Due to the use of prepared statements
+    *  declared at the backend, we should deallocate these if we
+    *  get a new query. This is done in here automatically.
+    */
+   protected void setSqlFragments(String s) throws SQLException
+   {
+      resetSqlFragments();
+      String l_sql = replaceProcessing(s);
+      m_sqlFragments = new String[] {l_sql};
+      m_binds = nullarr;
+   }
 
 	/*
 	 * Execute a SQL statement that retruns a single ResultSet
@@ -127,18 +163,8 @@
 	 */
 	public java.sql.ResultSet executeQuery(String p_sql) throws SQLException
 	{
-		String l_sql = replaceProcessing(p_sql);
-		m_sqlFragments = new String[] {l_sql};
-		m_binds = new Object[0];
-		//If we have already created a server prepared statement, we need
-		//to deallocate the existing one
-		if (m_statementName != null) {
-			((AbstractJdbc1Connection)connection).ExecSQL("DEALLOCATE " + m_statementName);
-			m_statementName = null;
-			m_origSqlFragments = null;
-			m_executeSqlFragments = null;
-		}
-		return executeQuery();
+      setSqlFragments(p_sql);
+      return this.executeQuery();
 	}
 
 	/*
@@ -150,7 +176,7 @@
 	 */
 	public java.sql.ResultSet executeQuery() throws SQLException
 	{
-		this.execute();
+      this.execute(false);
 		while (result != null && !((AbstractJdbc1ResultSet)result).reallyResultSet())
 			result = ((AbstractJdbc1ResultSet)result).getNext();
 		if (result == null)
@@ -158,6 +184,7 @@
 		return result;
 	}
 
+
 	/*
 	 * Execute a SQL INSERT, UPDATE or DELETE statement.  In addition
 	 * SQL statements that return nothing such as SQL DDL statements
@@ -169,17 +196,7 @@
 	 */
 	public int executeUpdate(String p_sql) throws SQLException
 	{
-		String l_sql = replaceProcessing(p_sql);
-		m_sqlFragments = new String[] {l_sql};
-		m_binds = new Object[0];
-		//If we have already created a server prepared statement, we need
-		//to deallocate the existing one
-		if (m_statementName != null) {
-			((AbstractJdbc1Connection)connection).ExecSQL("DEALLOCATE " + m_statementName);
-			m_statementName = null;
-			m_origSqlFragments = null;
-			m_executeSqlFragments = null;
-		}
+      setSqlFragments(p_sql);
 		return executeUpdate();
 	}
 
@@ -194,7 +211,7 @@
 	 */
 	public int executeUpdate() throws SQLException
 	{
-		this.execute();
+      this.execute(true);
 		if (((AbstractJdbc1ResultSet)result).reallyResultSet())
 			throw new PSQLException("postgresql.stat.result");
 		return this.getUpdateCount();
@@ -213,18 +230,8 @@
 	 */
 	public boolean execute(String p_sql) throws SQLException
 	{
-		String l_sql = replaceProcessing(p_sql);
-		m_sqlFragments = new String[] {l_sql};
-		m_binds = new Object[0];
-		//If we have already created a server prepared statement, we need
-		//to deallocate the existing one
-		if (m_statementName != null) {
-			((AbstractJdbc1Connection)connection).ExecSQL("DEALLOCATE " + m_statementName);
-			m_statementName = null;
-			m_origSqlFragments = null;
-			m_executeSqlFragments = null;
-		}
-		return execute();
+      setSqlFragments(p_sql);
+      return this.execute(false);
 	}
 
 	/*
@@ -238,6 +245,19 @@
 	 */
 	public boolean execute() throws SQLException
 	{
+      return this.execute(false);
+   }
+
+   /*
+    * The "real" worker behind all execute*(*) methods.
+    * @param update tip if we are NOT expecting a big result set
+    *     (so we won't use cursor for it)
+    * @return true if the next result is a ResultSet; false if it is an
+    *     update count or no result at all.
+    * @exception SQLException if a database access error occurs
+    */
+   protected boolean execute(boolean update) throws SQLException
+   {
 		if (isFunction && !returnTypeSet)
 			throw new PSQLException("postgresql.call.noreturntype");
 		if (isFunction)
@@ -257,11 +277,18 @@
 			if (rs != null)
 				rs.close();
 		}
+      // cursors dont work in autocommit mode
+      // fetchsize must be set >0
+      // we should be aware of a result set (so no update calls or somewhat like that.
+      boolean use_cursor=true;
+      if ((m_fetchSize<1) || update || (((AbstractJdbc1Connection)connection).autoCommit))
+         use_cursor=false;
 
+      String[] frags;
 		//Use server prepared statements if directed
-		if (m_useServerPrepare)
+      if (m_useServerPrepare && !use_cursor) // we have to change that as soon as cursors AND preparing work (7.4?)
 		{
-			if (m_statementName == null)
+         if (m_statementName == null) // statement is not declared till now, so let's declare
 			{
 				m_statementName = "JDBC_STATEMENT_" + m_preparedCount++;
 				m_origSqlFragments = new String[m_sqlFragments.length];
@@ -303,21 +330,49 @@
 						sbuf.append(m_origSqlFragments[i]);
 					}
 					sbuf.append("; ");
-
+               /* we have to wait for 7.4 to use this :-(
+               // in case of cursor usage, prepend cursor declaration string
+               if (use_cursor)
+                  sbuf.append(getBeginCursorDeclString(m_executeSqlFragments[0]));
+               else
+               */
 					sbuf.append(m_executeSqlFragments[0]);
+
 					m_sqlFragments[0] = sbuf.toString();
-					System.arraycopy(m_executeSqlFragments, 1, m_sqlFragments, 1, m_sqlFragments.length - 1);
+               int l=m_sqlFragments.length-1;
+               System.arraycopy(m_executeSqlFragments, 1, m_sqlFragments, 1, l);
+               /* we have to wait for 7.4 to use this :-(
+               // if cursor is used, we modify the "tail" on m_sqlFragments
+               if (use_cursor)
+                  m_sqlFragments[l]=getEndCursorDeclString(m_sqlFragments[l]);
+               */
+               frags=m_sqlFragments;
 				}
 
 			}
-			else
+         else // already declared, to call it ("execute..."), just use executeSQLFragments
 			{
 				m_sqlFragments = m_executeSqlFragments;
+            /* see above. 7.4. sigh.
+            if (use_cursor)
+               frags=getCursoredSqlFrags(m_sqlFragments);
+            else // no cursor
+            */
+               frags=m_sqlFragments;
+         }
 			}
+      else // no server prepare at all. Maybe cursor?
+      {
+         if (use_cursor)
+            frags=getCursoredSqlFrags(m_sqlFragments);
+         else //  no cursor
+            frags=m_sqlFragments;
 		}
 
 		// New in 7.1, pass Statement so that ExecSQL can customise to it
-		result = ((AbstractJdbc1Connection)connection).ExecSQL(m_sqlFragments, m_binds, (java.sql.Statement)this);
+      result = ((AbstractJdbc1Connection)connection).createResultSet((java.sql.Statement)this);
+      ((AbstractJdbc1Connection)connection).execSQL(frags, m_binds,
+                           (java.sql.Statement)this, result);
 
 		//If we are executing a callable statement function set the return data
 		if (isFunction)
@@ -341,6 +396,40 @@
 		}
 	}
 
+   public String[] getCursoredSqlFrags(String[] org_frags)
+   {
+      int l=org_frags.length;
+      String[] frags=new String[l];
+      System.arraycopy(org_frags,0,frags,0,l);
+      if (l>0)
+      {
+         frags[0]=getBeginCursorDeclString(frags[0]);
+         frags[l-1]=getEndCursorDeclString(frags[l-1]);
+      }
+      return frags;
+   }
+
+   public String getBeginCursorDeclString(String first)
+   {
+      m_cursorName= "JDBC_CURS_"+m_preparedCount++;
+      return new StringBuffer("DECLARE ")
+                  .append(m_cursorName)
+                  .append(" CURSOR FOR ")
+                  .append(first)
+                  .toString();
+   }
+
+   public String getEndCursorDeclString(String last)
+   {
+      return new StringBuffer(last)
+                  .append(";FETCH FORWARD ")
+                  .append(m_fetchSize)
+                  .append(" FROM ")
+                  .append(m_cursorName)
+                  .toString();
+   }
+
+
 	/*
 	 * setCursorName defines the SQL cursor name that will be used by
 	 * subsequent execute methods.	This name can then be used in SQL
@@ -590,14 +679,11 @@
 		java.sql.ResultSet rs = getResultSet();
 		if (rs != null)
 			rs.close();
-
-		// If using server prepared statements deallocate them
-		if (m_useServerPrepare && m_statementName != null) {
-			((AbstractJdbc1Connection)connection).ExecSQL("DEALLOCATE " + m_statementName);
-		}
-
 		// Disasociate it from us (For Garbage Collection)
 		result = null;
+      // if any server side prepared statements were created, dealloc them.
+      resetSqlFragments();
+
 	}
 
 	/*
@@ -727,6 +813,9 @@
         String l_pgType;
 		switch (sqlType)
 		{
+         case Types.BIT:
+            l_pgType = PG_BOOLEAN;
+            break;
 			case Types.INTEGER:
 				l_pgType = PG_INTEGER;
 				break;
@@ -838,6 +927,8 @@
 	public void setLong(int parameterIndex, long x) throws SQLException
 	{
 		bind(parameterIndex, Long.toString(x), PG_INT8);
+      // fix for slow index lookup on non-explicit cast to bigint.
+      //bind(parameterIndex, Long.toString(x)+"::bigint", PG_TEXT);
 	}
 
 	/*
@@ -1344,9 +1435,13 @@
 			case Types.INTEGER:
 				bind(parameterIndex, x.toString(), PG_INTEGER);
 				break;
+         case Types.BIGINT:
+            bind(parameterIndex, x.toString(), PG_INT8);
+            //fix for bad index lookup performance in bigint-case. Explicit cast helps here...
+            //bind(parameterIndex, x.toString()+"::bigint", PG_TEXT);
+            break;
 			case Types.TINYINT:
 			case Types.SMALLINT:
-			case Types.BIGINT:
 			case Types.REAL:
 			case Types.FLOAT:
 			case Types.DOUBLE:
@@ -1374,7 +1469,7 @@
 			case Types.BIT:
 				if (x instanceof Boolean)
 				{
-					bind(parameterIndex, ((Boolean)x).booleanValue() ? "TRUE" : "FALSE", PG_TEXT);
+               bind(parameterIndex, ((Boolean)x).booleanValue() ? "TRUE" : "FALSE", PG_BOOLEAN);
 				}
 				else
 				{
@@ -1907,12 +2002,14 @@
 
 
     public void setUseServerPrepare(boolean flag) throws SQLException {
+      if (m_useServerPrepare == flag) // no change?
+         return ;
         //Server side prepared statements were introduced in 7.3
         if (connection.haveMinimumServerVersion("7.3")) {
 			//If turning server prepared statements off deallocate statement
 			//and reset statement name
 			if (m_useServerPrepare != flag && !flag)
-				((AbstractJdbc1Connection)connection).ExecSQL("DEALLOCATE " + m_statementName);
+            ((AbstractJdbc1Connection)connection).doQuery("DEALLOCATE " + m_statementName);
 			m_statementName = null;
 			m_useServerPrepare = flag;
 		} else {
Index: org/postgresql/jdbc1/Jdbc1Connection.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Connection.java,v
retrieving revision 1.5
diff -u -w -r1.5 Jdbc1Connection.java
--- org/postgresql/jdbc1/Jdbc1Connection.java	2002/09/06 21:23:06	1.5
+++ org/postgresql/jdbc1/Jdbc1Connection.java	2003/01/02 15:14:54
@@ -46,6 +46,12 @@
 		return new Jdbc1ResultSet(this, stat, fields, tuples, status, updateCount, 0, false);
 	}
 
+
+	public java.sql.ResultSet createResultSet (java.sql.Statement stat) throws SQLException
+	{
+		// This needs doing.
+		return null;
+	}
 }
 
 
Index: org/postgresql/jdbc1/Jdbc1PreparedStatement.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1PreparedStatement.java,v
retrieving revision 1.1
diff -u -w -r1.1 Jdbc1PreparedStatement.java
--- org/postgresql/jdbc1/Jdbc1PreparedStatement.java	2002/07/24 22:08:40	1.1
+++ org/postgresql/jdbc1/Jdbc1PreparedStatement.java	2003/01/02 15:14:54
@@ -10,5 +10,11 @@
 	{
 		super(connection, sql);
 	}
+
+   public void initDefaults()
+   {
+      super.initDefaults();
+      m_useServerPrepare=!((AbstractJdbc1Connection) connection).useServerPrepareNever;
+   }
 
 }
Index: org/postgresql/jdbc1/Jdbc1Statement.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Statement.java,v
retrieving revision 1.3
diff -u -w -r1.3 Jdbc1Statement.java
--- org/postgresql/jdbc1/Jdbc1Statement.java	2002/09/06 21:23:06	1.3
+++ org/postgresql/jdbc1/Jdbc1Statement.java	2003/01/02 15:14:54
@@ -15,5 +15,11 @@
 	{
 		super(c);
 	}
+
+   public void initDefaults()
+   {
+      super.initDefaults();
+      m_useServerPrepare=((AbstractJdbc1Connection) connection).useServerPrepareAlways;
+   }
 
 }
Index: org/postgresql/jdbc2/AbstractJdbc2Connection.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Connection.java,v
retrieving revision 1.2
diff -u -w -r1.2 AbstractJdbc2Connection.java
--- org/postgresql/jdbc2/AbstractJdbc2Connection.java	2002/09/06 21:23:06	1.2
+++ org/postgresql/jdbc2/AbstractJdbc2Connection.java	2003/01/02 15:14:55
@@ -6,6 +6,7 @@
 import java.sql.*;
 import org.postgresql.util.PSQLException;
 
+
 /* $Header: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Connection.java,v 1.2 2002/09/06 21:23:06 momjian Exp $
  * This class defines methods of the jdbc2 specification.  This class extends
  * org.postgresql.jdbc1.AbstractJdbc1Connection which provides the jdbc1
Index: org/postgresql/jdbc2/AbstractJdbc2ResultSet.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java,v
retrieving revision 1.11
diff -u -w -r1.11 AbstractJdbc2ResultSet.java
--- org/postgresql/jdbc2/AbstractJdbc2ResultSet.java	2002/12/23 16:12:36	1.11
+++ org/postgresql/jdbc2/AbstractJdbc2ResultSet.java	2003/01/02 15:14:55
@@ -39,6 +39,11 @@
 	private PreparedStatement selectStatement = null;
 
 
+   public AbstractJdbc2ResultSet(org.postgresql.PGConnection conn, Statement statement)
+   {
+      super(conn, statement);
+   }
+
 
 	public AbstractJdbc2ResultSet(org.postgresql.PGConnection conn, Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor)
 	{
@@ -142,6 +147,14 @@
 				{
 					return getString(columnIndex);
 				}
+            else if (type.equals("refcursor"))
+            {
+               // We must return a ResultSet with the results packaged.
+                    // We should probably check that auto commit is turned off.
+                    String cursorName = getString(columnIndex);
+               // return new RefCursorResultSet(cursorName);
+               return null;
+            }
 				else
 				{
 					return connection.getObject(field.getPGType(), getString(columnIndex));
@@ -362,15 +375,16 @@
 		//PostgreSQL normally sends rows first->last
 		return java.sql.ResultSet.FETCH_FORWARD;
 	}
-
 
+   /* already declared in AbstractJdbc1ResultSet due to Cursor awareness...
 	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();
+      return super.getFetchSize();
 	}
+   */
 
 
 	public Object getObject(String columnName, java.util.Map map) throws SQLException
@@ -754,7 +768,6 @@
 		}
 
 		updateValue(columnIndex, theData);
-
 	}
 
 
@@ -787,7 +800,6 @@
 			throw new PSQLException("postgresql.updateable.ioerror" + ie);
 		}
 		updateValue(columnIndex, theData);
-
 	}
 
 
Index: org/postgresql/jdbc2/AbstractJdbc2Statement.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java,v
retrieving revision 1.10
diff -u -w -r1.10 AbstractJdbc2Statement.java
--- org/postgresql/jdbc2/AbstractJdbc2Statement.java	2002/11/20 20:37:53	1.10
+++ org/postgresql/jdbc2/AbstractJdbc2Statement.java	2003/01/02 15:14:56
@@ -7,13 +7,15 @@
 import java.util.Vector;
 import org.postgresql.largeobject.*;
 import org.postgresql.util.PSQLException;
+import org.postgresql.jdbc1.AbstractJdbc1Connection;
+import org.postgresql.jdbc1.AbstractJdbc1Statement;
 
 /* $Header: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java,v 1.10 2002/11/20 20:37:53 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
  */
-public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.AbstractJdbc1Statement
+public abstract class AbstractJdbc2Statement extends AbstractJdbc1Statement
 {
 
 	protected Vector batch = null;
@@ -133,7 +135,7 @@
 
 	public int getFetchSize() throws SQLException
 	{
-		return 0;
+      return super.m_fetchSize;
 	}
 
 	public int getResultSetConcurrency() throws SQLException
@@ -148,12 +150,17 @@
 
 	public void setFetchDirection(int direction) throws SQLException
 	{
-		throw org.postgresql.Driver.notImplemented();
+      // I don't think this should happen, since it's a hint it should just
+      // fail quietly.
+      //   throw org.postgresql.Driver.notImplemented();
 	}
 
 	public void setFetchSize(int rows) throws SQLException
 	{
-		throw org.postgresql.Driver.notImplemented();
+      // if the Fetchsize is forced, ignore setting it.
+      if (((AbstractJdbc1Connection) connection).forceFetchSize)
+         return;
+      super.m_fetchSize = rows;
 	}
 
 	public void setResultSetConcurrency(int value) throws SQLException
Index: org/postgresql/jdbc2/Array.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc2/Array.java,v
retrieving revision 1.18
diff -u -w -r1.18 Array.java
--- org/postgresql/jdbc2/Array.java	2002/09/06 21:23:06	1.18
+++ org/postgresql/jdbc2/Array.java	2003/01/02 15:14:56
@@ -343,7 +343,10 @@
 			default:
 				throw org.postgresql.Driver.notImplemented();
 		}
-		return ((AbstractJdbc2Connection)conn).getResultSet(null, fields, rows, "OK", 1 );
+		java.sql.Statement stat = ((AbstractJdbc2Connection)conn).createStatement();
+		java.sql.ResultSet retRs = ((AbstractJdbc2Connection)conn).createResultSet(stat);
+		((AbstractJdbc2ResultSet)retRs).init(fields, rows, "OK", 1, 0, false);
+		return retRs;
 	}
 
 	public String toString()
Index: org/postgresql/jdbc2/Jdbc2Connection.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Connection.java,v
retrieving revision 1.5
diff -u -w -r1.5 Jdbc2Connection.java
--- org/postgresql/jdbc2/Jdbc2Connection.java	2002/09/06 21:23:06	1.5
+++ org/postgresql/jdbc2/Jdbc2Connection.java	2003/01/02 15:14:56
@@ -46,6 +46,38 @@
 		return metadata;
 	}
 
+
+
+	// the new method override which re-inits existing resultsets
+	public java.sql.ResultSet getResultSet(java.sql.Statement stat,
+					       org.postgresql.jdbc1.AbstractJdbc1ResultSet rs,
+					       Field[] fields,
+					       Vector tuples,
+					       String status,
+					       int updateCount, long insertOID, boolean binaryCursor)
+		throws SQLException
+	{
+		if (rs == null)
+			return new Jdbc2ResultSet(this, stat, fields,
+						  tuples, status,
+						  updateCount, insertOID, binaryCursor);
+		else
+		{
+			rs.init(fields, tuples, status, updateCount, insertOID, binaryCursor);
+			return (java.sql.ResultSet) rs;
+		}
+	}
+
+
+
+
+	/** new nic method **/
+	public java.sql.ResultSet createResultSet (Statement statement)
+	{
+		return new Jdbc2ResultSet(this, statement);
+	}
+
+
 	public java.sql.ResultSet getResultSet(Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException
 	{
 		return new Jdbc2ResultSet(this, statement, fields, tuples, status, updateCount, insertOID, binaryCursor);
Index: org/postgresql/jdbc2/Jdbc2PreparedStatement.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2PreparedStatement.java,v
retrieving revision 1.2
diff -u -w -r1.2 Jdbc2PreparedStatement.java
--- org/postgresql/jdbc2/Jdbc2PreparedStatement.java	2002/08/14 20:35:39	1.2
+++ org/postgresql/jdbc2/Jdbc2PreparedStatement.java	2003/01/02 15:14:56
@@ -10,6 +10,12 @@
 	{
 		super(connection, sql);
 	}
+
+   public void initDefaults()
+   {
+      super.initDefaults();
+      m_useServerPrepare=!((AbstractJdbc2Connection) connection).useServerPrepareNever;
+   }
 
 }
 
Index: org/postgresql/jdbc2/Jdbc2ResultSet.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2ResultSet.java,v
retrieving revision 1.6
diff -u -w -r1.6 Jdbc2ResultSet.java
--- org/postgresql/jdbc2/Jdbc2ResultSet.java	2002/09/11 05:38:45	1.6
+++ org/postgresql/jdbc2/Jdbc2ResultSet.java	2003/01/02 15:14:56
@@ -13,6 +13,12 @@
 public class Jdbc2ResultSet extends org.postgresql.jdbc2.AbstractJdbc2ResultSet implements java.sql.ResultSet
 {
 
+	Jdbc2ResultSet (org.postgresql.PGConnection conn, Statement statement)
+	{
+		super (conn, statement);
+	}
+
+
 	public Jdbc2ResultSet(Jdbc2Connection conn, Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor)
 	{
 		super(conn, statement, fields, tuples, status, updateCount, insertOID, binaryCursor);
Index: org/postgresql/jdbc2/Jdbc2Statement.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Statement.java,v
retrieving revision 1.3
diff -u -w -r1.3 Jdbc2Statement.java
--- org/postgresql/jdbc2/Jdbc2Statement.java	2002/09/06 21:23:06	1.3
+++ org/postgresql/jdbc2/Jdbc2Statement.java	2003/01/02 15:14:56
@@ -15,5 +15,11 @@
 	{
 		super(c);
 	}
+
+   public void initDefaults()
+   {
+      super.initDefaults();
+      m_useServerPrepare=((AbstractJdbc2Connection) connection).useServerPrepareAlways;
+   }
 
 }
Index: org/postgresql/jdbc3/AbstractJdbc3ResultSet.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc3/AbstractJdbc3ResultSet.java,v
retrieving revision 1.2
diff -u -w -r1.2 AbstractJdbc3ResultSet.java
--- org/postgresql/jdbc3/AbstractJdbc3ResultSet.java	2002/09/06 21:23:06	1.2
+++ org/postgresql/jdbc3/AbstractJdbc3ResultSet.java	2003/01/02 15:14:57
@@ -12,6 +12,11 @@
 public abstract class AbstractJdbc3ResultSet extends org.postgresql.jdbc2.AbstractJdbc2ResultSet
 {
 
+	public AbstractJdbc3ResultSet(org.postgresql.PGConnection conn, Statement statement)
+	{
+		super(conn, statement);
+	}
+
 	public AbstractJdbc3ResultSet(org.postgresql.PGConnection conn, Statement statement, org.postgresql.Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor)
 	{
 		super (conn, statement, fields, tuples, status, updateCount, insertOID, binaryCursor);
Index: org/postgresql/jdbc3/Jdbc3Connection.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3Connection.java,v
retrieving revision 1.2
diff -u -w -r1.2 Jdbc3Connection.java
--- org/postgresql/jdbc3/Jdbc3Connection.java	2002/09/06 21:23:06	1.2
+++ org/postgresql/jdbc3/Jdbc3Connection.java	2003/01/02 15:14:57
@@ -56,6 +56,11 @@
 		return new Jdbc3ResultSet(this, statement, fields, tuples, status, updateCount, 0, false);
 	}
 
+	/** new nic method **/
+	public java.sql.ResultSet createResultSet (Statement statement)
+	{
+		return new Jdbc3ResultSet(this, statement);
+	}
 }
 
 
Index: org/postgresql/jdbc3/Jdbc3PreparedStatement.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3PreparedStatement.java,v
retrieving revision 1.2
diff -u -w -r1.2 Jdbc3PreparedStatement.java
--- org/postgresql/jdbc3/Jdbc3PreparedStatement.java	2002/09/06 21:23:06	1.2
+++ org/postgresql/jdbc3/Jdbc3PreparedStatement.java	2003/01/02 15:14:57
@@ -10,6 +10,12 @@
 	{
 		super(connection, sql);
 	}
+
+   public void initDefaults()
+   {
+      super.initDefaults();
+      m_useServerPrepare=!((AbstractJdbc3Connection) connection).useServerPrepareNever;
+   }
 
 }
 
Index: org/postgresql/jdbc3/Jdbc3ResultSet.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ResultSet.java,v
retrieving revision 1.3
diff -u -w -r1.3 Jdbc3ResultSet.java
--- org/postgresql/jdbc3/Jdbc3ResultSet.java	2002/09/11 05:38:45	1.3
+++ org/postgresql/jdbc3/Jdbc3ResultSet.java	2003/01/02 15:14:57
@@ -13,6 +13,11 @@
 public class Jdbc3ResultSet extends org.postgresql.jdbc3.AbstractJdbc3ResultSet implements java.sql.ResultSet
 {
 
+	public Jdbc3ResultSet(org.postgresql.PGConnection conn, Statement statement)
+	{
+		super (conn, statement);
+	}
+
 	public Jdbc3ResultSet(Jdbc3Connection conn, Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor)
 	{
 		super(conn, statement, fields, tuples, status, updateCount, insertOID, binaryCursor);
Index: org/postgresql/jdbc3/Jdbc3Statement.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3Statement.java,v
retrieving revision 1.2
diff -u -w -r1.2 Jdbc3Statement.java
--- org/postgresql/jdbc3/Jdbc3Statement.java	2002/09/06 21:23:06	1.2
+++ org/postgresql/jdbc3/Jdbc3Statement.java	2003/01/02 15:14:57
@@ -15,5 +15,11 @@
 	{
 		super(c);
 	}
+
+   public void initDefaults()
+   {
+      super.initDefaults();
+      m_useServerPrepare=((AbstractJdbc3Connection) connection).useServerPrepareAlways;
+   }
 
 }
Index: org/postgresql/test/jdbc2/DatabaseMetaDataTest.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java,v
retrieving revision 1.16
diff -u -w -r1.16 DatabaseMetaDataTest.java
Index: org/postgresql/test/jdbc2/optional/ConnectionPoolTest.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/ConnectionPoolTest.java,v
retrieving revision 1.5
diff -u -w -r1.5 ConnectionPoolTest.java
--- org/postgresql/test/jdbc2/optional/ConnectionPoolTest.java	2002/12/20 14:10:34	1.5
+++ org/postgresql/test/jdbc2/optional/ConnectionPoolTest.java	2003/01/02 15:14:59
@@ -392,38 +392,6 @@
     }
 
     /**
-     * Ensures that the Statement proxy generated by the Connection handle
-     * throws the correct kind of exception.
-     */
-    public void testStatementProxy() {
-            Statement s = null;
-            try 
-            {
-                    PooledConnection pc = getPooledConnection();
-                    Connection con = pc.getConnection();
-                    s = con.createStatement();
-            } 
-            catch (SQLException e) 
-            {
-                    fail(e.getMessage());
-            }
-            try 
-            {
-                    s.executeQuery("SELECT * FROM THIS_TABLE_SHOULD_NOT_EXIST");
-                    fail("An SQL exception was not thrown that should have been");
-            } 
-            catch (SQLException e) 
-            {
-                    ; // This is the expected and correct path
-            }
-            catch (Exception e) 
-            {
-                    fail("bad exception; was expecting SQLException, not" +
-                         e.getClass().getName());
-            }
-    }
-
-    /**
      * Ensures that a prepared statement generated by a proxied connection
      * returns the proxied connection from getConnection() [not the physical
      * connection].
Index: org/postgresql/util/Serialize.java
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/util/Serialize.java,v
retrieving revision 1.14
diff -u -w -r1.14 Serialize.java
--- org/postgresql/util/Serialize.java	2002/10/01 00:39:02	1.14
+++ org/postgresql/util/Serialize.java	2003/01/02 15:15:00
@@ -405,7 +405,7 @@
 
 			if (Driver.logDebug)
 				Driver.debug("Serialize.store: " + sb.toString() );
-			ResultSet rs = ((org.postgresql.jdbc1.AbstractJdbc1Connection)conn).ExecSQL(sb.toString());
+			ResultSet rs = ((org.postgresql.jdbc1.AbstractJdbc1Connection)conn).doQuery(sb.toString());
 
 			// fetch the OID for returning
 			if (update)
