From 1e3187366ca96069e71527cf109198f645e14252 Mon Sep 17 00:00:00 2001
From: Barry Lind <barry@xythos.com>
Date: Tue, 23 Jul 2002 03:59:55 +0000
Subject: [PATCH] Initial restructuring to add jdbc3 support.  There was a
 significant amount of duplicated code between the jdbc1 and jdbc2.  This
 checkin restructures the code so that the duplication is removed so that the
 jdbc3 support can be added without adding yet another copy of everything. 
 Also many classes were renamed to avoid confusion with multiple different
 objects having the same name.  The timestamp tests were also updated to add
 support for testing timestamp without time zone in addition to timestamp with
 time zone

 Modified Files:
 	jdbc/Makefile jdbc/build.xml jdbc/example/ImageViewer.java
 	jdbc/example/basic.java jdbc/example/blobtest.java
 	jdbc/example/threadsafe.java
 	jdbc/org/postgresql/Driver.java.in
 	jdbc/org/postgresql/Field.java
 	jdbc/org/postgresql/core/QueryExecutor.java
 	jdbc/org/postgresql/fastpath/Fastpath.java
 	jdbc/org/postgresql/jdbc1/CallableStatement.java
 	jdbc/org/postgresql/jdbc1/DatabaseMetaData.java
 	jdbc/org/postgresql/jdbc1/PreparedStatement.java
 	jdbc/org/postgresql/jdbc2/Array.java
 	jdbc/org/postgresql/jdbc2/CallableStatement.java
 	jdbc/org/postgresql/jdbc2/DatabaseMetaData.java
 	jdbc/org/postgresql/jdbc2/PreparedStatement.java
 	jdbc/org/postgresql/jdbc2/UpdateableResultSet.java
 	jdbc/org/postgresql/largeobject/LargeObjectManager.java
 	jdbc/org/postgresql/largeobject/PGblob.java
 	jdbc/org/postgresql/largeobject/PGclob.java
 	jdbc/org/postgresql/test/jdbc2/BlobTest.java
 	jdbc/org/postgresql/test/jdbc2/ConnectionTest.java
 	jdbc/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java
 	jdbc/org/postgresql/test/jdbc2/TimestampTest.java
 	jdbc/org/postgresql/test/jdbc2/UpdateableResultTest.java
 	jdbc/org/postgresql/util/Serialize.java
 Added Files:
 	jdbc/org/postgresql/PGConnection.java
 	jdbc/org/postgresql/PGStatement.java
 	jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java
 	jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java
 	jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java
 	jdbc/org/postgresql/jdbc1/Jdbc1Connection.java
 	jdbc/org/postgresql/jdbc1/Jdbc1ResultSet.java
 	jdbc/org/postgresql/jdbc1/Jdbc1Statement.java
 	jdbc/org/postgresql/jdbc2/AbstractJdbc2Connection.java
 	jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java
 	jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java
 	jdbc/org/postgresql/jdbc2/Jdbc2Connection.java
 	jdbc/org/postgresql/jdbc2/Jdbc2ResultSet.java
 	jdbc/org/postgresql/jdbc2/Jdbc2Statement.java
 Removed Files:
 	jdbc/org/postgresql/Connection.java
 	jdbc/org/postgresql/ResultSet.java
 	jdbc/org/postgresql/Statement.java
 	jdbc/org/postgresql/jdbc1/Connection.java
 	jdbc/org/postgresql/jdbc1/ResultSet.java
 	jdbc/org/postgresql/jdbc1/Statement.java
 	jdbc/org/postgresql/jdbc2/Connection.java
 	jdbc/org/postgresql/jdbc2/ResultSet.java
 	jdbc/org/postgresql/jdbc2/Statement.java
---
 src/interfaces/jdbc/Makefile                  |    4 +-
 src/interfaces/jdbc/build.xml                 |   43 +-
 src/interfaces/jdbc/example/ImageViewer.java  |    4 +-
 src/interfaces/jdbc/example/basic.java        |    5 +-
 src/interfaces/jdbc/example/blobtest.java     |    2 +-
 src/interfaces/jdbc/example/threadsafe.java   |    2 +-
 .../jdbc/org/postgresql/Driver.java.in        |    2 +-
 src/interfaces/jdbc/org/postgresql/Field.java |    6 +-
 .../jdbc/org/postgresql/PGConnection.java     |   72 +
 .../jdbc/org/postgresql/PGStatement.java      |   21 +
 .../jdbc/org/postgresql/ResultSet.java        |  264 ---
 .../org/postgresql/core/QueryExecutor.java    |   10 +-
 .../org/postgresql/fastpath/Fastpath.java     |    6 +-
 .../AbstractJdbc1Connection.java}             |  251 ++-
 .../jdbc1/AbstractJdbc1ResultSet.java         |  957 +++++++++
 .../AbstractJdbc1Statement.java}              |  218 +-
 .../postgresql/jdbc1/CallableStatement.java   |    2 +-
 .../jdbc/org/postgresql/jdbc1/Connection.java |  214 --
 .../postgresql/jdbc1/DatabaseMetaData.java    |   36 +-
 .../org/postgresql/jdbc1/Jdbc1Connection.java |   47 +
 .../org/postgresql/jdbc1/Jdbc1ResultSet.java  |   32 +
 .../org/postgresql/jdbc1/Jdbc1Statement.java  |   19 +
 .../postgresql/jdbc1/PreparedStatement.java   |    6 +-
 .../jdbc/org/postgresql/jdbc1/ResultSet.java  | 1026 ----------
 .../jdbc/org/postgresql/jdbc1/Statement.java  |  144 --
 .../jdbc2/AbstractJdbc2Connection.java        |  203 ++
 .../jdbc2/AbstractJdbc2ResultSet.java         |  752 +++++++
 .../jdbc2/AbstractJdbc2Statement.java         |  142 ++
 .../jdbc/org/postgresql/jdbc2/Array.java      |   56 +-
 .../postgresql/jdbc2/CallableStatement.java   |    2 +-
 .../jdbc/org/postgresql/jdbc2/Connection.java |  332 ---
 .../postgresql/jdbc2/DatabaseMetaData.java    |   32 +-
 .../org/postgresql/jdbc2/Jdbc2Connection.java |   62 +
 .../org/postgresql/jdbc2/Jdbc2ResultSet.java  |   32 +
 .../org/postgresql/jdbc2/Jdbc2Statement.java  |   21 +
 .../postgresql/jdbc2/PreparedStatement.java   |    6 +-
 .../jdbc/org/postgresql/jdbc2/ResultSet.java  | 1802 -----------------
 .../jdbc/org/postgresql/jdbc2/Statement.java  |  381 ----
 .../postgresql/jdbc2/UpdateableResultSet.java |   12 +-
 .../largeobject/LargeObjectManager.java       |    6 +-
 .../org/postgresql/largeobject/PGblob.java    |    6 +-
 .../org/postgresql/largeobject/PGclob.java    |    6 +-
 .../org/postgresql/test/jdbc2/BlobTest.java   |    6 +-
 .../postgresql/test/jdbc2/ConnectionTest.java |    6 +-
 .../test/jdbc2/DatabaseMetaDataTest.java      |   32 +-
 .../postgresql/test/jdbc2/TimestampTest.java  |  238 ++-
 .../test/jdbc2/UpdateableResultTest.java      |    3 +-
 .../jdbc/org/postgresql/util/Serialize.java   |   24 +-
 48 files changed, 3033 insertions(+), 4522 deletions(-)
 create mode 100644 src/interfaces/jdbc/org/postgresql/PGConnection.java
 create mode 100644 src/interfaces/jdbc/org/postgresql/PGStatement.java
 delete mode 100644 src/interfaces/jdbc/org/postgresql/ResultSet.java
 rename src/interfaces/jdbc/org/postgresql/{Connection.java => jdbc1/AbstractJdbc1Connection.java} (89%)
 create mode 100644 src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java
 rename src/interfaces/jdbc/org/postgresql/{Statement.java => jdbc1/AbstractJdbc1Statement.java} (61%)
 delete mode 100644 src/interfaces/jdbc/org/postgresql/jdbc1/Connection.java
 create mode 100644 src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Connection.java
 create mode 100644 src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1ResultSet.java
 create mode 100644 src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Statement.java
 delete mode 100644 src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java
 delete mode 100644 src/interfaces/jdbc/org/postgresql/jdbc1/Statement.java
 create mode 100644 src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Connection.java
 create mode 100644 src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java
 create mode 100644 src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java
 delete mode 100644 src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java
 create mode 100644 src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Connection.java
 create mode 100644 src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2ResultSet.java
 create mode 100644 src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Statement.java
 delete mode 100644 src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java
 delete mode 100644 src/interfaces/jdbc/org/postgresql/jdbc2/Statement.java

diff --git a/src/interfaces/jdbc/Makefile b/src/interfaces/jdbc/Makefile
index 3b88af4d3c7..fc881a34ba2 100644
--- a/src/interfaces/jdbc/Makefile
+++ b/src/interfaces/jdbc/Makefile
@@ -4,7 +4,7 @@
 #
 # Copyright (c) 2001, PostgreSQL Global Development Group
 #
-# $Header: /cvsroot/pgsql/src/interfaces/jdbc/Attic/Makefile,v 1.34 2002/03/05 17:55:23 momjian Exp $
+# $Header: /cvsroot/pgsql/src/interfaces/jdbc/Attic/Makefile,v 1.35 2002/07/23 03:59:54 barry Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -38,5 +38,5 @@ uninstall:
 clean distclean maintainer-clean:
 	$(ANT) -buildfile $(srcdir)/build.xml clean
 
-check:
+check: all
 	$(ANT) -buildfile $(srcdir)/build.xml test
diff --git a/src/interfaces/jdbc/build.xml b/src/interfaces/jdbc/build.xml
index c8b541d6a66..278053eeace 100644
--- a/src/interfaces/jdbc/build.xml
+++ b/src/interfaces/jdbc/build.xml
@@ -6,7 +6,7 @@
 
   This file now requires Ant 1.4.1.  2002-04-18
 
-  $Header: /cvsroot/pgsql/src/interfaces/jdbc/Attic/build.xml,v 1.24 2002/06/27 04:38:01 barry Exp $
+  $Header: /cvsroot/pgsql/src/interfaces/jdbc/Attic/build.xml,v 1.25 2002/07/23 03:59:54 barry Exp $
 
 -->
 
@@ -29,7 +29,7 @@
     in the CLASSPATH (ie JDK1.2 or later), and then enterprise if the
     javax.sql.DataSource class is present.
 
-    Important: This must have the following order: jdbc1, jdbc2, enterprise
+    Important: This must have the following order: jdbc1, jdbc2, jdbc3
   -->
   <target name="check_versions">
     <condition property="jdbc1">
@@ -39,22 +39,12 @@
       <or>
         <equals arg1="${ant.java.version}" arg2="1.2"/>
         <equals arg1="${ant.java.version}" arg2="1.3"/>
-        <equals arg1="${ant.java.version}" arg2="1.4"/>
       </or>
     </condition> 
     <condition property="jdbc3">
         <equals arg1="${ant.java.version}" arg2="1.4"/>
     </condition> 
-    <condition property="datasource">
-      <and>
-      <or>
-        <equals arg1="${ant.java.version}" arg2="1.2"/>
-        <equals arg1="${ant.java.version}" arg2="1.3"/>
-        <equals arg1="${ant.java.version}" arg2="1.4"/>
-      </or>     
-        <available classname="javax.sql.DataSource"/>
-      </and>
-    </condition>
+    <available property="datasource" classname="javax.sql.DataSource"/>
     <available property="junit" classname="junit.framework.Test" />
   </target>
 
@@ -97,16 +87,17 @@
 
       <exclude name="${package}/jdbc1/**" unless="jdbc1"/>
       <exclude name="${package}/jdbc2/**" unless="jdbc2"/>
+      <exclude name="${package}/jdbc3/**" unless="jdbc3"/>
  
-      <exclude name="${package}/largeobject/PGblob.java" unless="jdbc2" />
-      <exclude name="${package}/largeobject/PGclob.java" unless="jdbc2" />
+      <exclude name="${package}/largeobject/PGblob.java" if="jdbc1" />
+      <exclude name="${package}/largeobject/PGclob.java" if="jdbc1" />
 
       <exclude name="${package}/PostgresqlDataSource.java" unless="datasource" />
       <exclude name="${package}/xa/**" unless="datasource" />
 
       <exclude name="${package}/test/**" unless="junit" />
-      <exclude name="${package}/test/jdbc2/**" unless="jdbc2" />
-      <exclude name="${package}/test/JDBC2Tests.java" unless="jdbc2" />
+      <exclude name="${package}/test/jdbc2/**" if="jdbc1" />
+      <exclude name="${package}/test/JDBC2Tests.java" if="jdbc1" />
     </javac>
   </target>
 
@@ -121,10 +112,10 @@
         <equals arg1="${jdbc1}" arg2="true"/>
     </condition>
     <condition property="edition" value="JDBC2">
-      <or>
         <equals arg1="${jdbc2}" arg2="true"/>
-        <equals arg1="${jdbc3}" arg2="true"/> <!-- fake it for now -->
-      </or>
+    </condition>
+    <condition property="edition" value="JDBC3">
+        <equals arg1="${jdbc3}" arg2="true"/> 
     </condition>
     <condition property="edition" value="JDBC2 Enterprise">
       <and>
@@ -134,8 +125,8 @@
     </condition>
 
     <!-- determine the connection class -->
-    <property name="connectclass" value="org.postgresql.jdbc1.Connection" />
-    <available property="connectclass" value="org.postgresql.jdbc2.Connection" classname="java.lang.ThreadLocal" />
+    <property name="connectclass" value="org.postgresql.jdbc1.Jdbc1Connection" />
+    <available property="connectclass" value="org.postgresql.jdbc2.Jdbc2Connection" classname="java.lang.ThreadLocal" />
 
     <!-- Some defaults -->
     <filter token="MAJORVERSION" value="${major}" />
@@ -173,13 +164,13 @@
     <javac srcdir="${srcdir}" destdir="${builddir}" debug="${debug}">
       <include name="example/**" />
       <exclude name="example/corba/**"/>
-      <exclude name="example/blobtest.java" unless="jdk1.2+"/>
+      <exclude name="example/blobtest.java" if="jdbc1"/>
     </javac>
   </target>
 
 
   <!-- Builds the corba example -->
-  <target name="corba" if="jdk1.2+">
+  <target name="corba" if="jdbc2">
     <exec dir="${srcdir}/example/corba" executable="idl2java">
       <arg value="stock.idl" />
     </exec>
@@ -230,8 +221,8 @@
 
   <target name="test" depends="jar" if="junit">
     <javac srcdir="${srcdir}" destdir="${builddir}" debug="${debug}">
-      <include name="${package}/test/jdbc2/**" if="jdk1.2+" />
-      <include name="${package}/test/java2ee/**" if="jdk1.2e+" />
+      <include name="${package}/test/jdbc2/**" if="jdbc2" />
+      <include name="${package}/test/jdbc2/**" if="jdbc3" />
     </javac>
 
     <java fork="yes" classname="junit.${junit.ui}.TestRunner" taskname="junit" failonerror="true">
diff --git a/src/interfaces/jdbc/example/ImageViewer.java b/src/interfaces/jdbc/example/ImageViewer.java
index f61a8870e7b..0401780b5ca 100644
--- a/src/interfaces/jdbc/example/ImageViewer.java
+++ b/src/interfaces/jdbc/example/ImageViewer.java
@@ -205,7 +205,7 @@ public class ImageViewer implements ItemListener
 		stat = db.createStatement();
 
 		// Also, get the LargeObjectManager for this connection
-		lom = ((org.postgresql.Connection)db).getLargeObjectAPI();
+		lom = ((org.postgresql.PGConnection)db).getLargeObjectAPI();
 
 		// Now refresh the image selection list
 		refreshList();
@@ -299,7 +299,7 @@ public class ImageViewer implements ItemListener
 				try
 				{
 					// fetch the large object manager
-					LargeObjectManager lom = ((org.postgresql.Connection)db).getLargeObjectAPI();
+					LargeObjectManager lom = ((org.postgresql.PGConnection)db).getLargeObjectAPI();
 
 					db.setAutoCommit(false);
 
diff --git a/src/interfaces/jdbc/example/basic.java b/src/interfaces/jdbc/example/basic.java
index 9a4469d83a0..5f07a56c3f5 100644
--- a/src/interfaces/jdbc/example/basic.java
+++ b/src/interfaces/jdbc/example/basic.java
@@ -6,7 +6,7 @@ import java.text.*;
 
 /*
  *
- * $Id: basic.java,v 1.11 2001/11/25 23:26:56 barry Exp $
+ * $Id: basic.java,v 1.12 2002/07/23 03:59:54 barry Exp $
  *
  * This example tests the basic components of the JDBC driver, and shows
  * how even the simplest of queries can be implemented.
@@ -87,9 +87,8 @@ public class basic
 		st.executeUpdate("insert into basic values (3,1)");
 
 		// This shows how to get the oid of a just inserted row
-		// updated for 7.1
 		st.executeUpdate("insert into basic values (4,1)");
-		long insertedOID = ((org.postgresql.Statement)st).getLastOID();
+		long insertedOID = ((org.postgresql.PGStatement)st).getLastOID();
 		System.out.println("Inserted row with oid " + insertedOID);
 
 		// Now change the value of b from 1 to 8
diff --git a/src/interfaces/jdbc/example/blobtest.java b/src/interfaces/jdbc/example/blobtest.java
index 271026250dd..d517d267b75 100644
--- a/src/interfaces/jdbc/example/blobtest.java
+++ b/src/interfaces/jdbc/example/blobtest.java
@@ -76,7 +76,7 @@ public class blobtest
 		// objects, however the unique methods available to postgresql makes
 		// things a little easier.
 		System.out.println("Gaining access to large object api");
-		lobj = ((org.postgresql.Connection)db).getLargeObjectAPI();
+		lobj = ((org.postgresql.PGConnection)db).getLargeObjectAPI();
 
 		int oid = ownapi_test1();
 		ownapi_test2(oid);
diff --git a/src/interfaces/jdbc/example/threadsafe.java b/src/interfaces/jdbc/example/threadsafe.java
index cca7be75bee..c35570a4c2a 100644
--- a/src/interfaces/jdbc/example/threadsafe.java
+++ b/src/interfaces/jdbc/example/threadsafe.java
@@ -301,7 +301,7 @@ public class threadsafe
 			//st = c.createStatement();
 
 			// create a blob
-			lom = ((org.postgresql.Connection)c).getLargeObjectAPI();
+			lom = ((org.postgresql.PGConnection)c).getLargeObjectAPI();
 			oid = lom.create();
 			System.out.println("Thread 3 has created a blob of oid " + oid);
 		}
diff --git a/src/interfaces/jdbc/org/postgresql/Driver.java.in b/src/interfaces/jdbc/org/postgresql/Driver.java.in
index c53747902ff..ecb22c7a0da 100644
--- a/src/interfaces/jdbc/org/postgresql/Driver.java.in
+++ b/src/interfaces/jdbc/org/postgresql/Driver.java.in
@@ -116,7 +116,7 @@ public class Driver implements java.sql.Driver
 		{
 			if (Driver.logDebug) Driver.debug("connect " + url);
 
-			org.postgresql.Connection con = (org.postgresql.Connection)(Class.forName("@JDBCCONNECTCLASS@").newInstance());
+			@JDBCCONNECTCLASS@ con = (@JDBCCONNECTCLASS@)(Class.forName("@JDBCCONNECTCLASS@").newInstance());
 			con.openConnection (host(), port(), props, database(), url, this);
 			return (java.sql.Connection)con;
 		}
diff --git a/src/interfaces/jdbc/org/postgresql/Field.java b/src/interfaces/jdbc/org/postgresql/Field.java
index 8ab28057ef2..1dbaa72c097 100644
--- a/src/interfaces/jdbc/org/postgresql/Field.java
+++ b/src/interfaces/jdbc/org/postgresql/Field.java
@@ -17,7 +17,7 @@ public class Field
 	private int mod;		// type modifier of this field
 	private String name;		// Name of this field
 
-	private Connection conn;	// Connection Instantation
+	private org.postgresql.PGConnection conn;	// Connection Instantation
 
 
 	/*
@@ -28,7 +28,7 @@ public class Field
 	 * @param oid the OID of the field
 	 * @param len the length of the field
 	 */
-	public Field(Connection conn, String name, int oid, int length, int mod)
+	public Field(org.postgresql.PGConnection conn, String name, int oid, int length, int mod)
 	{
 		this.conn = conn;
 		this.name = name;
@@ -45,7 +45,7 @@ public class Field
 	 * @param oid the OID of the field
 	 * @param len the length of the field
 	 */
-	public Field(Connection conn, String name, int oid, int length)
+	public Field(org.postgresql.PGConnection conn, String name, int oid, int length)
 	{
 		this(conn, name, oid, length, 0);
 	}
diff --git a/src/interfaces/jdbc/org/postgresql/PGConnection.java b/src/interfaces/jdbc/org/postgresql/PGConnection.java
new file mode 100644
index 00000000000..c05f31222c5
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/PGConnection.java
@@ -0,0 +1,72 @@
+package org.postgresql;
+
+import java.sql.*;
+import java.util.Properties;
+import java.util.Vector;
+import org.postgresql.core.Encoding;
+import org.postgresql.fastpath.Fastpath;
+import org.postgresql.largeobject.LargeObjectManager;
+
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/PGConnection.java,v 1.1 2002/07/23 03:59:55 barry Exp $
+ * This interface defines PostgreSQL extentions to the java.sql.Connection interface.
+ * Any java.sql.Connection object returned by the driver will also implement this 
+ * interface
+ */
+public interface PGConnection
+{
+    /*
+     * Get the character encoding to use for this connection.
+     */
+    public Encoding getEncoding() throws SQLException;
+
+    /* 
+     * This method returns the java.sql.Types type for a postgres datatype name
+     */
+    public int getSQLType(String pgTypeName) throws SQLException;
+
+    /*
+     * This returns the java.sql.Types type for a postgres datatype OID
+     */
+    public int getSQLType(int oid) throws SQLException;
+
+    /*
+     * This returns the postgres datatype name from the 
+     * postgres datatype OID
+     */
+    public String getPGType(int oid) throws SQLException;
+
+    /*
+     * This returns the postgres datatype OID from the
+     * postgres datatype name
+     */
+    public int getPGType(String typeName) throws SQLException;
+
+    /*
+     * This returns the LargeObject API for the current connection.
+     */
+    public LargeObjectManager getLargeObjectAPI() throws SQLException;
+
+    /*
+     * This returns the Fastpath API for the current connection.
+     */
+    public Fastpath getFastpathAPI() throws SQLException;
+
+    /*
+     * This method is used internally to return an object based around
+     * org.postgresql's more unique data types.
+     *
+     * <p>It uses an internal Hashtable to get the handling class. If the
+     * type is not supported, then an instance of org.postgresql.util.PGobject
+     * is returned.
+     *
+     * You can use the getValue() or setValue() methods to handle the returned
+     * object. Custom objects can have their own methods.
+     *
+     * @return PGobject for this type, and set to value
+     * @exception SQLException if value is not correct for this type
+     * @see org.postgresql.util.Serialize
+     */
+    public Object getObject(String type, String value) throws SQLException;
+
+}
+
diff --git a/src/interfaces/jdbc/org/postgresql/PGStatement.java b/src/interfaces/jdbc/org/postgresql/PGStatement.java
new file mode 100644
index 00000000000..1295afbe5aa
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/PGStatement.java
@@ -0,0 +1,21 @@
+package org.postgresql;
+
+
+import java.sql.*;
+
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/PGStatement.java,v 1.3 2002/07/23 03:59:55 barry Exp $
+ * This interface defines PostgreSQL extentions to the java.sql.Statement interface.
+ * Any java.sql.Statement object returned by the driver will also implement this 
+ * interface
+ */
+public interface PGStatement
+{
+
+	/*
+	 * Returns the Last inserted/updated oid. 
+	 * @return OID of last insert
+         * @since 7.3
+	 */
+        public long getLastOID() throws SQLException;
+
+}
diff --git a/src/interfaces/jdbc/org/postgresql/ResultSet.java b/src/interfaces/jdbc/org/postgresql/ResultSet.java
deleted file mode 100644
index 6e533eed010..00000000000
--- a/src/interfaces/jdbc/org/postgresql/ResultSet.java
+++ /dev/null
@@ -1,264 +0,0 @@
-package org.postgresql;
-
-import java.lang.*;
-import java.io.*;
-import java.math.*;
-import java.text.*;
-import java.util.*;
-import java.sql.*;
-import org.postgresql.largeobject.*;
-import org.postgresql.util.*;
-
-/*
- * This class implements the common internal methods used by both JDBC 1 and
- * JDBC 2 specifications.
- */
-public abstract class ResultSet
-{
-	protected Vector rows;			// The results
-	protected Field fields[];		// The field descriptions
-	protected String status;		// Status of the result
-	protected boolean binaryCursor = false; // is the data binary or Strings
-	protected int updateCount;		// How many rows did we get back?
-	protected long insertOID;		// The oid of an inserted row
-	protected int current_row;		// Our pointer to where we are at
-	protected byte[][] this_row;		// the current row result
-	protected Connection connection;	// the connection which we returned from
-	protected SQLWarning warnings = null;	// The warning chain
-	protected boolean wasNullFlag = false;	// the flag for wasNull()
-
-	//	We can chain multiple resultSets together - this points to
-	// next resultSet in the chain.
-	protected ResultSet next = null;
-
-	/*
-	 * 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 ResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor)
-	{
-		this.connection = conn;
-		this.fields = fields;
-		this.rows = tuples;
-		this.status = status;
-		this.updateCount = updateCount;
-		this.insertOID = insertOID;
-		this.this_row = null;
-		this.current_row = -1;
-		this.binaryCursor = binaryCursor;
-	}
-
-
-	/*
-	 * 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 ResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount)
-	{
-		this(conn, fields, tuples, status, updateCount, 0, false);
-	}
-
-	/*
-	 * We at times need to know if the resultSet we are working
-	 * with is the result of an UPDATE, DELETE or INSERT (in which
-	 * case, we only have a row count), or of a SELECT operation
-	 * (in which case, we have multiple fields) - this routine
-	 * tells us.
-	 *
-	 * @return true if we have tuples available
-	 */
-	public boolean reallyResultSet()
-	{
-		return (fields != null);
-	}
-
-	/*
-	 * Since ResultSets can be chained, we need some method of
-	 * finding the next one in the chain.  The method getNext()
-	 * returns the next one in the chain.
-	 *
-	 * @return the next ResultSet, or null if there are none
-	 */
-	public java.sql.ResultSet getNext()
-	{
-		return (java.sql.ResultSet)next;
-	}
-
-	/*
-	 * This following method allows us to add a ResultSet object
-	 * to the end of the current chain.
-	 *
-	 * @param r the resultset to add to the end of the chain.
-	 */
-	public void append(ResultSet r)
-	{
-		if (next == null)
-			next = r;
-		else
-			next.append(r);
-	}
-
-	/*
-	 * If we are just a place holder for results, we still need
-	 * to get an updateCount.  This method returns it.
-	 *
-	 * @return the updateCount
-	 */
-	public int getResultCount()
-	{
-		return updateCount;
-	}
-
-	/*
-	 * We also need to provide a couple of auxiliary functions for
-	 * the implementation of the ResultMetaData functions.	In
-	 * particular, we need to know the number of rows and the
-	 * number of columns.  Rows are also known as Tuples
-	 *
-	 * @return the number of rows
-	 */
-	public int getTupleCount()
-	{
-		return rows.size();
-	}
-
-	/*
-	 * getColumnCount returns the number of columns
-	 *
-	 * @return the number of columns
-	 */
-	public int getColumnCount()
-	{
-		return fields.length;
-	}
-
-	/*
-	 * Returns the status message from the backend.<p>
-	 * It is used internally by the driver.
-	 *
-	 * @return the status string from the backend
-	 */
-	public String getStatusString()
-	{
-		return status;
-	}
-
-	/*
-	 * returns the OID of a field.<p>
-	 * It is used internally by the driver.
-	 *
-	 * @param field field id
-	 * @return the oid of that field's type
-	 */
-	public int getColumnOID(int field)
-	{
-		return fields[field -1].getOID();
-	}
-
-	/*
-	 * returns the OID of the last inserted row.  Deprecated in 7.2 because
-         * range for OID values is greater than java signed int.
-	 * @deprecated Replaced by getLastOID() in 7.2
-	 */
-	public int getInsertedOID()
-	{
-	    return (int) getLastOID();
-	}
-
-
-	/*
-	 * returns the OID of the last inserted row
-         * @since 7.2
-	 */
-	public long getLastOID()
-	{
-		return insertOID;
-	}
-
-	/*
-	 * This is part of the JDBC API, but is required by org.postgresql.Field
-	 */
-	public abstract void close() throws SQLException;
-	public abstract boolean next() throws SQLException;
-	public abstract String getString(int i) throws SQLException;
-
-	/*
-	 * This is used to fix get*() methods on Money fields. It should only be
-	 * used by those methods!
-	 *
-	 * It converts ($##.##) to -##.## and $##.## to ##.##
-	 */
-	public String getFixedString(int col) throws SQLException
-	{
-		String s = getString(col);
-
-		// Handle SQL Null
-		wasNullFlag = (this_row[col - 1] == null);
-		if (wasNullFlag)
-			return null;
-
-		// Handle Money
-		if (s.charAt(0) == '(')
-		{
-			s = "-" + org.postgresql.util.PGtokenizer.removePara(s).substring(1);
-		}
-		if (s.charAt(0) == '$')
-		{
-			s = s.substring(1);
-		}
-
-		return s;
-	}
-
-	/**
-	 * The first warning reported by calls on this ResultSet is
-	 * returned.  Subsequent ResultSet warnings will be chained
-	 * to this SQLWarning.
-	 *
-	 * <p>The warning chain is automatically cleared each time a new
-	 * row is read.
-	 *
-	 * <p><B>Note:</B> This warning chain only covers warnings caused by
-	 * ResultSet methods.  Any warnings caused by statement methods
-	 * (such as reading OUT parameters) will be chained on the
-	 * Statement object.
-	 *
-	 * @return the first SQLWarning or null;
-	 * @exception SQLException if a database access error occurs.
-	 */
-	public SQLWarning getWarnings() throws SQLException
-	{
-		return warnings;
-	}
-
-        /**
-	 * Add a warning chain to the current warning chain
-	 * @param warnings warnings to add
-	 */    
-        public void addWarnings(SQLWarning warnings) {
-	    if ( this.warnings != null )
-		this.warnings.setNextWarning(warnings);
-	    else
-		this.warnings = warnings;
-	}
-	protected void checkResultSet( int column ) throws SQLException
-	{
-		if ( this_row == null ) throw new PSQLException("postgresql.res.nextrequired");
-		if ( column < 1 || column > fields.length ) throw new PSQLException("postgresql.res.colrange" );
-	}
-}
-
diff --git a/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java b/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java
index bfa6af35723..40c6a31d7f8 100644
--- a/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java
+++ b/src/interfaces/jdbc/org/postgresql/core/QueryExecutor.java
@@ -13,7 +13,7 @@ import org.postgresql.util.PSQLException;
  * <p>The lifetime of a QueryExecutor object is from sending the query
  * until the response has been received from the backend.
  *
- * $Id: QueryExecutor.java,v 1.12 2002/03/26 05:52:49 barry Exp $
+ * $Id: QueryExecutor.java,v 1.13 2002/07/23 03:59:55 barry Exp $
  */
 
 public class QueryExecutor
@@ -22,18 +22,18 @@ public class QueryExecutor
         private final String sql;
         private final java.sql.Statement statement;
         private final PG_Stream pg_stream;
-        private final org.postgresql.Connection connection;
+        private final org.postgresql.jdbc1.AbstractJdbc1Connection connection;
 
         public QueryExecutor(String sql,
                                                  java.sql.Statement statement,
                                                  PG_Stream pg_stream,
-                                                 org.postgresql.Connection connection)
+                                                 java.sql.Connection connection)
         throws SQLException
         {
                 this.sql = sql;
                 this.statement = statement;
                 this.pg_stream = pg_stream;
-                this.connection = connection;
+                this.connection = (org.postgresql.jdbc1.AbstractJdbc1Connection)connection;
 
                 if (statement != null)
                         maxRows = statement.getMaxRows();
@@ -122,7 +122,7 @@ public class QueryExecutor
                         if ( errorMessage != null )
                                 throw new SQLException( errorMessage.toString() );
 
-                        return connection.getResultSet(connection, statement, fields, tuples, status, update_count, insert_oid, binaryCursor);
+                        return connection.getResultSet(statement, fields, tuples, status, update_count, insert_oid, binaryCursor);
                 }
         }
 
