From d634a5903f615a45cb463155c04d3df904e1b91a Mon Sep 17 00:00:00 2001
From: Barry Lind <barry@xythos.com>
Date: Wed, 11 Sep 2002 05:38:45 +0000
Subject: [PATCH] Patches submitted by Kris Jurka (jurka@ejurka.com) for the
 following bugs:   - Properly drop tables in jdbc regression tests with
 cascade for 7.3   - problem with Statement.execute() and executeUpdate() not
 clearing binds   - problem with ResultSet not correctly handling default
 encoding   - changes to correctly support show transaction isolation level in
 7.3   - changed DatabaseMetaDataTest to handle differences in FK names in 7.3
   - better fix for dynamically checking server NAME data length   (With the
 fixes above the jdbc regression tests pass on jdbc2 and jdbc3    against both
 a 7.2 and 7.3 server) Patchs submitted by David Wall (d.wall@computer.org):  
 - problem with getBlob when largeobject oid is null   - improvements to
 BlobOutputStream Patch submitted by Haris Peco (snpe@snpe.co.yu):   - problem
 with callable statement not supporting prepared statement methods

 Modified Files:
 	jdbc/org/postgresql/Driver.java.in
 	jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java
 	jdbc/org/postgresql/jdbc1/AbstractJdbc1DatabaseMetaData.java
 	jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java
 	jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java
 	jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java
 	jdbc/org/postgresql/jdbc2/Jdbc2ResultSet.java
 	jdbc/org/postgresql/jdbc3/Jdbc3ResultSet.java
 	jdbc/org/postgresql/largeobject/BlobOutputStream.java
 	jdbc/org/postgresql/largeobject/LargeObject.java
 	jdbc/org/postgresql/test/TestUtil.java
 	jdbc/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java
 	jdbc/org/postgresql/test/jdbc2/UpdateableResultTest.java
 	jdbc/org/postgresql/test/jdbc2/optional/BaseDataSourceTest.java
 	jdbc/org/postgresql/test/jdbc2/optional/ConnectionPoolTest.java
 	jdbc/org/postgresql/test/jdbc2/optional/SimpleDataSourceTest.java
---
 .../jdbc/org/postgresql/Driver.java.in        |  2 +-
 .../jdbc1/AbstractJdbc1Connection.java        | 35 ++++++++++++-------
 .../jdbc1/AbstractJdbc1DatabaseMetaData.java  | 17 ++++++---
 .../jdbc1/AbstractJdbc1Statement.java         | 10 +++++-
 .../jdbc2/AbstractJdbc2ResultSet.java         | 11 ++----
 .../jdbc2/AbstractJdbc2Statement.java         | 18 +++++++---
 .../org/postgresql/jdbc2/Jdbc2ResultSet.java  | 10 +++++-
 .../org/postgresql/jdbc3/Jdbc3ResultSet.java  | 10 +++++-
 .../largeobject/BlobOutputStream.java         | 20 +++++++++++
 .../postgresql/largeobject/LargeObject.java   |  4 +--
 .../jdbc/org/postgresql/test/TestUtil.java    | 19 ++++++++--
 .../test/jdbc2/DatabaseMetaDataTest.java      | 12 ++++---
 .../test/jdbc2/UpdateableResultTest.java      |  1 +
 .../jdbc2/optional/BaseDataSourceTest.java    | 19 +++++-----
 .../jdbc2/optional/ConnectionPoolTest.java    | 10 +++---
 .../jdbc2/optional/SimpleDataSourceTest.java  | 10 +++---
 16 files changed, 147 insertions(+), 61 deletions(-)

diff --git a/src/interfaces/jdbc/org/postgresql/Driver.java.in b/src/interfaces/jdbc/org/postgresql/Driver.java.in
index 019a78dbebc..328c06ce6b9 100644
--- a/src/interfaces/jdbc/org/postgresql/Driver.java.in
+++ b/src/interfaces/jdbc/org/postgresql/Driver.java.in
@@ -446,6 +446,6 @@ public class Driver implements java.sql.Driver
 	}
 
 	//The build number should be incremented for every new build
