diff --git a/src/interfaces/jdbc/Makefile b/src/interfaces/jdbc/Makefile
index 3b88af4d3c718718aa8a338b4c38aa56c8b3f41e..fc881a34ba2060eda6f14c69aade7a64831c7659 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 c8b541d6a66b2f4425d308b47cf979affedf2fc8..278053eeace0d0ea095e228f291c1a73c52539f5 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 f61a8870e7be88c0e336b4bd0ed838bef5806a5b..0401780b5cae23f22a253313ad4c0c42669f26d3 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 9a4469d83a0d92555df9246ce59302818ad0eb14..5f07a56c3f52a423e6905765624f4faa61aaf26c 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 271026250dd63ee646675e9d9f84b13e8ea65326..d517d267b75b644fc4de07396993b3b4b727de1a 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 cca7be75beec695d903e8868091c0fe601315100..c35570a4c2a424ef7bc353cdcaa3a507f867e1b8 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 c53747902ff90662e4ecc8428c5f977e44a3498d..ecb22c7a0daf2e0341d7f1478b8638a2f02d22f3 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 8ab28057ef2850b6c78338de4649779d87e4735b..1dbaa72c0977e0b466be718e27145f041531aeb3 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 0000000000000000000000000000000000000000..c05f31222c57a046b3a678687d7f263913c4a200
--- /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 0000000000000000000000000000000000000000..1295afbe5aa57e6a571c2dae2b22fac954df5b7f
--- /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 6e533eed01086d75d5737edd986990ab32c50c71..0000000000000000000000000000000000000000
--- 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 bfa6af3572380fef41cae2f54c3edc634d73b7ea..40c6a31d7f8a12f286c642f03a92a4ccaefbcf9d 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 20f5a6f3e2610eb39a560524bdb7958e409d454e..d166b10f83b658f48f42801793464ded4efa6660 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 7951ddd1ecb1cec5e90c59b14e639e9c7b5e0e69..98aa33e5c916e5fed394c05618fa608314ccf1a3 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 0000000000000000000000000000000000000000..5aa4f90298a07ab1153a3fee44934309f686f41e
--- /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 ea2cc0d0c33094ca88ab5f7d2750e86e41180fdb..9c4d2b1cd9cbfe6105ad1bfac3783dbbca085192 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 4a006cd2208fb7abdf40a266fb995c002c2925d4..10e8c5f4171db2f1f73b8494d0b8f344abe95dfa 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 4d3e087f76b65a170ee5724ea118318830ebd3d2..0000000000000000000000000000000000000000
--- 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 5fba1d68c00c3770c6bb94e8f6495f084dc7ce21..747ee1f1ea4f2209350fe4fa292f5a9dfa9374ae 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 0000000000000000000000000000000000000000..55e527bd4908c6c6d033978c3e9f64efffcf6078
--- /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 0000000000000000000000000000000000000000..a959fef9d392539880ac74dd33e0db4d4b1fe08f
--- /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 0000000000000000000000000000000000000000..bb073eae99871cdfaae4186c57815a14e14efaf9
--- /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 31926c500bd07153a678e54780dc942aec760f41..9ef9a4289e59f816e05289b4ed642a68e54a7493 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 b6e054a33689c76c74a6efc3c40b0caef255c776..0000000000000000000000000000000000000000
--- 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 8898f5a69dd3e3daaf59d2f7dfbe30e68d9c690e..0000000000000000000000000000000000000000
--- 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 0000000000000000000000000000000000000000..8faefad65ff6ae1db59023212cc168aacb57afcf
--- /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 0000000000000000000000000000000000000000..50c5d942bbf63ce71e53e46d756bf8c681b6d123
--- /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 0000000000000000000000000000000000000000..3d6f6553ced3fea5afba83d7e4c81cbbcabf5d1d
--- /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 7cc842ec36e0ad7f30f617a770308031c7f5a9ee..2105802d66a17fa1e77efeedf3c828bda5c7f1db 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 4aa034832537c9e78c27d7e6a9a89ad08c6f7d86..9d37bf04bc50c42cacc133b394cb719e3a1f6289 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 9ab3cced8edb3138bd01e0a1ca553a2a02878a01..0000000000000000000000000000000000000000
--- 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 3cc224e6e8f665b2809e8491d9bdf7adaef70756..77415d051d428a0732626fef15ac2d8481691b9d 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 0000000000000000000000000000000000000000..cfbb3486ec6f6d25dc6b0ca25110bedf73a6e65e
--- /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 0000000000000000000000000000000000000000..7200cf549ad586ddfc49d5a518e06482a7949d26
--- /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 0000000000000000000000000000000000000000..31cec93821a4f8dde7b01b811a3d584c5e579246
--- /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 5638a2692d657704414e6322930c76d660229f28..21aba8d9ee089ff84ad991c7873d25f6e66a7bec 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 f5489f4e9793aea143173a15de31e21639b9ed95..0000000000000000000000000000000000000000
--- 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 a00025ff72ae77ab0617b40fc725b58d27fa9b6b..0000000000000000000000000000000000000000
--- 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 9ff8be4080d5cc9001a1ead433eb0ea4428aa1d7..6f6f67d8394376c2e1e224dad9fce676f5723b43 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 e5296189cdc8725db12bd8e76c86b4d6c817080e..a037ab28a21719cc183e5fc246badf38d06341dc 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 12e04e4c14aba302762871347b5b172285d9f211..87c1ac247742538964273fa212d6c5ceba150bfc 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 63d39c07b0f7b09dda53f860ea98b204babb0781..71c3f8a2f0c40e9884b02a38eda3c1df4f24583e 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 ae436fbf18b4c78c5dd412a40e0a303d5e8f026d..45bab13b0e0798d0fe7b8b1aa4d63dd1937d1b05 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 6db4f4121846fca5dcc8dfa378cee978a2086d17..682118b6c1733cdd415fe759af5277c0498a4b67 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 e6acfc0d700cbae444599a71bc8bba5201c152ef..26675a7ca6aebae3cd286a1c27a36555960b026c 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 f7bf62e6d60e63e664014256ef546c08aa593158..37eff6c5b7591546c299474f2e03690ed05664ba 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 722dd78398a634a6abcb34ec6992b330860f3234..056e68eba0524ea5bca755dcf805765045c75984 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 80d10bc54106d96b9cf2bdaaa651cd637dce106b..f1f12520baaf2ddd680c1149d108708d59822009 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.