diff --git a/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java b/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java
index 20f5a6f3e26..d166b10f83b 100644
--- a/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java
+++ b/src/interfaces/jdbc/org/postgresql/fastpath/Fastpath.java
@@ -28,7 +28,7 @@ public class Fastpath
         // to a connection).
         protected Hashtable func = new Hashtable();
 
-        protected org.postgresql.Connection conn;		// our connection
+        protected org.postgresql.PGConnection conn;		// our connection
         protected org.postgresql.PG_Stream stream;	// the network stream
 
         /*
@@ -41,7 +41,7 @@ public class Fastpath
          * @param conn org.postgresql.Connection to attach to
          * @param stream The network stream to the backend
          */
-        public Fastpath(org.postgresql.Connection conn, org.postgresql.PG_Stream stream)
+        public Fastpath(org.postgresql.PGConnection conn, org.postgresql.PG_Stream stream)
         {
                 this.conn = conn;
                 this.stream = stream;
@@ -113,7 +113,7 @@ public class Fastpath
                                                 //------------------------------
                                                 // Notice from backend
                                         case 'N':
-                                                conn.addWarning(stream.ReceiveString(conn.getEncoding()));
+                                                ((org.postgresql.jdbc1.AbstractJdbc1Connection)conn).addWarning(stream.ReceiveString(conn.getEncoding()));
                                                 break;
 
                                         case 'V':
diff --git a/src/interfaces/jdbc/org/postgresql/Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java
similarity index 89%
rename from src/interfaces/jdbc/org/postgresql/Connection.java
rename to src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java
index 7951ddd1ecb..98aa33e5c91 100644
--- a/src/interfaces/jdbc/org/postgresql/Connection.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java
@@ -1,34 +1,38 @@
-package org.postgresql;
+package org.postgresql.jdbc1;
 
-import java.io.*;
-import java.net.*;
+
+import java.io.IOException;
+import java.net.ConnectException;
 import java.sql.*;
 import java.util.*;
 import org.postgresql.Driver;
-import org.postgresql.Field;
-import org.postgresql.fastpath.*;
-import org.postgresql.largeobject.*;
-import org.postgresql.util.*;
+import org.postgresql.PG_Stream;
 import org.postgresql.core.*;
+import org.postgresql.fastpath.Fastpath;
+import org.postgresql.largeobject.LargeObjectManager;
+import org.postgresql.util.*;
+
 
-/*
- * $Id: Connection.java,v 1.48 2002/06/11 02:55:15 barry Exp $
- *
- * This abstract class is used by org.postgresql.Driver to open either the JDBC1 or
- * JDBC2 versions of the Connection class.
- *
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Connection.java,v 1.1 2002/07/23 03:59:55 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
  */
-public abstract class Connection
+public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnection
 {
         // This is the network stream associated with this connection
         public PG_Stream pg_stream;
 
-        private String PG_HOST;
-        private int PG_PORT;
-        private String PG_USER;
-        private String PG_DATABASE;
-        private boolean PG_STATUS;
-        private String compatible;
+        protected String PG_HOST;
+        protected int PG_PORT;
+        protected String PG_USER;
+        protected String PG_DATABASE;
+        protected boolean PG_STATUS;
+        protected String compatible;
+
+        // The PID an cancellation key we get from the backend process
+        protected int pid;
+        protected int ckey;
 
         /*
          The encoding to use for this connection.
@@ -43,7 +47,7 @@ public abstract class Connection
         public boolean autoCommit = true;
         public boolean readOnly = false;
 
-        public Driver this_driver;
+        public org.postgresql.Driver this_driver;
         private String this_url;
         private String cursor = null;	// The positioned update cursor name
 
@@ -74,50 +78,6 @@ public abstract class Connection
          */
         private int isolationLevel = java.sql.Connection.TRANSACTION_READ_COMMITTED;
 
-        // The PID an cancellation key we get from the backend process
-        public int pid;
-        public int ckey;
-
-        /*
-         * This is called by Class.forName() from within org.postgresql.Driver
-         */
-        public Connection()
-        {}
-
-        public void cancelQuery() throws SQLException
-        {
-                PG_Stream cancelStream = null;
-                try {
-                        cancelStream = new PG_Stream(PG_HOST, PG_PORT);
-                } catch (ConnectException cex) {
-                        // Added by Peter Mount <peter@retep.org.uk>
-                        // ConnectException is thrown when the connection cannot be made.
-                        // we trap this an return a more meaningful message for the end user
-                        throw new PSQLException ("postgresql.con.refused");
-                } catch (IOException e) {
-                        throw new PSQLException ("postgresql.con.failed",e);
-                }
-
-                // Now we need to construct and send a cancel packet
-                try {
-                        cancelStream.SendInteger(16, 4);
-                        cancelStream.SendInteger(80877102, 4);
-                        cancelStream.SendInteger(pid, 4);
-                        cancelStream.SendInteger(ckey, 4);
-                        cancelStream.flush();
-                }
-                catch(IOException e) {
-                        throw new PSQLException("postgresql.con.failed",e);
-                }
-                finally {
-                        try {
-                                if(cancelStream != null)
-                                        cancelStream.close();
-                        }
-                        catch(IOException e) {} // Ignore
-                }
-        }
-
         /*
          * This method actually opens the connection. It is called by Driver.
          *
@@ -125,12 +85,11 @@ public abstract class Connection
          * @param port the port number of the postmaster process
          * @param info a Properties[] thing of the user and password
          * @param database the database to connect to
-         * @param u the URL of the connection
+         * @param url the URL of the connection
          * @param d the Driver instantation of the connection
-         * @return a valid connection profile
          * @exception SQLException if a database access error occurs
          */
-        protected void openConnection(String host, int port, Properties info, String database, String url, Driver d) throws SQLException
+        public void openConnection(String host, int port, Properties info, String database, String url, org.postgresql.Driver d) throws SQLException
         {
                 firstWarning = null;
 
@@ -140,7 +99,7 @@ public abstract class Connection
                 if (info.getProperty("user") == null)
                         throw new PSQLException("postgresql.con.user");
 
-                this_driver = d;
+                this_driver = (org.postgresql.Driver)d;
                 this_url = url;
 
                 PG_DATABASE = database;
@@ -168,19 +127,19 @@ public abstract class Connection
                 int l_logLevel = 0;
                 try {
 		    l_logLevel = Integer.parseInt(l_logLevelProp);
-                    if (l_logLevel > Driver.DEBUG || l_logLevel < Driver.INFO) {
+                    if (l_logLevel > org.postgresql.Driver.DEBUG || l_logLevel < org.postgresql.Driver.INFO) {
                         l_logLevel = 0;
 		    }
 		} catch (Exception l_e) {
                     //invalid value for loglevel ignore
 		}
                 if (l_logLevel > 0) {
-                    Driver.setLogLevel(l_logLevel);
+                    org.postgresql.Driver.setLogLevel(l_logLevel);
                     enableDriverManagerLogging();
 		}
 
                 //Print out the driver version number
-                if (Driver.logInfo) Driver.info(Driver.getVersion());
+                if (org.postgresql.Driver.logInfo) org.postgresql.Driver.info(org.postgresql.Driver.getVersion());
 
                 // Now make the initial connection
                 try
@@ -238,7 +197,7 @@ public abstract class Connection
                                                         rst[0] = (byte)pg_stream.ReceiveChar();
                                                         rst[1] = (byte)pg_stream.ReceiveChar();
                                                         salt = new String(rst, 0, 2);
-                                                        if (Driver.logDebug) Driver.debug("Crypt salt=" + salt);
+                                                        if (org.postgresql.Driver.logDebug) org.postgresql.Driver.debug("Crypt salt=" + salt);
                                                 }
 
                                                 // Or get the md5 password salt if there is one
@@ -250,7 +209,7 @@ public abstract class Connection
                                                         rst[2] = (byte)pg_stream.ReceiveChar();
                                                         rst[3] = (byte)pg_stream.ReceiveChar();
                                                         salt = new String(rst, 0, 4);
-                                                        if (Driver.logDebug) Driver.debug("MD5 salt=" + salt);
+                                                        if (org.postgresql.Driver.logDebug) org.postgresql.Driver.debug("MD5 salt=" + salt);
                                                 }
 
                                                 // now send the auth packet
@@ -260,15 +219,15 @@ public abstract class Connection
                                                                 break;
 
                                                         case AUTH_REQ_KRB4:
-                                                                if (Driver.logDebug) Driver.debug("postgresql: KRB4");
+                                                                if (org.postgresql.Driver.logDebug) org.postgresql.Driver.debug("postgresql: KRB4");
                                                                 throw new PSQLException("postgresql.con.kerb4");
 
                                                         case AUTH_REQ_KRB5:
-                                                                if (Driver.logDebug) Driver.debug("postgresql: KRB5");
+                                                                if (org.postgresql.Driver.logDebug) org.postgresql.Driver.debug("postgresql: KRB5");
                                                                 throw new PSQLException("postgresql.con.kerb5");
 
                                                         case AUTH_REQ_PASSWORD:
-                                                                if (Driver.logDebug) Driver.debug("postgresql: PASSWORD");
+                                                                if (org.postgresql.Driver.logDebug) org.postgresql.Driver.debug("postgresql: PASSWORD");
                                                                 pg_stream.SendInteger(5 + password.length(), 4);
                                                                 pg_stream.Send(password.getBytes());
                                                                 pg_stream.SendInteger(0, 1);
@@ -276,7 +235,7 @@ public abstract class Connection
                                                                 break;
 
                                                         case AUTH_REQ_CRYPT:
-                                                                if (Driver.logDebug) Driver.debug("postgresql: CRYPT");
+                                                                if (org.postgresql.Driver.logDebug) org.postgresql.Driver.debug("postgresql: CRYPT");
                                                                 String crypted = UnixCrypt.crypt(salt, password);
                                                                 pg_stream.SendInteger(5 + crypted.length(), 4);
                                                                 pg_stream.Send(crypted.getBytes());
@@ -285,7 +244,7 @@ public abstract class Connection
                                                                 break;
 
                                                         case AUTH_REQ_MD5:
-                                                                if (Driver.logDebug) Driver.debug("postgresql: MD5");
+                                                                if (org.postgresql.Driver.logDebug) org.postgresql.Driver.debug("postgresql: MD5");
                                                                 byte[] digest = MD5Digest.encode(PG_USER, password, salt);
                                                                 pg_stream.SendInteger(5 + digest.length, 4);
                                                                 pg_stream.Send(digest);
@@ -386,10 +345,23 @@ public abstract class Connection
                 PG_STATUS = CONNECTION_OK;
         }
 
+
+        /*
+         * Return the instance of org.postgresql.Driver
+         * that created this connection
+         */
+        public org.postgresql.Driver getDriver()
+        {
+	    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.
 
+//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;
+
         /*
          * This adds a warning to the warning chain.
          * @param msg message to add
@@ -448,7 +420,7 @@ public abstract class Connection
          */
         public java.sql.ResultSet ExecSQL(String sql, java.sql.Statement stat) throws SQLException
         {
-                return new QueryExecutor(sql, stat, pg_stream, this).execute();
+                return new QueryExecutor(sql, stat, pg_stream, (java.sql.Connection)this).execute();
         }
 
         /*
@@ -569,7 +541,7 @@ public abstract class Connection
         public LargeObjectManager getLargeObjectAPI() throws SQLException
         {
                 if (largeobject == null)
-                        largeobject = new LargeObjectManager(this);
+                        largeobject = new LargeObjectManager((java.sql.Connection)this);
                 return largeobject;
         }
 
@@ -606,7 +578,7 @@ public abstract class Connection
                         // can handle it
                         if (o == null)
                         {
-                                Serialize ser = new Serialize(this, type);
+                                Serialize ser = new Serialize((java.sql.Connection)this, type);
                                 objectTypes.put(type, ser);
                                 return ser.fetch(Integer.parseInt(value));
                         }
@@ -679,7 +651,7 @@ public abstract class Connection
                         // can handle it
                         if (x == null)
                         {
-                                Serialize ser = new Serialize(this, type);
+                                Serialize ser = new Serialize((java.sql.Connection)this, type);
                                 objectTypes.put(type, ser);
                                 return ser.storeObject(o);
                         }
@@ -756,15 +728,6 @@ public abstract class Connection
                         objectTypes.put(defaultObjectTypes[i][0], defaultObjectTypes[i][1]);
         }
 
-        // These are required by other common classes
-        public abstract java.sql.Statement createStatement() throws SQLException;
-
-        /*
-         * This returns a resultset. It must be overridden, so that the correct
-         * version (from jdbc1 or jdbc2) are returned.
-         */
-        public abstract java.sql.ResultSet getResultSet(org.postgresql.Connection conn, java.sql.Statement stat, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException;
-
         /*
          * In some cases, it is desirable to immediately release a Connection's
          * database and JDBC resources instead of waiting for them to be
@@ -1162,8 +1125,8 @@ public abstract class Connection
                 // it's not in the cache, so perform a query, and add the result to the cache
                 if (sqlType == null)
                 {
-                        ResultSet result = (org.postgresql.ResultSet)ExecSQL("select typname from pg_type where oid = " + oid);
-                        if (result.getColumnCount() != 1 || result.getTupleCount() != 1)
+                        ResultSet result = ExecSQL("select typname from pg_type where oid = " + oid);
+                        if (((AbstractJdbc1ResultSet)result).getColumnCount() != 1 || ((AbstractJdbc1ResultSet)result).getTupleCount() != 1)
                                 throw new PSQLException("postgresql.unexpected");
                         result.next();
                         String pgType = result.getString(1);
@@ -1177,20 +1140,12 @@ public abstract class Connection
                 return sqlType.intValue();
         }
 
-        /*
-         * This returns the java.sql.Types type for a PG type
-         *
-         * @param pgTypeName PostgreSQL type name
-         * @return the java.sql.Types type
-         */
-        public abstract int getSQLType(String pgTypeName);
-
         /*
          * This returns the oid for a given PG data type
          * @param typeName PostgreSQL type name
          * @return PostgreSQL oid value for a field of this type
          */
-        public int getOID(String typeName) throws SQLException
+        public int getPGType(String typeName) throws SQLException
         {
                 int oid = -1;
                 if (typeName != null)
@@ -1203,9 +1158,9 @@ public abstract class Connection
                         else
                         {
                                 // it's not in the cache, so perform a query, and add the result to the cache
-                                ResultSet result = (org.postgresql.ResultSet)ExecSQL("select oid from pg_type where typname='"
+                                ResultSet result = ExecSQL("select oid from pg_type where typname='"
                                                                    + typeName + "'");
-                                if (result.getColumnCount() != 1 || result.getTupleCount() != 1)
+                                if (((AbstractJdbc1ResultSet)result).getColumnCount() != 1 || ((AbstractJdbc1ResultSet)result).getTupleCount() != 1)
                                         throw new PSQLException("postgresql.unexpected");
                                 result.next();
                                 oid = Integer.parseInt(result.getString(1));
@@ -1242,5 +1197,91 @@ public abstract class Connection
 	    }
 	}
 
+	// This is a cache of the DatabaseMetaData instance for this connection
+	protected java.sql.DatabaseMetaData metadata;
+
+
+	/*
+	 * Tests to see if a Connection is closed
+	 *
+	 * @return the status of the connection
+	 * @exception SQLException (why?)
+	 */
+	public boolean isClosed() throws SQLException
+	{
+		return (pg_stream == null);
+	}
+
+	/* 
+	 * This implemetation uses the jdbc1Types array to support the jdbc1
+	 * datatypes.  Basically jdbc1 and jdbc2 are the same, except that
+	 * jdbc2 adds the Array types.
+	 */
+	public int getSQLType(String pgTypeName)
+	{
+		int sqlType = Types.OTHER; // default value
+		for (int i = 0;i < jdbc1Types.length;i++)
+		{
+			if (pgTypeName.equals(jdbc1Types[i]))
+			{
+				sqlType = jdbc1Typei[i];
+				break;
+			}
+		}
+		return sqlType;
+	}
+
+	/*
+	 * This table holds the org.postgresql names for the types supported.
+	 * Any types that map to Types.OTHER (eg POINT) don't go into this table.
+	 * They default automatically to Types.OTHER
+	 *
+	 * Note: This must be in the same order as below.
+	 *
+	 * Tip: keep these grouped together by the Types. value
+	 */
+	private static final String jdbc1Types[] = {
+				"int2",
+				"int4", "oid",
+				"int8",
+				"cash", "money",
+				"numeric",
+				"float4",
+				"float8",
+				"bpchar", "char", "char2", "char4", "char8", "char16",
+				"varchar", "text", "name", "filename",
+				"bytea",
+				"bool",
+				"date",
+				"time",
+				"abstime", "timestamp", "timestamptz"
+			};
+
+	/*
+	 * This table holds the JDBC type for each entry above.
+	 *
+	 * Note: This must be in the same order as above
+	 *
+	 * Tip: keep these grouped together by the Types. value
+	 */
+	private static final int jdbc1Typei[] = {
+												Types.SMALLINT,
+												Types.INTEGER, Types.INTEGER,
+												Types.BIGINT,
+												Types.DOUBLE, Types.DOUBLE,
+												Types.NUMERIC,
+												Types.REAL,
+												Types.DOUBLE,
+												Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR,
+												Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+												Types.BINARY,
+												Types.BIT,
+												Types.DATE,
+												Types.TIME,
+												Types.TIMESTAMP, Types.TIMESTAMP, Types.TIMESTAMP
+											};
+
+
 }
 
+
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java
new file mode 100644
index 00000000000..5aa4f90298a
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java
@@ -0,0 +1,957 @@
+package org.postgresql.jdbc1;
+
+
+import java.math.BigDecimal;
+import java.io.*;
+import java.sql.*;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Vector;
+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/jdbc1/Attic/AbstractJdbc1ResultSet.java,v 1.1 2002/07/23 03:59:55 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 Field fields[];		// The field descriptions
+	protected String status;		// Status of the result
+	protected boolean binaryCursor = false; // is the data binary or Strings
+	protected int updateCount;		// How many rows did we get back?
+	protected long insertOID;		// The oid of an inserted row
+	protected int current_row;		// Our pointer to where we are at
+	protected byte[][] this_row;		// the current row result
+	protected org.postgresql.PGConnection connection;	// the connection which we returned from
+	protected SQLWarning warnings = null;	// The warning chain
+	protected boolean wasNullFlag = false;	// the flag for wasNull()
+
+	//	We can chain multiple resultSets together - this points to
+	// next resultSet in the chain.
+	protected ResultSet next = null;
+
+	protected StringBuffer sbuf = null;
+	public byte[][] rowBuffer=null;
+
+
+	public AbstractJdbc1ResultSet(org.postgresql.PGConnection conn, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor)
+	{
+		this.connection = conn;
+		this.fields = fields;
+		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 next() throws SQLException
+	{
+                if (rows == null)
+                        throw new PSQLException("postgresql.con.closed");
+
+		if (++current_row >= rows.size())
+			return false;
+
+		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 close() throws SQLException
+	{
+		//release resources held (memory for tuples)
+		if (rows != null)
+		{
+			rows = null;
+		}
+	}
+
+	public boolean wasNull() throws SQLException
+	{
+		return wasNullFlag;
+	}
+
+	public String getString(int columnIndex) throws SQLException
+	{
+		checkResultSet( columnIndex );
+		wasNullFlag = (this_row[columnIndex - 1] == null);
+		if (wasNullFlag)
+			return null;
+
+		Encoding encoding = connection.getEncoding();
+		return encoding.decode(this_row[columnIndex - 1]);
+	}
+
+	public boolean getBoolean(int columnIndex) throws SQLException
+	{
+		return toBoolean( getString(columnIndex) );
+	}
+
+
+	public byte getByte(int columnIndex) throws SQLException
+	{
+		String s = getString(columnIndex);
+
+		if (s != null)
+		{
+			try
+			{
+				return Byte.parseByte(s);
+			}
+			catch (NumberFormatException e)
+			{
+				throw new PSQLException("postgresql.res.badbyte", s);
+			}
+		}
+		return 0;		// SQL NULL
+	}
+
+	public short getShort(int columnIndex) throws SQLException
+	{
+		String s = getFixedString(columnIndex);
+
+		if (s != null)
+		{
+			try
+			{
+				return Short.parseShort(s);
+			}
+			catch (NumberFormatException e)
+			{
+				throw new PSQLException("postgresql.res.badshort", s);
+			}
+		}
+		return 0;		// SQL NULL
+	}
+
+	public int getInt(int columnIndex) throws SQLException
+	{
+		return toInt( getFixedString(columnIndex) );
+	}
+
+	public long getLong(int columnIndex) throws SQLException
+	{
+		return toLong( getFixedString(columnIndex) );
+	}
+
+	public float getFloat(int columnIndex) throws SQLException
+	{
+		return toFloat( getFixedString(columnIndex) );
+	}
+
+	public double getDouble(int columnIndex) throws SQLException
+	{
+		return toDouble( getFixedString(columnIndex) );
+	}
+
+	public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException
+	{
+		return toBigDecimal( getFixedString(columnIndex), scale );
+	}
+
+	/*
+	 * Get the value of a column in the current row as a Java byte array.
+	 *
+	 * <p>In normal use, the bytes represent the raw values returned by the
+	 * backend. However, if the column is an OID, then it is assumed to
+	 * refer to a Large Object, and that object is returned as a byte array.
+	 *
+	 * <p><b>Be warned</b> If the large object is huge, then you may run out
+	 * of memory.
+	 *
+	 * @param columnIndex the first column is 1, the second is 2, ...
+	 * @return the column value; if the value is SQL NULL, the result
+	 *	is null
+	 * @exception SQLException if a database access error occurs
+	 */
+	public byte[] getBytes(int columnIndex) throws SQLException
+	{
+		checkResultSet( columnIndex );
+		wasNullFlag = (this_row[columnIndex - 1] == null);
+		if (!wasNullFlag)
+		{
+			if (binaryCursor)
+			{
+				//If the data is already binary then just return it
+				return this_row[columnIndex - 1];
+			}
+			else if (((AbstractJdbc1Connection)connection).haveMinimumCompatibleVersion("7.2"))
+			{
+				//Version 7.2 supports the bytea datatype for byte arrays
+				if (fields[columnIndex - 1].getPGType().equals("bytea"))
+				{
+					return PGbytea.toBytes(this_row[columnIndex - 1]);
+				}
+				else
+				{
+					return this_row[columnIndex - 1];
+				}
+			}
+			else
+			{
+				//Version 7.1 and earlier supports LargeObjects for byte arrays
+				// Handle OID's as BLOBS
+				if ( fields[columnIndex - 1].getOID() == 26)
+				{
+					LargeObjectManager lom = connection.getLargeObjectAPI();
+					LargeObject lob = lom.open(getInt(columnIndex));
+					byte buf[] = lob.read(lob.size());
+					lob.close();
+					return buf;
+				}
+				else
+				{
+					return this_row[columnIndex - 1];
+				}
+			}
+		}
+		return null;
+	}
+
+	public java.sql.Date getDate(int columnIndex) throws SQLException
+	{
+		return toDate( getString(columnIndex) );
+	}
+
+	public Time getTime(int columnIndex) throws SQLException
+	{
+		return toTime( getString(columnIndex), (java.sql.ResultSet)this, fields[columnIndex-1].getPGType() );
+	}
+
+	public Timestamp getTimestamp(int columnIndex) throws SQLException
+	{
+		return toTimestamp( getString(columnIndex), (java.sql.ResultSet)this, fields[columnIndex-1].getPGType() );
+	}
+
+	public InputStream getAsciiStream(int columnIndex) throws SQLException
+	{
+		checkResultSet( columnIndex );
+		wasNullFlag = (this_row[columnIndex - 1] == null);
+		if (wasNullFlag)
+			return null;
+
+		if (((AbstractJdbc1Connection)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
+			try
+			{
+				return new ByteArrayInputStream(getString(columnIndex).getBytes("ASCII"));
+			}
+			catch (UnsupportedEncodingException l_uee)
+			{
+				throw new PSQLException("postgresql.unusual", l_uee);
+			}
+		}
+		else
+		{
+			// In 7.1 Handle as BLOBS so return the LargeObject input stream
+			return getBinaryStream(columnIndex);
+		}
+	}
+
+	public InputStream getUnicodeStream(int columnIndex) throws SQLException
+	{
+		checkResultSet( columnIndex );
+		wasNullFlag = (this_row[columnIndex - 1] == null);
+		if (wasNullFlag)
+			return null;
+
+		if (((AbstractJdbc1Connection)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
+			try
+			{
+				return new ByteArrayInputStream(getString(columnIndex).getBytes("UTF-8"));
+			}
+			catch (UnsupportedEncodingException l_uee)
+			{
+				throw new PSQLException("postgresql.unusual", l_uee);
+			}
+		}
+		else
+		{
+			// In 7.1 Handle as BLOBS so return the LargeObject input stream
+			return getBinaryStream(columnIndex);
+		}
+	}
+
+	public InputStream getBinaryStream(int columnIndex) throws SQLException
+	{
+		checkResultSet( columnIndex );
+		wasNullFlag = (this_row[columnIndex - 1] == null);
+		if (wasNullFlag)
+			return null;
+
+		if (((AbstractJdbc1Connection)connection).haveMinimumCompatibleVersion("7.2"))
+		{
+			//Version 7.2 supports BinaryStream for all PG bytea type
+			//As the spec/javadoc for this method indicate this is to be used for
+			//large binary values (i.e. LONGVARBINARY)	PG doesn't have a separate
+			//long binary datatype, but with toast the bytea datatype is capable of
+			//handling very large values.  Thus the implementation ends up calling
+			//getBytes() since there is no current way to stream the value from the server
+			byte b[] = getBytes(columnIndex);
+			if (b != null)
+				return new ByteArrayInputStream(b);
+		}
+		else
+		{
+			// In 7.1 Handle as BLOBS so return the LargeObject input stream
+			if ( fields[columnIndex - 1].getOID() == 26)
+			{
+				LargeObjectManager lom = connection.getLargeObjectAPI();
+				LargeObject lob = lom.open(getInt(columnIndex));
+				return lob.getInputStream();
+			}
+		}
+		return null;
+	}
+
+	public String getString(String columnName) throws SQLException
+	{
+		return getString(findColumn(columnName));
+	}
+
+	public boolean getBoolean(String columnName) throws SQLException
+	{
+		return getBoolean(findColumn(columnName));
+	}
+
+	public byte getByte(String columnName) throws SQLException
+	{
+
+		return getByte(findColumn(columnName));
+	}
+
+	public short getShort(String columnName) throws SQLException
+	{
+		return getShort(findColumn(columnName));
+	}
+
+	public int getInt(String columnName) throws SQLException
+	{
+		return getInt(findColumn(columnName));
+	}
+
+	public long getLong(String columnName) throws SQLException
+	{
+		return getLong(findColumn(columnName));
+	}
+
+	public float getFloat(String columnName) throws SQLException
+	{
+		return getFloat(findColumn(columnName));
+	}
+
+	public double getDouble(String columnName) throws SQLException
+	{
+		return getDouble(findColumn(columnName));
+	}
+
+	public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException
+	{
+		return getBigDecimal(findColumn(columnName), scale);
+	}
+
+	public byte[] getBytes(String columnName) throws SQLException
+	{
+		return getBytes(findColumn(columnName));
+	}
+
+	public java.sql.Date getDate(String columnName) throws SQLException
+	{
+		return getDate(findColumn(columnName));
+	}
+
+	public Time getTime(String columnName) throws SQLException
+	{
+		return getTime(findColumn(columnName));
+	}
+
+	public Timestamp getTimestamp(String columnName) throws SQLException
+	{
+		return getTimestamp(findColumn(columnName));
+	}
+
+	public InputStream getAsciiStream(String columnName) throws SQLException
+	{
+		return getAsciiStream(findColumn(columnName));
+	}
+
+	public InputStream getUnicodeStream(String columnName) throws SQLException
+	{
+		return getUnicodeStream(findColumn(columnName));
+	}
+
+	public InputStream getBinaryStream(String columnName) throws SQLException
+	{
+		return getBinaryStream(findColumn(columnName));
+	}
+
+	public SQLWarning getWarnings() throws SQLException
+	{
+		return warnings;
+	}
+
+	public void clearWarnings() throws SQLException
+	{
+		warnings = null;
+	}
+
+        public void addWarnings(SQLWarning warnings) {
+	    if ( this.warnings != null )
+		this.warnings.setNextWarning(warnings);
+	    else
+		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
+	 *
+	 * <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;
+
+		if (columnIndex < 1 || columnIndex > fields.length)
+			throw new PSQLException("postgresql.res.colrange");
+		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);
+			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 Object getObject(String columnName) throws SQLException
+	{
+		return getObject(findColumn(columnName));
+	}
+
+	/*
+	 * Map a ResultSet column name to a ResultSet column index
+	 */
+	public int findColumn(String columnName) throws SQLException
+	{
+		int i;
+
+		final int flen = fields.length;
+		for (i = 0 ; i < flen; ++i)
+			if (fields[i].getName().equalsIgnoreCase(columnName))
+				return (i + 1);
+		throw new PSQLException ("postgresql.res.colname", columnName);
+	}
+
+
+	/*
+	 * We at times need to know if the resultSet we are working
+	 * with is the result of an UPDATE, DELETE or INSERT (in which
+	 * case, we only have a row count), or of a SELECT operation
+	 * (in which case, we have multiple fields) - this routine
+	 * tells us.
+	 */
+	public boolean reallyResultSet()
+	{
+		return (fields != null);
+	}
+
+	/*
+	 * Since ResultSets can be chained, we need some method of
+	 * finding the next one in the chain.  The method getNext()
+	 * returns the next one in the chain.
+	 *
+	 * @return the next ResultSet, or null if there are none
+	 */
+	public java.sql.ResultSet getNext()
+	{
+		return (java.sql.ResultSet)next;
+	}
+
+	/*
+	 * This following method allows us to add a ResultSet object
+	 * to the end of the current chain.
+	 */
+	public void append(AbstractJdbc1ResultSet r)
+	{
+		if (next == null)
+			next = (java.sql.ResultSet)r;
+		else
+			((AbstractJdbc1ResultSet)next).append(r);
+	}
+
+	/*
+	 * If we are just a place holder for results, we still need
+	 * to get an updateCount.  This method returns it.
+	 */
+	public int getResultCount()
+	{
+		return updateCount;
+	}
+
+	/*
+	 * We also need to provide a couple of auxiliary functions for
+	 * the implementation of the ResultMetaData functions.	In
+	 * particular, we need to know the number of rows and the
+	 * number of columns.  Rows are also known as Tuples
+	 */
+	public int getTupleCount()
+	{
+		return rows.size();
+	}
+
+	/*
+	 * getColumnCount returns the number of columns
+	 */
+	public int getColumnCount()
+	{
+		return fields.length;
+	}
+
+	/*
+	 * Returns the status message from the backend.<p>
+	 * It is used internally by the driver.
+	 */
+	public String getStatusString()
+	{
+		return status;
+	}
+
+	/*
+	 * returns the OID of a field.<p>
+	 * It is used internally by the driver.
+	 */
+	public int getColumnOID(int field)
+	{
+		return fields[field -1].getOID();
+	}
+
+	/*
+	 * returns the OID of the last inserted row.  Deprecated in 7.2 because
+         * range for OID values is greater than java signed int.
+	 * @deprecated Replaced by getLastOID() in 7.2
+	 */
+	public int getInsertedOID()
+	{
+	    return (int) getLastOID();
+	}
+
+
+	/*
+	 * returns the OID of the last inserted row
+         * @since 7.2
+	 */
+	public long getLastOID()
+	{
+		return insertOID;
+	}
+
+	/*
+	 * This is used to fix get*() methods on Money fields. It should only be
+	 * used by those methods!
+	 *
+	 * It converts ($##.##) to -##.## and $##.## to ##.##
+	 */
+	public String getFixedString(int col) throws SQLException
+	{
+		String s = getString(col);
+
+		// Handle SQL Null
+		wasNullFlag = (this_row[col - 1] == null);
+		if (wasNullFlag)
+			return null;
+
+		// Handle Money
+		if (s.charAt(0) == '(')
+		{
+			s = "-" + org.postgresql.util.PGtokenizer.removePara(s).substring(1);
+		}
+		if (s.charAt(0) == '$')
+		{
+			s = s.substring(1);
+		}
+
+		return s;
+	}
+
+	protected void checkResultSet( int column ) throws SQLException
+	{
+		if ( this_row == null ) throw new PSQLException("postgresql.res.nextrequired");
+		if ( column < 1 || column > fields.length ) throw new PSQLException("postgresql.res.colrange" );
+	}
+
+	//----------------- Formatting Methods -------------------
+
+	public static boolean toBoolean(String s)
+	{
+		if (s != null)
+		{
+			int c = s.charAt(0);
+			return ((c == 't') || (c == 'T') || (c == '1'));
+		}
+		return false;		// SQL NULL
+	}
+
+	public static int toInt(String s) throws SQLException
+	{
+		if (s != null)
+		{
+			try
+			{
+				return Integer.parseInt(s);
+			}
+			catch (NumberFormatException e)
+			{
+				throw new PSQLException ("postgresql.res.badint", s);
+			}
+		}
+		return 0;		// SQL NULL
+	}
+
+	public static long toLong(String s) throws SQLException
+	{
+		if (s != null)
+		{
+			try
+			{
+				return Long.parseLong(s);
+			}
+			catch (NumberFormatException e)
+			{
+				throw new PSQLException ("postgresql.res.badlong", s);
+			}
+		}
+		return 0;		// SQL NULL
+	}
+
+	public static BigDecimal toBigDecimal(String s, int scale) throws SQLException
+	{
+		BigDecimal val;
+		if (s != null)
+		{
+			try
+			{
+				val = new BigDecimal(s);
+			}
+			catch (NumberFormatException e)
+			{
+				throw new PSQLException ("postgresql.res.badbigdec", s);
+			}
+			if (scale == -1)
+				return val;
+			try
+			{
+				return val.setScale(scale);
+			}
+			catch (ArithmeticException e)
+			{
+				throw new PSQLException ("postgresql.res.badbigdec", s);
+			}
+		}
+		return null;		// SQL NULL
+	}
+
+	public static float toFloat(String s) throws SQLException
+	{
+		if (s != null)
+		{
+			try
+			{
+				return Float.valueOf(s).floatValue();
+			}
+			catch (NumberFormatException e)
+			{
+				throw new PSQLException ("postgresql.res.badfloat", s);
+			}
+		}
+		return 0;		// SQL NULL
+	}
+
+	public static double toDouble(String s) throws SQLException
+	{
+		if (s != null)
+		{
+			try
+			{
+				return Double.valueOf(s).doubleValue();
+			}
+			catch (NumberFormatException e)
+			{
+				throw new PSQLException ("postgresql.res.baddouble", s);
+			}
+		}
+		return 0;		// SQL NULL
+	}
+
+	public static java.sql.Date toDate(String s) throws SQLException
+	{
+		if (s == null)
+			return null;
+		// length == 10: SQL Date
+		// length >  10: SQL Timestamp, assumes PGDATESTYLE=ISO
+		try
+		{
+			return java.sql.Date.valueOf((s.length() == 10) ? s : s.substring(0, 10));
+		}
+		catch (NumberFormatException e)
+		{
+			throw new PSQLException("postgresql.res.baddate", s);
+		}
+	}
+
+	public static Time toTime(String s, java.sql.ResultSet resultSet, String pgDataType) throws SQLException
+	{
+		if (s == null)
+			return null; // SQL NULL
+		try
+		{
+                   if (s.length() == 8) {
+                     //value is a time value
+                     return java.sql.Time.valueOf(s);
+                   } else if (s.indexOf(".") == 8) {
+                     //value is a time value with fractional seconds
+                     java.sql.Time l_time = java.sql.Time.valueOf(s.substring(0,8));
+                     String l_strMillis = s.substring(9);
+                     if (l_strMillis.length() > 3)
+                       l_strMillis = l_strMillis.substring(0,3);
+                     int l_millis = Integer.parseInt(l_strMillis);
+                     if (l_millis < 10) {
+                       l_millis = l_millis * 100;
+                     } else if (l_millis < 100) {
+                       l_millis = l_millis * 10;
+                     }
+                     return new java.sql.Time(l_time.getTime() + l_millis);
+                   } else {
+                     //value is a timestamp
+                     return new java.sql.Time(toTimestamp(s, resultSet, pgDataType).getTime());
+                   }
+		}
+		catch (NumberFormatException e)
+		{
+			throw new PSQLException("postgresql.res.badtime", s);
+		}
+	}
+
+	/**
+	* Parse a string and return a timestamp representing its value.
+	*
+	* The driver is set to return ISO date formated strings. We modify this
+	* string from the ISO format to a format that Java can understand. Java
+	* expects timezone info as 'GMT+09:00' where as ISO gives '+09'.
+	* Java also expects fractional seconds to 3 places where postgres
+	* will give, none, 2 or 6 depending on the time and postgres version.
+	* From version 7.2 postgres returns fractional seconds to 6 places.
+	* If available, we drop the last 3 digits.
+	*
+	* @param s         The ISO formated date string to parse.
+	* @param resultSet The ResultSet this date is part of.
+	*
+	* @return null if s is null or a timestamp of the parsed string s.
+	*
+	* @throws SQLException if there is a problem parsing s.
+	**/
+	public static Timestamp toTimestamp(String s, java.sql.ResultSet resultSet, String pgDataType)
+	throws SQLException
+	{
+                AbstractJdbc1ResultSet rs = (AbstractJdbc1ResultSet)resultSet;
+		if (s == null)
+			return null;
+
+		// We must be synchronized here incase more theads access the ResultSet
+		// bad practice but possible. Anyhow this is to protect sbuf and
+		// SimpleDateFormat objects
+		synchronized (rs)
+		{
+			SimpleDateFormat df = null;
+			if ( org.postgresql.Driver.logDebug ) org.postgresql.Driver.debug("the data from the DB is "+s);
+
+			// If first time, create the buffer, otherwise clear it.
+			if (rs.sbuf == null)
+				rs.sbuf = new StringBuffer();
+			else
+				rs.sbuf.setLength(0);
+
+			// Copy s into sbuf for parsing.
+			rs.sbuf.append(s);
+			int slen = s.length();
+
+			if (slen > 19)
+			{
+				// The len of the ISO string to the second value is 19 chars. If
+				// greater then 19, there may be tz info and perhaps fractional
+				// second info which we need to change to java to read it.
+
+				// cut the copy to second value "2001-12-07 16:29:22"
+				int i = 19;
+				rs.sbuf.setLength(i);
+
+				char c = s.charAt(i++);
+				if (c == '.')
+				{
+					// Found a fractional value. Append up to 3 digits including
+					// the leading '.'
+					do
+					{
+						if (i < 24)
+							rs.sbuf.append(c);
+						c = s.charAt(i++);
+					} while (i < slen && Character.isDigit(c));
+
+					// If there wasn't at least 3 digits we should add some zeros
+					// to make up the 3 digits we tell java to expect.
+					for (int j = i; j < 24; j++)
+						rs.sbuf.append('0');
+				}
+				else
+				{
+					// No fractional seconds, lets add some.
+					rs.sbuf.append(".000");
+				}
+
+				if (i < slen)
+				{
+					// prepend the GMT part and then add the remaining bit of
+					// the string.
+					rs.sbuf.append(" GMT");
+					rs.sbuf.append(c);
+					rs.sbuf.append(s.substring(i, slen));
+
+					// Lastly, if the tz part doesn't specify the :MM part then
+					// we add ":00" for java.
+					if (slen - i < 5)
+						rs.sbuf.append(":00");
+
+					// we'll use this dateformat string to parse the result.
+					df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z");
+				}
+				else
+				{
+				    // Just found fractional seconds but no timezone.
+				    //If timestamptz then we use GMT, else local timezone
+		                    if (pgDataType.equals("timestamptz")) {
+				        rs.sbuf.append(" GMT");
+					df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z");
+			            } else {
+					df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+			            }
+				}
+			}
+			else if (slen == 19)
+			{
+			    // No tz or fractional second info.
+			    //If timestamptz then we use GMT, else local timezone
+		            if (pgDataType.equals("timestamptz")) {
+				rs.sbuf.append(" GMT");
+				df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
+			    } else {
+				df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+			    }
+			}
+			else
+			{
+				// We must just have a date. This case is
+				// needed if this method is called on a date
+				// column
+				df = new SimpleDateFormat("yyyy-MM-dd");
+			}
+
+			try
+			{
+				// All that's left is to parse the string and return the ts.
+				if ( org.postgresql.Driver.logDebug ) org.postgresql.Driver.debug( "" + df.parse(rs.sbuf.toString()).getTime() );
+
+				return new Timestamp(df.parse(rs.sbuf.toString()).getTime());
+			}
+			catch (ParseException e)
+			{
+				throw new PSQLException("postgresql.res.badtimestamp", new Integer(e.getErrorOffset()), s);
+			}
+		}
+	}
+
+
+
+}
+
diff --git a/src/interfaces/jdbc/org/postgresql/Statement.java b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java
similarity index 61%
rename from src/interfaces/jdbc/org/postgresql/Statement.java
rename to src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java
index ea2cc0d0c33..9c4d2b1cd9c 100644
--- a/src/interfaces/jdbc/org/postgresql/Statement.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java
@@ -1,24 +1,22 @@
-package org.postgresql;
+package org.postgresql.jdbc1;
 
 import java.sql.*;
 import org.postgresql.util.PSQLException;
 
-/*
- * This class defines methods implemented by the two subclasses
- * org.postgresql.jdbc1.Statement and org.postgresql.jdbc2.Statement that are
- * unique to PostgreSQL's JDBC driver.
- *
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.1 2002/07/23 03:59:55 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
  */
-
-public abstract class Statement
+public abstract class AbstractJdbc1Statement implements org.postgresql.PGStatement
 {
 
+        // The connection who created us
+	protected AbstractJdbc1Connection connection;  
+
 	/** The warnings chain. */
 	protected SQLWarning warnings = null;
 
-	/** The current results */
-	protected java.sql.ResultSet result = null;
-
 	/** Maximum number of rows to return, 0 = unlimited */
 	protected int maxrows = 0;
 
@@ -27,14 +25,146 @@ public abstract class Statement
 
 	protected boolean escapeProcessing = true;
 
+	/** The current results */
+	protected java.sql.ResultSet result = null;
+
 	// Static variables for parsing SQL when escapeProcessing is true.
 	private static final short IN_SQLCODE = 0;
 	private static final short IN_STRING = 1;
 	private static final short BACKSLASH = 2;
 	private static final short ESC_TIMEDATE = 3;
 
-	public Statement()
-	{}
+	/*
+	 * Execute a SQL statement that retruns a single ResultSet
+	 *
+	 * @param sql typically a static SQL SELECT statement
+	 * @return a ResulSet that contains the data produced by the query
+	 * @exception SQLException if a database access error occurs
+	 */
+	public java.sql.ResultSet executeQuery(String sql) throws SQLException
+	{
+		this.execute(sql);
+		while (result != null && !((AbstractJdbc1ResultSet)result).reallyResultSet())
+			result = ((AbstractJdbc1ResultSet)result).getNext();
+		if (result == null)
+			throw new PSQLException("postgresql.stat.noresult");
+		return result;
+	}
+
+	/*
+	 * Execute a SQL INSERT, UPDATE or DELETE statement.  In addition
+	 * SQL statements that return nothing such as SQL DDL statements
+	 * can be executed
+	 *
+	 * @param sql a SQL statement
+	 * @return either a row count, or 0 for SQL commands
+	 * @exception SQLException if a database access error occurs
+	 */
+	public int executeUpdate(String sql) throws SQLException
+	{
+		this.execute(sql);
+		if (((AbstractJdbc1ResultSet)result).reallyResultSet())
+			throw new PSQLException("postgresql.stat.result");
+		return this.getUpdateCount();
+	}
+
+	/*
+	 * Execute a SQL statement that may return multiple results. We
+	 * don't have to worry about this since we do not support multiple
+	 * ResultSets.	 You can use getResultSet or getUpdateCount to
+	 * retrieve the result.
+	 *
+	 * @param sql any SQL statement
+	 * @return true if the next result is a ResulSet, false if it is
+	 *	an update count or there are no more results
+	 * @exception SQLException if a database access error occurs
+	 */
+	public boolean execute(String sql) throws SQLException
+	{
+		if (escapeProcessing)
+			sql = escapeSQL(sql);
+
+		// New in 7.1, if we have a previous resultset then force it to close
+		// This brings us nearer to compliance, and helps memory management.
+		// Internal stuff will call ExecSQL directly, bypassing this.
+		if (result != null)
+		{
+			java.sql.ResultSet rs = getResultSet();
+			if (rs != null)
+				rs.close();
+		}
+
+
+		// 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());
+	}
+
+	/*
+	 * setCursorName defines the SQL cursor name that will be used by
+	 * subsequent execute methods.	This name can then be used in SQL
+	 * positioned update/delete statements to identify the current row
+	 * in the ResultSet generated by this statement.  If a database
+	 * doesn't support positioned update/delete, this method is a
+	 * no-op.
+	 *
+	 * <p><B>Note:</B> By definition, positioned update/delete execution
+	 * must be done by a different Statement than the one which
+	 * generated the ResultSet being used for positioning.	Also, cursor
+	 * names must be unique within a Connection.
+	 *
+	 * <p>We throw an additional constriction.	There can only be one
+	 * cursor active at any one time.
+	 *
+	 * @param name the new cursor name
+	 * @exception SQLException if a database access error occurs
+	 */
+	public void setCursorName(String name) throws SQLException
+	{
+		((AbstractJdbc1Connection)connection).setCursorName(name);
+	}
+
+
+	/*
+	 * getUpdateCount returns the current result as an update count,
+	 * if the result is a ResultSet or there are no more results, -1
+	 * is returned.  It should only be called once per result.
+	 *
+	 * @return the current result as an update count.
+	 * @exception SQLException if a database access error occurs
+	 */
+	public int getUpdateCount() throws SQLException
+	{
+		if (result == null)
+			return -1;
+		if (((AbstractJdbc1ResultSet)result).reallyResultSet())
+			return -1;
+		return ((AbstractJdbc1ResultSet)result).getResultCount();
+	}
+
+	/*
+	 * getMoreResults moves to a Statement's next result.  If it returns
+	 * true, this result is a ResulSet.
+	 *
+	 * @return true if the next ResultSet is valid
+	 * @exception SQLException if a database access error occurs
+	 */
+	public boolean getMoreResults() throws SQLException
+	{
+		result = ((AbstractJdbc1ResultSet)result).getNext();
+		return (result != null && ((AbstractJdbc1ResultSet)result).reallyResultSet());
+	}
+
+
+
+
+
+
+
+
+
+
 
 	/*
 	 * Returns the status message from the current Result.<p>
@@ -46,7 +176,7 @@ public abstract class Statement
 	{
 		if (result == null)
 			return null;
-		return ((org.postgresql.ResultSet) result).getStatusString();
+		return ((AbstractJdbc1ResultSet)result).getStatusString();
 	}
 
 	/*
@@ -194,30 +324,6 @@ public abstract class Statement
 		throw new PSQLException("postgresql.unimplemented"); 
 	}
 
-	/*
-	 * Returns the Last inserted/updated oid.  Deprecated in 7.2 because
-         * range of OID values is greater than a java signed int.
-	 * @deprecated Replaced by getLastOID in 7.2
-	 */
-	public int getInsertedOID() throws SQLException
-	{
-		if (result == null)
-			return 0;
-		return (int)((org.postgresql.ResultSet) result).getLastOID();
-	}
-
-	/*
-	 * Returns the Last inserted/updated oid. 
-	 * @return OID of last insert
-         * @since 7.2
-	 */
-	public long getLastOID() throws SQLException
-	{
-		if (result == null)
-			return 0;
-		return ((org.postgresql.ResultSet) result).getLastOID();
-	}
-
 	/*
 	 * getResultSet returns the current result as a ResultSet.	It
 	 * should only be called once per result.
@@ -227,7 +333,7 @@ public abstract class Statement
 	 */
 	public java.sql.ResultSet getResultSet() throws SQLException
 	{
-		if (result != null && ((org.postgresql.ResultSet) result).reallyResultSet())
+		if (result != null && ((AbstractJdbc1ResultSet) result).reallyResultSet())
 			return result;
 		return null;
 	}
@@ -328,4 +434,38 @@ public abstract class Statement
 
 		return newsql.toString();
 	}
+
+    /* 
+     *
+     * The following methods are postgres extensions and are defined 
+     * in the interface org.postgresql.Statement
+     *
+     */
+
+	/*
+	 * Returns the Last inserted/updated oid.  Deprecated in 7.2 because
+         * range of OID values is greater than a java signed int.
+	 * @deprecated Replaced by getLastOID in 7.2
+	 */
+	public int getInsertedOID() throws SQLException
+	{
+		if (result == null)
+			return 0;
+		return (int)((AbstractJdbc1ResultSet)result).getLastOID();
+	}
+
+	/*
+	 * Returns the Last inserted/updated oid. 
+	 * @return OID of last insert
+         * @since 7.2
+	 */
+	public long getLastOID() throws SQLException
+	{
+		if (result == null)
+			return 0;
+		return ((AbstractJdbc1ResultSet)result).getLastOID();
+	}
+
+
+
 }
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/CallableStatement.java b/src/interfaces/jdbc/org/postgresql/jdbc1/CallableStatement.java
index 4a006cd2208..10e8c5f4171 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/CallableStatement.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/CallableStatement.java
@@ -44,7 +44,7 @@ public class CallableStatement extends PreparedStatement implements java.sql.Cal
 	/*
 	 * @exception SQLException on failure
 	 */
-	CallableStatement(Connection c, String q) throws SQLException
+	CallableStatement(Jdbc1Connection c, String q) throws SQLException
 	{
 		super(c, q);
 	}
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc1/Connection.java
deleted file mode 100644
index 4d3e087f76b..00000000000
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/Connection.java
+++ /dev/null
@@ -1,214 +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.io.*;
-import java.lang.*;
-import java.lang.reflect.*;
-import java.net.*;
-import java.util.*;
-import java.sql.*;
-import org.postgresql.Field;
-import org.postgresql.fastpath.*;
-import org.postgresql.largeobject.*;
-import org.postgresql.util.*;
-
-/*
- * $Id: Connection.java,v 1.15 2002/01/15 06:55:13 barry Exp $
- *
- * A Connection represents a session with a specific database.	Within the
- * context of a Connection, SQL statements are executed and results are
- * returned.
- *
- * <P>A Connection's database is able to provide information describing
- * its tables, its supported SQL grammar, its stored procedures, the
- * capabilities of this connection, etc.  This information is obtained
- * with the getMetaData method.
- *
- * <p><B>Note:</B> By default, the Connection automatically commits changes
- * after executing each statement.	If auto-commit has been disabled, an
- * explicit commit must be done or database changes will not be saved.
- *
- * @see java.sql.Connection
- */
-public class Connection extends org.postgresql.Connection implements java.sql.Connection
-{
-	// This is a cache of the DatabaseMetaData instance for this connection
-	protected DatabaseMetaData metadata;
-
-	/*
-	 * SQL statements without parameters are normally executed using
-	 * Statement objects.  If the same SQL statement is executed many
-	 * times, it is more efficient to use a PreparedStatement
-	 *
-	 * @return a new Statement object
-	 * @exception SQLException passed through from the constructor
-	 */
-	public java.sql.Statement createStatement() throws SQLException
-	{
-		return new Statement(this);
-	}
-
-	/*
-	 * A SQL statement with or without IN parameters can be pre-compiled
-	 * and stored in a PreparedStatement object.  This object can then
-	 * be used to efficiently execute this statement multiple times.
-	 *
-	 * <B>Note:</B> This method is optimized for handling parametric
-	 * SQL statements that benefit from precompilation if the drivers
-	 * supports precompilation.  PostgreSQL does not support precompilation.
-	 * In this case, the statement is not sent to the database until the
-	 * PreparedStatement is executed.  This has no direct effect on users;
-	 * however it does affect which method throws certain SQLExceptions
-	 *
-	 * @param sql a SQL statement that may contain one or more '?' IN
-	 *	parameter placeholders
-	 * @return a new PreparedStatement object containing the pre-compiled
-	 *	statement.
-	 * @exception SQLException if a database access error occurs.
-	 */
-	public java.sql.PreparedStatement prepareStatement(String sql) throws SQLException
-	{
-		return new PreparedStatement(this, sql);
-	}
-
-	/*
-	 * A SQL stored procedure call statement is handled by creating a
-	 * CallableStatement for it.  The CallableStatement provides methods
-	 * for setting up its IN and OUT parameters and methods for executing
-	 * it.
-	 *
-	 * <B>Note:</B> This method is optimised for handling stored procedure
-	 * call statements.  Some drivers may send the call statement to the
-	 * database when the prepareCall is done; others may wait until the
-	 * CallableStatement is executed.  This has no direct effect on users;
-	 * however, it does affect which method throws certain SQLExceptions
-	 *
-	 * @param sql a SQL statement that may contain one or more '?' parameter
-	 *	placeholders.  Typically this statement is a JDBC function call
-	 *	escape string.
-	 * @return a new CallableStatement object containing the pre-compiled
-	 *	SQL statement
-	 * @exception SQLException if a database access error occurs
-	 */
-	public java.sql.CallableStatement prepareCall(String sql) throws SQLException
-	{
-		throw new PSQLException("postgresql.con.call");
-		//		return new CallableStatement(this, sql);
-	}
-
-	/*
-	 * Tests to see if a Connection is closed
-	 *
-	 * @return the status of the connection
-	 * @exception SQLException (why?)
-	 */
-	public boolean isClosed() throws SQLException
-	{
-		return (pg_stream == null);
-	}
-
-	/*
-	 * A connection's database is able to provide information describing
-	 * its tables, its supported SQL grammar, its stored procedures, the
-	 * capabilities of this connection, etc.  This information is made
-	 * available through a DatabaseMetaData object.
-	 *
-	 * @return a DatabaseMetaData object for this connection
-	 * @exception SQLException if a database access error occurs
-	 */
-	public java.sql.DatabaseMetaData getMetaData() throws SQLException
-	{
-		if (metadata == null)
-			metadata = new DatabaseMetaData(this);
-		return metadata;
-	}
-
-	/*
-	 * This overides the method in org.postgresql.Connection and returns a
-	 * ResultSet.
-	 */
-	public java.sql.ResultSet getResultSet(org.postgresql.Connection conn, java.sql.Statement stat, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException
-	{
-		// in jdbc1 stat is ignored.
-		return new org.postgresql.jdbc1.ResultSet((org.postgresql.jdbc1.Connection)conn, fields, tuples, status, updateCount, insertOID, binaryCursor);
-	}
-
-
-	/* An implementation of the abstract method in the parent class.
-	 * This implemetation uses the jdbc1Types array to support the jdbc1
-	 * datatypes.  Basically jdbc1 and jdbc2 are the same, except that
-	 * jdbc2 adds the Array types.
-	 */
-	public int getSQLType(String pgTypeName)
-	{
-		int sqlType = Types.OTHER; // default value
-		for (int i = 0;i < jdbc1Types.length;i++)
-		{
-			if (pgTypeName.equals(jdbc1Types[i]))
-			{
-				sqlType = jdbc1Typei[i];
-				break;
-			}
-		}
-		return sqlType;
-	}
-
-	/*
-	 * This table holds the org.postgresql names for the types supported.
-	 * Any types that map to Types.OTHER (eg POINT) don't go into this table.
-	 * They default automatically to Types.OTHER
-	 *
-	 * Note: This must be in the same order as below.
-	 *
-	 * Tip: keep these grouped together by the Types. value
-	 */
-	private static final String jdbc1Types[] = {
-				"int2",
-				"int4", "oid",
-				"int8",
-				"cash", "money",
-				"numeric",
-				"float4",
-				"float8",
-				"bpchar", "char", "char2", "char4", "char8", "char16",
-				"varchar", "text", "name", "filename",
-				"bytea",
-				"bool",
-				"date",
-				"time",
-				"abstime", "timestamp", "timestamptz"
-			};
-
-	/*
-	 * This table holds the JDBC type for each entry above.
-	 *
-	 * Note: This must be in the same order as above
-	 *
-	 * Tip: keep these grouped together by the Types. value
-	 */
-	private static final int jdbc1Typei[] = {
-												Types.SMALLINT,
-												Types.INTEGER, Types.INTEGER,
-												Types.BIGINT,
-												Types.DOUBLE, Types.DOUBLE,
-												Types.NUMERIC,
-												Types.REAL,
-												Types.DOUBLE,
-												Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR,
-												Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
-												Types.BINARY,
-												Types.BIT,
-												Types.DATE,
-												Types.TIME,
-												Types.TIMESTAMP, Types.TIMESTAMP, Types.TIMESTAMP
-											};
-
-
-}
-
-// ***********************************************************************
-
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java b/src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java
index 5fba1d68c00..747ee1f1ea4 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.47 2002/06/20 16:00:44 momjian Exp $
+ * $Id: DatabaseMetaData.java,v 1.48 2002/07/23 03:59:55 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
@@ -37,7 +37,7 @@ import org.postgresql.util.PSQLException;
  */
 public class DatabaseMetaData implements java.sql.DatabaseMetaData
 {
-	Connection connection;		// The connection association
+	Jdbc1Connection connection;		// The connection association
 
 	// These define various OID's. Hopefully they will stay constant.
 	static final int iVarcharOid = 1043;	// OID for varchar
@@ -46,7 +46,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
 	static final int iInt4Oid = 23; // OID for int4
 	static final int VARHDRSZ = 4;	// length for int4
 
-	public DatabaseMetaData(Connection conn)
+	public DatabaseMetaData(Jdbc1Connection conn)
 	{
 		this.connection = conn;
 	}
@@ -196,7 +196,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
 	 */
 	public String getDriverVersion() throws SQLException
 	{
-		return connection.this_driver.getVersion();
+		return connection.getDriver().getVersion();
 	}
 
 	/*
@@ -206,7 +206,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
 	 */
 	public int getDriverMajorVersion()
 	{
-		return connection.this_driver.getMajorVersion();
+		return connection.getDriver().getMajorVersion();
 	}
 
 	/*
@@ -216,7 +216,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
 	 */
 	public int getDriverMinorVersion()
 	{
-		return connection.this_driver.getMinorVersion();
+		return connection.getDriver().getMinorVersion();
 	}
 
 	/*
@@ -1549,7 +1549,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
 
 			v.addElement(tuple);
 		}
-		return new ResultSet(connection, f, v, "OK", 1);
+		return new Jdbc1ResultSet(connection, f, v, "OK", 1);
 	}
 
 	/*
@@ -1627,7 +1627,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
 
 		// add query loop here
 
-		return new ResultSet(connection, f, v, "OK", 1);
+		return new Jdbc1ResultSet(connection, f, v, "OK", 1);
 	}
 
 	/*
@@ -1721,7 +1721,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
 
 			byte remarks[] = null;
 
-			if (((org.postgresql.ResultSet)dr).getTupleCount() == 1)
+			if (((AbstractJdbc1ResultSet)dr).getTupleCount() == 1)
 			{
 				dr.next();
 				remarks = dr.getBytes(1);
@@ -1762,7 +1762,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
 			v.addElement(tuple);
 		}
 		r.close();
-		return new ResultSet(connection, f, v, "OK", 1);
+		return new Jdbc1ResultSet(connection, 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 ResultSet(connection, f, v, "OK", 1);
+		return new Jdbc1ResultSet(connection, 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 ResultSet(connection, f, v, "OK", 1);
+		return new Jdbc1ResultSet(connection, f, v, "OK", 1);
 	}
 
 	/*
@@ -2050,7 +2050,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
 		}
 		r.close();
 
-		return new ResultSet(connection, f, v, "OK", 1);
+		return new Jdbc1ResultSet(connection, f, v, "OK", 1);
 	}
 
 	/*
@@ -2113,7 +2113,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
 			//v.addElement(tuple);
 		}
 
-		return new ResultSet(connection, f, v, "OK", 1);
+		return new Jdbc1ResultSet(connection, 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 ResultSet(connection, f, v, "OK", 1);
+		return new Jdbc1ResultSet(connection, f, v, "OK", 1);
 	}
 
 	/*
@@ -2413,7 +2413,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
 			while (hasMore);
 		}
 
-		return new ResultSet(connection, f, tuples, "OK", 1);
+		return new Jdbc1ResultSet(connection, f, tuples, "OK", 1);
 	}
 
 	/*
@@ -2692,7 +2692,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
 				v.addElement(tuple);
 			}
 			rs.close();
-			return new ResultSet(connection, f, v, "OK", 1);
+			return new Jdbc1ResultSet(connection, f, v, "OK", 1);
 		}
 
 		throw new PSQLException("postgresql.metadata.unavailable");
@@ -2832,7 +2832,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
 			}
 		}
 
-		return new ResultSet(connection, f, v, "OK", 1);
+		return new Jdbc1ResultSet(connection, f, v, "OK", 1);
 	}
 
 }
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Connection.java
new file mode 100644
index 00000000000..55e527bd490
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Connection.java
@@ -0,0 +1,47 @@
+package org.postgresql.jdbc1;
+
+
+import java.util.Vector;
+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.1 2002/07/23 03:59:55 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
+ */
+public class Jdbc1Connection extends org.postgresql.jdbc1.AbstractJdbc1Connection implements java.sql.Connection
+{
+
+	public java.sql.Statement createStatement() throws SQLException
+	{
+		return new org.postgresql.jdbc1.Jdbc1Statement(this);
+	}
+
+	public java.sql.PreparedStatement prepareStatement(String sql) throws SQLException
+	{
+		return new org.postgresql.jdbc1.PreparedStatement(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");
+	}
+
+	public java.sql.DatabaseMetaData getMetaData() throws SQLException
+	{
+		if (metadata == null)
+			metadata = new org.postgresql.jdbc1.DatabaseMetaData(this);
+		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
+	{
+		return new Jdbc1ResultSet(this, fields, tuples, status, updateCount, insertOID, binaryCursor);
+	}
+
+}
+
+
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1ResultSet.java
new file mode 100644
index 00000000000..a959fef9d39
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1ResultSet.java
@@ -0,0 +1,32 @@
+package org.postgresql.jdbc1;
+
+
+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 $
+ * This class implements the java.sql.ResultSet interface for JDBC1.
+ * However most of the implementation is really done in 
+ * org.postgresql.jdbc1.AbstractJdbc1ResultSet
+ */
+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)
+	{
+		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);
+	}
+
+	public java.sql.ResultSetMetaData getMetaData() throws SQLException
+	{
+		return new ResultSetMetaData(rows, fields);
+	}
+
+}
+
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Statement.java b/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Statement.java
new file mode 100644
index 00000000000..bb073eae998
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/Jdbc1Statement.java
@@ -0,0 +1,19 @@
+package org.postgresql.jdbc1;
+
+
+import java.sql.*;
+
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1Statement.java,v 1.1 2002/07/23 03:59:55 barry Exp $
+ * This class implements the java.sql.Statement interface for JDBC1.
+ * However most of the implementation is really done in 
+ * org.postgresql.jdbc1.AbstractJdbc1Statement
+ */
+public class Jdbc1Statement extends org.postgresql.jdbc1.AbstractJdbc1Statement implements java.sql.Statement
+{
+
+	public Jdbc1Statement (Jdbc1Connection c)
+	{
+		connection = c;
+	}
+
+}
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/PreparedStatement.java b/src/interfaces/jdbc/org/postgresql/jdbc1/PreparedStatement.java
index 31926c500bd..9ef9a4289e5 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/PreparedStatement.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/PreparedStatement.java
@@ -29,12 +29,12 @@ import org.postgresql.util.*;
  * @see ResultSet
  * @see java.sql.PreparedStatement
  */
-public class PreparedStatement extends Statement implements java.sql.PreparedStatement
+public class PreparedStatement extends Jdbc1Statement implements java.sql.PreparedStatement
 {
 	String sql;
 	String[] templateStrings;
 	String[] inStrings;
-	Connection connection;
+	Jdbc1Connection connection;
 
 	// Some performance caches
 	private StringBuffer sbuf = new StringBuffer();
@@ -49,7 +49,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
 	 * @param sql the SQL statement with ? for IN markers
 	 * @exception SQLException if something bad occurs
 	 */
-	public PreparedStatement(Connection connection, String sql) throws SQLException
+	public PreparedStatement(Jdbc1Connection connection, String sql) throws SQLException
 	{
 		super(connection);
 
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java
deleted file mode 100644
index b6e054a3368..00000000000
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java
+++ /dev/null
@@ -1,1026 +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.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.core.Encoding;
-
-/*
- * A ResultSet provides access to a table of data generated by executing a
- * Statement.  The table rows are retrieved in sequence.  Within a row its
- * column values can be accessed in any order.
- *
- * <P>A ResultSet maintains a cursor pointing to its current row of data.
- * Initially the cursor is positioned before the first row.  The 'next'
- * method moves the cursor to the next row.
- *
- * <P>The getXXX methods retrieve column values for the current row.  You can
- * retrieve values either using the index number of the column, or by using
- * the name of the column.	In general using the column index will be more
- * efficient.  Columns are numbered from 1.
- *
- * <P>For maximum portability, ResultSet columns within each row should be read
- * in left-to-right order and each column should be read only once.
- *
- *<P> For the getXXX methods, the JDBC driver attempts to convert the
- * underlying data to the specified Java type and returns a suitable Java
- * value.  See the JDBC specification for allowable mappings from SQL types
- * to Java types with the ResultSet getXXX methods.
- *
- * <P>Column names used as input to getXXX methods are case insenstive.  When
- * performing a getXXX using a column name, if several columns have the same
- * name, then the value of the first matching column will be returned.	The
- * column name option is designed to be used when column names are used in the
- * SQL Query.  For columns that are NOT explicitly named in the query, it is
- * best to use column numbers.	If column names were used there is no way for
- * the programmer to guarentee that they actually refer to the intended
- * columns.
- *
- * <P>A ResultSet is automatically closed by the Statement that generated it
- * when that Statement is closed, re-executed, or is used to retrieve the
- * next result from a sequence of multiple results.
- *
- * <P>The number, types and properties of a ResultSet's columns are provided by
- * the ResultSetMetaData object returned by the getMetaData method.
- *
- * @see ResultSetMetaData
- * @see java.sql.ResultSet
- */
-public class ResultSet extends org.postgresql.ResultSet implements java.sql.ResultSet
-{
-	/*
-	 * 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 ResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor)
-	{
-		super(conn, fields, tuples, status, updateCount, insertOID, binaryCursor);
-	}
-
-	/*
-	 * 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 ResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount)
-	{
-		super(conn, fields, tuples, status, updateCount, 0, false);
-	}
-
-	/*
-	 * A ResultSet is initially positioned before its first row,
-	 * the first call to next makes the first row the current row;
-	 * the second call makes the second row the current row, etc.
-	 *
-	 * <p>If an input stream from the previous row is open, it is
-	 * implicitly closed.  The ResultSet's warning chain is cleared
-	 * when a new row is read
-	 *
-	 * @return true if the new current is valid; false if there are no
-	 *	more rows
-	 * @exception SQLException if a database access error occurs
-	 */
-	public boolean next() throws SQLException
-	{
- 	    if (rows == null)
- 		throw new PSQLException("postgresql.con.closed");
-
-		if (++current_row >= rows.size())
-			return false;
-		this_row = (byte [][])rows.elementAt(current_row);
-		return true;
-	}
-
-	/*
-	 * In some cases, it is desirable to immediately release a ResultSet
-	 * database and JDBC resources instead of waiting for this to happen
-	 * when it is automatically closed.  The close method provides this
-	 * immediate release.
-	 *
-	 * <p><B>Note:</B> A ResultSet is automatically closed by the Statement
-	 * the Statement that generated it when that Statement is closed,
-	 * re-executed, or is used to retrieve the next result from a sequence
-	 * of multiple results.  A ResultSet is also automatically closed
-	 * when it is garbage collected.
-	 *
-	 * @exception SQLException if a database access error occurs
-	 */
-	public void close() throws SQLException
-	{
-		//release resources held (memory for tuples)
-		rows.setSize(0);
-	}
-
-	/*
-	 * A column may have the value of SQL NULL; wasNull() reports whether
-	 * the last column read had this special value.  Note that you must
-	 * first call getXXX on a column to try to read its value and then
-	 * call wasNull() to find if the value was SQL NULL
-	 *
-	 * @return true if the last column read was SQL NULL
-	 * @exception SQLException if a database access error occurred
-	 */
-	public boolean wasNull() throws SQLException
-	{
-		return wasNullFlag;
-	}
-
-	/*
-	 * Get the value of a column in the current row as a Java String
-	 *
-	 * @param columnIndex the first column is 1, the second is 2...
-	 * @return the column value, null for SQL NULL
-	 * @exception SQLException if a database access error occurs
-	 */
-	public String getString(int columnIndex) throws SQLException
-	{
-		checkResultSet( columnIndex );
-		wasNullFlag = (this_row[columnIndex - 1] == null);
-		if (wasNullFlag)
-			return null;
-
-		Encoding encoding = connection.getEncoding();
-		return encoding.decode(this_row[columnIndex - 1]);
-	}
-
-	/*
-	 * Get the value of a column in the current row as a Java boolean
-	 *
-	 * @param columnIndex the first column is 1, the second is 2...
-	 * @return the column value, false for SQL NULL
-	 * @exception SQLException if a database access error occurs
-	 */
-	public boolean getBoolean(int columnIndex) throws SQLException
-	{
-		String s = getString(columnIndex);
-
-		if (s != null)
-		{
-			int c = s.charAt(0);
-			return ((c == 't') || (c == 'T') || (c == '1'));
-		}
-		return false;		// SQL NULL
-	}
-
-	/*
-	 * Get the value of a column in the current row as a Java byte.
-	 *
-	 * @param columnIndex the first column is 1, the second is 2,...
-	 * @return the column value; 0 if SQL NULL
-	 * @exception SQLException if a database access error occurs
-	 */
-	public byte getByte(int columnIndex) throws SQLException
-	{
-		String s = getString(columnIndex);
-
-		if (s != null)
-		{
-			try
-			{
-				return Byte.parseByte(s);
-			}
-			catch (NumberFormatException e)
-			{
-				throw new PSQLException("postgresql.res.badbyte", s);
-			}
-		}
-		return 0;		// SQL NULL
-	}
-
-	/*
-	 * Get the value of a column in the current row as a Java short.
-	 *
-	 * @param columnIndex the first column is 1, the second is 2,...
-	 * @return the column value; 0 if SQL NULL
-	 * @exception SQLException if a database access error occurs
-	 */
-	public short getShort(int columnIndex) throws SQLException
-	{
-		String s = getFixedString(columnIndex);
-
-		if (s != null)
-		{
-			try
-			{
-				return Short.parseShort(s);
-			}
-			catch (NumberFormatException e)
-			{
-				throw new PSQLException("postgresql.res.badshort", s);
-			}
-		}
-		return 0;		// SQL NULL
-	}
-
-	/*
-	 * Get the value of a column in the current row as a Java int.
-	 *
-	 * @param columnIndex the first column is 1, the second is 2,...
-	 * @return the column value; 0 if SQL NULL
-	 * @exception SQLException if a database access error occurs
-	 */
-	public int getInt(int columnIndex) throws SQLException
-	{
-		String s = getFixedString(columnIndex);
-
-		if (s != null)
-		{
-			try
-			{
-				return Integer.parseInt(s);
-			}
-			catch (NumberFormatException e)
-			{
-				throw new PSQLException ("postgresql.res.badint", s);
-			}
-		}
-		return 0;		// SQL NULL
-	}
-
-	/*
-	 * Get the value of a column in the current row as a Java long.
-	 *
-	 * @param columnIndex the first column is 1, the second is 2,...
-	 * @return the column value; 0 if SQL NULL
-	 * @exception SQLException if a database access error occurs
-	 */
-	public long getLong(int columnIndex) throws SQLException
-	{
-		String s = getFixedString(columnIndex);
-
-		if (s != null)
-		{
-			try
-			{
-				return Long.parseLong(s);
-			}
-			catch (NumberFormatException e)
-			{
-				throw new PSQLException ("postgresql.res.badlong", s);
-			}
-		}
-		return 0;		// SQL NULL
-	}
-
-	/*
-	 * Get the value of a column in the current row as a Java float.
-	 *
-	 * @param columnIndex the first column is 1, the second is 2,...
-	 * @return the column value; 0 if SQL NULL
-	 * @exception SQLException if a database access error occurs
-	 */
-	public float getFloat(int columnIndex) throws SQLException
-	{
-		String s = getFixedString(columnIndex);
-
-		if (s != null)
-		{
-			try
-			{
-				return Float.valueOf(s).floatValue();
-			}
-			catch (NumberFormatException e)
-			{
-				throw new PSQLException ("postgresql.res.badfloat", s);
-			}
-		}
-		return 0;		// SQL NULL
-	}
-
-	/*
-	 * Get the value of a column in the current row as a Java double.
-	 *
-	 * @param columnIndex the first column is 1, the second is 2,...
-	 * @return the column value; 0 if SQL NULL
-	 * @exception SQLException if a database access error occurs
-	 */
-	public double getDouble(int columnIndex) throws SQLException
-	{
-		String s = getFixedString(columnIndex);
-
-		if (s != null)
-		{
-			try
-			{
-				return Double.valueOf(s).doubleValue();
-			}
-			catch (NumberFormatException e)
-			{
-				throw new PSQLException ("postgresql.res.baddouble", s);
-			}
-		}
-		return 0;		// SQL NULL
-	}
-
-	/*
-	 * Get the value of a column in the current row as a
-	 * java.math.BigDecimal object
-	 *
-	 * @param columnIndex  the first column is 1, the second is 2...
-	 * @param scale the number of digits to the right of the decimal
-	 * @return the column value; if the value is SQL NULL, null
-	 * @exception SQLException if a database access error occurs
-	 */
-	public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException
-	{
-		String s = getFixedString(columnIndex);
-		BigDecimal val;
-
-		if (s != null)
-		{
-			try
-			{
-				val = new BigDecimal(s);
-			}
-			catch (NumberFormatException e)
-			{
-				throw new PSQLException ("postgresql.res.badbigdec", s);
-			}
-			try
-			{
-				return val.setScale(scale);
-			}
-			catch (ArithmeticException e)
-			{
-				throw new PSQLException ("postgresql.res.badbigdec", s);
-			}
-		}
-		return null;		// SQL NULL
-	}
-
-	/*
-	 * Get the value of a column in the current row as a Java byte array.
-	 *
-	 * <p>In normal use, the bytes represent the raw values returned by the
-	 * backend. However, if the column is an OID, then it is assumed to
-	 * refer to a Large Object, and that object is returned as a byte array.
-	 *
-	 * <p><b>Be warned</b> If the large object is huge, then you may run out
-	 * of memory.
-	 *
-	 * @param columnIndex the first column is 1, the second is 2, ...
-	 * @return the column value; if the value is SQL NULL, the result
-	 *	is null
-	 * @exception SQLException if a database access error occurs
-	 */
-	public byte[] getBytes(int columnIndex) throws SQLException
-	{
-		checkResultSet( columnIndex );
-		wasNullFlag = (this_row[columnIndex - 1] == null);
-		if (!wasNullFlag)
-		{
-			if (binaryCursor)
-			{
-				//If the data is already binary then just return it
-				return this_row[columnIndex - 1];
-			}
-			else if (connection.haveMinimumCompatibleVersion("7.2"))
-			{
-				//Version 7.2 supports the bytea datatype for byte arrays
-				if (fields[columnIndex - 1].getPGType().equals("bytea"))
-				{
-					return PGbytea.toBytes(this_row[columnIndex - 1]);
-				}
-				else
-				{
-					return this_row[columnIndex - 1];
-				}
-			}
-			else
-			{
-				//Version 7.1 and earlier supports LargeObjects for byte arrays
-				// Handle OID's as BLOBS
-				if ( fields[columnIndex - 1].getOID() == 26)
-				{
-					LargeObjectManager lom = connection.getLargeObjectAPI();
-					LargeObject lob = lom.open(getInt(columnIndex));
-					byte buf[] = lob.read(lob.size());
-					lob.close();
-					return buf;
-				}
-				else
-				{
-					return this_row[columnIndex - 1];
-				}
-			}
-		}
-		return null;
-	}
-
-	/*
-	 * Get the value of a column in the current row as a java.sql.Date
-	 * object
-	 *
-	 * @param columnIndex the first column is 1, the second is 2...
-	 * @return the column value; null if SQL NULL
-	 * @exception SQLException if a database access error occurs
-	 */
-	public java.sql.Date getDate(int columnIndex) throws SQLException
-	{
-		String s = getString(columnIndex);
-		if (s == null)
-			return null;
-		// length == 10: SQL Date
-		// length >  10: SQL Timestamp, assumes PGDATESTYLE=ISO
-		try
-		{
-			return java.sql.Date.valueOf((s.length() == 10) ? s : s.substring(0, 10));
-		}
-		catch (NumberFormatException e)
-		{
-			throw new PSQLException("postgresql.res.baddate", s);
-		}
-	}
-
-	/*
-	 * Get the value of a column in the current row as a java.sql.Time
-	 * object
-	 *
-	 * @param columnIndex the first column is 1, the second is 2...
-	 * @return the column value; null if SQL NULL
-	 * @exception SQLException if a database access error occurs
-	 */
-	public Time getTime(int columnIndex) throws SQLException
-	{
-		String s = getString(columnIndex);
-
-		if (s == null)
-			return null; // SQL NULL
-		try
-		{
-                   if (s.length() == 8) {
-                     //value is a time value
-                     return java.sql.Time.valueOf(s);
-                   } else if (s.indexOf(".") == 8) {
-                     //value is a time value with fractional seconds
-                     java.sql.Time l_time = java.sql.Time.valueOf(s.substring(0,8));
-                     String l_strMillis = s.substring(9);
-                     if (l_strMillis.length() > 3)
-                       l_strMillis = l_strMillis.substring(0,3);
-                     int l_millis = Integer.parseInt(l_strMillis);
-                     if (l_millis < 10) {
-                       l_millis = l_millis * 100;
-                     } else if (l_millis < 100) {
-                       l_millis = l_millis * 10;
-                     }
-                     return new java.sql.Time(l_time.getTime() + l_millis);
-                   } else {
-                     //value is a timestamp
-                     return new java.sql.Time(getTimestamp(columnIndex).getTime());
-                   }
-		}
-		catch (NumberFormatException e)
-		{
-			throw new PSQLException("postgresql.res.badtime", s);
-		}
-	}
-
-	/*
-	 * Get the value of a column in the current row as a
-	 * java.sql.Timestamp object
-	 *
-	 * The driver is set to return ISO date formated strings. We modify this
-    * string from the ISO format to a format that Java can understand. Java
-    * expects timezone info as 'GMT+09:00' where as ISO gives '+09'.
-    * Java also expects fractional seconds to 3 places where postgres
-    * will give, none, 2 or 6 depending on the time and postgres version.
-    * From version 7.2 postgres returns fractional seconds to 6 places.
-    * If available, we drop the last 3 digits.
-	 *
-	 * @param columnIndex the first column is 1, the second is 2...
-	 * @return the column value; null if SQL NULL
-	 * @exception SQLException if a database access error occurs
-	 */
-	public Timestamp getTimestamp(int columnIndex) throws SQLException
-	{
-		String s = getString(columnIndex);
-
-		if (s == null)
-			return null;
-
-		StringBuffer sbuf = new StringBuffer(s);
-		SimpleDateFormat df = null;
-
-		int slen = s.length();
-
-		if (slen > 19)
-		{
-			// The len of the ISO string to the second value is 19 chars. If
-			// greater then 19, there should be tz info and perhaps fractional
-			// second info which we need to change to java to read it.
-
-			// cut the copy to second value "2001-12-07 16:29:22"
-			int i = 19;
-			sbuf.setLength(i);
-
-			char c = s.charAt(i++);
-			if (c == '.')
-			{
-				// Found a fractional value. Append up to 3 digits including
-				// the leading '.'
-				do
-				{
-					if (i < 24)
-						sbuf.append(c);
-					c = s.charAt(i++);
-				} while (i < slen && Character.isDigit(c));
-
-				// If there wasn't at least 3 digits we should add some zeros
-				// to make up the 3 digits we tell java to expect.
-				for (int j = i; j < 24; j++)
-					sbuf.append('0');
-			}
-			else
-			{
-				// No fractional seconds, lets add some.
-				sbuf.append(".000");
-			}
-
-			if (i < slen)
-			{
-				// prepend the GMT part and then add the remaining bit of
-				// the string.
-				sbuf.append(" GMT");
-				sbuf.append(c);
-				sbuf.append(s.substring(i, slen));
-
-				// Lastly, if the tz part doesn't specify the :MM part then
-				// we add ":00" for java.
-				if (slen - i < 5)
-					sbuf.append(":00");
-
-				// we'll use this dateformat string to parse the result.
-				df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z");
-			}
-			else
-			{
-			    //if type is timestamptz then data is in GMT, else it is in local timezone
-			    if (fields[columnIndex - 1].getPGType().equals("timestamptz")) {
-				sbuf.append(" GMT");
-				df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z");
-			    } else {
-                                df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
-			    }
-			}
-		}
-		else if (slen == 19)
-		{
-			// No tz or fractional second info.
-			// if type is timestamptz then data is in GMT, else it is in local timezone
-		    if (fields[columnIndex - 1].getPGType().equals("timestamptz")) {
-			sbuf.append(" GMT");
-			df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
-		    } else {
-			df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-		    }
-		}
-		else
-		{
-			// We must just have a date. This case is
-			// needed if this method is called on a date column
-			df = new SimpleDateFormat("yyyy-MM-dd");
-		}
-
-		try
-		{
-			// All that's left is to parse the string and return the ts.
-			return new Timestamp(df.parse(sbuf.toString()).getTime());
-		}
-		catch (ParseException e)
-		{
-			throw new PSQLException("postgresql.res.badtimestamp", new Integer(e.getErrorOffset()), s);
-		}
-	}
-
-	/*
-	 * A column value can be retrieved as a stream of ASCII characters
-	 * and then read in chunks from the stream.  This method is
-	 * particular suitable for retrieving large LONGVARCHAR values.
-	 * The JDBC driver will do any necessary conversion from the
-	 * database format into ASCII.
-	 *
-	 * <p><B>Note:</B> All the data in the returned stream must be read
-	 * prior to getting the value of any other column.	The next call
-	 * to a get method implicitly closes the stream.  Also, a stream
-	 * may return 0 for available() whether there is data available
-	 * or not.
-	 *
-	 *<p> We implement an ASCII stream as a Binary stream - we should really
-	 * do the data conversion, but I cannot be bothered to implement this
-	 * right now.
-	 *
-	 * @param columnIndex the first column is 1, the second is 2, ...
-	 * @return a Java InputStream that delivers the database column
-	 *	value as a stream of one byte ASCII characters.  If the
-	 *	value is SQL NULL then the result is null
-	 * @exception SQLException if a database access error occurs
-	 * @see getBinaryStream
-	 */
-	public InputStream getAsciiStream(int columnIndex) throws SQLException
-	{
-		checkResultSet( columnIndex );
-		wasNullFlag = (this_row[columnIndex - 1] == null);
-		if (wasNullFlag)
-			return null;
-
-		if (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
-			try
-			{
-				return new ByteArrayInputStream(getString(columnIndex).getBytes("ASCII"));
-			}
-			catch (UnsupportedEncodingException l_uee)
-			{
-				throw new PSQLException("postgresql.unusual", l_uee);
-			}
-		}
-		else
-		{
-			// In 7.1 Handle as BLOBS so return the LargeObject input stream
-			return getBinaryStream(columnIndex);
-		}
-	}
-
-	/*
-	 * A column value can also be retrieved as a stream of Unicode
-	 * characters. We implement this as a binary stream.
-	 *
-	 * @param columnIndex the first column is 1, the second is 2...
-	 * @return a Java InputStream that delivers the database column value
-	 *	as a stream of two byte Unicode characters.  If the value is
-	 *	SQL NULL, then the result is null
-	 * @exception SQLException if a database access error occurs
-	 * @see getAsciiStream
-	 * @see getBinaryStream
-	 */
-	public InputStream getUnicodeStream(int columnIndex) throws SQLException
-	{
-		checkResultSet( columnIndex );
-		wasNullFlag = (this_row[columnIndex - 1] == null);
-		if (wasNullFlag)
-			return null;
-
-		if (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
-			try
-			{
-				return new ByteArrayInputStream(getString(columnIndex).getBytes("UTF-8"));
-			}
-			catch (UnsupportedEncodingException l_uee)
-			{
-				throw new PSQLException("postgresql.unusual", l_uee);
-			}
-		}
-		else
-		{
-			// In 7.1 Handle as BLOBS so return the LargeObject input stream
-			return getBinaryStream(columnIndex);
-		}
-	}
-
-	/*
-	 * A column value can also be retrieved as a binary strea.	This
-	 * method is suitable for retrieving LONGVARBINARY values.
-	 *
-	 * @param columnIndex the first column is 1, the second is 2...
-	 * @return a Java InputStream that delivers the database column value
-	 * as a stream of bytes.  If the value is SQL NULL, then the result
-	 * is null
-	 * @exception SQLException if a database access error occurs
-	 * @see getAsciiStream
-	 * @see getUnicodeStream
-	 */
-	public InputStream getBinaryStream(int columnIndex) throws SQLException
-	{
-		checkResultSet( columnIndex );
-		wasNullFlag = (this_row[columnIndex - 1] == null);
-		if (wasNullFlag)
-			return null;
-
-		if (connection.haveMinimumCompatibleVersion("7.2"))
-		{
-			//Version 7.2 supports BinaryStream for all PG bytea type
-			//As the spec/javadoc for this method indicate this is to be used for
-			//large binary values (i.e. LONGVARBINARY)	PG doesn't have a separate
-			//long binary datatype, but with toast the bytea datatype is capable of
-			//handling very large values.  Thus the implementation ends up calling
-			//getBytes() since there is no current way to stream the value from the server
-			byte b[] = getBytes(columnIndex);
-			if (b != null)
-				return new ByteArrayInputStream(b);
-		}
-		else
-		{
-			// In 7.1 Handle as BLOBS so return the LargeObject input stream
-			if ( fields[columnIndex - 1].getOID() == 26)
-			{
-				LargeObjectManager lom = connection.getLargeObjectAPI();
-				LargeObject lob = lom.open(getInt(columnIndex));
-				return lob.getInputStream();
-			}
-		}
-		return null;
-	}
-
-	/*
-	 * The following routines simply convert the columnName into
-	 * a columnIndex and then call the appropriate routine above.
-	 *
-	 * @param columnName is the SQL name of the column
-	 * @return the column value
-	 * @exception SQLException if a database access error occurs
-	 */
-	public String getString(String columnName) throws SQLException
-	{
-		return getString(findColumn(columnName));
-	}
-
-	public boolean getBoolean(String columnName) throws SQLException
-	{
-		return getBoolean(findColumn(columnName));
-	}
-
-	public byte getByte(String columnName) throws SQLException
-	{
-
-		return getByte(findColumn(columnName));
-	}
-
-	public short getShort(String columnName) throws SQLException
-	{
-		return getShort(findColumn(columnName));
-	}
-
-	public int getInt(String columnName) throws SQLException
-	{
-		return getInt(findColumn(columnName));
-	}
-
-	public long getLong(String columnName) throws SQLException
-	{
-		return getLong(findColumn(columnName));
-	}
-
-	public float getFloat(String columnName) throws SQLException
-	{
-		return getFloat(findColumn(columnName));
-	}
-
-	public double getDouble(String columnName) throws SQLException
-	{
-		return getDouble(findColumn(columnName));
-	}
-
-	public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException
-	{
-		return getBigDecimal(findColumn(columnName), scale);
-	}
-
-	public byte[] getBytes(String columnName) throws SQLException
-	{
-		return getBytes(findColumn(columnName));
-	}
-
-	public java.sql.Date getDate(String columnName) throws SQLException
-	{
-		return getDate(findColumn(columnName));
-	}
-
-	public Time getTime(String columnName) throws SQLException
-	{
-		return getTime(findColumn(columnName));
-	}
-
-	public Timestamp getTimestamp(String columnName) throws SQLException
-	{
-		return getTimestamp(findColumn(columnName));
-	}
-
-	public InputStream getAsciiStream(String columnName) throws SQLException
-	{
-		return getAsciiStream(findColumn(columnName));
-	}
-
-	public InputStream getUnicodeStream(String columnName) throws SQLException
-	{
-		return getUnicodeStream(findColumn(columnName));
-	}
-
-	public InputStream getBinaryStream(String columnName) throws SQLException
-	{
-		return getBinaryStream(findColumn(columnName));
-	}
-
-	/*
-	 * The first warning reported by calls on this ResultSet is
-	 * returned.  Subsequent ResultSet warnings will be chained
-	 * to this SQLWarning.
-	 *
-	 * <p>The warning chain is automatically cleared each time a new
-	 * row is read.
-	 *
-	 * <p><B>Note:</B> This warning chain only covers warnings caused by
-	 * ResultSet methods.  Any warnings caused by statement methods
-	 * (such as reading OUT parameters) will be chained on the
-	 * Statement object.
-	 *
-	 * @return the first SQLWarning or null;
-	 * @exception SQLException if a database access error occurs.
-	 */
-	public SQLWarning getWarnings() throws SQLException
-	{
-		return warnings;
-	}
-
-	/*
-	 * After this call, getWarnings returns null until a new warning
-	 * is reported for this ResultSet
-	 *
-	 * @exception SQLException if a database access error occurs
-	 */
-	public void clearWarnings() throws SQLException
-	{
-		warnings = null;
-	}
-
-	/*
-	 * Get the name of the SQL cursor used by this ResultSet
-	 *
-	 * <p>In SQL, a result table is retrieved though a cursor that is
-	 * named.  The current row of a result can be updated or deleted
-	 * using a positioned update/delete statement that references
-	 * the cursor name.
-	 *
-	 * <p>JDBC supports this SQL feature by providing the name of the
-	 * SQL cursor used by a ResultSet.	The current row of a ResulSet
-	 * is also the current row of this SQL cursor.
-	 *
-	 * <p><B>Note:</B> If positioned update is not supported, a SQLException
-	 * is thrown.
-	 *
-	 * @return the ResultSet's SQL cursor name.
-	 * @exception SQLException if a database access error occurs
-	 */
-	public String getCursorName() throws SQLException
-	{
-		return connection.getCursorName();
-	}
-
-	/*
-	 * The numbers, types and properties of a ResultSet's columns are
-	 * provided by the getMetaData method
-	 *
-	 * @return a description of the ResultSet's columns
-	 * @exception SQLException if a database access error occurs
-	 */
-	public java.sql.ResultSetMetaData getMetaData() throws SQLException
-	{
-		return new ResultSetMetaData(rows, fields);
-	}
-
-	/*
-	 * 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;
-
-		if (columnIndex < 1 || columnIndex > fields.length)
-			throw new PSQLException("postgresql.res.colrange");
-		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() - 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);
-			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));
-				}
-		}
-	}
-
-	/*
-	 * 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 columnName is the SQL name of the column
-	 * @return a Object holding the column value
-	 * @exception SQLException if a database access error occurs
-	 */
-	public Object getObject(String columnName) throws SQLException
-	{
-		return getObject(findColumn(columnName));
-	}
-
-	/*
-	 * Map a ResultSet column name to a ResultSet column index
-	 *
-	 * @param columnName the name of the column
-	 * @return the column index
-	 * @exception SQLException if a database access error occurs
-	 */
-	public int findColumn(String columnName) throws SQLException
-	{
-		int i;
-
-		for (i = 0 ; i < fields.length; ++i)
-			if (fields[i].getName().equalsIgnoreCase(columnName))
-				return (i + 1);
-		throw new PSQLException ("postgresql.res.colname", columnName);
-	}
-}
-
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/Statement.java b/src/interfaces/jdbc/org/postgresql/jdbc1/Statement.java
deleted file mode 100644
index 8898f5a69dd..00000000000
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/Statement.java
+++ /dev/null
@@ -1,144 +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 org.postgresql.util.PSQLException;
-
-/*
- * A Statement object is used for executing a static SQL statement and
- * obtaining the results produced by it.
- *
- * <p>Only one ResultSet per Statement can be open at any point in time.
- * Therefore, if the reading of one ResultSet is interleaved with the
- * reading of another, each must have been generated by different
- * Statements.	All statement execute methods implicitly close a
- * statement's current ResultSet if an open one exists.
- *
- * @see java.sql.Statement
- * @see ResultSet
- */
-public class Statement extends org.postgresql.Statement implements java.sql.Statement
-{
-	private Connection connection;		// The connection who created us
-
-	/*
-	 * Constructor for a Statement.  It simply sets the connection
-	 * that created us.
-	 *
-	 * @param c the Connection instantation that creates us
-	 */
-	public Statement (Connection c)
-	{
-		connection = c;
-	}
-
-	/*
-	 * Execute a SQL statement that retruns a single ResultSet
-	 *
-	 * @param sql typically a static SQL SELECT statement
-	 * @return a ResulSet that contains the data produced by the query
-	 * @exception SQLException if a database access error occurs
-	 */
-	public java.sql.ResultSet executeQuery(String sql) throws SQLException
-	{
-		this.execute(sql);
-		while (result != null && !((org.postgresql.ResultSet)result).reallyResultSet())
-			result = ((org.postgresql.ResultSet)result).getNext();
-		if (result == null)
-			throw new PSQLException("postgresql.stat.noresult");
-		return result;
-	}
-
-	/*
-	 * Execute a SQL INSERT, UPDATE or DELETE statement.  In addition
-	 * SQL statements that return nothing such as SQL DDL statements
-	 * can be executed
-	 *
-	 * @param sql a SQL statement
-	 * @return either a row count, or 0 for SQL commands
-	 * @exception SQLException if a database access error occurs
-	 */
-	public int executeUpdate(String sql) throws SQLException
-	{
-		this.execute(sql);
-		return this.getUpdateCount();
-	}
-
-	/*
-	 * setCursorName defines the SQL cursor name that will be used by
-	 * subsequent execute methods.	This name can then be used in SQL
-	 * positioned update/delete statements to identify the current row
-	 * in the ResultSet generated by this statement.  If a database
-	 * doesn't support positioned update/delete, this method is a
-	 * no-op.
-	 *
-	 * <p><B>Note:</B> By definition, positioned update/delete execution
-	 * must be done by a different Statement than the one which
-	 * generated the ResultSet being used for positioning.	Also, cursor
-	 * names must be unique within a Connection.
-	 *
-	 * <p>We throw an additional constriction.	There can only be one
-	 * cursor active at any one time.
-	 *
-	 * @param name the new cursor name
-	 * @exception SQLException if a database access error occurs
-	 */
-	public void setCursorName(String name) throws SQLException
-	{
-		connection.setCursorName(name);
-	}
-
-	/*
-	 * Execute a SQL statement that may return multiple results. We
-	 * don't have to worry about this since we do not support multiple
-	 * ResultSets.	 You can use getResultSet or getUpdateCount to
-	 * retrieve the result.
-	 *
-	 * @param sql any SQL statement
-	 * @return true if the next result is a ResulSet, false if it is
-	 *	an update count or there are no more results
-	 * @exception SQLException if a database access error occurs
-	 */
-	public boolean execute(String sql) throws SQLException
-	{
-		if (escapeProcessing)
-			sql = escapeSQL(sql);
-		result = connection.ExecSQL(sql);
-		return (result != null && ((org.postgresql.ResultSet)result).reallyResultSet());
-	}
-
-	/*
-	 * getUpdateCount returns the current result as an update count,
-	 * if the result is a ResultSet or there are no more results, -1
-	 * is returned.  It should only be called once per result.
-	 *
-	 * @return the current result as an update count.
-	 * @exception SQLException if a database access error occurs
-	 */
-	public int getUpdateCount() throws SQLException
-	{
-		if (result == null)
-			return -1;
-		if (((org.postgresql.ResultSet)result).reallyResultSet())
-			return -1;
-		return ((org.postgresql.ResultSet)result).getResultCount();
-	}
-
-	/*
-	 * getMoreResults moves to a Statement's next result.  If it returns
-	 * true, this result is a ResulSet.
-	 *
-	 * @return true if the next ResultSet is valid
-	 * @exception SQLException if a database access error occurs
-	 */
-	public boolean getMoreResults() throws SQLException
-	{
-		result = ((org.postgresql.ResultSet)result).getNext();
-		return (result != null && ((org.postgresql.ResultSet)result).reallyResultSet());
-	}
-}
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Connection.java
new file mode 100644
index 00000000000..8faefad65ff
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Connection.java
@@ -0,0 +1,203 @@
+package org.postgresql.jdbc2;
+
+
+import java.io.*;
+import java.net.ConnectException;
+import java.sql.*;
+import org.postgresql.util.PSQLException;
+
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Connection.java,v 1.1 2002/07/23 03:59:55 barry Exp $
+ * This class defines methods of the jdbc2 specification.  This class extends
+ * org.postgresql.jdbc1.AbstractJdbc1Connection which provides the jdbc1
+ * methods.  The real Connection class (for jdbc2) is org.postgresql.jdbc2.Jdbc2Connection
+ */
+public abstract class AbstractJdbc2Connection extends org.postgresql.jdbc1.AbstractJdbc1Connection
+{
+        /*
+         * The current type mappings
+         */
+        protected java.util.Map typemap;
+
+        public java.sql.Statement createStatement() throws SQLException
+        {
+                // The spec says default of TYPE_FORWARD_ONLY but everyone is used to
+                // using TYPE_SCROLL_INSENSITIVE
+                return createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY);
+        }
+
+        public abstract java.sql.Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException;
+
+        public java.sql.PreparedStatement prepareStatement(String sql) throws SQLException
+        {
+                return prepareStatement(sql, java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY);
+        }
+
+        public abstract java.sql.PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException;
+
+        public java.sql.CallableStatement prepareCall(String sql) throws SQLException
+        {
+                return prepareCall(sql, java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY);
+        }
+
+        public abstract java.sql.CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException;
+
+        public java.util.Map getTypeMap() throws SQLException
+        {
+                return typemap;
+        }
+
+
+        public void setTypeMap(java.util.Map map) throws SQLException
+        {
+                typemap = map;
+        }
+
+        public void cancelQuery() throws SQLException
+        {
+                org.postgresql.PG_Stream cancelStream = null;
+                try {
+                        cancelStream = new org.postgresql.PG_Stream(PG_HOST, PG_PORT);
+                } catch (ConnectException cex) {
+                        // Added by Peter Mount <peter@retep.org.uk>
+                        // ConnectException is thrown when the connection cannot be made.
+                        // we trap this an return a more meaningful message for the end user
+                        throw new PSQLException ("postgresql.con.refused");
+                } catch (IOException e) {
+                        throw new PSQLException ("postgresql.con.failed",e);
+                }
+
+                // Now we need to construct and send a cancel packet
+                try {
+                        cancelStream.SendInteger(16, 4);
+                        cancelStream.SendInteger(80877102, 4);
+                        cancelStream.SendInteger(pid, 4);
+                        cancelStream.SendInteger(ckey, 4);
+                        cancelStream.flush();
+                }
+                catch(IOException e) {
+                        throw new PSQLException("postgresql.con.failed",e);
+                }
+                finally {
+                        try {
+                                if(cancelStream != null)
+                                        cancelStream.close();
+                        }
+                        catch(IOException e) {} // Ignore
+                }
+        }
+
+
+        /*
+         * This overides the standard internal getObject method so that we can
+         * check the jdbc2 type map first
+         */
+        public Object getObject(String type, String value) throws SQLException
+        {
+                if (typemap != null)
+                {
+                        SQLData d = (SQLData) typemap.get(type);
+                        if (d != null)
+                        {
+                                // Handle the type (requires SQLInput & SQLOutput classes to be implemented)
+                                throw org.postgresql.Driver.notImplemented();
+                        }
+                }
+
+                // Default to the original method
+                return super.getObject(type, value);
+        }
+
+
+        //Because the get/setLogStream methods are deprecated in JDBC2
+        //we use the get/setLogWriter methods here for JDBC2 by overriding
+        //the base version of this method
+        protected void enableDriverManagerLogging() {
+            if (DriverManager.getLogWriter() == null) {
+                DriverManager.setLogWriter(new PrintWriter(System.out));
+	    }
+	}
+
+
+        /* 
+         * This implemetation uses the jdbc2Types array to support the jdbc2
+         * datatypes.  Basically jdbc1 and jdbc2 are the same, except that
+         * jdbc2 adds the Array types.
+         */
+        public int getSQLType(String pgTypeName)
+        {
+                int sqlType = Types.OTHER; // default value
+                for (int i = 0;i < jdbc2Types.length;i++)
+                {
+                        if (pgTypeName.equals(jdbc2Types[i]))
+                        {
+                                sqlType = jdbc2Typei[i];
+                                break;
+                        }
+                }
+                return sqlType;
+        }
+
+        /*
+         * This table holds the org.postgresql names for the types supported.
+         * Any types that map to Types.OTHER (eg POINT) don't go into this table.
+         * They default automatically to Types.OTHER
+         *
+         * Note: This must be in the same order as below.
+         *
+         * Tip: keep these grouped together by the Types. value
+         */
+        private static final String jdbc2Types[] = {
+                                "int2",
+                                "int4", "oid",
+                                "int8",
+                                "cash", "money",
+                                "numeric",
+                                "float4",
+                                "float8",
+                                "bpchar", "char", "char2", "char4", "char8", "char16",
+                                "varchar", "text", "name", "filename",
+                                "bytea",
+                                "bool",
+                                "date",
+                                "time",
+                                "abstime", "timestamp", "timestamptz",
+                                "_bool", "_char", "_int2", "_int4", "_text",
+                                "_oid", "_varchar", "_int8", "_float4", "_float8",
+                                "_abstime", "_date", "_time", "_timestamp", "_numeric",
+                                "_bytea"
+                        };
+
+        /*
+         * This table holds the JDBC type for each entry above.
+         *
+         * Note: This must be in the same order as above
+         *
+         * Tip: keep these grouped together by the Types. value
+         */
+        private static final int jdbc2Typei[] = {
+                                Types.SMALLINT,
+                                Types.INTEGER, Types.INTEGER,
+                                Types.BIGINT,
+                                Types.DOUBLE, Types.DOUBLE,
+                                Types.NUMERIC,
+                                Types.REAL,
+                                Types.DOUBLE,
+                                Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR,
+                                Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+                                Types.BINARY,
+                                Types.BIT,
+                                Types.DATE,
+                                Types.TIME,
+                                Types.TIMESTAMP, Types.TIMESTAMP, Types.TIMESTAMP,
+                                Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY,
+                                Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY,
+                                Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY,
+                                Types.ARRAY
+         };
+
+
+
+
+}
+
+
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java
new file mode 100644
index 00000000000..50c5d942bbf
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java
@@ -0,0 +1,752 @@
+package org.postgresql.jdbc2;
+
+
+import java.math.BigDecimal;
+import java.io.*;
+import java.sql.*;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Vector;
+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.1 2002/07/23 03:59:55 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 Jdbc2Statement 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 java.sql.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(Jdbc2Statement statement)
+	{
+		this.statement = statement;
+	}
+
+	public void setSQLQuery(String sqlQuery) {
+		this.sqlQuery=sqlQuery;
+	}
+}
+
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java
new file mode 100644
index 00000000000..3d6f6553ced
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java
@@ -0,0 +1,142 @@
+package org.postgresql.jdbc2;
+
+
+import java.sql.*;
+import java.util.Vector;
+import org.postgresql.util.PSQLException;
+
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Statement.java,v 1.1 2002/07/23 03:59:55 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
+{
+
+	protected Vector batch = null;
+	protected int resultsettype;		 // the resultset type to return
+	protected int concurrency;		 // is it updateable or not?
+
+	/*
+	 * Execute a SQL statement that may return multiple results. We
+	 * don't have to worry about this since we do not support multiple
+	 * ResultSets.	 You can use getResultSet or getUpdateCount to
+	 * retrieve the result.
+	 *
+	 * @param sql any SQL statement
+	 * @return true if the next result is a ResulSet, false if it is
+	 *	an update count or there are no more results
+	 * @exception SQLException if a database access error occurs
+	 */
+	public boolean execute(String sql) throws SQLException
+	{
+	        boolean l_return = super.execute(sql);
+
+                //Now do the jdbc2 specific stuff
+		//required for ResultSet.getStatement() to work
+		((AbstractJdbc2ResultSet)result).setStatement((Jdbc2Statement)this);
+
+		// Added this so that the Updateable resultset knows the query that gave this
+		((AbstractJdbc2ResultSet)result).setSQLQuery(sql);
+
+		return l_return;
+	}
+
+	// ** JDBC 2 Extensions **
+
+	public void addBatch(String sql) throws SQLException
+	{
+		if (batch == null)
+			batch = new Vector();
+		batch.addElement(sql);
+	}
+
+	public void clearBatch() throws SQLException
+	{
+		if (batch != null)
+			batch.removeAllElements();
+	}
+
+	public int[] executeBatch() throws SQLException
+	{
+		if (batch == null)
+			batch = new Vector();
+		int size = batch.size();
+		int[] result = new int[size];
+		int i = 0;
+		try
+		{
+			for (i = 0;i < size;i++)
+				result[i] = this.executeUpdate((String)batch.elementAt(i));
+		}
+		catch (SQLException e)
+		{
+			int[] resultSucceeded = new int[i];
+			System.arraycopy(result, 0, resultSucceeded, 0, i);
+
+			PBatchUpdateException updex =
+				new PBatchUpdateException("postgresql.stat.batch.error",
+						          new Integer(i), batch.elementAt(i), resultSucceeded);
+			updex.setNextException(e);
+
+			throw updex;
+		}
+		finally
+		{
+			batch.removeAllElements();
+		}
+		return result;
+	}
+
+	public void cancel() throws SQLException
+	{
+		((AbstractJdbc2Connection)connection).cancelQuery();
+	}
+
+	public java.sql.Connection getConnection() throws SQLException
+	{
+		return (java.sql.Connection)connection;
+	}
+
+	public int getFetchDirection() throws SQLException
+	{
+		throw new PSQLException("postgresql.psqlnotimp");
+	}
+
+	public int getFetchSize() throws SQLException
+	{
+		// This one can only return a valid value when were a cursor?
+		throw org.postgresql.Driver.notImplemented();
+	}
+
+	public int getResultSetConcurrency() throws SQLException
+	{
+		return concurrency;
+	}
+
+	public int getResultSetType() throws SQLException
+	{
+		return resultsettype;
+	}
+
+	public void setFetchDirection(int direction) throws SQLException
+	{
+		throw org.postgresql.Driver.notImplemented();
+	}
+
+	public void setFetchSize(int rows) throws SQLException
+	{
+		throw org.postgresql.Driver.notImplemented();
+	}
+
+	public void setResultSetConcurrency(int value) throws SQLException
+	{
+		concurrency = value;
+	}
+
+	public void setResultSetType(int value) throws SQLException
+	{
+		resultsettype = value;
+	}
+
+}
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/Array.java b/src/interfaces/jdbc/org/postgresql/jdbc2/Array.java
index 7cc842ec36e..2105802d66a 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/Array.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/Array.java
@@ -25,9 +25,9 @@ import org.postgresql.util.*;
 
 public class Array implements java.sql.Array
 {
-	private org.postgresql.Connection conn = null;
+	private org.postgresql.PGConnection conn = null;
 	private org.postgresql.Field field = null;
-	private org.postgresql.jdbc2.ResultSet rs = null;
+        private ResultSet rs;
 	private int idx = 0;
 	private String rawString = null;
 
@@ -39,14 +39,14 @@ public class Array implements java.sql.Array
 	 * @param field the Field descriptor for the field to load into this Array
 	 * @param rs the ResultSet from which to get the data for this Array
 	 */
-	public Array( org.postgresql.Connection conn, int idx, Field field, org.postgresql.jdbc2.ResultSet rs )
+	public Array( org.postgresql.PGConnection conn, int idx, Field field, ResultSet rs )
 	throws SQLException
 	{
 		this.conn = conn;
 		this.field = field;
-		this.rs = rs;
+                this.rs = rs;
 		this.idx = idx;
-		this.rawString = rs.getFixedString(idx);
+		this.rawString = ((AbstractJdbc2ResultSet)rs).getFixedString(idx);
 	}
 
 	public Object getArray() throws SQLException
@@ -124,33 +124,33 @@ public class Array implements java.sql.Array
 			case Types.BIT:
 				retVal = new boolean[ count ];
 				for ( ; count > 0; count-- )
-					((boolean[])retVal)[i++] = ResultSet.toBoolean( arrayContents[(int)index++] );
+					((boolean[])retVal)[i++] = Jdbc2ResultSet.toBoolean( arrayContents[(int)index++] );
 				break;
 			case Types.SMALLINT:
 			case Types.INTEGER:
 				retVal = new int[ count ];
 				for ( ; count > 0; count-- )
-					((int[])retVal)[i++] = ResultSet.toInt( arrayContents[(int)index++] );
+					((int[])retVal)[i++] = Jdbc2ResultSet.toInt( arrayContents[(int)index++] );
 				break;
 			case Types.BIGINT:
 				retVal = new long[ count ];
 				for ( ; count > 0; count-- )
-					((long[])retVal)[i++] = ResultSet.toLong( arrayContents[(int)index++] );
+					((long[])retVal)[i++] = Jdbc2ResultSet.toLong( arrayContents[(int)index++] );
 				break;
 			case Types.NUMERIC:
 				retVal = new BigDecimal[ count ];
 				for ( ; count > 0; count-- )
-					((BigDecimal[])retVal)[i++] = ResultSet.toBigDecimal( arrayContents[(int)index++], 0 );
+					((BigDecimal[])retVal)[i++] = Jdbc2ResultSet.toBigDecimal( arrayContents[(int)index++], 0 );
 				break;
 			case Types.REAL:
 				retVal = new float[ count ];
 				for ( ; count > 0; count-- )
-					((float[])retVal)[i++] = ResultSet.toFloat( arrayContents[(int)index++] );
+					((float[])retVal)[i++] = Jdbc2ResultSet.toFloat( arrayContents[(int)index++] );
 				break;
 			case Types.DOUBLE:
 				retVal = new double[ count ];
 				for ( ; count > 0; count-- )
-					((double[])retVal)[i++] = ResultSet.toDouble( arrayContents[(int)index++] );
+					((double[])retVal)[i++] = Jdbc2ResultSet.toDouble( arrayContents[(int)index++] );
 				break;
 			case Types.CHAR:
 			case Types.VARCHAR:
@@ -161,18 +161,18 @@ public class Array implements java.sql.Array
 			case Types.DATE:
 				retVal = new java.sql.Date[ count ];
 				for ( ; count > 0; count-- )
-					((java.sql.Date[])retVal)[i++] = ResultSet.toDate( arrayContents[(int)index++] );
+					((java.sql.Date[])retVal)[i++] = Jdbc2ResultSet.toDate( arrayContents[(int)index++] );
 				break;
 			case Types.TIME:
 				retVal = new java.sql.Time[ count ];
 				for ( ; count > 0; count-- )
-					((java.sql.Time[])retVal)[i++] = ResultSet.toTime( arrayContents[(int)index++], rs, getBaseTypeName() );
+					((java.sql.Time[])retVal)[i++] = Jdbc2ResultSet.toTime( arrayContents[(int)index++], rs, getBaseTypeName() );
 				break;
 			case Types.TIMESTAMP:
 				retVal = new Timestamp[ count ];
 				StringBuffer sbuf = null;
 				for ( ; count > 0; count-- )
-					((java.sql.Timestamp[])retVal)[i++] = ResultSet.toTimestamp( arrayContents[(int)index++], rs, getBaseTypeName() );
+					((java.sql.Timestamp[])retVal)[i++] = Jdbc2ResultSet.toTimestamp( arrayContents[(int)index++], rs, getBaseTypeName() );
 				break;
 
 				// Other datatypes not currently supported.  If you are really using other types ask
@@ -216,12 +216,12 @@ public class Array implements java.sql.Array
 		Object array = getArray( index, count, map );
 		Vector rows = new Vector();
 		Field[] fields = new Field[2];
-		fields[0] = new Field(conn, "INDEX", conn.getOID("int2"), 2);
+		fields[0] = new Field(conn, "INDEX", conn.getPGType("int2"), 2);
 		switch ( getBaseType() )
 		{
 			case Types.BIT:
 				boolean[] booleanArray = (boolean[]) array;
-				fields[1] = new Field(conn, "VALUE", conn.getOID("bool"), 1);
+				fields[1] = new Field(conn, "VALUE", conn.getPGType("bool"), 1);
 				for ( int i = 0; i < booleanArray.length; i++ )
 				{
 					byte[][] tuple = new byte[2][0];
@@ -230,11 +230,11 @@ public class Array implements java.sql.Array
 					rows.addElement(tuple);
 				}
 			case Types.SMALLINT:
-				fields[1] = new Field(conn, "VALUE", conn.getOID("int2"), 2);
+				fields[1] = new Field(conn, "VALUE", conn.getPGType("int2"), 2);
 			case Types.INTEGER:
 				int[] intArray = (int[]) array;
 				if ( fields[1] == null )
-					fields[1] = new Field(conn, "VALUE", conn.getOID("int4"), 4);
+					fields[1] = new Field(conn, "VALUE", conn.getPGType("int4"), 4);
 				for ( int i = 0; i < intArray.length; i++ )
 				{
 					byte[][] tuple = new byte[2][0];
@@ -245,7 +245,7 @@ public class Array implements java.sql.Array
 				break;
 			case Types.BIGINT:
 				long[] longArray = (long[]) array;
-				fields[1] = new Field(conn, "VALUE", conn.getOID("int8"), 8);
+				fields[1] = new Field(conn, "VALUE", conn.getPGType("int8"), 8);
 				for ( int i = 0; i < longArray.length; i++ )
 				{
 					byte[][] tuple = new byte[2][0];
@@ -256,7 +256,7 @@ public class Array implements java.sql.Array
 				break;
 			case Types.NUMERIC:
 				BigDecimal[] bdArray = (BigDecimal[]) array;
-				fields[1] = new Field(conn, "VALUE", conn.getOID("numeric"), -1);
+				fields[1] = new Field(conn, "VALUE", conn.getPGType("numeric"), -1);
 				for ( int i = 0; i < bdArray.length; i++ )
 				{
 					byte[][] tuple = new byte[2][0];
@@ -267,7 +267,7 @@ public class Array implements java.sql.Array
 				break;
 			case Types.REAL:
 				float[] floatArray = (float[]) array;
-				fields[1] = new Field(conn, "VALUE", conn.getOID("float4"), 4);
+				fields[1] = new Field(conn, "VALUE", conn.getPGType("float4"), 4);
 				for ( int i = 0; i < floatArray.length; i++ )
 				{
 					byte[][] tuple = new byte[2][0];
@@ -278,7 +278,7 @@ public class Array implements java.sql.Array
 				break;
 			case Types.DOUBLE:
 				double[] doubleArray = (double[]) array;
-				fields[1] = new Field(conn, "VALUE", conn.getOID("float8"), 8);
+				fields[1] = new Field(conn, "VALUE", conn.getPGType("float8"), 8);
 				for ( int i = 0; i < doubleArray.length; i++ )
 				{
 					byte[][] tuple = new byte[2][0];
@@ -288,11 +288,11 @@ public class Array implements java.sql.Array
 				}
 				break;
 			case Types.CHAR:
-				fields[1] = new Field(conn, "VALUE", conn.getOID("char"), 1);
+				fields[1] = new Field(conn, "VALUE", conn.getPGType("char"), 1);
 			case Types.VARCHAR:
 				String[] strArray = (String[]) array;
 				if ( fields[1] == null )
-					fields[1] = new Field(conn, "VALUE", conn.getOID("varchar"), -1);
+					fields[1] = new Field(conn, "VALUE", conn.getPGType("varchar"), -1);
 				for ( int i = 0; i < strArray.length; i++ )
 				{
 					byte[][] tuple = new byte[2][0];
@@ -303,7 +303,7 @@ public class Array implements java.sql.Array
 				break;
 			case Types.DATE:
 				java.sql.Date[] dateArray = (java.sql.Date[]) array;
-				fields[1] = new Field(conn, "VALUE", conn.getOID("date"), 4);
+				fields[1] = new Field(conn, "VALUE", conn.getPGType("date"), 4);
 				for ( int i = 0; i < dateArray.length; i++ )
 				{
 					byte[][] tuple = new byte[2][0];
@@ -314,7 +314,7 @@ public class Array implements java.sql.Array
 				break;
 			case Types.TIME:
 				java.sql.Time[] timeArray = (java.sql.Time[]) array;
-				fields[1] = new Field(conn, "VALUE", conn.getOID("time"), 8);
+				fields[1] = new Field(conn, "VALUE", conn.getPGType("time"), 8);
 				for ( int i = 0; i < timeArray.length; i++ )
 				{
 					byte[][] tuple = new byte[2][0];
@@ -325,7 +325,7 @@ public class Array implements java.sql.Array
 				break;
 			case Types.TIMESTAMP:
 				java.sql.Timestamp[] timestampArray = (java.sql.Timestamp[]) array;
-				fields[1] = new Field(conn, "VALUE", conn.getOID("timestamp"), 8);
+				fields[1] = new Field(conn, "VALUE", conn.getPGType("timestamp"), 8);
 				for ( int i = 0; i < timestampArray.length; i++ )
 				{
 					byte[][] tuple = new byte[2][0];
@@ -340,7 +340,7 @@ public class Array implements java.sql.Array
 			default:
 				throw org.postgresql.Driver.notImplemented();
 		}
-		return new ResultSet((org.postgresql.jdbc2.Connection)conn, fields, rows, "OK", 1 );
+		return new Jdbc2ResultSet((org.postgresql.jdbc2.Jdbc2Connection)conn, 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
index 4aa03483253..9d37bf04bc5 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/CallableStatement.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/CallableStatement.java
@@ -45,7 +45,7 @@ public class CallableStatement extends org.postgresql.jdbc2.PreparedStatement im
 	/*
 	 * @exception SQLException on failure
 	 */
-	public CallableStatement(Connection c, String q) throws SQLException
+	public CallableStatement(Jdbc2Connection c, String q) throws SQLException
 	{
 		super(c, q); // don't parse yet..
 	}
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java
deleted file mode 100644
index 9ab3cced8ed..00000000000
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/Connection.java
+++ /dev/null
@@ -1,332 +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.io.*;
-import java.lang.*;
-import java.lang.reflect.*;
-import java.net.*;
-import java.util.*;
-import java.sql.*;
-import org.postgresql.Field;
-import org.postgresql.fastpath.*;
-import org.postgresql.largeobject.*;
-import org.postgresql.util.*;
-
-/*
- * $Id: Connection.java,v 1.20 2002/06/24 06:16:27 barry Exp $
- *
- * A Connection represents a session with a specific database.	Within the
- * context of a Connection, SQL statements are executed and results are
- * returned.
- *
- * <P>A Connection's database is able to provide information describing
- * its tables, its supported SQL grammar, its stored procedures, the
- * capabilities of this connection, etc.  This information is obtained
- * with the getMetaData method.
- *
- * <p><B>Note:</B> By default, the Connection automatically commits changes
- * after executing each statement.	If auto-commit has been disabled, an
- * explicit commit must be done or database changes will not be saved.
- *
- * @see java.sql.Connection
- */
-public class Connection extends org.postgresql.Connection implements java.sql.Connection
-{
-        // This is a cache of the DatabaseMetaData instance for this connection
-        protected DatabaseMetaData metadata;
-
-        /*
-         * The current type mappings
-         */
-        protected java.util.Map typemap;
-
-        /*
-         * SQL statements without parameters are normally executed using
-         * Statement objects.  If the same SQL statement is executed many
-         * times, it is more efficient to use a PreparedStatement
-         *
-         * @return a new Statement object
-         * @exception SQLException passed through from the constructor
-         */
-        public java.sql.Statement createStatement() throws SQLException
-        {
-                // The spec says default of TYPE_FORWARD_ONLY but everyone is used to
-                // using TYPE_SCROLL_INSENSITIVE
-                return createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY);
-        }
-
-        /*
-         * SQL statements without parameters are normally executed using
-         * Statement objects.  If the same SQL statement is executed many
-         * times, it is more efficient to use a PreparedStatement
-         *
-         * @param resultSetType to use
-         * @param resultSetCuncurrency to use
-         * @return a new Statement object
-         * @exception SQLException passed through from the constructor
-         */
-        public java.sql.Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException
-        {
-                Statement s = new Statement(this);
-                s.setResultSetType(resultSetType);
-                s.setResultSetConcurrency(resultSetConcurrency);
-                return s;
-        }
-
-
-        /*
-         * A SQL statement with or without IN parameters can be pre-compiled
-         * and stored in a PreparedStatement object.  This object can then
-         * be used to efficiently execute this statement multiple times.
-         *
-         * <B>Note:</B> This method is optimized for handling parametric
-         * SQL statements that benefit from precompilation if the drivers
-         * supports precompilation.  PostgreSQL does not support precompilation.
-         * In this case, the statement is not sent to the database until the
-         * PreparedStatement is executed.  This has no direct effect on users;
-         * however it does affect which method throws certain SQLExceptions
-         *
-         * @param sql a SQL statement that may contain one or more '?' IN
-	 *     	 parameter placeholders
-         * @return a new PreparedStatement object containing the pre-compiled
-	 *     	 statement.
-         * @exception SQLException if a database access error occurs.
-         */
-        public java.sql.PreparedStatement prepareStatement(String sql) throws SQLException
-        {
-                return prepareStatement(sql, java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY);
-        }
-
-        public java.sql.PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
-        {
-                PreparedStatement s = new PreparedStatement(this, sql);
-                s.setResultSetType(resultSetType);
-                s.setResultSetConcurrency(resultSetConcurrency);
-                return s;
-        }
-
-        /*
-         * A SQL stored procedure call statement is handled by creating a
-         * CallableStatement for it.  The CallableStatement provides methods
-         * for setting up its IN and OUT parameters and methods for executing
-         * it.
-         *
-         * <B>Note:</B> This method is optimised for handling stored procedure
-         * call statements.  Some drivers may send the call statement to the
-         * database when the prepareCall is done; others may wait until the
-         * CallableStatement is executed.  This has no direct effect on users;
-         * however, it does affect which method throws certain SQLExceptions
-         *
-         * @param sql a SQL statement that may contain one or more '?' parameter
-	 *     	 placeholders.  Typically this statement is a JDBC function call
-	 *     	 escape string.
-         * @return a new CallableStatement object containing the pre-compiled
-	 *     	 SQL statement
-         * @exception SQLException if a database access error occurs
-         */
-        public java.sql.CallableStatement prepareCall(String sql) throws SQLException
-        {
-                return prepareCall(sql, java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY);
-        }
-
-        public java.sql.CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
-        {
-			CallableStatement s = new CallableStatement(this,sql);
-			s.setResultSetType(resultSetType);
-			s.setResultSetConcurrency(resultSetConcurrency);
-			return s;
-        }
-
-        /*
-         * Tests to see if a Connection is closed.
-         *
-         * Peter Feb 7 2000: Now I've discovered that this doesn't actually obey the
-         * specifications. Under JDBC2.1, this should only be valid _after_ close()
-         * has been called. It's result is not guraranteed to be valid before, and
-         * client code should not use it to see if a connection is open. The spec says
-         * that the client should monitor the SQLExceptions thrown when their queries
-         * fail because the connection is dead.
-         *
-         * I don't like this definition. As it doesn't hurt breaking it here, our
-         * isClosed() implementation does test the connection, so for PostgreSQL, you
-         * can rely on isClosed() returning a valid result.
-         *
-         * @return the status of the connection
-         * @exception SQLException (why?)
-         */
-        public boolean isClosed() throws SQLException
-        {
-                // If the stream is gone, then close() was called
-                if (pg_stream == null)
-                        return true;
-                return false;
-        }
-
-        /*
-         * A connection's database is able to provide information describing
-         * its tables, its supported SQL grammar, its stored procedures, the
-         * capabilities of this connection, etc.  This information is made
-         * available through a DatabaseMetaData object.
-         *
-         * @return a DatabaseMetaData object for this connection
-         * @exception SQLException if a database access error occurs
-         */
-        public java.sql.DatabaseMetaData getMetaData() throws SQLException
-        {
-                if (metadata == null)
-                        metadata = new DatabaseMetaData(this);
-                return metadata;
-        }
-
-        /*
-         * This overides the method in org.postgresql.Connection and returns a
-         * ResultSet.
-         */
-        public java.sql.ResultSet getResultSet(org.postgresql.Connection conn, java.sql.Statement stat, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException
-        {
-                // In 7.1 we now test concurrency to see which class to return. If we are not working with a
-                // Statement then default to a normal ResultSet object.
-                if (stat != null)
-                {
-                        if (stat.getResultSetConcurrency() == java.sql.ResultSet.CONCUR_UPDATABLE)
-                                return new org.postgresql.jdbc2.UpdateableResultSet((org.postgresql.jdbc2.Connection)conn, fields, tuples, status, updateCount, insertOID, binaryCursor);
-                }
-
-                return new org.postgresql.jdbc2.ResultSet((org.postgresql.jdbc2.Connection)conn, fields, tuples, status, updateCount, insertOID, binaryCursor);
-        }
-
-        // *****************
-        // JDBC 2 extensions
-        // *****************
-
-        public java.util.Map getTypeMap() throws SQLException
-        {
-                // new in 7.1
-                return typemap;
-        }
-
-
-        public void setTypeMap(java.util.Map map) throws SQLException
-        {
-                // new in 7.1
-                typemap = map;
-        }
-
-        /*
-         * This overides the standard internal getObject method so that we can
-         * check the jdbc2 type map first
-         *
-         * @return PGobject for this type, and set to value
-         * @exception SQLException if value is not correct for this type
-         * @see org.postgresql.util.Serialize
-         */
-        public Object getObject(String type, String value) throws SQLException
-        {
-                if (typemap != null)
-                {
-                        SQLData d = (SQLData) typemap.get(type);
-                        if (d != null)
-                        {
-                                // Handle the type (requires SQLInput & SQLOutput classes to be implemented)
-                                throw org.postgresql.Driver.notImplemented();
-                        }
-                }
-
-                // Default to the original method
-                return super.getObject(type, value);
-        }
-
-        /* An implementation of the abstract method in the parent class.
-         * This implemetation uses the jdbc2Types array to support the jdbc2
-         * datatypes.  Basically jdbc1 and jdbc2 are the same, except that
-         * jdbc2 adds the Array types.
-         */
-        public int getSQLType(String pgTypeName)
-        {
-                int sqlType = Types.OTHER; // default value
-                for (int i = 0;i < jdbc2Types.length;i++)
-                {
-                        if (pgTypeName.equals(jdbc2Types[i]))
-                        {
-                                sqlType = jdbc2Typei[i];
-                                break;
-                        }
-                }
-                return sqlType;
-        }
-
-        /*
-         * This table holds the org.postgresql names for the types supported.
-         * Any types that map to Types.OTHER (eg POINT) don't go into this table.
-         * They default automatically to Types.OTHER
-         *
-         * Note: This must be in the same order as below.
-         *
-         * Tip: keep these grouped together by the Types. value
-         */
-        private static final String jdbc2Types[] = {
-                                "int2",
-                                "int4", "oid",
-                                "int8",
-                                "cash", "money",
-                                "numeric",
-                                "float4",
-                                "float8",
-                                "bpchar", "char", "char2", "char4", "char8", "char16",
-                                "varchar", "text", "name", "filename",
-                                "bytea",
-                                "bool",
-                                "date",
-                                "time",
-                                "abstime", "timestamp", "timestamptz",
-                                "_bool", "_char", "_int2", "_int4", "_text",
-                                "_oid", "_varchar", "_int8", "_float4", "_float8",
-                                "_abstime", "_date", "_time", "_timestamp", "_numeric",
-                                "_bytea"
-                        };
-
-        /*
-         * This table holds the JDBC type for each entry above.
-         *
-         * Note: This must be in the same order as above
-         *
-         * Tip: keep these grouped together by the Types. value
-         */
-        private static final int jdbc2Typei[] = {
-                                                                                                Types.SMALLINT,
-                                                                                                Types.INTEGER, Types.INTEGER,
-                                                                                                Types.BIGINT,
-                                                                                                Types.DOUBLE, Types.DOUBLE,
-                                                                                                Types.NUMERIC,
-                                                                                                Types.REAL,
-                                                                                                Types.DOUBLE,
-                                                                                                Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR,
-                                                                                                Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
-                                                                                                Types.BINARY,
-                                                                                                Types.BIT,
-                                                                                                Types.DATE,
-                                                                                                Types.TIME,
-                                                                                                Types.TIMESTAMP, Types.TIMESTAMP, Types.TIMESTAMP,
-                                                                                                Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY,
-                                                                                                Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY,
-                                                                                                Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY,
-                                                                                                Types.ARRAY
-                                                                                        };
-
-        //Because the get/setLogStream methods are deprecated in JDBC2
-        //we use the get/setLogWriter methods here for JDBC2 by overriding
-        //the base version of this method
-        protected void enableDriverManagerLogging() {
-            if (DriverManager.getLogWriter() == null) {
-                DriverManager.setLogWriter(new PrintWriter(System.out));
-	    }
-	}
-
-}
-
-// ***********************************************************************
-
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/DatabaseMetaData.java b/src/interfaces/jdbc/org/postgresql/jdbc2/DatabaseMetaData.java
index 3cc224e6e8f..77415d051d4 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.58 2002/07/12 13:07:48 davec Exp $
+ * $Id: DatabaseMetaData.java,v 1.59 2002/07/23 03:59:55 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
@@ -39,7 +39,7 @@ import org.postgresql.util.PSQLException;
  */
 public class DatabaseMetaData implements java.sql.DatabaseMetaData
 {
-	Connection connection;		// The connection association
+	Jdbc2Connection connection;		// The connection association
 
 	// These define various OID's. Hopefully they will stay constant.
 	static final int iVarcharOid = 1043;	// OID for varchar
@@ -48,7 +48,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
 	static final int iInt4Oid = 23; // OID for int4
 	static final int VARHDRSZ = 4;	// length for int4
 
-	public DatabaseMetaData(Connection conn)
+	public DatabaseMetaData(Jdbc2Connection conn)
 	{
 		this.connection = conn;
 	}
@@ -1653,7 +1653,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
 
 			v.addElement(tuple);
 		}
-		return new ResultSet(connection, f, v, "OK", 1);
+		return new Jdbc2ResultSet(connection, f, v, "OK", 1);
 	}
 
 	/*
@@ -1731,7 +1731,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
 
 		// add query loop here
 
-		return new ResultSet(connection, f, v, "OK", 1);
+		return new Jdbc2ResultSet(connection, f, v, "OK", 1);
 	}
 
 	/*
@@ -1825,7 +1825,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
 
 			byte remarks[] = null;
 
-			if (((org.postgresql.ResultSet)dr).getTupleCount() == 1)
+			if (((AbstractJdbc2ResultSet)dr).getTupleCount() == 1)
 			{
 				dr.next();
 				remarks = dr.getBytes(1);
@@ -1866,7 +1866,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
 			v.addElement(tuple);
 		}
 		r.close();
-		return new ResultSet(connection, f, v, "OK", 1);
+		return new Jdbc2ResultSet(connection, 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 ResultSet(connection, f, v, "OK", 1);
+		return new Jdbc2ResultSet(connection, 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 ResultSet(connection, f, v, "OK", 1);
+		return new Jdbc2ResultSet(connection, f, v, "OK", 1);
 	}
 
 	/*
@@ -2154,7 +2154,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
 		}
 		r.close();
 
-		return new ResultSet(connection, f, v, "OK", 1);
+		return new Jdbc2ResultSet(connection, f, v, "OK", 1);
 	}
 
 	/*
@@ -2218,7 +2218,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
 			//v.addElement(tuple);
 		}
 
-		return new ResultSet(connection, f, v, "OK", 1);
+		return new Jdbc2ResultSet(connection, f, v, "OK", 1);
 	}
 
 	/*
@@ -2281,7 +2281,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
 			//v.addElement(tuple);
 		}
 
-		return new ResultSet(connection, f, v, "OK", 1);
+		return new Jdbc2ResultSet(connection, 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 ResultSet(connection, f, v, "OK", 1);
+		return new Jdbc2ResultSet(connection, f, v, "OK", 1);
 	}
 
 	/*
@@ -2680,7 +2680,7 @@ WHERE
       tuples.addElement(tuple);
     }
 
-    return new ResultSet(connection, f, tuples, "OK", 1);
+    return new Jdbc2ResultSet(connection, f, tuples, "OK", 1);
 	}
 
 	/*
@@ -2959,7 +2959,7 @@ WHERE
 				v.addElement(tuple);
 			}
 			rs.close();
-			return new ResultSet(connection, f, v, "OK", 1);
+			return new Jdbc2ResultSet(connection, f, v, "OK", 1);
 		}
 
 		throw new PSQLException("postgresql.metadata.unavailable");
@@ -3097,7 +3097,7 @@ WHERE
 			}
 		}
 
-		return new ResultSet(connection, f, v, "OK", 1);
+		return new Jdbc2ResultSet(connection, f, v, "OK", 1);
 	}
 
 
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Connection.java
new file mode 100644
index 00000000000..cfbb3486ec6
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Connection.java
@@ -0,0 +1,62 @@
+package org.postgresql.jdbc2;
+
+
+import java.sql.*;
+import java.util.Vector;
+import org.postgresql.Field;
+
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2Connection.java,v 1.1 2002/07/23 03:59:55 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
+ */
+public class Jdbc2Connection extends org.postgresql.jdbc2.AbstractJdbc2Connection implements java.sql.Connection
+{
+
+        public java.sql.Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException
+        {
+                Jdbc2Statement s = new Jdbc2Statement(this);
+                s.setResultSetType(resultSetType);
+                s.setResultSetConcurrency(resultSetConcurrency);
+                return s;
+        }
+
+
+        public java.sql.PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
+        {
+                org.postgresql.jdbc2.PreparedStatement s = new org.postgresql.jdbc2.PreparedStatement(this, sql);
+                s.setResultSetType(resultSetType);
+                s.setResultSetConcurrency(resultSetConcurrency);
+                return s;
+        }
+
+        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);
+		s.setResultSetType(resultSetType);
+	      	s.setResultSetConcurrency(resultSetConcurrency);
+	       	return s;
+        }
+
+        public java.sql.DatabaseMetaData getMetaData() throws SQLException
+        {
+                if (metadata == null)
+                        metadata = new org.postgresql.jdbc2.DatabaseMetaData(this);
+                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
+        {
+                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, fields, tuples, status, updateCount, insertOID, binaryCursor);
+        }
+
+
+}
+
+
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2ResultSet.java
new file mode 100644
index 00000000000..7200cf549ad
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2ResultSet.java
@@ -0,0 +1,32 @@
+package org.postgresql.jdbc2;
+
+
+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 $
+ * 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
+ */
+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)
+	{
+		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);
+	}
+
+	public java.sql.ResultSetMetaData getMetaData() throws SQLException
+	{
+		return new ResultSetMetaData(rows, fields);
+	}
+
+}
+
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Statement.java b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Statement.java
new file mode 100644
index 00000000000..31cec93821a
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2Statement.java
@@ -0,0 +1,21 @@
+package org.postgresql.jdbc2;
+
+
+import java.sql.*;
+
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2Statement.java,v 1.1 2002/07/23 03:59:55 barry Exp $
+ * This class implements the java.sql.Statement interface for JDBC2.
+ * However most of the implementation is really done in 
+ * org.postgresql.jdbc2.AbstractJdbc2Statement or one of it's parents
+ */
+public class Jdbc2Statement extends org.postgresql.jdbc2.AbstractJdbc2Statement implements java.sql.Statement
+{
+
+	public Jdbc2Statement (Jdbc2Connection c)
+	{
+		connection = c;
+		resultsettype = java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE;
+		concurrency = java.sql.ResultSet.CONCUR_READ_ONLY;
+	}
+
+}
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java b/src/interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java
index 5638a2692d6..21aba8d9ee0 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java
@@ -29,12 +29,12 @@ import org.postgresql.util.*;
  * @see ResultSet
  * @see java.sql.PreparedStatement
  */
-public class PreparedStatement extends Statement implements java.sql.PreparedStatement
+public class PreparedStatement extends Jdbc2Statement implements java.sql.PreparedStatement
 {
 	String sql;
 	String[] templateStrings;
 	String[] inStrings;
-	Connection connection;
+	Jdbc2Connection connection;
 
 	// Some performance caches
 	private StringBuffer sbuf = new StringBuffer();
@@ -49,7 +49,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
 	 * @param sql the SQL statement with ? for IN markers
 	 * @exception SQLException if something bad occurs
 	 */
-	public PreparedStatement(Connection connection, String sql) throws SQLException
+	public PreparedStatement(Jdbc2Connection connection, String sql) throws SQLException
 	{
 		super(connection);
 
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java
deleted file mode 100644
index f5489f4e979..00000000000
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java
+++ /dev/null
@@ -1,1802 +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.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.core.Encoding;
-
-/*
- * A ResultSet provides access to a table of data generated by executing a
- * Statement.  The table rows are retrieved in sequence.  Within a row its
- * column values can be accessed in any order.
- *
- * <P>A ResultSet maintains a cursor pointing to its current row of data.
- * Initially the cursor is positioned before the first row.  The 'next'
- * method moves the cursor to the next row.
- *
- * <P>The getXXX methods retrieve column values for the current row.  You can
- * retrieve values either using the index number of the column, or by using
- * the name of the column.	In general using the column index will be more
- * efficient.  Columns are numbered from 1.
- *
- * <P>For maximum portability, ResultSet columns within each row should be read
- * in left-to-right order and each column should be read only once.
- *
- *<P> For the getXXX methods, the JDBC driver attempts to convert the
- * underlying data to the specified Java type and returns a suitable Java
- * value.  See the JDBC specification for allowable mappings from SQL types
- * to Java types with the ResultSet getXXX methods.
- *
- * <P>Column names used as input to getXXX methods are case insenstive.  When
- * performing a getXXX using a column name, if several columns have the same
- * name, then the value of the first matching column will be returned.	The
- * column name option is designed to be used when column names are used in the
- * SQL Query.  For columns that are NOT explicitly named in the query, it is
- * best to use column numbers.	If column names were used there is no way for
- * the programmer to guarentee that they actually refer to the intended
- * columns.
- *
- * <P>A ResultSet is automatically closed by the Statement that generated it
- * when that Statement is closed, re-executed, or is used to retrieve the
- * next result from a sequence of multiple results.
- *
- * <P>The number, types and properties of a ResultSet's columns are provided by
- * the ResultSetMetaData object returned by the getMetaData method.
- *
- * @see ResultSetMetaData
- * @see java.sql.ResultSet
- */
-public class ResultSet extends org.postgresql.ResultSet implements java.sql.ResultSet
-{
-	protected org.postgresql.jdbc2.Statement statement;
-
-	private StringBuffer sbuf = null;
-	protected byte[][] rowBuffer=null;
-	protected String sqlQuery=null;
-
-	/*
-	 * 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 ResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor)
-	{
-		super(conn, fields, tuples, status, updateCount, insertOID, binaryCursor);
-	}
-
-	/*
-	 * 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 ResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount)
-	{
-		super(conn, fields, tuples, status, updateCount, 0, false);
-	}
-
-	/*
-	 * A ResultSet is initially positioned before its first row,
-	 * the first call to next makes the first row the current row;
-	 * the second call makes the second row the current row, etc.
-	 *
-	 * <p>If an input stream from the previous row is open, it is
-	 * implicitly closed.  The ResultSet's warning chain is cleared
-	 * when a new row is read
-	 *
-	 * @return true if the new current is valid; false if there are no
-	 *	more rows
-	 * @exception SQLException if a database access error occurs
-	 */
-	public boolean next() throws SQLException
-	{
-    if (rows == null)
-       throw new PSQLException("postgresql.con.closed");
-
-
-		if (++current_row >= rows.size())
-			return false;
-
-		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;
-	}
-
-	/*
-	 * In some cases, it is desirable to immediately release a ResultSet
-	 * database and JDBC resources instead of waiting for this to happen
-	 * when it is automatically closed.  The close method provides this
-	 * immediate release.
-	 *
-	 * <p><B>Note:</B> A ResultSet is automatically closed by the Statement
-	 * the Statement that generated it when that Statement is closed,
-	 * re-executed, or is used to retrieve the next result from a sequence
-	 * of multiple results.  A ResultSet is also automatically closed
-	 * when it is garbage collected.
-	 *
-	 * @exception SQLException if a database access error occurs
-	 */
-	public void close() throws SQLException
-	{
-		//release resources held (memory for tuples)
-		if (rows != null)
-		{
-			rows = null;
-		}
-	}
-
-	/*
-	 * A column may have the value of SQL NULL; wasNull() reports whether
-	 * the last column read had this special value.  Note that you must
-	 * first call getXXX on a column to try to read its value and then
-	 * call wasNull() to find if the value was SQL NULL
-	 *
-	 * @return true if the last column read was SQL NULL
-	 * @exception SQLException if a database access error occurred
-	 */
-	public boolean wasNull() throws SQLException
-	{
-		return wasNullFlag;
-	}
-
-	/*
-	 * Get the value of a column in the current row as a Java String
-	 *
-	 * @param columnIndex the first column is 1, the second is 2...
-	 * @return the column value, null for SQL NULL
-	 * @exception SQLException if a database access error occurs
-	 */
-	public String getString(int columnIndex) throws SQLException
-	{
-		checkResultSet( columnIndex );
-		wasNullFlag = (this_row[columnIndex - 1] == null);
-		if (wasNullFlag)
-			return null;
-
-		Encoding encoding = connection.getEncoding();
-		return encoding.decode(this_row[columnIndex - 1]);
-	}
-
-	/*
-	 * Get the value of a column in the current row as a Java boolean
-	 *
-	 * @param columnIndex the first column is 1, the second is 2...
-	 * @return the column value, false for SQL NULL
-	 * @exception SQLException if a database access error occurs
-	 */
-	public boolean getBoolean(int columnIndex) throws SQLException
-	{
-		return toBoolean( getString(columnIndex) );
-	}
-
-	/*
-	 * Get the value of a column in the current row as a Java byte.
-	 *
-	 * @param columnIndex the first column is 1, the second is 2,...
-	 * @return the column value; 0 if SQL NULL
-	 * @exception SQLException if a database access error occurs
-	 */
-	public byte getByte(int columnIndex) throws SQLException
-	{
-		String s = getString(columnIndex);
-
-		if (s != null)
-		{
-			try
-			{
-				return Byte.parseByte(s);
-			}
-			catch (NumberFormatException e)
-			{
-				throw new PSQLException("postgresql.res.badbyte", s);
-			}
-		}
-		return 0;		// SQL NULL
-	}
-
-	/*
-	 * Get the value of a column in the current row as a Java short.
-	 *
-	 * @param columnIndex the first column is 1, the second is 2,...
-	 * @return the column value; 0 if SQL NULL
-	 * @exception SQLException if a database access error occurs
-	 */
-	public short getShort(int columnIndex) throws SQLException
-	{
-		String s = getFixedString(columnIndex);
-
-		if (s != null)
-		{
-			try
-			{
-				return Short.parseShort(s);
-			}
-			catch (NumberFormatException e)
-			{
-				throw new PSQLException("postgresql.res.badshort", s);
-			}
-		}
-		return 0;		// SQL NULL
-	}
-
-	/*
-	 * Get the value of a column in the current row as a Java int.
-	 *
-	 * @param columnIndex the first column is 1, the second is 2,...
-	 * @return the column value; 0 if SQL NULL
-	 * @exception SQLException if a database access error occurs
-	 */
-	public int getInt(int columnIndex) throws SQLException
-	{
-		return toInt( getFixedString(columnIndex) );
-	}
-
-	/*
-	 * Get the value of a column in the current row as a Java long.
-	 *
-	 * @param columnIndex the first column is 1, the second is 2,...
-	 * @return the column value; 0 if SQL NULL
-	 * @exception SQLException if a database access error occurs
-	 */
-	public long getLong(int columnIndex) throws SQLException
-	{
-		return toLong( getFixedString(columnIndex) );
-	}
-
-	/*
-	 * Get the value of a column in the current row as a Java float.
-	 *
-	 * @param columnIndex the first column is 1, the second is 2,...
-	 * @return the column value; 0 if SQL NULL
-	 * @exception SQLException if a database access error occurs
-	 */
-	public float getFloat(int columnIndex) throws SQLException
-	{
-		return toFloat( getFixedString(columnIndex) );
-	}
-
-	/*
-	 * Get the value of a column in the current row as a Java double.
-	 *
-	 * @param columnIndex the first column is 1, the second is 2,...
-	 * @return the column value; 0 if SQL NULL
-	 * @exception SQLException if a database access error occurs
-	 */
-	public double getDouble(int columnIndex) throws SQLException
-	{
-		return toDouble( getFixedString(columnIndex) );
-	}
-
-	/*
-	 * Get the value of a column in the current row as a
-	 * java.math.BigDecimal object
-	 *
-	 * @param columnIndex  the first column is 1, the second is 2...
-	 * @param scale the number of digits to the right of the decimal
-	 * @return the column value; if the value is SQL NULL, null
-	 * @exception SQLException if a database access error occurs
-	 * @deprecated
-	 */
-	public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException
-	{
-		return toBigDecimal( getFixedString(columnIndex), scale );
-	}
-
-	/*
-	 * Get the value of a column in the current row as a Java byte array.
-	 *
-	 * <p>In normal use, the bytes represent the raw values returned by the
-	 * backend. However, if the column is an OID, then it is assumed to
-	 * refer to a Large Object, and that object is returned as a byte array.
-	 *
-	 * <p><b>Be warned</b> If the large object is huge, then you may run out
-	 * of memory.
-	 *
-	 * @param columnIndex the first column is 1, the second is 2, ...
-	 * @return the column value; if the value is SQL NULL, the result
-	 *	is null
-	 * @exception SQLException if a database access error occurs
-	 */
-	public byte[] getBytes(int columnIndex) throws SQLException
-	{
-		checkResultSet( columnIndex );
-		wasNullFlag = (this_row[columnIndex - 1] == null);
-		if (!wasNullFlag)
-		{
-			if (binaryCursor)
-			{
-				//If the data is already binary then just return it
-				return this_row[columnIndex - 1];
-			}
-			else if (connection.haveMinimumCompatibleVersion("7.2"))
-			{
-				//Version 7.2 supports the bytea datatype for byte arrays
-				if (fields[columnIndex - 1].getPGType().equals("bytea"))
-				{
-					return PGbytea.toBytes(this_row[columnIndex - 1]);
-				}
-				else
-				{
-					return this_row[columnIndex - 1];
-				}
-			}
-			else
-			{
-				//Version 7.1 and earlier supports LargeObjects for byte arrays
-				// Handle OID's as BLOBS
-				if ( fields[columnIndex - 1].getOID() == 26)
-				{
-					LargeObjectManager lom = connection.getLargeObjectAPI();
-					LargeObject lob = lom.open(getInt(columnIndex));
-					byte buf[] = lob.read(lob.size());
-					lob.close();
-					return buf;
-				}
-				else
-				{
-					return this_row[columnIndex - 1];
-				}
-			}
-		}
-		return null;
-	}
-
-	/*
-	 * Get the value of a column in the current row as a java.sql.Date
-	 * object
-	 *
-	 * @param columnIndex the first column is 1, the second is 2...
-	 * @return the column value; null if SQL NULL
-	 * @exception SQLException if a database access error occurs
-	 */
-	public java.sql.Date getDate(int columnIndex) throws SQLException
-	{
-		return toDate( getString(columnIndex) );
-	}
-
-	/*
-	 * Get the value of a column in the current row as a java.sql.Time
-	 * object
-	 *
-	 * @param columnIndex the first column is 1, the second is 2...
-	 * @return the column value; null if SQL NULL
-	 * @exception SQLException if a database access error occurs
-	 */
-	public Time getTime(int columnIndex) throws SQLException
-	{
-		return toTime( getString(columnIndex), this, fields[columnIndex-1].getPGType() );
-	}
-
-	/*
-	 * Get the value of a column in the current row as a
-	 * java.sql.Timestamp object
-	 *
-	 * @param columnIndex the first column is 1, the second is 2...
-	 * @return the column value; null if SQL NULL
-	 * @exception SQLException if a database access error occurs
-	 */
-	public Timestamp getTimestamp(int columnIndex) throws SQLException
-	{
-		return toTimestamp( getString(columnIndex), this, fields[columnIndex-1].getPGType() );
-	}
-
-	/*
-	 * A column value can be retrieved as a stream of ASCII characters
-	 * and then read in chunks from the stream.  This method is
-	 * particular suitable for retrieving large LONGVARCHAR values.
-	 * The JDBC driver will do any necessary conversion from the
-	 * database format into ASCII.
-	 *
-	 * <p><B>Note:</B> All the data in the returned stream must be read
-	 * prior to getting the value of any other column.	The next call
-	 * to a get method implicitly closes the stream.  Also, a stream
-	 * may return 0 for available() whether there is data available
-	 * or not.
-	 *
-	 *<p> We implement an ASCII stream as a Binary stream - we should really
-	 * do the data conversion, but I cannot be bothered to implement this
-	 * right now.
-	 *
-	 * @param columnIndex the first column is 1, the second is 2, ...
-	 * @return a Java InputStream that delivers the database column
-	 *	value as a stream of one byte ASCII characters.  If the
-	 *	value is SQL NULL then the result is null
-	 * @exception SQLException if a database access error occurs
-	 * @see getBinaryStream
-	 */
-	public InputStream getAsciiStream(int columnIndex) throws SQLException
-	{
-		checkResultSet( columnIndex );
-		wasNullFlag = (this_row[columnIndex - 1] == null);
-		if (wasNullFlag)
-			return null;
-
-		if (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
-			try
-			{
-				return new ByteArrayInputStream(getString(columnIndex).getBytes("ASCII"));
-			}
-			catch (UnsupportedEncodingException l_uee)
-			{
-				throw new PSQLException("postgresql.unusual", l_uee);
-			}
-		}
-		else
-		{
-			// In 7.1 Handle as BLOBS so return the LargeObject input stream
-			return getBinaryStream(columnIndex);
-		}
-	}
-
-	/*
-	 * A column value can also be retrieved as a stream of Unicode
-	 * characters. We implement this as a binary stream.
-	 *
-	 * ** DEPRECATED IN JDBC 2 **
-	 *
-	 * @param columnIndex the first column is 1, the second is 2...
-	 * @return a Java InputStream that delivers the database column value
-	 *	as a stream of two byte Unicode characters.  If the value is
-	 *	SQL NULL, then the result is null
-	 * @exception SQLException if a database access error occurs
-	 * @see getAsciiStream
-	 * @see getBinaryStream
-	 * @deprecated in JDBC2.0
-	 */
-	public InputStream getUnicodeStream(int columnIndex) throws SQLException
-	{
-		checkResultSet( columnIndex );
-		wasNullFlag = (this_row[columnIndex - 1] == null);
-		if (wasNullFlag)
-			return null;
-
-		if (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
-			try
-			{
-				return new ByteArrayInputStream(getString(columnIndex).getBytes("UTF-8"));
-			}
-			catch (UnsupportedEncodingException l_uee)
-			{
-				throw new PSQLException("postgresql.unusual", l_uee);
-			}
-		}
-		else
-		{
-			// In 7.1 Handle as BLOBS so return the LargeObject input stream
-			return getBinaryStream(columnIndex);
-		}
-	}
-
-	/*
-	 * A column value can also be retrieved as a binary strea.	This
-	 * method is suitable for retrieving LONGVARBINARY values.
-	 *
-	 * @param columnIndex the first column is 1, the second is 2...
-	 * @return a Java InputStream that delivers the database column value
-	 * as a stream of bytes.  If the value is SQL NULL, then the result
-	 * is null
-	 * @exception SQLException if a database access error occurs
-	 * @see getAsciiStream
-	 * @see getUnicodeStream
-	 */
-	public InputStream getBinaryStream(int columnIndex) throws SQLException
-	{
-		checkResultSet( columnIndex );
-		wasNullFlag = (this_row[columnIndex - 1] == null);
-		if (wasNullFlag)
-			return null;
-
-		if (connection.haveMinimumCompatibleVersion("7.2"))
-		{
-			//Version 7.2 supports BinaryStream for all PG bytea type
-			//As the spec/javadoc for this method indicate this is to be used for
-			//large binary values (i.e. LONGVARBINARY)	PG doesn't have a separate
-			//long binary datatype, but with toast the bytea datatype is capable of
-			//handling very large values.  Thus the implementation ends up calling
-			//getBytes() since there is no current way to stream the value from the server
-			byte b[] = getBytes(columnIndex);
-			if (b != null)
-				return new ByteArrayInputStream(b);
-		}
-		else
-		{
-			// In 7.1 Handle as BLOBS so return the LargeObject input stream
-			if ( fields[columnIndex - 1].getOID() == 26)
-			{
-				LargeObjectManager lom = connection.getLargeObjectAPI();
-				LargeObject lob = lom.open(getInt(columnIndex));
-				return lob.getInputStream();
-			}
-		}
-		return null;
-	}
-
-	/*
-	 * The following routines simply convert the columnName into
-	 * a columnIndex and then call the appropriate routine above.
-	 *
-	 * @param columnName is the SQL name of the column
-	 * @return the column value
-	 * @exception SQLException if a database access error occurs
-	 */
-	public String getString(String columnName) throws SQLException
-	{
-		return getString(findColumn(columnName));
-	}
-
-	public boolean getBoolean(String columnName) throws SQLException
-	{
-		return getBoolean(findColumn(columnName));
-	}
-
-	public byte getByte(String columnName) throws SQLException
-	{
-
-		return getByte(findColumn(columnName));
-	}
-
-	public short getShort(String columnName) throws SQLException
-	{
-		return getShort(findColumn(columnName));
-	}
-
-	public int getInt(String columnName) throws SQLException
-	{
-		return getInt(findColumn(columnName));
-	}
-
-	public long getLong(String columnName) throws SQLException
-	{
-		return getLong(findColumn(columnName));
-	}
-
-	public float getFloat(String columnName) throws SQLException
-	{
-		return getFloat(findColumn(columnName));
-	}
-
-	public double getDouble(String columnName) throws SQLException
-	{
-		return getDouble(findColumn(columnName));
-	}
-
-	/*
-	 * @deprecated
-	 */
-	public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException
-	{
-		return getBigDecimal(findColumn(columnName), scale);
-	}
-
-	public byte[] getBytes(String columnName) throws SQLException
-	{
-		return getBytes(findColumn(columnName));
-	}
-
-	public java.sql.Date getDate(String columnName) throws SQLException
-	{
-		return getDate(findColumn(columnName));
-	}
-
-	public Time getTime(String columnName) throws SQLException
-	{
-		return getTime(findColumn(columnName));
-	}
-
-	public Timestamp getTimestamp(String columnName) throws SQLException
-	{
-		return getTimestamp(findColumn(columnName));
-	}
-
-	public InputStream getAsciiStream(String columnName) throws SQLException
-	{
-		return getAsciiStream(findColumn(columnName));
-	}
-
-	/*
-	 *
-	 * ** DEPRECATED IN JDBC 2 **
-	 *
-	 * @deprecated
-	 */
-	public InputStream getUnicodeStream(String columnName) throws SQLException
-	{
-		return getUnicodeStream(findColumn(columnName));
-	}
-
-	public InputStream getBinaryStream(String columnName) throws SQLException
-	{
-		return getBinaryStream(findColumn(columnName));
-	}
-
-	public java.net.URL getURL(int columnIndex) throws SQLException
-	{
-		return null;
-	}
-
-	public java.net.URL getURL(String columnName) throws SQLException
-	{
-		return null;
-
-	}
-
-	public void updateRef(int colIndex,java.sql.Ref ref) throws SQLException {
-
-	}
-	public void updateRef(String colName,java.sql.Ref ref) throws SQLException {
-	}
-	public void updateBlob(int colIndex,java.sql.Blob blob) throws SQLException {
-	}
-	public void updateBlob(String colName,java.sql.Blob blob) throws SQLException {
-	}
-	public void updateClob(int colIndex,java.sql.Clob clob) throws SQLException {
-	}
-	public void updateClob(String colName,java.sql.Clob clob) throws SQLException {
-	}
-	public void updateArray(int colIndex,java.sql.Array array) throws SQLException {
-	}
-	public void updateArray(String colName,java.sql.Array array) throws SQLException {
-	}
-
-	/*
-	 * The first warning reported by calls on this ResultSet is
-	 * returned.  Subsequent ResultSet warnings will be chained
-	 * to this SQLWarning.
-	 *
-	 * <p>The warning chain is automatically cleared each time a new
-	 * row is read.
-	 *
-	 * <p><B>Note:</B> This warning chain only covers warnings caused by
-	 * ResultSet methods.  Any warnings caused by statement methods
-	 * (such as reading OUT parameters) will be chained on the
-	 * Statement object.
-	 *
-	 * @return the first SQLWarning or null;
-	 * @exception SQLException if a database access error occurs.
-	 */
-	public SQLWarning getWarnings() throws SQLException
-	{
-		return warnings;
-	}
-
-	/*
-	 * After this call, getWarnings returns null until a new warning
-	 * is reported for this ResultSet
-	 *
-	 * @exception SQLException if a database access error occurs
-	 */
-	public void clearWarnings() throws SQLException
-	{
-		warnings = null;
-	}
-
-	/*
-	 * Get the name of the SQL cursor used by this ResultSet
-	 *
-	 * <p>In SQL, a result table is retrieved though a cursor that is
-	 * named.  The current row of a result can be updated or deleted
-	 * using a positioned update/delete statement that references
-	 * the cursor name.
-	 *
-	 * <p>JDBC supports this SQL feature by providing the name of the
-	 * SQL cursor used by a ResultSet.	The current row of a ResulSet
-	 * is also the current row of this SQL cursor.
-	 *
-	 * <p><B>Note:</B> If positioned update is not supported, a SQLException
-	 * is thrown.
-	 *
-	 * @return the ResultSet's SQL cursor name.
-	 * @exception SQLException if a database access error occurs
-	 */
-	public String getCursorName() throws SQLException
-	{
-		return connection.getCursorName();
-	}
-
-	/*
-	 * The numbers, types and properties of a ResultSet's columns are
-	 * provided by the getMetaData method
-	 *
-	 * @return a description of the ResultSet's columns
-	 * @exception SQLException if a database access error occurs
-	 */
-	public java.sql.ResultSetMetaData getMetaData() throws SQLException
-	{
-		return new ResultSetMetaData(rows, fields);
-	}
-
-	/*
-	 * 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));
-				}
-		}
-	}
-
-	/*
-	 * 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 columnName is the SQL name of the column
-	 * @return a Object holding the column value
-	 * @exception SQLException if a database access error occurs
-	 */
-	public Object getObject(String columnName) throws SQLException
-	{
-		return getObject(findColumn(columnName));
-	}
-
-	/*
-	 * Map a ResultSet column name to a ResultSet column index
-	 *
-	 * @param columnName the name of the column
-	 * @return the column index
-	 * @exception SQLException if a database access error occurs
-	 */
-	public int findColumn(String columnName) throws SQLException
-	{
-		int i;
-
-		final int flen = fields.length;
-		for (i = 0 ; i < flen; ++i)
-			if (fields[i].getName().equalsIgnoreCase(columnName))
-				return (i + 1);
-		throw new PSQLException ("postgresql.res.colname", columnName);
-	}
-
-	// ** JDBC 2 Extensions **
-
-	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], 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 (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);
-		}
-	}
-
-	/*
-	 * New in 7.1
-	 */
-	public Clob getClob(String columnName) throws SQLException
-	{
-		return getClob(findColumn(columnName));
-	}
-
-	/*
-	 * New in 7.1
-	 */
-	public Clob getClob(int i) throws SQLException
-	{
-		return new org.postgresql.largeobject.PGclob(connection, getInt(i));
-	}
-
-	public int getConcurrency() throws SQLException
-	{
-		// New in 7.1 - The standard ResultSet class will now return
-		// CONCUR_READ_ONLY. A sub-class will overide this if the query was
-		// updateable.
-		return CONCUR_READ_ONLY;
-	}
-
-	public java.sql.Date getDate(int i, java.util.Calendar cal) throws SQLException
-	{
-		// new in 7.1: 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
-	{
-		// new in 7.1: 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
-	{
-		// new in 7.1: 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
-	{
-		// new in 7.1: PostgreSQL normally sends rows first->last
-		return FETCH_FORWARD;
-	}
-
-	public int getFetchSize() throws SQLException
-	{
-		// new in 7.1: 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
-	{
-		/* In preparation
-		SQLInput s = new PSQLInput(this,i);
-		String t = getTypeName(i);
-		SQLData o = (SQLData) map.get(t);
-		// If the type is not in the map, then pass to the existing code
-		if (o==null)
-		  return getObject(i);
-		o.readSQL(s,t);
-		return o;
-		*/throw org.postgresql.Driver.notImplemented();
-	}
-
-	public Ref getRef(String columnName) throws SQLException
-	{
-		return getRef(findColumn(columnName));
-	}
-
-	public Ref getRef(int i) throws SQLException
-	{
-		// new in 7.1: 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 java.sql.Statement getStatement() throws SQLException
-	{
-		return statement;
-	}
-
-	public int getType() throws SQLException
-	{
-		// New in 7.1. This implementation allows scrolling but is not able to
-		// see any changes. Sub-classes may overide this to return a more
-		// meaningful result.
-		return 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");
-	}
-
-	// Peter: Implemented in 7.0
-	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
-	{
-		// In 7.1, the backend doesn't yet support this
-		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");
-	}
-
-	/*
-	 * This is called by Statement to register itself with this statement.
-	 * It's used currently by getStatement() but may also with the new core
-	 * package.
-	 */
-	public void setStatement(org.postgresql.jdbc2.Statement statement)
-	{
-		this.statement = statement;
-	}
-
-	//----------------- Formatting Methods -------------------
-
-	public static boolean toBoolean(String s)
-	{
-		if (s != null)
-		{
-			int c = s.charAt(0);
-			return ((c == 't') || (c == 'T') || (c == '1'));
-		}
-		return false;		// SQL NULL
-	}
-
-	public static int toInt(String s) throws SQLException
-	{
-		if (s != null)
-		{
-			try
-			{
-				return Integer.parseInt(s);
-			}
-			catch (NumberFormatException e)
-			{
-				throw new PSQLException ("postgresql.res.badint", s);
-			}
-		}
-		return 0;		// SQL NULL
-	}
-
-	public static long toLong(String s) throws SQLException
-	{
-		if (s != null)
-		{
-			try
-			{
-				return Long.parseLong(s);
-			}
-			catch (NumberFormatException e)
-			{
-				throw new PSQLException ("postgresql.res.badlong", s);
-			}
-		}
-		return 0;		// SQL NULL
-	}
-
-	public static BigDecimal toBigDecimal(String s, int scale) throws SQLException
-	{
-		BigDecimal val;
-		if (s != null)
-		{
-			try
-			{
-				val = new BigDecimal(s);
-			}
-			catch (NumberFormatException e)
-			{
-				throw new PSQLException ("postgresql.res.badbigdec", s);
-			}
-			if (scale == -1)
-				return val;
-			try
-			{
-				return val.setScale(scale);
-			}
-			catch (ArithmeticException e)
-			{
-				throw new PSQLException ("postgresql.res.badbigdec", s);
-			}
-		}
-		return null;		// SQL NULL
-	}
-
-	public static float toFloat(String s) throws SQLException
-	{
-		if (s != null)
-		{
-			try
-			{
-				return Float.valueOf(s).floatValue();
-			}
-			catch (NumberFormatException e)
-			{
-				throw new PSQLException ("postgresql.res.badfloat", s);
-			}
-		}
-		return 0;		// SQL NULL
-	}
-
-	public static double toDouble(String s) throws SQLException
-	{
-		if (s != null)
-		{
-			try
-			{
-				return Double.valueOf(s).doubleValue();
-			}
-			catch (NumberFormatException e)
-			{
-				throw new PSQLException ("postgresql.res.baddouble", s);
-			}
-		}
-		return 0;		// SQL NULL
-	}
-
-	public static java.sql.Date toDate(String s) throws SQLException
-	{
-		if (s == null)
-			return null;
-		// length == 10: SQL Date
-		// length >  10: SQL Timestamp, assumes PGDATESTYLE=ISO
-		try
-		{
-			return java.sql.Date.valueOf((s.length() == 10) ? s : s.substring(0, 10));
-		}
-		catch (NumberFormatException e)
-		{
-			throw new PSQLException("postgresql.res.baddate", s);
-		}
-	}
-
-	public static Time toTime(String s, ResultSet resultSet, String pgDataType) throws SQLException
-	{
-		if (s == null)
-			return null; // SQL NULL
-		try
-		{
-                   if (s.length() == 8) {
-                     //value is a time value
-                     return java.sql.Time.valueOf(s);
-                   } else if (s.indexOf(".") == 8) {
-                     //value is a time value with fractional seconds
-                     java.sql.Time l_time = java.sql.Time.valueOf(s.substring(0,8));
-                     String l_strMillis = s.substring(9);
-                     if (l_strMillis.length() > 3)
-                       l_strMillis = l_strMillis.substring(0,3);
-                     int l_millis = Integer.parseInt(l_strMillis);
-                     if (l_millis < 10) {
-                       l_millis = l_millis * 100;
-                     } else if (l_millis < 100) {
-                       l_millis = l_millis * 10;
-                     }
-                     return new java.sql.Time(l_time.getTime() + l_millis);
-                   } else {
-                     //value is a timestamp
-                     return new java.sql.Time(toTimestamp(s, resultSet, pgDataType).getTime());
-                   }
-		}
-		catch (NumberFormatException e)
-		{
-			throw new PSQLException("postgresql.res.badtime", s);
-		}
-	}
-
-	/**
-	* Parse a string and return a timestamp representing its value.
-	*
-	* The driver is set to return ISO date formated strings. We modify this
-	* string from the ISO format to a format that Java can understand. Java
-	* expects timezone info as 'GMT+09:00' where as ISO gives '+09'.
-	* Java also expects fractional seconds to 3 places where postgres
-	* will give, none, 2 or 6 depending on the time and postgres version.
-	* From version 7.2 postgres returns fractional seconds to 6 places.
-	* If available, we drop the last 3 digits.
-	*
-	* @param s         The ISO formated date string to parse.
-	* @param resultSet The ResultSet this date is part of.
-	*
-	* @return null if s is null or a timestamp of the parsed string s.
-	*
-	* @throws SQLException if there is a problem parsing s.
-	**/
-	public static Timestamp toTimestamp(String s, ResultSet resultSet, String pgDataType)
-	throws SQLException
-	{
-		if (s == null)
-			return null;
-
-		// We must be synchronized here incase more theads access the ResultSet
-		// bad practice but possible. Anyhow this is to protect sbuf and
-		// SimpleDateFormat objects
-		synchronized (resultSet)
-		{
-			SimpleDateFormat df = null;
-			if ( org.postgresql.Driver.logDebug ) org.postgresql.Driver.debug("the data from the DB is "+s);
-
-			// If first time, create the buffer, otherwise clear it.
-			if (resultSet.sbuf == null)
-				resultSet.sbuf = new StringBuffer();
-			else
-				resultSet.sbuf.setLength(0);
-
-			// Copy s into sbuf for parsing.
-			resultSet.sbuf.append(s);
-			int slen = s.length();
-
-			if (slen > 19)
-			{
-				// The len of the ISO string to the second value is 19 chars. If
-				// greater then 19, there may be tz info and perhaps fractional
-				// second info which we need to change to java to read it.
-
-				// cut the copy to second value "2001-12-07 16:29:22"
-				int i = 19;
-				resultSet.sbuf.setLength(i);
-
-				char c = s.charAt(i++);
-				if (c == '.')
-				{
-					// Found a fractional value. Append up to 3 digits including
-					// the leading '.'
-					do
-					{
-						if (i < 24)
-							resultSet.sbuf.append(c);
-						c = s.charAt(i++);
-					} while (i < slen && Character.isDigit(c));
-
-					// If there wasn't at least 3 digits we should add some zeros
-					// to make up the 3 digits we tell java to expect.
-					for (int j = i; j < 24; j++)
-						resultSet.sbuf.append('0');
-				}
-				else
-				{
-					// No fractional seconds, lets add some.
-					resultSet.sbuf.append(".000");
-				}
-
-				if (i < slen)
-				{
-					// prepend the GMT part and then add the remaining bit of
-					// the string.
-					resultSet.sbuf.append(" GMT");
-					resultSet.sbuf.append(c);
-					resultSet.sbuf.append(s.substring(i, slen));
-
-					// Lastly, if the tz part doesn't specify the :MM part then
-					// we add ":00" for java.
-					if (slen - i < 5)
-						resultSet.sbuf.append(":00");
-
-					// we'll use this dateformat string to parse the result.
-					df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z");
-				}
-				else
-				{
-				    // Just found fractional seconds but no timezone.
-				    //If timestamptz then we use GMT, else local timezone
-		                    if (pgDataType.equals("timestamptz")) {
-				        resultSet.sbuf.append(" GMT");
-					df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z");
-			            } else {
-					df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
-			            }
-				}
-			}
-			else if (slen == 19)
-			{
-			    // No tz or fractional second info.
-			    //If timestamptz then we use GMT, else local timezone
-		            if (pgDataType.equals("timestamptz")) {
-				resultSet.sbuf.append(" GMT");
-				df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
-			    } else {
-				df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-			    }
-			}
-			else
-			{
-				// We must just have a date. This case is
-				// needed if this method is called on a date
-				// column
-				df = new SimpleDateFormat("yyyy-MM-dd");
-			}
-
-			try
-			{
-				// All that's left is to parse the string and return the ts.
-				if ( org.postgresql.Driver.logDebug ) org.postgresql.Driver.debug( "" + df.parse(resultSet.sbuf.toString()).getTime() );
-
-				return new Timestamp(df.parse(resultSet.sbuf.toString()).getTime());
-			}
-			catch (ParseException e)
-			{
-				throw new PSQLException("postgresql.res.badtimestamp", new Integer(e.getErrorOffset()), s);
-			}
-		}
-	}
-
-	public void setSQLQuery(String sqlQuery) {
-		this.sqlQuery=sqlQuery;
-	}
-}
-
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/Statement.java b/src/interfaces/jdbc/org/postgresql/jdbc2/Statement.java
deleted file mode 100644
index a00025ff72a..00000000000
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/Statement.java
+++ /dev/null
@@ -1,381 +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.util.Vector;
-import org.postgresql.util.*;
-
-/*
- * A Statement object is used for executing a static SQL statement and
- * obtaining the results produced by it.
- *
- * <p>Only one ResultSet per Statement can be open at any point in time.
- * Therefore, if the reading of one ResultSet is interleaved with the
- * reading of another, each must have been generated by different
- * Statements.	All statement execute methods implicitly close a
- * statement's current ResultSet if an open one exists.
- *
- * @see java.sql.Statement
- * @see ResultSet
- */
-public class Statement extends org.postgresql.Statement implements java.sql.Statement
-{
-	private Connection connection;		// The connection who created us
-	private Vector batch = null;
-	private int resultsettype;				  // the resultset type to return
-	private int concurrency;		 // is it updateable or not?
-
-	/*
-	 * Constructor for a Statement.  It simply sets the connection
-	 * that created us.
-	 *
-	 * @param c the Connection instantation that creates us
-	 */
-	public Statement (Connection c)
-	{
-		connection = c;
-		resultsettype = java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE;
-		concurrency = java.sql.ResultSet.CONCUR_READ_ONLY;
-	}
-
-	/*
-	 * Execute a SQL statement that retruns a single ResultSet
-	 *
-	 * @param sql typically a static SQL SELECT statement
-	 * @return a ResulSet that contains the data produced by the query
-	 * @exception SQLException if a database access error occurs
-	 */
-	public java.sql.ResultSet executeQuery(String sql) throws SQLException
-	{
-		this.execute(sql);
-		while (result != null && !((org.postgresql.ResultSet)result).reallyResultSet())
-			result = ((org.postgresql.ResultSet)result).getNext();
-		if (result == null)
-			throw new PSQLException("postgresql.stat.noresult");
-		return result;
-	}
-
-	/*
-	 * Execute a SQL INSERT, UPDATE or DELETE statement.  In addition
-	 * SQL statements that return nothing such as SQL DDL statements
-	 * can be executed
-	 *
-	 * @param sql a SQL statement
-	 * @return either a row count, or 0 for SQL commands
-	 * @exception SQLException if a database access error occurs
-	 */
-	public int executeUpdate(String sql) throws SQLException
-	{
-		this.execute(sql);
-		if (((org.postgresql.ResultSet)result).reallyResultSet())
-			throw new PSQLException("postgresql.stat.result");
-		return this.getUpdateCount();
-	}
-
-	/*
-	 * setCursorName defines the SQL cursor name that will be used by
-	 * subsequent execute methods.	This name can then be used in SQL
-	 * positioned update/delete statements to identify the current row
-	 * in the ResultSet generated by this statement.  If a database
-	 * doesn't support positioned update/delete, this method is a
-	 * no-op.
-	 *
-	 * <p><B>Note:</B> By definition, positioned update/delete execution
-	 * must be done by a different Statement than the one which
-	 * generated the ResultSet being used for positioning.	Also, cursor
-	 * names must be unique within a Connection.
-	 *
-	 * <p>We throw an additional constriction.	There can only be one
-	 * cursor active at any one time.
-	 *
-	 * @param name the new cursor name
-	 * @exception SQLException if a database access error occurs
-	 */
-	public void setCursorName(String name) throws SQLException
-	{
-		connection.setCursorName(name);
-	}
-
-	/*
-	 * Execute a SQL statement that may return multiple results. We
-	 * don't have to worry about this since we do not support multiple
-	 * ResultSets.	 You can use getResultSet or getUpdateCount to
-	 * retrieve the result.
-	 *
-	 * @param sql any SQL statement
-	 * @return true if the next result is a ResulSet, false if it is
-	 *	an update count or there are no more results
-	 * @exception SQLException if a database access error occurs
-	 */
-	public boolean execute(String sql) throws SQLException
-	{
-		if (escapeProcessing)
-			sql = escapeSQL(sql);
-
-		// New in 7.1, if we have a previous resultset then force it to close
-		// This brings us nearer to compliance, and helps memory management.
-		// Internal stuff will call ExecSQL directly, bypassing this.
-		if (result != null)
-		{
-			java.sql.ResultSet rs = getResultSet();
-			if (rs != null)
-				rs.close();
-		}
-
-
-		// New in 7.1, pass Statement so that ExecSQL can customise to it
-		result = connection.ExecSQL(sql, this);
-
-		// New in 7.1, required for ResultSet.getStatement() to work
-		((org.postgresql.jdbc2.ResultSet)result).setStatement(this);
-
-		// Added this so that the Updateable resultset knows the query that gave this
-		((org.postgresql.jdbc2.ResultSet)result).setSQLQuery(sql);
-
-
-		return (result != null && ((org.postgresql.ResultSet)result).reallyResultSet());
-	}
-
-	/*
-	 * getUpdateCount returns the current result as an update count,
-	 * if the result is a ResultSet or there are no more results, -1
-	 * is returned.  It should only be called once per result.
-	 *
-	 * @return the current result as an update count.
-	 * @exception SQLException if a database access error occurs
-	 */
-	public int getUpdateCount() throws SQLException
-	{
-		if (result == null)
-			return -1;
-		if (((org.postgresql.ResultSet)result).reallyResultSet())
-			return -1;
-		return ((org.postgresql.ResultSet)result).getResultCount();
-	}
-
-	/*
-	 * getMoreResults moves to a Statement's next result.  If it returns
-	 * true, this result is a ResulSet.
-	 *
-	 * @return true if the next ResultSet is valid
-	 * @exception SQLException if a database access error occurs
-	 */
-	public boolean getMoreResults() throws SQLException
-	{
-		result = ((org.postgresql.ResultSet)result).getNext();
-		return (result != null && ((org.postgresql.ResultSet)result).reallyResultSet());
-	}
-
-	// ** JDBC 2 Extensions **
-
-	public void addBatch(String sql) throws SQLException
-	{
-		if (batch == null)
-			batch = new Vector();
-		batch.addElement(sql);
-	}
-
-	public void clearBatch() throws SQLException
-	{
-		if (batch != null)
-			batch.removeAllElements();
-	}
-
-	public int[] executeBatch() throws SQLException
-	{
-		if (batch == null)
-			batch = new Vector();
-		int size = batch.size();
-		int[] result = new int[size];
-		int i = 0;
-		try
-		{
-			for (i = 0;i < size;i++)
-				result[i] = this.executeUpdate((String)batch.elementAt(i));
-		}
-		catch (SQLException e)
-		{
-			int[] resultSucceeded = new int[i];
-			System.arraycopy(result, 0, resultSucceeded, 0, i);
-
-			PBatchUpdateException updex =
-				new PBatchUpdateException("postgresql.stat.batch.error",
-										  new Integer(i), batch.elementAt(i), resultSucceeded);
-			updex.setNextException(e);
-
-			throw updex;
-		}
-		finally
-		{
-			batch.removeAllElements();
-		}
-		return result;
-	}
-
-	public void cancel() throws SQLException
-	{
-		connection.cancelQuery();
-	}
-
-	public java.sql.Connection getConnection() throws SQLException
-	{
-		return (java.sql.Connection)connection;
-	}
-
-	public int getFetchDirection() throws SQLException
-	{
-		throw new PSQLException("postgresql.psqlnotimp");
-	}
-
-	public int getFetchSize() throws SQLException
-	{
-		// This one can only return a valid value when were a cursor?
-		throw org.postgresql.Driver.notImplemented();
-	}
-
-	public int getResultSetConcurrency() throws SQLException
-	{
-		// new in 7.1
-		return concurrency;
-	}
-
-	public int getResultSetType() throws SQLException
-	{
-		// new in 7.1
-		return resultsettype;
-	}
-
-	public void setFetchDirection(int direction) throws SQLException
-	{
-		throw org.postgresql.Driver.notImplemented();
-	}
-
-	public void setFetchSize(int rows) throws SQLException
-	{
-		throw org.postgresql.Driver.notImplemented();
-	}
-
-	/*
-	 * New in 7.1
-	 */
-	public void setResultSetConcurrency(int value) throws SQLException
-	{
-		concurrency = value;
-	}
-
-	/*
-	 * New in 7.1
-	 */
-	public void setResultSetType(int value) throws SQLException
-	{
-		resultsettype = value;
-	}
-
-	// In JDK 1.4 not implemented
-  /**
-   *
-   * @param num
-   * @return
-   * @throws SQLException
-   */
-	public boolean getMoreResults(int num) throws SQLException
-  {
-		throw org.postgresql.Driver.notImplemented();
-	}
-
-  /**
-   *
-   * @return
-   * @throws SQLException
-   */
-	public java.sql.ResultSet getGeneratedKeys() throws SQLException
-  {
-		throw org.postgresql.Driver.notImplemented();
-	}
-
-  /**
-   *
-   * @param a
-   * @param b
-   * @return
-   * @throws SQLException
-   */
-	public int executeUpdate(String a, int b) throws SQLException
-  {
-		throw org.postgresql.Driver.notImplemented();
-	}
-
-  /**
-   *
-   * @param a
-   * @param b
-   * @return
-   * @throws SQLException
-   */
-	public int executeUpdate(String a, int[] b) throws SQLException
-  {
-		throw org.postgresql.Driver.notImplemented();
-
-	}
-
-	public int executeUpdate(String a, String[] b) throws SQLException
-  {
-		throw org.postgresql.Driver.notImplemented();
-
-	}
-
-  /**
-   *
-   * @param a
-   * @param b
-   * @return
-   * @throws SQLException
-   */
-	public boolean execute(String a, int b) throws SQLException
-  {
-		throw org.postgresql.Driver.notImplemented();
-
-	}
-
-  /**
-   *
-   * @param a
-   * @param b
-   * @return
-   * @throws SQLException
-   */
-	public boolean execute(String a, int[] b) throws SQLException
-  {
-		throw org.postgresql.Driver.notImplemented();
-
-	}
-
-  /**
-   *
-   * @param a
-   * @param b
-   * @return
-   * @throws SQLException
-   */
-	public boolean execute(String a, String[] b) throws SQLException
-  {
-		throw org.postgresql.Driver.notImplemented();
-
-	}
-
-  /**
-   *
-   * @return
-   * @throws SQLException
-   */
-	public int getResultSetHoldability() throws SQLException
-  {
-		throw org.postgresql.Driver.notImplemented();
-
-	}
-
-}
\ No newline at end of file
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/UpdateableResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc2/UpdateableResultSet.java
index 9ff8be4080d..6f6f67d8394 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/UpdateableResultSet.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/UpdateableResultSet.java
@@ -1,9 +1,7 @@
 package org.postgresql.jdbc2;
 
 // IMPORTANT NOTE: This is the begining of supporting updateable ResultSets.
-// It is not a working solution (yet)!
 //
-// You will notice here we really do throw org.postgresql.Driver.notImplemented()
 // This is because here we should be updateable, so any unimplemented methods
 // must say so.
 //
@@ -27,7 +25,7 @@ import org.postgresql.Driver;
  * @see ResultSetMetaData
  * @see java.sql.ResultSet
  */
-public class UpdateableResultSet extends org.postgresql.jdbc2.ResultSet
+public class UpdateableResultSet extends org.postgresql.jdbc2.Jdbc2ResultSet
 {
 
 
@@ -118,7 +116,7 @@ public class UpdateableResultSet extends org.postgresql.jdbc2.ResultSet
 	 * @param updateCount the number of rows affected by the operation
 	 * @param cursor the positioned update/delete cursor name
 	 */
-	public UpdateableResultSet(Connection conn, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor)
+	public UpdateableResultSet(Jdbc2Connection conn, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor)
 	{
 		super(conn, fields, tuples, status, updateCount, insertOID, binaryCursor);
 	}
@@ -274,7 +272,7 @@ public class UpdateableResultSet extends org.postgresql.jdbc2.ResultSet
       {
         // we have to get the last inserted OID and put it in the resultset
 
-        long insertedOID = ((org.postgresql.Statement)insertStatement).getLastOID();
+        long insertedOID = ((AbstractJdbc2Statement)insertStatement).getLastOID();
 
         updateValues.put("oid", new Long(insertedOID) );
 
@@ -670,7 +668,7 @@ public class UpdateableResultSet extends org.postgresql.jdbc2.ResultSet
         selectStatement.setObject( i, ((PrimaryKey)primaryKeys.get(j)).getValue() );
       }
 
-      org.postgresql.jdbc2.ResultSet rs = (org.postgresql.jdbc2.ResultSet) selectStatement.executeQuery();
+      Jdbc2ResultSet rs = (Jdbc2ResultSet) selectStatement.executeQuery();
 
       if( rs.first() )
       {
@@ -1274,7 +1272,7 @@ public class UpdateableResultSet extends org.postgresql.jdbc2.ResultSet
     else
     {
       // otherwise go and get the primary keys and create a hashtable of keys
-      java.sql.ResultSet rs  = ((org.postgresql.jdbc2.Connection)connection).getMetaData().getPrimaryKeys("","",tableName);
+      java.sql.ResultSet rs  = ((java.sql.Connection)connection).getMetaData().getPrimaryKeys("","",tableName);
 
 
       for( ; rs.next(); i++ )
diff --git a/src/interfaces/jdbc/org/postgresql/largeobject/LargeObjectManager.java b/src/interfaces/jdbc/org/postgresql/largeobject/LargeObjectManager.java
index e5296189cdc..a037ab28a21 100644
--- a/src/interfaces/jdbc/org/postgresql/largeobject/LargeObjectManager.java
+++ b/src/interfaces/jdbc/org/postgresql/largeobject/LargeObjectManager.java
@@ -94,16 +94,16 @@ public class LargeObjectManager
 	 * org.postgresql.Connection class keeps track of the various extension API's
 	 * and it's advised you use those to gain access, and not going direct.
 	 */
-	public LargeObjectManager(org.postgresql.Connection conn) throws SQLException
+	public LargeObjectManager(Connection conn) throws SQLException
 	{
 		// We need Fastpath to do anything
-		this.fp = conn.getFastpathAPI();
+		this.fp = ((org.postgresql.PGConnection)conn).getFastpathAPI();
 
 		// Now get the function oid's for the api
 		//
 		// This is an example of Fastpath.addFunctions();
 		//
-		java.sql.ResultSet res = (java.sql.ResultSet)conn.createStatement().executeQuery("select proname, oid from pg_proc" +
+		ResultSet res = conn.createStatement().executeQuery("select proname, oid from pg_proc" +
 								 " where proname = 'lo_open'" +
 								 "    or proname = 'lo_close'" +
 								 "    or proname = 'lo_creat'" +
diff --git a/src/interfaces/jdbc/org/postgresql/largeobject/PGblob.java b/src/interfaces/jdbc/org/postgresql/largeobject/PGblob.java
index 12e04e4c14a..87c1ac24774 100644
--- a/src/interfaces/jdbc/org/postgresql/largeobject/PGblob.java
+++ b/src/interfaces/jdbc/org/postgresql/largeobject/PGblob.java
@@ -20,18 +20,16 @@ import org.postgresql.largeobject.*;
  * This implements the Blob interface, which is basically another way to
  * access a LargeObject.
  *
- * $Id: PGblob.java,v 1.3 2001/11/19 22:33:39 momjian Exp $
+ * $Id: PGblob.java,v 1.4 2002/07/23 03:59:55 barry Exp $
  *
  */
 public class PGblob implements java.sql.Blob
 {
-	private org.postgresql.Connection conn;
 	private int oid;
 	private LargeObject lo;
 
-	public PGblob(org.postgresql.Connection conn, int oid) throws SQLException
+	public PGblob(org.postgresql.PGConnection conn, int oid) throws SQLException
 	{
-		this.conn = conn;
 		this.oid = oid;
 		LargeObjectManager lom = conn.getLargeObjectAPI();
 		this.lo = lom.open(oid);
diff --git a/src/interfaces/jdbc/org/postgresql/largeobject/PGclob.java b/src/interfaces/jdbc/org/postgresql/largeobject/PGclob.java
index 63d39c07b0f..71c3f8a2f0c 100644
--- a/src/interfaces/jdbc/org/postgresql/largeobject/PGclob.java
+++ b/src/interfaces/jdbc/org/postgresql/largeobject/PGclob.java
@@ -20,18 +20,16 @@ import org.postgresql.largeobject.*;
  * This implements the Blob interface, which is basically another way to
  * access a LargeObject.
  *
- * $Id: PGclob.java,v 1.3 2001/11/19 22:33:39 momjian Exp $
+ * $Id: PGclob.java,v 1.4 2002/07/23 03:59:55 barry Exp $
  *
  */
 public class PGclob implements java.sql.Clob
 {
-	private org.postgresql.Connection conn;
 	private int oid;
 	private LargeObject lo;
 
-	public PGclob(org.postgresql.Connection conn, int oid) throws SQLException
+	public PGclob(org.postgresql.PGConnection conn, int oid) throws SQLException
 	{
-		this.conn = conn;
 		this.oid = oid;
 		LargeObjectManager lom = conn.getLargeObjectAPI();
 		this.lo = lom.open(oid);
diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc2/BlobTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc2/BlobTest.java
index ae436fbf18b..45bab13b0e0 100644
--- a/src/interfaces/jdbc/org/postgresql/test/jdbc2/BlobTest.java
+++ b/src/interfaces/jdbc/org/postgresql/test/jdbc2/BlobTest.java
@@ -8,7 +8,7 @@ import java.sql.*;
 import org.postgresql.largeobject.*;
 
 /*
- * $Id: BlobTest.java,v 1.5 2001/11/19 23:16:46 momjian Exp $
+ * $Id: BlobTest.java,v 1.6 2002/07/23 03:59:55 barry Exp $
  *
  * Some simple tests based on problems reported by users. Hopefully these will
  * help prevent previous problems from re-occuring ;-)
@@ -95,7 +95,7 @@ public class BlobTest extends TestCase
 	 */
 	private int uploadFile(String file, int method) throws Exception
 	{
-		LargeObjectManager lom = ((org.postgresql.Connection)con).getLargeObjectAPI();
+		LargeObjectManager lom = ((org.postgresql.PGConnection)con).getLargeObjectAPI();
 
 		FileInputStream fis = new FileInputStream(file);
 
@@ -160,7 +160,7 @@ public class BlobTest extends TestCase
 	{
 		boolean result = true;
 
-		LargeObjectManager lom = ((org.postgresql.Connection)con).getLargeObjectAPI();
+		LargeObjectManager lom = ((org.postgresql.PGConnection)con).getLargeObjectAPI();
 
 		Statement st = con.createStatement();
 		ResultSet rs = st.executeQuery(JDBC2Tests.selectSQL("testblob", "id,lo"));
diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc2/ConnectionTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc2/ConnectionTest.java
index 6db4f412184..682118b6c17 100644
--- a/src/interfaces/jdbc/org/postgresql/test/jdbc2/ConnectionTest.java
+++ b/src/interfaces/jdbc/org/postgresql/test/jdbc2/ConnectionTest.java
@@ -10,7 +10,7 @@ import java.sql.*;
  *
  * PS: Do you know how difficult it is to type on a train? ;-)
  *
- * $Id: ConnectionTest.java,v 1.7 2001/11/19 22:33:39 momjian Exp $
+ * $Id: ConnectionTest.java,v 1.8 2002/07/23 03:59:55 barry Exp $
  */
 
 public class ConnectionTest extends TestCase
@@ -199,13 +199,13 @@ public class ConnectionTest extends TestCase
 			String testStr = "This Is OuR TeSt message";
 
 			// The connection must be ours!
-			assertTrue(con instanceof org.postgresql.Connection);
+			assertTrue(con instanceof org.postgresql.PGConnection);
 
 			// Clear any existing warnings
 			con.clearWarnings();
 
 			// Set the test warning
-			((org.postgresql.Connection)con).addWarning(testStr);
+			((org.postgresql.jdbc2.AbstractJdbc2Connection)con).addWarning(testStr);
 
 			// Retrieve it
 			SQLWarning warning = con.getWarnings();
diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java
index e6acfc0d700..26675a7ca6a 100644
--- a/src/interfaces/jdbc/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java
+++ b/src/interfaces/jdbc/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java
@@ -9,7 +9,7 @@ import java.sql.*;
  *
  * PS: Do you know how difficult it is to type on a train? ;-)
  *
- * $Id: DatabaseMetaDataTest.java,v 1.8 2002/06/05 19:12:01 davec Exp $
+ * $Id: DatabaseMetaDataTest.java,v 1.9 2002/07/23 03:59:55 barry Exp $
  */
 
 public class DatabaseMetaDataTest extends TestCase
@@ -163,13 +163,13 @@ public class DatabaseMetaDataTest extends TestCase
 			// We need to type cast the connection to get access to the
 			// PostgreSQL-specific method haveMinimumServerVersion().
 			// This is not available through the java.sql.Connection interface.
-			assertTrue( con instanceof org.postgresql.Connection );
+			assertTrue( con instanceof org.postgresql.PGConnection );
 
 			assertTrue(!dbmd.nullsAreSortedAtStart());
 			assertTrue( dbmd.nullsAreSortedAtEnd() !=
-						((org.postgresql.Connection)con).haveMinimumServerVersion("7.2"));
+						((org.postgresql.jdbc2.AbstractJdbc2Connection)con).haveMinimumServerVersion("7.2"));
 			assertTrue( dbmd.nullsAreSortedHigh() ==
-						((org.postgresql.Connection)con).haveMinimumServerVersion("7.2"));
+						((org.postgresql.jdbc2.AbstractJdbc2Connection)con).haveMinimumServerVersion("7.2"));
 			assertTrue(!dbmd.nullsAreSortedLow());
 
 			assertTrue(dbmd.nullPlusNonNullIsNull());
@@ -250,7 +250,7 @@ public class DatabaseMetaDataTest extends TestCase
       {
 
          String pkTableName = rs.getString( "PKTABLE_NAME" );
-         assertTrue (  pkTableName.equals("people") || pkTableName.equals("policy")  );
+	 assertTrue (  pkTableName.equals("people") || pkTableName.equals("policy")  );
 
          String pkColumnName = rs.getString( "PKCOLUMN_NAME" );
          assertTrue( pkColumnName.equals("id") );
@@ -367,14 +367,20 @@ public class DatabaseMetaDataTest extends TestCase
 	{
 		try
 		{
-			assertTrue(con instanceof org.postgresql.Connection);
-			org.postgresql.Connection pc = (org.postgresql.Connection) con;
+		        assertTrue(con instanceof org.postgresql.PGConnection);
+			org.postgresql.jdbc2.AbstractJdbc2Connection pc = (org.postgresql.jdbc2.AbstractJdbc2Connection) con;
 
 			DatabaseMetaData dbmd = con.getMetaData();
 			assertNotNull(dbmd);
 
 			assertTrue(dbmd.getDatabaseProductName().equals("PostgreSQL"));
-			assertTrue(dbmd.getDatabaseProductVersion().startsWith(Integer.toString(pc.this_driver.getMajorVersion()) + "." + Integer.toString(pc.this_driver.getMinorVersion())));
+                        //The test below doesn't make sense to me, it tests that 
+                        //the version of the driver = the version of the database it is connected to
+                        //since the driver should be backwardly compatible this test is commented out 
+			//assertTrue(dbmd.getDatabaseProductVersion().startsWith(
+                        //         Integer.toString(pc.getDriver().getMajorVersion()) 
+                        //         + "." 
+                        //         + Integer.toString(pc.getDriver().getMinorVersion())));
 			assertTrue(dbmd.getDriverName().equals("PostgreSQL Native Driver"));
 
 		}
@@ -388,15 +394,15 @@ public class DatabaseMetaDataTest extends TestCase
 	{
 		try
 		{
-			assertTrue(con instanceof org.postgresql.Connection);
-			org.postgresql.Connection pc = (org.postgresql.Connection) con;
+			assertTrue(con instanceof org.postgresql.PGConnection);
+			org.postgresql.jdbc2.AbstractJdbc2Connection pc = (org.postgresql.jdbc2.AbstractJdbc2Connection) con;
 
 			DatabaseMetaData dbmd = con.getMetaData();
 			assertNotNull(dbmd);
 
-			assertTrue(dbmd.getDriverVersion().equals(pc.this_driver.getVersion()));
-			assertTrue(dbmd.getDriverMajorVersion() == pc.this_driver.getMajorVersion());
-			assertTrue(dbmd.getDriverMinorVersion() == pc.this_driver.getMinorVersion());
+			assertTrue(dbmd.getDriverVersion().equals(pc.getDriver().getVersion()));
+			assertTrue(dbmd.getDriverMajorVersion() == pc.getDriver().getMajorVersion());
+			assertTrue(dbmd.getDriverMinorVersion() == pc.getDriver().getMinorVersion());
 
 
 		}
diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc2/TimestampTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc2/TimestampTest.java
index f7bf62e6d60..37eff6c5b75 100644
--- a/src/interfaces/jdbc/org/postgresql/test/jdbc2/TimestampTest.java
+++ b/src/interfaces/jdbc/org/postgresql/test/jdbc2/TimestampTest.java
@@ -5,12 +5,10 @@ import junit.framework.TestCase;
 import java.sql.*;
 
 /*
- * $Id: TimestampTest.java,v 1.6 2001/11/19 22:33:39 momjian Exp $
+ * $Id: TimestampTest.java,v 1.7 2002/07/23 03:59:55 barry Exp $
  *
- * This has been the most controversial pair of methods since 6.5 was released!
- *
- * From now on, any changes made to either getTimestamp or setTimestamp
- * MUST PASS this TestCase!!!
+ * Test get/setTimestamp for both timestamp with time zone and 
+ * timestamp without time zone datatypes
  *
  */
 public class TimestampTest extends TestCase
@@ -28,39 +26,74 @@ public class TimestampTest extends TestCase
 		con = JDBC2Tests.openDB();
 		Statement stmt = con.createStatement();
 
-		JDBC2Tests.createTable(con, "testtimestamp", "ts timestamp");
+		JDBC2Tests.createTable(con, TSWTZ_TABLE, "ts timestamp with time zone");
+		JDBC2Tests.createTable(con, TSWOTZ_TABLE, "ts timestamp without time zone");
 	}
 
 	protected void tearDown() throws Exception
 	{
-		JDBC2Tests.dropTable(con, "testtimestamp");
+		JDBC2Tests.dropTable(con, TSWTZ_TABLE);
+		JDBC2Tests.dropTable(con, TSWOTZ_TABLE);
 		JDBC2Tests.closeDB(con);
 	}
 
 	/*
-	 * Tests the time methods in ResultSet
+	 * Tests the timestamp methods in ResultSet on timestamp with time zone
+         * we insert a known string value (don't use setTimestamp) then see that 
+         * we get back the same value from getTimestamp   
 	 */
-	public void testGetTimestamp()
+	public void testGetTimestampWTZ()
 	{
 		try
 		{
 			Statement stmt = con.createStatement();
 
-			assertEquals(1, stmt.executeUpdate(JDBC2Tests.insertSQL("testtimestamp",
-											   "'1950-02-07 15:00:00'")));
+                        //Insert the three timestamp values in raw pg format
+			assertEquals(1, stmt.executeUpdate(JDBC2Tests.insertSQL(TSWTZ_TABLE,"'" + TS1WTZ_PGFORMAT + "'")));
+			assertEquals(1, stmt.executeUpdate(JDBC2Tests.insertSQL(TSWTZ_TABLE,"'" + TS2WTZ_PGFORMAT + "'")));
+			assertEquals(1, stmt.executeUpdate(JDBC2Tests.insertSQL(TSWTZ_TABLE,"'" + TS3WTZ_PGFORMAT + "'")));
+
+			// Fall through helper
+                        timestampTestWTZ();
+
+                        assertEquals(3, stmt.executeUpdate("DELETE FROM " + TSWTZ_TABLE));
+
+			stmt.close();
+		}
+		catch (Exception ex)
+		{
+			fail(ex.getMessage());
+		}
+	}
+
+	/*
+	 * Tests the timestamp methods in PreparedStatement on timestamp with time zone
+         * we insert a value using setTimestamp then see that 
+         * we get back the same value from getTimestamp (which we know works as it was tested
+         * independently of setTimestamp
+	 */
+	public void testSetTimestampWTZ()
+	{
+		try
+		{
+			Statement stmt = con.createStatement();
+			PreparedStatement pstmt = con.prepareStatement(JDBC2Tests.insertSQL(TSWTZ_TABLE, "?"));
 
-			assertEquals(1, stmt.executeUpdate(JDBC2Tests.insertSQL("testtimestamp", "'" +
-											   getTimestamp(1970, 6, 2, 8, 13, 0, 0).toString() +
-											   "'")));
+			pstmt.setTimestamp(1, TS1WTZ);
+                        assertEquals(1, pstmt.executeUpdate());
 
-			assertEquals(1, stmt.executeUpdate(JDBC2Tests.insertSQL("testtimestamp",
-											   "'1970-06-02 08:13:00'")));
+			pstmt.setTimestamp(1, TS2WTZ);
+                        assertEquals(1, pstmt.executeUpdate());
+
+			pstmt.setTimestamp(1, TS3WTZ);
+                        assertEquals(1, pstmt.executeUpdate());
 
 			// Fall through helper
-			timestampTest();
+			timestampTestWTZ();
 
-			assertEquals(3, stmt.executeUpdate("DELETE FROM testtimestamp"));
+                        assertEquals(3, stmt.executeUpdate("DELETE FROM " + TSWTZ_TABLE));
 
+			pstmt.close();
 			stmt.close();
 		}
 		catch (Exception ex)
@@ -70,28 +103,61 @@ public class TimestampTest extends TestCase
 	}
 
 	/*
-	 * Tests the time methods in PreparedStatement
+	 * Tests the timestamp methods in ResultSet on timestamp without time zone
+         * we insert a known string value (don't use setTimestamp) then see that 
+         * we get back the same value from getTimestamp   
 	 */
-	public void testSetTimestamp()
+	public void testGetTimestampWOTZ()
 	{
 		try
 		{
 			Statement stmt = con.createStatement();
-			PreparedStatement pstmt = con.prepareStatement(JDBC2Tests.insertSQL("testtimestamp", "?"));
 
-			pstmt.setTimestamp(1, getTimestamp(1950, 2, 7, 15, 0, 0, 0));
-			assertEquals(1, pstmt.executeUpdate());
+                        //Insert the three timestamp values in raw pg format
+			assertEquals(1, stmt.executeUpdate(JDBC2Tests.insertSQL(TSWOTZ_TABLE,"'" + TS1WOTZ_PGFORMAT + "'")));
+			assertEquals(1, stmt.executeUpdate(JDBC2Tests.insertSQL(TSWOTZ_TABLE,"'" + TS2WOTZ_PGFORMAT + "'")));
+			assertEquals(1, stmt.executeUpdate(JDBC2Tests.insertSQL(TSWOTZ_TABLE,"'" + TS3WOTZ_PGFORMAT + "'")));
+
+			// Fall through helper
+			timestampTestWOTZ();
+
+                        assertEquals(3, stmt.executeUpdate("DELETE FROM " + TSWOTZ_TABLE));
 
-			pstmt.setTimestamp(1, getTimestamp(1970, 6, 2, 8, 13, 0, 0));
-			assertEquals(1, pstmt.executeUpdate());
+			stmt.close();
+		}
+		catch (Exception ex)
+		{
+			fail(ex.getMessage());
+		}
+	}
 
-			pstmt.setTimestamp(1, getTimestamp(1970, 6, 2, 8, 13, 0, 0));
-			assertEquals(1, pstmt.executeUpdate());
+
+	/*
+	 * Tests the timestamp methods in PreparedStatement on timestamp without time zone
+         * we insert a value using setTimestamp then see that 
+         * we get back the same value from getTimestamp (which we know works as it was tested
+         * independently of setTimestamp
+	 */
+	public void testSetTimestampWOTZ()
+	{
+		try
+		{
+			Statement stmt = con.createStatement();
+			PreparedStatement pstmt = con.prepareStatement(JDBC2Tests.insertSQL(TSWOTZ_TABLE, "?"));
+
+			pstmt.setTimestamp(1, TS1WOTZ);
+                        assertEquals(1, pstmt.executeUpdate());
+
+			pstmt.setTimestamp(1, TS2WOTZ);
+                        assertEquals(1, pstmt.executeUpdate());
+
+			pstmt.setTimestamp(1, TS3WOTZ);
+                        assertEquals(1, pstmt.executeUpdate());
 
 			// Fall through helper
-			timestampTest();
+			timestampTestWOTZ();
 
-			assertEquals(3, stmt.executeUpdate("DELETE FROM testtimestamp"));
+                        assertEquals(3, stmt.executeUpdate("DELETE FROM " + TSWOTZ_TABLE));
 
 			pstmt.close();
 			stmt.close();
@@ -103,31 +169,64 @@ public class TimestampTest extends TestCase
 	}
 
 	/*
-	 * Helper for the TimeTests. It tests what should be in the db
+	 * Helper for the TimestampTests. It tests what should be in the db
+	 */
+	private void timestampTestWTZ() throws SQLException
+	{
+		Statement stmt = con.createStatement();
+		ResultSet rs;
+		java.sql.Timestamp t;
+
+		rs = stmt.executeQuery("select ts from " + TSWTZ_TABLE + " order by ts");
+                assertNotNull(rs);
+
+		assertTrue(rs.next());
+		t = rs.getTimestamp(1);
+                assertNotNull(t);
+		assertTrue(t.equals(TS1WTZ));
+
+		assertTrue(rs.next());
+		t = rs.getTimestamp(1);
+                assertNotNull(t);
+		assertTrue(t.equals(TS2WTZ));
+
+		assertTrue(rs.next());
+		t = rs.getTimestamp(1);
+                assertNotNull(t);
+                assertTrue(t.equals(TS3WTZ));
+
+		assertTrue(! rs.next()); // end of table. Fail if more entries exist.
+
+		rs.close();
+		stmt.close();
+	}
+
+	/*
+	 * Helper for the TimestampTests. It tests what should be in the db
 	 */
-	private void timestampTest() throws SQLException
+	private void timestampTestWOTZ() throws SQLException
 	{
 		Statement stmt = con.createStatement();
 		ResultSet rs;
 		java.sql.Timestamp t;
 
-		rs = stmt.executeQuery(JDBC2Tests.selectSQL("testtimestamp", "ts"));
-		assertNotNull(rs);
+		rs = stmt.executeQuery("select ts from " + TSWOTZ_TABLE + " order by ts");
+                assertNotNull(rs);
 
 		assertTrue(rs.next());
 		t = rs.getTimestamp(1);
-		assertNotNull(t);
-		assertTrue(t.equals(getTimestamp(1950, 2, 7, 15, 0, 0, 0)));
+                assertNotNull(t);
+		assertTrue(t.toString().equals(TS1WOTZ_JAVAFORMAT));
 
 		assertTrue(rs.next());
 		t = rs.getTimestamp(1);
-		assertNotNull(t);
-		assertTrue(t.equals(getTimestamp(1970, 6, 2, 8, 13, 0, 0)));
+                assertNotNull(t);
+		assertTrue(t.toString().equals(TS2WOTZ_JAVAFORMAT));
 
 		assertTrue(rs.next());
 		t = rs.getTimestamp(1);
-		assertNotNull(t);
-		assertTrue(t.equals(getTimestamp(1970, 6, 2, 8, 13, 0, 0)));
+                assertNotNull(t);
+		assertTrue(t.toString().equals(TS3WOTZ_JAVAFORMAT));
 
 		assertTrue(! rs.next()); // end of table. Fail if more entries exist.
 
@@ -135,14 +234,59 @@ public class TimestampTest extends TestCase
 		stmt.close();
 	}
 
-	private java.sql.Timestamp getTimestamp(int y, int m, int d, int h, int mn, int se, int f)
+	private static java.sql.Timestamp getTimestamp(int y, int m, int d, int h, int mn, int se, int f, String tz)
 	{
-		return java.sql.Timestamp.valueOf(JDBC2Tests.fix(y, 4) + "-" +
-										  JDBC2Tests.fix(m, 2) + "-" +
-										  JDBC2Tests.fix(d, 2) + " " +
-										  JDBC2Tests.fix(h, 2) + ":" +
-										  JDBC2Tests.fix(mn, 2) + ":" +
-										  JDBC2Tests.fix(se, 2) + "." +
-										  JDBC2Tests.fix(f, 9));
+            java.sql.Timestamp l_return = null;
+            java.text.DateFormat l_df;
+	    try {
+   	        String l_ts;
+                l_ts = JDBC2Tests.fix(y, 4) + "-" +
+		   JDBC2Tests.fix(m, 2) + "-" +
+		   JDBC2Tests.fix(d, 2) + " " +
+		   JDBC2Tests.fix(h, 2) + ":" +
+		   JDBC2Tests.fix(mn, 2) + ":" +
+		   JDBC2Tests.fix(se, 2) + " ";
+
+                if (tz == null) {
+                    l_df = new java.text.SimpleDateFormat("y-M-d H:m:s");
+                } else {
+                    l_ts = l_ts + tz;
+                    l_df = new java.text.SimpleDateFormat("y-M-d H:m:s z");
+		}
+                java.util.Date l_date = l_df.parse(l_ts);
+	        l_return = new java.sql.Timestamp(l_date.getTime());
+                l_return.setNanos(f);
+ 	    } catch (Exception ex) {
+		fail(ex.getMessage());
+	    }
+            return l_return;
 	}
+
+    private static final java.sql.Timestamp TS1WTZ = getTimestamp(1950, 2, 7, 15, 0, 0, 100000000, "PST");
+    private static final String TS1WTZ_PGFORMAT = "1950-02-07 15:00:00.1-08";
+ 
+    private static final java.sql.Timestamp TS2WTZ = getTimestamp(2000, 2, 7, 15, 0, 0, 120000000, "GMT");
+    private static final String TS2WTZ_PGFORMAT = "2000-02-07 15:00:00.12+00";
+
+    private static final java.sql.Timestamp TS3WTZ = getTimestamp(2000, 7, 7, 15, 0, 0, 123000000, "GMT");
+    private static final String TS3WTZ_PGFORMAT = "2000-07-07 15:00:00.123+00";
+
+
+    private static final java.sql.Timestamp TS1WOTZ = getTimestamp(1950, 2, 7, 15, 0, 0, 100000000, null);
+    private static final String TS1WOTZ_PGFORMAT = "1950-02-07 15:00:00.1";
+    private static final String TS1WOTZ_JAVAFORMAT = "1950-02-07 15:00:00.1";
+ 
+    private static final java.sql.Timestamp TS2WOTZ = getTimestamp(2000, 2, 7, 15, 0, 0, 120000000, null);
+    private static final String TS2WOTZ_PGFORMAT = "2000-02-07 15:00:00.12";
+    //there is probably a bug here in that this needs to be .1 instead of .12, but I couldn't find it now
+    private static final String TS2WOTZ_JAVAFORMAT = "2000-02-07 15:00:00.1";
+
+    private static final java.sql.Timestamp TS3WOTZ = getTimestamp(2000, 7, 7, 15, 0, 0, 123000000, null);
+    private static final String TS3WOTZ_PGFORMAT = "2000-07-07 15:00:00.123";
+    //there is probably a bug here in that this needs to be .12 instead of .123, but I couldn't find it now
+    private static final String TS3WOTZ_JAVAFORMAT = "2000-07-07 15:00:00.12";
+
+    private static final String TSWTZ_TABLE = "testtimestampwtz";
+    private static final String TSWOTZ_TABLE = "testtimestampwotz";
+
 }
diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc2/UpdateableResultTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc2/UpdateableResultTest.java
index 722dd78398a..056e68eba05 100644
--- a/src/interfaces/jdbc/org/postgresql/test/jdbc2/UpdateableResultTest.java
+++ b/src/interfaces/jdbc/org/postgresql/test/jdbc2/UpdateableResultTest.java
@@ -28,7 +28,6 @@ public class UpdateableResultTest extends TestCase
 			Connection con = JDBC2Tests.openDB();
       JDBC2Tests.createTable(con, "updateable","id int primary key, name text, notselected text");
       JDBC2Tests.createTable(con, "second","id1 int primary key, name1 text");
-
       Statement st1 = con.createStatement();
       boolean retVal = st1.execute( "insert into updateable ( id, name, notselected ) values (1, 'jake', 'avalue')" );
       assert( retVal== false );
@@ -132,4 +131,4 @@ public class UpdateableResultTest extends TestCase
 	}
 
 
-}
\ No newline at end of file
+}
diff --git a/src/interfaces/jdbc/org/postgresql/util/Serialize.java b/src/interfaces/jdbc/org/postgresql/util/Serialize.java
index 80d10bc5410..f1f12520baa 100644
--- a/src/interfaces/jdbc/org/postgresql/util/Serialize.java
+++ b/src/interfaces/jdbc/org/postgresql/util/Serialize.java
@@ -109,7 +109,7 @@ import java.sql.*;
 public class Serialize
 {
 	// This is the connection that the instance refers to
-	protected org.postgresql.Connection conn;
+	protected Connection conn;
 
 	// This is the table name
 	protected String tableName;
@@ -124,7 +124,7 @@ public class Serialize
 	 * This creates an instance that can be used to serialize or deserialize
 	 * a Java object from a PostgreSQL table.
 	 */
-	public Serialize(org.postgresql.Connection c, String type) throws SQLException
+	public Serialize(Connection c, String type) throws SQLException
 	{
 		try
 		{
@@ -142,7 +142,7 @@ public class Serialize
 
 		// Second check, the type must be a table
 		boolean status = false;
-		ResultSet rs = conn.ExecSQL("select typname from pg_type,pg_class where typname=relname and typname='" + tableName + "'");
+		ResultSet rs = ((org.postgresql.jdbc1.AbstractJdbc1Connection)conn).ExecSQL("select typname from pg_type,pg_class where typname=relname and typname='" + tableName + "'");
 		if (rs != null)
 		{
 			if (rs.next())
@@ -164,7 +164,7 @@ public class Serialize
 	/*
 	 * Constructor when Object is passed in
 	 */
-	public Serialize(org.postgresql.Connection c, Object o) throws SQLException
+	public Serialize(Connection c, Object o) throws SQLException
 	{
 		this(c, o.getClass().getName());
 	}
@@ -172,7 +172,7 @@ public class Serialize
 	/*
 	 * Constructor when Class is passed in
 	 */
-	public Serialize(org.postgresql.Connection c, Class cls) throws SQLException
+	public Serialize(Connection c, Class cls) throws SQLException
 	{
 		this(c, cls.getName());
 	}
@@ -221,7 +221,7 @@ public class Serialize
 			sb.append(oid);
 
 			if (Driver.logDebug) Driver.debug("Serialize.fetch: " + sb.toString());
-			ResultSet rs = conn.ExecSQL(sb.toString());
+			ResultSet rs = ((org.postgresql.jdbc1.AbstractJdbc1Connection)conn).ExecSQL(sb.toString());
 
 			if (rs != null)
 			{
@@ -390,7 +390,7 @@ public class Serialize
 			}
 
 			if (Driver.logDebug) Driver.debug("Serialize.store: " + sb.toString() );
-			org.postgresql.ResultSet rs = (org.postgresql.ResultSet) conn.ExecSQL(sb.toString());
+			ResultSet rs = ((org.postgresql.jdbc1.AbstractJdbc1Connection)conn).ExecSQL(sb.toString());
 
 			// fetch the OID for returning
 			if (update)
@@ -403,7 +403,7 @@ public class Serialize
 			else
 			{
 				// new record inserted has new oid; rs should be not null
-				long newOID = ((org.postgresql.ResultSet)rs).getLastOID();
+				long newOID = ((org.postgresql.jdbc1.AbstractJdbc1ResultSet)rs).getLastOID();
 				rs.close();
 				// update the java object's oid field if it has the oid field
 				if (hasOID)
@@ -472,7 +472,7 @@ public class Serialize
 	 * @param o Object to base table on
 	 * @exception SQLException on error
 	 */
-	public static void create(org.postgresql.Connection con, Object o) throws SQLException
+	public static void create(Connection con, Object o) throws SQLException
 	{
 		create(con, o.getClass());
 	}
@@ -485,7 +485,7 @@ public class Serialize
 	 * @param o Class to base table on
 	 * @exception SQLException on error
 	 */
-	public static void create(org.postgresql.Connection con, Class c) throws SQLException
+	public static void create(Connection con, Class c) throws SQLException
 	{
 		if (c.isInterface())
 			throw new PSQLException("postgresql.serial.interface");
@@ -493,7 +493,7 @@ public class Serialize
 		// See if the table exists
 		String tableName = toPostgreSQL(c.getName());
 
-		ResultSet rs = con.ExecSQL("select relname from pg_class where relname = '" + tableName + "'");
+		ResultSet rs = ((org.postgresql.jdbc1.AbstractJdbc1Connection)con).ExecSQL("select relname from pg_class where relname = '" + tableName + "'");
 		if ( rs.next() )
 		{
 			if (Driver.logDebug) Driver.debug("Serialize.create: table " + tableName + " exists, skipping");
@@ -549,7 +549,7 @@ public class Serialize
 
 		// Now create the table
 		if (Driver.logDebug) Driver.debug("Serialize.create: " + sb );
-		con.ExecSQL(sb.toString());
+		((org.postgresql.jdbc1.AbstractJdbc1Connection)con).ExecSQL(sb.toString());
 	}
 
 	// This is used to translate between Java primitives and PostgreSQL types.
-- 
GitLab