-	private static int m_buildNumber = 104;
+	private static int m_buildNumber = 105;
 
 }
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java
index 45160ba34fc..bf4ee76bd74 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java
@@ -14,7 +14,7 @@ import org.postgresql.largeobject.LargeObjectManager;
 import org.postgresql.util.*;
 
 
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Connection.java,v 1.8 2002/09/06 21:23:05 momjian Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Connection.java,v 1.9 2002/09/11 05:38:44 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
@@ -982,21 +982,32 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec
 	 */
 	public int getTransactionIsolation() throws SQLException
 	{
-		clearWarnings();
-		ExecSQL("show transaction isolation level");
-
-		SQLWarning warning = getWarnings();
-		if (warning != null)
-		{
-			String message = warning.getMessage();
+		String sql = "show transaction isolation level";
+		String level = null;
+		if (haveMinimumServerVersion("7.3")) {
+			ResultSet rs = ExecSQL(sql);
+			if (rs.next()) {
+				level = rs.getString(1);
+			}
+			rs.close();
+		} else {
 			clearWarnings();
-			if (message.indexOf("READ COMMITTED") != -1)
+			ExecSQL(sql);
+			SQLWarning warning = getWarnings();
+			if (warning != null)
+			{
+				level = warning.getMessage();
+			}
+			clearWarnings();
+		}
+		if (level != null) {
+			if (level.indexOf("READ COMMITTED") != -1)
 				return java.sql.Connection.TRANSACTION_READ_COMMITTED;
-			else if (message.indexOf("READ UNCOMMITTED") != -1)
+			else if (level.indexOf("READ UNCOMMITTED") != -1)
 				return java.sql.Connection.TRANSACTION_READ_UNCOMMITTED;
-			else if (message.indexOf("REPEATABLE READ") != -1)
+			else if (level.indexOf("REPEATABLE READ") != -1)
 				return java.sql.Connection.TRANSACTION_REPEATABLE_READ;
-			else if (message.indexOf("SERIALIZABLE") != -1)
+			else if (level.indexOf("SERIALIZABLE") != -1)
 				return java.sql.Connection.TRANSACTION_SERIALIZABLE;
 		}
 		return java.sql.Connection.TRANSACTION_READ_COMMITTED;
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1DatabaseMetaData.java b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1DatabaseMetaData.java
index 59958e592dc..cdf6e8073ec 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1DatabaseMetaData.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1DatabaseMetaData.java
@@ -27,19 +27,28 @@ public abstract class AbstractJdbc1DatabaseMetaData
 	protected static final int iInt2Oid = 21; // OID for int2
 	protected static final int iInt4Oid = 23; // OID for int4
 	protected static final int VARHDRSZ = 4;	// length for int4
-	protected static int NAME_SIZE = 64;	// length for name datatype
+	protected static int NAME_SIZE = 63;	// length for name datatype
 
 	public AbstractJdbc1DatabaseMetaData(AbstractJdbc1Connection conn)
 	{
 		this.connection = conn;
+		String sql;
 		try {
 			if (connection.haveMinimumServerVersion("7.3")) {
-				NAME_SIZE = 64;
+				sql = "SELECT t.typlen FROM pg_catalog.pg_type t, pg_catalog.pg_namespace n WHERE t.typnamespace=n.oid AND t.typname='name' AND n.nspname='pg_catalog'";
+				NAME_SIZE = 63;
 			} else {
-				NAME_SIZE = 32;
+				sql = "SELECT typlen FROM pg_type WHERE typname='name'";
+				NAME_SIZE = 31;
 			}
+			ResultSet rs = connection.createStatement().executeQuery(sql);
+			if (rs.next()) {
+				NAME_SIZE = rs.getInt("typlen") - 1;
+			}
+			rs.close();
 		} catch (SQLException l_se) {
-			//leave value at default
+			// depending on the error the NAME_SIZE value will
+			// be the original or the value set before the query.
 		}
 	}
 
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java
index 672d0eefc7a..e7e5d85d226 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java
@@ -8,7 +8,7 @@ import java.util.Vector;
 import org.postgresql.largeobject.*;
 import org.postgresql.util.*;
 
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.8 2002/09/08 00:15:29 barry Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.9 2002/09/11 05:38:44 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
@@ -170,6 +170,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
 	{
 		String l_sql = replaceProcessing(p_sql);
 		m_sqlFragments = new String[] {l_sql};
+		m_binds = new Object[0];
 		//If we have already created a server prepared statement, we need
 		//to deallocate the existing one
 		if (m_statementName != null) {
@@ -213,6 +214,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
 	{
 		String l_sql = replaceProcessing(p_sql);
 		m_sqlFragments = new String[] {l_sql};
+		m_binds = new Object[0];
 		//If we have already created a server prepared statement, we need
 		//to deallocate the existing one
 		if (m_statementName != null) {
@@ -1775,6 +1777,12 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
 	 */
 	private String modifyJdbcCall(String p_sql) throws SQLException
 	{
+		//Check that this is actually a call which should start with a {
+        //if not do nothing and treat this as a standard prepared sql
+		if (!p_sql.trim().startsWith("{")) {
+			return p_sql;
+		}
+
 		// syntax checking is not complete only a few basics :(
 		originalSql = p_sql; // save for error msgs..
 		String l_sql = p_sql;
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java
index cc468ff50a1..de0266ae7d0 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java
@@ -15,7 +15,7 @@ import org.postgresql.util.PGbytea;
 import org.postgresql.util.PSQLException;
 
 
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2ResultSet.java,v 1.7 2002/09/06 21:23:06 momjian Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2ResultSet.java,v 1.8 2002/09/11 05:38:45 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
@@ -1546,14 +1546,7 @@ public abstract class AbstractJdbc2ResultSet extends org.postgresql.jdbc1.Abstra
 				case Types.REAL:
 				case Types.TINYINT:
 
-					try
-					{
-						rowBuffer[columnIndex] = String.valueOf( updateValues.get( columnName ) ).getBytes(connection.getEncoding().name() );
-					}
-					catch ( UnsupportedEncodingException ex)
-					{
-						throw new SQLException("Unsupported Encoding " + connection.getEncoding().name());
-					}
+					rowBuffer[columnIndex] = connection.getEncoding().encode(String.valueOf( updateValues.get( columnName ) ));
 
 				case Types.NULL:
 					continue;
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java
index 7debda09ba8..b9e4f44ef1d 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java
@@ -8,7 +8,7 @@ import java.util.Vector;
 import org.postgresql.largeobject.*;
 import org.postgresql.util.PSQLException;
 
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Statement.java,v 1.6 2002/09/06 21:23:06 momjian Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Statement.java,v 1.7 2002/09/11 05:38:45 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
@@ -187,16 +187,26 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra
 			while (numRead != -1 && bytesRemaining > 0)
 			{
 				bytesRemaining -= numRead;
-				los.write(buf, 0, numRead);
+				if ( numRead == buf.length )
+					los.write(buf); // saves a buffer creation and copy in LargeObject since it's full
+				else
+					los.write(buf,0,numRead);
 				numRead = l_inStream.read(buf, 0, Math.min(buf.length, bytesRemaining));
 			}
-			los.close();
 		}
 		catch (IOException se)
 		{
 			throw new PSQLException("postgresql.unusual", se);
 		}
-		// lob is closed by the stream so don't call lob.close()
+		finally
+		{
+			try
+			{
+				los.close();
+                l_inStream.close();
+            }
+            catch( Exception e ) {}
+		}
 		setInt(i, oid);
 	}
 
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2ResultSet.java
index 84e3a7b9e6b..36e3aa048ec 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2ResultSet.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/Jdbc2ResultSet.java
@@ -5,7 +5,7 @@ import java.sql.*;
 import java.util.Vector;
 import org.postgresql.Field;
 
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2ResultSet.java,v 1.5 2002/09/06 21:23:06 momjian Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2ResultSet.java,v 1.6 2002/09/11 05:38:45 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
@@ -25,11 +25,19 @@ public class Jdbc2ResultSet extends org.postgresql.jdbc2.AbstractJdbc2ResultSet
 
 	public java.sql.Clob getClob(int i) throws SQLException
 	{
+		wasNullFlag = (this_row[i - 1] == null);
+		if (wasNullFlag)
+			return null;
+
 		return new org.postgresql.jdbc2.Jdbc2Clob(connection, getInt(i));
 	}
 
 	public java.sql.Blob getBlob(int i) throws SQLException
 	{
+		wasNullFlag = (this_row[i - 1] == null);
+		if (wasNullFlag)
+			return null;
+
 		return new org.postgresql.jdbc2.Jdbc2Blob(connection, getInt(i));
 	}
 
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ResultSet.java
index c988127fe46..4e53404e8a9 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ResultSet.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc3/Jdbc3ResultSet.java
@@ -5,7 +5,7 @@ import java.sql.*;
 import java.util.Vector;
 import org.postgresql.Field;
 
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc3/Attic/Jdbc3ResultSet.java,v 1.2 2002/09/06 21:23:06 momjian Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc3/Attic/Jdbc3ResultSet.java,v 1.3 2002/09/11 05:38:45 barry Exp $
  * This class implements the java.sql.ResultSet interface for JDBC3.
  * However most of the implementation is really done in
  * org.postgresql.jdbc3.AbstractJdbc3ResultSet or one of it's parents
@@ -25,11 +25,19 @@ public class Jdbc3ResultSet extends org.postgresql.jdbc3.AbstractJdbc3ResultSet
 
 	public java.sql.Clob getClob(int i) throws SQLException
 	{
+		wasNullFlag = (this_row[i - 1] == null);
+		if (wasNullFlag)
+			return null;
+
 		return new Jdbc3Clob(connection, getInt(i));
 	}
 
 	public java.sql.Blob getBlob(int i) throws SQLException
 	{
+		wasNullFlag = (this_row[i - 1] == null);
+		if (wasNullFlag)
+			return null;
+
 		return new Jdbc3Blob(connection, getInt(i));
 	}
 
diff --git a/src/interfaces/jdbc/org/postgresql/largeobject/BlobOutputStream.java b/src/interfaces/jdbc/org/postgresql/largeobject/BlobOutputStream.java
index b56de6e5430..eb506b6771e 100644
--- a/src/interfaces/jdbc/org/postgresql/largeobject/BlobOutputStream.java
+++ b/src/interfaces/jdbc/org/postgresql/largeobject/BlobOutputStream.java
@@ -68,6 +68,26 @@ public class BlobOutputStream extends OutputStream
 		}
 	}
 
+	public void write(byte[] buf, int off, int len) throws java.io.IOException
+	{
+		try
+			{
+				// If we have any internally buffered data, send it first
+				if ( bpos > 0 )
+					flush();
+
+				if ( off == 0 && len == buf.length )
+					lo.write(buf); // save a buffer creation and copy since full buffer written
+				else
+					lo.write(buf,off,len);
+			}
+		catch (SQLException se)
+			{
+				throw new IOException(se.toString());
+			}
+	}
+
+
 	/*
 	 * Flushes this output stream and forces any buffered output bytes
 	 * to be written out. The general contract of <code>flush</code> is
diff --git a/src/interfaces/jdbc/org/postgresql/largeobject/LargeObject.java b/src/interfaces/jdbc/org/postgresql/largeobject/LargeObject.java
index 316716e42d0..5455e8e7698 100644
--- a/src/interfaces/jdbc/org/postgresql/largeobject/LargeObject.java
+++ b/src/interfaces/jdbc/org/postgresql/largeobject/LargeObject.java
@@ -304,7 +304,7 @@ public class LargeObject
 	 */
 	public InputStream getInputStream() throws SQLException
 	{
-		return new BlobInputStream(this);
+		return new BlobInputStream(this, 4096);
 	}
 
 	/*
@@ -318,7 +318,7 @@ public class LargeObject
 	public OutputStream getOutputStream() throws SQLException
 	{
 		if (os == null)
-			os = new BlobOutputStream(this);
+			os = new BlobOutputStream(this, 4096);
 		return os;
 	}
 
diff --git a/src/interfaces/jdbc/org/postgresql/test/TestUtil.java b/src/interfaces/jdbc/org/postgresql/test/TestUtil.java
index a9f9dfdf3f4..fc8dc70deb0 100644
--- a/src/interfaces/jdbc/org/postgresql/test/TestUtil.java
+++ b/src/interfaces/jdbc/org/postgresql/test/TestUtil.java
@@ -109,11 +109,26 @@ public class TestUtil
 			Statement stmt = con.createStatement();
 			try
 			{
-				stmt.executeUpdate("DROP TABLE " + table);
+				String sql = "DROP TABLE " + table;
+				if (con instanceof org.postgresql.jdbc1.AbstractJdbc1Connection && ((org.postgresql.jdbc1.AbstractJdbc1Connection)con).haveMinimumServerVersion("7.3")) {
+					sql += " CASCADE ";
+				}
+				stmt.executeUpdate(sql);
 			}
 			catch (SQLException ex)
 			{
-				// ignore
+				// Since every create table issues a drop table
+				// it's easy to get a table doesn't exist error.
+				// we want to ignore these, but if we're in a
+				// transaction we need to restart.
+				// If the test case wants to catch this error
+				// itself it should issue the drop SQL directly.
+				if (ex.getMessage().indexOf("does not exist") != -1) {
+					if (!con.getAutoCommit()) {
+						con.rollback();
+					}
+
+				}
 			}
 		}
 		catch (SQLException ex)
diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc2/DatabaseMetaDataTest.java
index 87341925c5d..0d1a962049a 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.13 2002/09/06 21:23:06 momjian Exp $
+ * $Id: DatabaseMetaDataTest.java,v 1.14 2002/09/11 05:38:45 barry Exp $
  */
 
 public class DatabaseMetaDataTest extends TestCase
@@ -264,7 +264,11 @@ public class DatabaseMetaDataTest extends TestCase
 				assertTrue( fkColumnName.equals( "m" ) || fkColumnName.equals( "n" ) ) ;
 
 				String fkName = rs.getString( "FK_NAME" );
-				assertTrue( fkName.equals( "<unnamed>") );
+				if (((org.postgresql.jdbc1.AbstractJdbc1Connection)con1).haveMinimumServerVersion("7.3")) {
+					assertTrue(fkName.startsWith("$1"));
+				} else {
+					assertTrue( fkName.startsWith( "<unnamed>") );
+				}
 
 				String pkName = rs.getString( "PK_NAME" );
 				assertTrue( pkName.equals("vv_pkey") );
@@ -317,7 +321,7 @@ public class DatabaseMetaDataTest extends TestCase
 				assertTrue( fkColumnName.equals( "people_id" ) || fkColumnName.equals( "policy_id" ) ) ;
 
 				String fkName = rs.getString( "FK_NAME" );
-				assertTrue( fkName.equals( "people") || fkName.equals( "policy" ) );
+				assertTrue( fkName.startsWith( "people") || fkName.startsWith( "policy" ) );
 
 				String pkName = rs.getString( "PK_NAME" );
 				assertTrue( pkName.equals( "people_pkey") || pkName.equals( "policy_pkey" ) );
@@ -337,7 +341,7 @@ public class DatabaseMetaDataTest extends TestCase
 			assertTrue( rs.getString( "FKTABLE_NAME" ).equals( "users" ) );
 			assertTrue( rs.getString( "FKCOLUMN_NAME" ).equals( "people_id" ) );
 
-			assertTrue( rs.getString( "FK_NAME" ).equals( "people" ) );
+			assertTrue( rs.getString( "FK_NAME" ).startsWith( "people" ) );
 
 
 			TestUtil.dropTable( con1, "users" );
diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc2/UpdateableResultTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc2/UpdateableResultTest.java
index 3e5519e3178..fcd6321803f 100644
--- a/src/interfaces/jdbc/org/postgresql/test/jdbc2/UpdateableResultTest.java
+++ b/src/interfaces/jdbc/org/postgresql/test/jdbc2/UpdateableResultTest.java
@@ -124,6 +124,7 @@ public class UpdateableResultTest extends TestCase
 			st.close();
 
 			TestUtil.dropTable( con, "updateable" );
+			TestUtil.dropTable( con, "second" );
 			TestUtil.closeDB( con );
 		}
 		catch (Exception ex)
diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/BaseDataSourceTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/BaseDataSourceTest.java
index dbb73d3e72d..7d041496c80 100644
--- a/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/BaseDataSourceTest.java
+++ b/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/BaseDataSourceTest.java
@@ -1,7 +1,7 @@
 package org.postgresql.test.jdbc2.optional;
 
 import junit.framework.TestCase;
-import org.postgresql.test.JDBC2Tests;
+import org.postgresql.test.TestUtil;
 import org.postgresql.jdbc2.optional.SimpleDataSource;
 import org.postgresql.jdbc2.optional.BaseDataSource;
 
@@ -15,7 +15,7 @@ import java.sql.*;
  * tests.
  *
  * @author Aaron Mulder (ammulder@chariotsolutions.com)
- * @version $Revision: 1.2 $
+ * @version $Revision: 1.3 $
  */
 public abstract class BaseDataSourceTest extends TestCase
 {
@@ -36,12 +36,12 @@ public abstract class BaseDataSourceTest extends TestCase
 	 */
 	protected void setUp() throws Exception
 	{
-		con = JDBC2Tests.openDB();
-		JDBC2Tests.createTable(con, "poolingtest", "id int4 not null primary key, name varchar(50)");
+		con = TestUtil.openDB();
+		TestUtil.createTable(con, "poolingtest", "id int4 not null primary key, name varchar(50)");
 		Statement stmt = con.createStatement();
 		stmt.executeUpdate("INSERT INTO poolingtest VALUES (1, 'Test Row 1')");
 		stmt.executeUpdate("INSERT INTO poolingtest VALUES (2, 'Test Row 2')");
-		JDBC2Tests.closeDB(con);
+		TestUtil.closeDB(con);
 	}
 
 	/**
@@ -50,9 +50,9 @@ public abstract class BaseDataSourceTest extends TestCase
 	 */
 	protected void tearDown() throws Exception
 	{
-		con = JDBC2Tests.openDB();
-		JDBC2Tests.dropTable(con, "poolingtest");
-		JDBC2Tests.closeDB(con);
+		con = TestUtil.openDB();
+		TestUtil.dropTable(con, "poolingtest");
+		TestUtil.closeDB(con);
 	}
 
 	/**
@@ -142,8 +142,7 @@ public abstract class BaseDataSourceTest extends TestCase
 		try
 		{
 			con = getDataSourceConnection();
-			JDBC2Tests.dropTable(con, "poolingtest");
-			JDBC2Tests.createTable(con, "poolingtest", "id int4 not null primary key, name varchar(50)");
+			TestUtil.createTable(con, "poolingtest", "id int4 not null primary key, name varchar(50)");
 			con.close();
 		}
 		catch (SQLException e)
diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/ConnectionPoolTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/ConnectionPoolTest.java
index 2e405f2a547..90a3b564a51 100644
--- a/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/ConnectionPoolTest.java
+++ b/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/ConnectionPoolTest.java
@@ -1,7 +1,7 @@
 package org.postgresql.test.jdbc2.optional;
 
 import org.postgresql.jdbc2.optional.ConnectionPool;
-import org.postgresql.test.JDBC2Tests;
+import org.postgresql.test.TestUtil;
 import javax.sql.*;
 import java.sql.*;
 
@@ -11,7 +11,7 @@ import java.sql.*;
  * interface to the PooledConnection is through the CPDS.
  *
  * @author Aaron Mulder (ammulder@chariotsolutions.com)
- * @version $Revision: 1.2 $
+ * @version $Revision: 1.3 $
  */
 public class ConnectionPoolTest extends BaseDataSourceTest
 {
@@ -31,7 +31,7 @@ public class ConnectionPoolTest extends BaseDataSourceTest
 		if (bds == null)
 		{
 			bds = new ConnectionPool();
-			String db = JDBC2Tests.getURL();
+			String db = TestUtil.getURL();
 			if (db.indexOf('/') > -1)
 			{
 				db = db.substring(db.lastIndexOf('/') + 1);
@@ -41,8 +41,8 @@ public class ConnectionPoolTest extends BaseDataSourceTest
 				db = db.substring(db.lastIndexOf(':') + 1);
 			}
 			bds.setDatabaseName(db);
-			bds.setUser(JDBC2Tests.getUser());
-			bds.setPassword(JDBC2Tests.getPassword());
+			bds.setUser(TestUtil.getUser());
+			bds.setPassword(TestUtil.getPassword());
 		}
 	}
 
diff --git a/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/SimpleDataSourceTest.java b/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/SimpleDataSourceTest.java
index 3eb42733a2c..b5c3e100ecd 100644
--- a/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/SimpleDataSourceTest.java
+++ b/src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/SimpleDataSourceTest.java
@@ -1,6 +1,6 @@
 package org.postgresql.test.jdbc2.optional;
 
-import org.postgresql.test.JDBC2Tests;
+import org.postgresql.test.TestUtil;
 import org.postgresql.jdbc2.optional.SimpleDataSource;
 
 /**
@@ -8,7 +8,7 @@ import org.postgresql.jdbc2.optional.SimpleDataSource;
  * configuration logic.
  *
  * @author Aaron Mulder (ammulder@chariotsolutions.com)
- * @version $Revision: 1.2 $
+ * @version $Revision: 1.3 $
  */
 public class SimpleDataSourceTest extends BaseDataSourceTest
 {
@@ -28,7 +28,7 @@ public class SimpleDataSourceTest extends BaseDataSourceTest
 		if (bds == null)
 		{
 			bds = new SimpleDataSource();
-			String db = JDBC2Tests.getURL();
+			String db = TestUtil.getURL();
 			if (db.indexOf('/') > -1)
 			{
 				db = db.substring(db.lastIndexOf('/') + 1);
@@ -38,8 +38,8 @@ public class SimpleDataSourceTest extends BaseDataSourceTest
 				db = db.substring(db.lastIndexOf(':') + 1);
 			}
 			bds.setDatabaseName(db);
-			bds.setUser(JDBC2Tests.getUser());
-			bds.setPassword(JDBC2Tests.getPassword());
+			bds.setUser(TestUtil.getUser());
+			bds.setPassword(TestUtil.getPassword());
 		}
 	}
 }
-- 
GitLab