You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by kr...@apache.org on 2012/06/28 13:58:19 UTC

svn commit: r1354960 [2/3] - in /db/derby/code/trunk/java/testing: ./ org/apache/derbyTesting/functionTests/tests/compatibility/ org/apache/derbyTesting/functionTests/tests/compatibility/helpers/ org/apache/derbyTesting/junit/

Copied: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/compatibility/JDBCDriverTest.java (from r1354909, db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/junitTests/compatibility/JDBCDriverTest.java)
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/compatibility/JDBCDriverTest.java?p2=db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/compatibility/JDBCDriverTest.java&p1=db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/junitTests/compatibility/JDBCDriverTest.java&r1=1354909&r2=1354960&rev=1354960&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/junitTests/compatibility/JDBCDriverTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/compatibility/JDBCDriverTest.java Thu Jun 28 11:58:16 2012
@@ -1,4 +1,4 @@
-/**
+/*
 
    Derby - Class org.apache.derbyTesting.functionTests.tests.compatibility.JDBCDriverTest
 
@@ -18,284 +18,302 @@
    limitations under the License.
 
  */
+package org.apache.derbyTesting.functionTests.tests.compatibility;
+
+import java.io.ByteArrayInputStream;
+import java.math.BigDecimal;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ParameterMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.util.HashMap;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.derbyTesting.junit.JDBC;
+import org.apache.derbyTesting.junit.TestConfiguration;
+
+import org.apache.derbyTesting.functionTests.tests.compatibility.helpers.DummyBlob;
+import org.apache.derbyTesting.functionTests.tests.compatibility.helpers.DummyClob;
+import org.apache.derbyTesting.junit.BaseJDBCTestSetup;
+import org.apache.derbyTesting.junit.DerbyVersion;
+
 /**
- * <p>
- * This JUnit test verifies the compatibility of Derby clients and
- * servers across Derby version levels and supported VMs.
- * </p>
- *
+ * A set of client driver compatibility tests.
  */
+public class JDBCDriverTest
+    extends AbstractCompatibilityTest {
+    /////////////////////////////////////////////////////////////
+    //
+    //    CONSTANTS
+    //
+    /////////////////////////////////////////////////////////////
 
-package org.apache.derbyTesting.functionTests.tests.junitTests.compatibility;
+    private    static    final        String    ALL_TYPES_TABLE = "allTypesTable";
+    private    static    final        String    KEY_COLUMN = "keyCol";
 
-import java.io.*;
-import java.math.*;
-import java.sql.*;
-import java.util.*;
-import java.util.regex.Pattern;
-import org.apache.derbyTesting.junit.JDBC;
+    //
+    // Data values to be stuffed into columns of ALL_TYPES_TABLE.
+    //
+    private    static    final        byte[]    SAMPLE_BYTES =
+        new byte[] { (byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 5 };
+    private    static    final        String    SAMPLE_STRING = "hello";
 
-public	class	JDBCDriverTest	extends	CompatibilitySuite
-{
-	/////////////////////////////////////////////////////////////
-	//
-	//	CONSTANTS
-	//
-	/////////////////////////////////////////////////////////////
-
-	private	static	final			String	ALL_TYPES_TABLE = "allTypesTable";
-	private	static	final			String	KEY_COLUMN = "keyCol";
-
-	//
-	// Data values to be stuffed into columns of ALL_TYPES_TABLE.
-	//
-	private	static	final			byte[]	SAMPLE_BYTES =
-		new byte[] { (byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 5 };
-	private	static	final			String	SAMPLE_STRING = "hello";
-
-	//
-	// These funny constants are defined this way to make the salient
-	// facts of the COERCIONS table leap out at you.
-	//
-	private	static	final			boolean	Y = true;
-	private	static	final			boolean	_ = false;
-
-	//
-	// This table declares the datatypes supported by Derby and the earliest
-	// versions of the Derby client which support these datatypes.
-	//
-	// If you add a type to this table, make sure you add a corresponding
-	// column to the following row table. Also add a corresponding row to the
-	// COERCIONS table.
-	//
-	private	static	final	TypeDescriptor[]	ALL_TYPES =
-	{
-		// 10.0 types
-		
-		new TypeDescriptor
-		( Types.BIGINT,			"bigint",	DRB_10_0),
-		new TypeDescriptor
-		( Types.BLOB,			"blob",	DRB_10_0),
-		new TypeDescriptor
-		( Types.CHAR,			"char(5)",	DRB_10_0),
-		new TypeDescriptor
-		( Types.BINARY,			"char(5) for bit data",	DRB_10_0),
-		new TypeDescriptor
-		( Types.CLOB,			"clob",	DRB_10_0),
-		new TypeDescriptor
-		( Types.DATE,			"date",	DRB_10_0),
-		new TypeDescriptor
-		( Types.DECIMAL,		"decimal",	DRB_10_0),
-		new TypeDescriptor
-		( Types.DOUBLE,			"double",	DRB_10_0),
-		new TypeDescriptor
-		( Types.DOUBLE,			"double precision",	DRB_10_0),
-		new TypeDescriptor
-		( Types.REAL,			"float(23)",	DRB_10_0),
-		new TypeDescriptor
-		( Types.DOUBLE,			"float",	DRB_10_0),
-		new TypeDescriptor
-		( Types.INTEGER,		"integer",	DRB_10_0),
-		new TypeDescriptor
-		( Types.LONGVARCHAR,	"long varchar",	DRB_10_0),
-		new TypeDescriptor
-		( Types.LONGVARBINARY,	"long varchar for bit data",	DRB_10_0),
-		new TypeDescriptor
-		( Types.NUMERIC,		"numeric",	DRB_10_0),
-		new TypeDescriptor
-		( Types.REAL,			"real",	DRB_10_0),
-		new TypeDescriptor
-		( Types.SMALLINT,		"smallint",	DRB_10_0),
-		new TypeDescriptor
-		( Types.TIME,			"time",	DRB_10_0),
-		new TypeDescriptor
-		( Types.TIMESTAMP,		"timestamp",	DRB_10_0),
-		new TypeDescriptor
-		( Types.VARCHAR,		"varchar(5)",	DRB_10_0),
-		new TypeDescriptor
-		( Types.VARBINARY,		"varchar(5) for bit data",	DRB_10_0),
-	};
-
-	//
-	// This table needs to have the same number of entries as ALL_TYPES.
-	// The testSanity() test case enforces this at run time.
-	//
-	private	static	final	Object[]	ROW_1 =
-	{
-		// 10.0 columns
-		
-		new Long( 1L ),
-		new MyBlob( SAMPLE_BYTES ),
-		SAMPLE_STRING,
-		SAMPLE_BYTES,
-		new MyClob( SAMPLE_STRING ),
-		new java.sql.Date( 1L ),
-		new BigDecimal( 1.0 ),
-		new Double( 1.0 ),
-		new Double( 1.0 ),
-		new Float( (float) 1.0 ),
-		new Double( 1.0 ),
-		new Integer( 1 ),
-		SAMPLE_STRING,
-		SAMPLE_BYTES,
-		new BigDecimal( 1.0 ),
-		new Float( (float) 1.0 ),
-		new Short( (short) 1 ),
-		new Time( 1L ),
-		new Timestamp( 1L ),
-		SAMPLE_STRING,
-		SAMPLE_BYTES,
-	};
-
-	//
-	// This table needs to have the same number of rows as ALL_TYPES.
-	// Each row in this table needs to have the same number of columns as
-	// rows in ALL_TYPES. The testSanity() test case enforces this at run time.
-	// Note how the funny synonyms for true and false
-	// make the salient facts of this table leap out at you.
-	//
-	// The ugly class name T_CN is an abbreviation which makes it possible to
-	// squeeze this table onto a readable screen.
-	//
-	// Please read the introductory comment top-to-bottom. 'Y' means a coercion
-	// is legal; '_' means it isn't.
-	//
-	private	static	final	T_CN[]	COERCIONS =
-	{
-		//												  B|B|C|B|C|D|D|D|R|I|L|L|N|R|S|T|T|V|V
-		//												  I|L|H|I|L|A|E|O|E|N|O|O|U|E|M|I|I|A|A
-		//												  G|O|A|N|O|T|C|U|A|T|N|N|M|A|A|M|M|R|R
-		//												  I|B|R|A|B|E|I|B|L|E|G|G|E|L|L|E|E|C|B
-		//												  N|-|-|R|-|-|M|L|-|G|V|V|R|-|L|-|S|H|I
-		//												  T|-|-|Y|-|-|A|E|-|E|A|A|I|-|I|-|T|A|N
-		//												  -|-|-|-|-|-|L|-|-|R|R|R|C|-|N|-|A|R|A
-		//												  -|-|-|-|-|-|-|-|-|-|C|B|-|-|T|-|M|-|R
-		//												  -|-|-|-|-|-|-|-|-|-|H|I|-|-|-|-|P|-|Y
-		//												  -|-|-|-|-|-|-|-|-|-|A|N|-|-|-|-|-|-|-
-		//												  -|-|-|-|-|-|-|-|-|-|R|A|-|-|-|-|-|-|-
-		//												  -|-|-|-|-|-|-|-|-|-|-|R|-|-|-|-|-|-|-
-		//												  -|-|-|-|-|-|-|-|-|-|-|Y|-|-|-|-|-|-|-
-		new T_CN( Types.BIGINT, new boolean[]			{ Y,_,Y,_,_,_,_,Y,Y,Y,Y,_,Y,Y,Y,_,_,Y,_ } ),
-		new T_CN( Types.BLOB, new boolean[] 			{ _,Y,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ } ),
-		new T_CN( Types.CHAR, new boolean[]				{ _,_,Y,_,_,_,_,_,_,_,Y,_,_,_,_,_,_,Y,_ } ),
-		new T_CN( Types.BINARY, new boolean[]			{ _,_,_,Y,_,_,_,_,_,_,_,Y,_,_,_,_,_,_,Y } ),
-		new T_CN( Types.CLOB, new boolean[]				{ _,_,_,_,Y,_,_,_,_,_,_,_,_,_,_,_,_,_,_ } ),
-		new T_CN( Types.DATE, new boolean[]				{ _,_,_,_,_,Y,_,_,_,_,_,_,_,_,_,_,_,_,_ } ),
-		new T_CN( Types.DECIMAL, new boolean[]			{ Y,_,_,_,_,_,Y,Y,Y,Y,Y,_,Y,Y,Y,_,_,Y,_ } ),
-		new T_CN( Types.DOUBLE, new boolean[]			{ Y,_,_,_,_,_,Y,Y,Y,Y,Y,_,Y,Y,Y,_,_,Y,_ } ),
-		new T_CN( Types.REAL, new boolean[]				{ Y,_,Y,_,_,_,Y,Y,Y,Y,Y,_,Y,Y,Y,_,_,Y,_ } ),
-		new T_CN( Types.INTEGER, new boolean[]			{ Y,_,Y,_,_,_,Y,Y,Y,Y,Y,_,Y,Y,Y,_,_,Y,_ } ),
-		new T_CN( Types.LONGVARCHAR, new boolean[]		{ _,_,Y,_,_,_,_,_,_,_,Y,_,_,_,_,_,_,Y,_ } ),
-		new T_CN( Types.LONGVARBINARY, new boolean[]	{ _,_,_,_,_,_,_,_,_,_,_,Y,_,_,_,_,_,_,Y } ),
-		new T_CN( Types.NUMERIC, new boolean[]			{ Y,_,Y,_,_,_,Y,Y,Y,Y,Y,_,Y,Y,Y,_,_,Y,_ } ),
-		new T_CN( Types.REAL, new boolean[]				{ Y,_,Y,_,_,_,Y,Y,Y,Y,Y,_,Y,Y,Y,_,_,Y,_ } ),
-		new T_CN( Types.SMALLINT, new boolean[]			{ Y,_,Y,_,_,_,Y,Y,Y,Y,Y,_,Y,Y,Y,_,_,Y,_ } ),
-		new T_CN( Types.TIME, new boolean[]				{ _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,Y,_,_,_ } ),
-		new T_CN( Types.TIMESTAMP, new boolean[]		{ _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,Y,_,_ } ),
-		new T_CN( Types.VARCHAR, new boolean[]			{ _,_,Y,_,_,_,_,_,_,_,Y,_,_,_,_,_,_,Y,_ } ),
-		new T_CN( Types.VARBINARY, new boolean[]		{ _,_,_,_,_,_,_,_,_,_,_,Y,_,_,_,_,_,_,Y } ),
-	};
-
-	/////////////////////////////////////////////////////////////
-	//
-	//	STATE
-	//
-	/////////////////////////////////////////////////////////////
-
-	// map derby type name to type descriptor
-	private	static	HashMap		_types = new HashMap();	// maps Derby type names to TypeDescriptors
-
-	// map jdbc type to index into COERCIONS
-	private	static	HashMap		_coercionIndex = new HashMap();	// maps jdbc types to legal coercions
-
-	/////////////////////////////////////////////////////////////
-	//
-	//	CONSTRUCTOR
-	//
-	/////////////////////////////////////////////////////////////
-	
-	public	JDBCDriverTest() {}
-
-	/////////////////////////////////////////////////////////////
-	//
-	//	TEST ENTRY POINTS
-	//
-	/////////////////////////////////////////////////////////////
-
-	/**
-	 * <p>
-	 * Sanity check the integrity of this test suite.
-	 * </p>
-	 */
-	public	void	testSanity()
-	{
-		assertEquals
-			( "ALL_TYPES.length == ROW_1.length", ALL_TYPES.length, ROW_1.length );
-
-		// make sure there we completely describe the coercibility of every jdbc type
-		int		coercionCount = COERCIONS.length;
-		for ( int i = 0; i < coercionCount; i++ )
-		{ assertEquals( "Coercion " + i, coercionCount, COERCIONS[ i ].getCoercions().length ); }
-	}
-
-	/**
-	 * <p>
-	 * Main test of jdbc drivers.
-	 * </p>
-	 */
-	public	void	testJDBCDriver()
-		throws Exception
-	{
-		Connection		conn = getConnection();
-		
-		dropSchema( conn );
-		createSchema( conn );
-
-		datatypesTest( conn );
-        udtTest( conn );
-        derby_2602_test( conn );
-        derby_4613_test( conn );
-        derby_4888_test( conn );
-        derby_5449_test( conn );
-
-		close( conn );
-	}
-	
-	/////////////////////////////////////////////////////////////
-	//
-	//	DERBY-4613
-    //
-    // Make embedded and network clients treat BOOLEAN values identically.
-	//
-	/////////////////////////////////////////////////////////////
-
-    //
-    // Verify that embedded and network clients handle BOOLEAN values the
-    // same way from release 10.7 onward.
-    //
-	private	void	derby_4613_test( Connection conn )
-		throws Exception
-	{
-        boolean correctBehavior =
-            usingEmbeddedClient() ||
-            (
-             getServerVersion().atLeast( DRB_10_7 ) &&
-             getDriverVersion().atLeast( DRB_10_7 )
-             );
+    //
+    // These funny constants are defined this way to make the salient
+    // facts of the COERCIONS table leap out at you.
+    //
+    private    static    final        boolean    Y = true;
+    private    static    final        boolean    _ = false;
+
+    //
+    // This table declares the datatypes supported by Derby and the earliest
+    // versions of the Derby client which support these datatypes.
+    //
+    // If you add a type to this table, make sure you add a corresponding
+    // column to the following row table. Also add a corresponding row to the
+    // COERCIONS table.
+    //
+    private    static    final    TypeDescriptor[]    ALL_TYPES =
+    {
+        // 10.0 types
+
+        new TypeDescriptor
+        ( Types.BIGINT,         "bigint",                   DerbyVersion._10_0),
+        new TypeDescriptor
+        ( Types.BLOB,           "blob",                     DerbyVersion._10_0),
+        new TypeDescriptor
+        ( Types.CHAR,           "char(5)",                  DerbyVersion._10_0),
+        new TypeDescriptor
+        ( Types.BINARY,         "char(5) for bit data",     DerbyVersion._10_0),
+        new TypeDescriptor
+        ( Types.CLOB,           "clob",                     DerbyVersion._10_0),
+        new TypeDescriptor
+        ( Types.DATE,           "date",                     DerbyVersion._10_0),
+        new TypeDescriptor
+        ( Types.DECIMAL,        "decimal",                  DerbyVersion._10_0),
+        new TypeDescriptor
+        ( Types.DOUBLE,         "double",                   DerbyVersion._10_0),
+        new TypeDescriptor
+        ( Types.DOUBLE,         "double precision",         DerbyVersion._10_0),
+        new TypeDescriptor
+        ( Types.REAL,           "float(23)",                DerbyVersion._10_0),
+        new TypeDescriptor
+        ( Types.DOUBLE,         "float",                    DerbyVersion._10_0),
+        new TypeDescriptor
+        ( Types.INTEGER,        "integer",                  DerbyVersion._10_0),
+        new TypeDescriptor
+        ( Types.LONGVARCHAR,    "long varchar",             DerbyVersion._10_0),
+        new TypeDescriptor
+        ( Types.LONGVARBINARY,  "long varchar for bit data",DerbyVersion._10_0),
+        new TypeDescriptor
+        ( Types.NUMERIC,        "numeric",                  DerbyVersion._10_0),
+        new TypeDescriptor
+        ( Types.REAL,           "real",                     DerbyVersion._10_0),
+        new TypeDescriptor
+        ( Types.SMALLINT,       "smallint",                 DerbyVersion._10_0),
+        new TypeDescriptor
+        ( Types.TIME,           "time",                     DerbyVersion._10_0),
+        new TypeDescriptor
+        ( Types.TIMESTAMP,      "timestamp",                DerbyVersion._10_0),
+        new TypeDescriptor
+        ( Types.VARCHAR,        "varchar(5)",               DerbyVersion._10_0),
+        new TypeDescriptor
+        ( Types.VARBINARY,      "varchar(5) for bit data",  DerbyVersion._10_0),
+    };
+
+    //
+    // This table needs to have the same number of entries as ALL_TYPES.
+    // The testSanity() test case enforces this at run time.
+    //
+    private    static    final    Object[]    ROW_1 =
+    {
+        // 10.0 columns
+
+        new Long( 1L ),
+        new DummyBlob( SAMPLE_BYTES ),
+        SAMPLE_STRING,
+        SAMPLE_BYTES,
+        new DummyClob( SAMPLE_STRING ),
+        new java.sql.Date( 1L ),
+        new BigDecimal( 1.0 ),
+        new Double( 1.0 ),
+        new Double( 1.0 ),
+        new Float( (float) 1.0 ),
+        new Double( 1.0 ),
+        new Integer( 1 ),
+        SAMPLE_STRING,
+        SAMPLE_BYTES,
+        new BigDecimal( 1.0 ),
+        new Float( (float) 1.0 ),
+        new Short( (short) 1 ),
+        new Time( 1L ),
+        new Timestamp( 1L ),
+        SAMPLE_STRING,
+        SAMPLE_BYTES,
+    };
+
+    //
+    // This table needs to have the same number of rows as ALL_TYPES.
+    // Each row in this table needs to have the same number of columns as
+    // rows in ALL_TYPES. The testSanity() test case enforces this at run time.
+    // Note how the funny synonyms for true and false
+    // make the salient facts of this table leap out at you.
+    //
+    // The ugly class name T_CN is an abbreviation which makes it possible to
+    // squeeze this table onto a readable screen.
+    //
+    // Please read the introductory comment top-to-bottom. 'Y' means a coercion
+    // is legal; '_' means it isn't.
+    //
+    private    static    final    T_CN[]    COERCIONS =
+    {
+        //                                                  B|B|C|B|C|D|D|D|R|I|L|L|N|R|S|T|T|V|V
+        //                                                  I|L|H|I|L|A|E|O|E|N|O|O|U|E|M|I|I|A|A
+        //                                                  G|O|A|N|O|T|C|U|A|T|N|N|M|A|A|M|M|R|R
+        //                                                  I|B|R|A|B|E|I|B|L|E|G|G|E|L|L|E|E|C|B
+        //                                                  N|-|-|R|-|-|M|L|-|G|V|V|R|-|L|-|S|H|I
+        //                                                  T|-|-|Y|-|-|A|E|-|E|A|A|I|-|I|-|T|A|N
+        //                                                  -|-|-|-|-|-|L|-|-|R|R|R|C|-|N|-|A|R|A
+        //                                                  -|-|-|-|-|-|-|-|-|-|C|B|-|-|T|-|M|-|R
+        //                                                  -|-|-|-|-|-|-|-|-|-|H|I|-|-|-|-|P|-|Y
+        //                                                  -|-|-|-|-|-|-|-|-|-|A|N|-|-|-|-|-|-|-
+        //                                                  -|-|-|-|-|-|-|-|-|-|R|A|-|-|-|-|-|-|-
+        //                                                  -|-|-|-|-|-|-|-|-|-|-|R|-|-|-|-|-|-|-
+        //                                                  -|-|-|-|-|-|-|-|-|-|-|Y|-|-|-|-|-|-|-
+        new T_CN( Types.BIGINT, new boolean[]             { Y,_,Y,_,_,_,_,Y,Y,Y,Y,_,Y,Y,Y,_,_,Y,_ } ),
+        new T_CN( Types.BLOB, new boolean[]               { _,Y,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_ } ),
+        new T_CN( Types.CHAR, new boolean[]               { _,_,Y,_,_,_,_,_,_,_,Y,_,_,_,_,_,_,Y,_ } ),
+        new T_CN( Types.BINARY, new boolean[]             { _,_,_,Y,_,_,_,_,_,_,_,Y,_,_,_,_,_,_,Y } ),
+        new T_CN( Types.CLOB, new boolean[]               { _,_,_,_,Y,_,_,_,_,_,_,_,_,_,_,_,_,_,_ } ),
+        new T_CN( Types.DATE, new boolean[]               { _,_,_,_,_,Y,_,_,_,_,_,_,_,_,_,_,_,_,_ } ),
+        new T_CN( Types.DECIMAL, new boolean[]            { Y,_,_,_,_,_,Y,Y,Y,Y,Y,_,Y,Y,Y,_,_,Y,_ } ),
+        new T_CN( Types.DOUBLE, new boolean[]             { Y,_,_,_,_,_,Y,Y,Y,Y,Y,_,Y,Y,Y,_,_,Y,_ } ),
+        new T_CN( Types.REAL, new boolean[]               { Y,_,Y,_,_,_,Y,Y,Y,Y,Y,_,Y,Y,Y,_,_,Y,_ } ),
+        new T_CN( Types.INTEGER, new boolean[]            { Y,_,Y,_,_,_,Y,Y,Y,Y,Y,_,Y,Y,Y,_,_,Y,_ } ),
+        new T_CN( Types.LONGVARCHAR, new boolean[]        { _,_,Y,_,_,_,_,_,_,_,Y,_,_,_,_,_,_,Y,_ } ),
+        new T_CN( Types.LONGVARBINARY, new boolean[]      { _,_,_,_,_,_,_,_,_,_,_,Y,_,_,_,_,_,_,Y } ),
+        new T_CN( Types.NUMERIC, new boolean[]            { Y,_,Y,_,_,_,Y,Y,Y,Y,Y,_,Y,Y,Y,_,_,Y,_ } ),
+        new T_CN( Types.REAL, new boolean[]               { Y,_,Y,_,_,_,Y,Y,Y,Y,Y,_,Y,Y,Y,_,_,Y,_ } ),
+        new T_CN( Types.SMALLINT, new boolean[]           { Y,_,Y,_,_,_,Y,Y,Y,Y,Y,_,Y,Y,Y,_,_,Y,_ } ),
+        new T_CN( Types.TIME, new boolean[]               { _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,Y,_,_,_ } ),
+        new T_CN( Types.TIMESTAMP, new boolean[]          { _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,Y,_,_ } ),
+        new T_CN( Types.VARCHAR, new boolean[]            { _,_,Y,_,_,_,_,_,_,_,Y,_,_,_,_,_,_,Y,_ } ),
+        new T_CN( Types.VARBINARY, new boolean[]          { _,_,_,_,_,_,_,_,_,_,_,Y,_,_,_,_,_,_,Y } ),
+    };
+
+    /////////////////////////////////////////////////////////////
+    //
+    //    STATE
+    //
+    /////////////////////////////////////////////////////////////
+
+    // map derby type name to type descriptor
+    private    static    HashMap        _types = new HashMap();    // maps Derby type names to TypeDescriptors
+
+    // map jdbc type to index into COERCIONS
+    private    static    HashMap        _coercionIndex = new HashMap();    // maps jdbc types to legal coercions
 
+    /////////////////////////////////////////////////////////////
+    //
+    //    CONSTRUCTOR
+    //
+    /////////////////////////////////////////////////////////////
+
+    public JDBCDriverTest(String name) {
+        super(name);
+    }
+
+    /////////////////////////////////////////////////////////////
+    //
+    //    TEST ENTRY POINTS
+    //
+    /////////////////////////////////////////////////////////////
+
+    /**
+     * Sanity check the integrity of this test suite.
+     */
+    public void testSanity()
+    {
+        assertEquals("ALL_TYPES.length == ROW_1.length",
+                ALL_TYPES.length, ROW_1.length );
+
+        // make sure we completely describe the coercibility of every jdbc type
+        int coercionCount = COERCIONS.length;
+        for ( int i = 0; i < coercionCount; i++ ) {
+            assertEquals("Coercion " + i,
+                    coercionCount, COERCIONS[ i ].getCoercions().length );
+        }
+    }
+
+    public void testVerifyVersions()
+            throws SQLException {
+        DerbyVersion server = getServerVersion();
+        DerbyVersion client = getDriverVersion();
+        println("server=" + server.toString() + " <-> client=" +
+                client.toString());
+        String expS = getSystemProperty("derby.tests.compat.expectedServer");
+        String expC = getSystemProperty("derby.tests.compat.expectedClient");
+        assertNotNull("expected server property missing", expS);
+        assertNotNull("expected client property missing", expC);
+        DerbyVersion expectedServer = DerbyVersion.parseVersionString(expS);
+        DerbyVersion expectedClient = DerbyVersion.parseVersionString(expC);
+        assertEquals("server version mismatch", expectedServer, server);
+        assertEquals("client version mismatch", expectedClient, client);
+    }
+
+    /**
+     * Tests compatibility for the available data types.
+     */
+    public void testDataTypesCompatibility() throws SQLException {
+        datatypesTest();
+    }
+
+    /////////////////////////////////////////////////////////////
+    //
+    //    DERBY-4613
+    //
+    // Make sure embedded and network clients treat BOOLEAN values identically.
+    //
+    /////////////////////////////////////////////////////////////
+
+    /**
+     * Verify that embedded and network clients handle BOOLEAN values the
+     * same way from release 10.7 onward.
+     */
+    public void testDerby4613(Connection conn)
+        throws Exception
+    {
+        boolean correctBehavior =
+                getServerVersion().atLeast( DerbyVersion._10_7 ) &&
+                getDriverVersion().atLeast( DerbyVersion._10_7 );
         println( "derby_4613_test correctBehavior = " + correctBehavior );
 
-        vet_isindex_column( conn, correctBehavior, "SYSTABLES_HEAP", false );
-        vet_isindex_column( conn, correctBehavior, "SYSTABLES_INDEX1", true );
+        vet_isindex_column(correctBehavior, "SYSTABLES_HEAP", false);
+        vet_isindex_column(correctBehavior, "SYSTABLES_INDEX1", true);
     }
+
     /**
-     * <p>
      * Vet boolean results.
-     * </p>
      */
-    private void vet_isindex_column( Connection conn, boolean correctBehavior, String conglomerateName, boolean expectedValue ) throws Exception
+    private void vet_isindex_column(boolean correctBehavior,
+                                    String conglomerateName,
+                                    boolean expectedValue)
+            throws Exception
     {
-        PreparedStatement ps = prepare( conn, "select isindex from sys.sysconglomerates where conglomeratename = ?" );
+        PreparedStatement ps = prepareStatement(
+                "select isindex from sys.sysconglomerates " +
+                "where conglomeratename = ?");
         ps.setString( 1, conglomerateName );
         ResultSet rs = ps.executeQuery();
         ResultSetMetaData rsmd = rs.getMetaData();
@@ -305,17 +323,18 @@ public	class	JDBCDriverTest	extends	Comp
         int precision = correctBehavior ? 1 : 5;
         int scale = 0;
         int columnDisplaySize = correctBehavior ? 5 : 6;
-        String columnClassName = correctBehavior ? "java.lang.Boolean" : "java.lang.Integer";
+        String columnClassName = correctBehavior ? "java.lang.Boolean"
+                                                 : "java.lang.Integer";
 
         Object objectValue;
         if ( correctBehavior )
         {
-            objectValue = new Boolean( expectedValue );
+            objectValue = Boolean.valueOf(expectedValue);
         }
         else
         {
             objectValue = expectedValue ? new Integer( 1 ) : new Integer( 0 );
-        }        
+        }
         String stringValue = objectValue.toString();
 
         assertEquals( jdbcType, rsmd.getColumnType( 1 ) );
@@ -326,7 +345,7 @@ public	class	JDBCDriverTest	extends	Comp
         assertEquals( columnClassName, rsmd.getColumnClassName( 1 ) );
 
         assertEquals( true, rs.next() );
-        
+
         assertEquals( expectedValue, rs.getBoolean( 1 ) );
         assertEquals( objectValue, rs.getObject( 1 ) );
         assertEquals( stringValue, rs.getString( 1 ) );
@@ -334,39 +353,35 @@ public	class	JDBCDriverTest	extends	Comp
         rs.close();
         ps.close();
     }
-    
-	/////////////////////////////////////////////////////////////
-	//
-	//	DERBY-2602
-	//
-	/////////////////////////////////////////////////////////////
 
+    /////////////////////////////////////////////////////////////
+    //
+    //    DERBY-2602
     //
-    // Verify that timestamps retain their nanosecond-precision
-    // across the network from release 10.6 onward.
-    //
-	private	void	derby_2602_test( Connection conn )
-		throws Exception
-	{
+    /////////////////////////////////////////////////////////////
+
+    /**
+     * Verifies that timestamps retain their nanosecond-precision
+     * across the network from release 10.6 onward.
+     */
+    public void testDerby2602() throws SQLException {
         //
         // We must expect truncation of timestamps in a network configuration
         // unless both the client and the server are at 10.6 or higher.
         // See DERBY-2602.
         //
         boolean correctBehavior =
-            usingEmbeddedClient() ||
-            (
-             getServerVersion().atLeast( DRB_10_6 ) &&
-             getDriverVersion().atLeast( DRB_10_6 )
-             );
+                getServerVersion().atLeast( DerbyVersion._10_6 ) &&
+                getDriverVersion().atLeast( DerbyVersion._10_6 );
 
         Timestamp ts = Timestamp.valueOf("2004-02-14 17:14:24.976255123");
-		PreparedStatement	insert = prepare( conn, "insert into t_2602( a ) values ( ? )" );
+        PreparedStatement    insert = prepareStatement(
+                "insert into t_2602( a ) values ( ? )");
         insert.setTimestamp(1,ts);
         insert.executeUpdate();
         insert.close();
 
-		PreparedStatement	select = prepare( conn, "select a from t_2602" );
+        PreparedStatement    select = prepareStatement("select a from t_2602" );
         ResultSet selectRS = select.executeQuery();
         selectRS.next();
         Timestamp resultTS = selectRS.getTimestamp( 1 );
@@ -380,9 +395,9 @@ public	class	JDBCDriverTest	extends	Comp
      * Test case for DERBY-4888. Check that we can call DatabaseMetaData
      * methods returning a boolean without errors.
      */
-    private void derby_4888_test(Connection conn) throws SQLException {
+    public void testDerby4888() throws SQLException {
         // Used to get a ClassCastException here in some combinations.
-        assertFalse(conn.getMetaData().storesLowerCaseIdentifiers());
+        assertFalse(getConnection().getMetaData().storesLowerCaseIdentifiers());
     }
 
     /**
@@ -398,58 +413,53 @@ public	class	JDBCDriverTest	extends	Comp
      * works across different versions. Used to fail with a ClassCastException
      * when talking to servers at version 10.7 and earlier.
      */
-    private void derby_5449_test(Connection conn) throws SQLException {
-        if (usingDerbyClient() &&
-                getServerVersion().compareTo(DRB_10_7) <= 0) {
+    public void testDerby5449() throws SQLException {
+        if (getServerVersion().compareTo(DerbyVersion._10_7) <= 0) {
             // Derby's client drivers on the 10.8 branch up to 10.8.2.2
             // suffered from DERBY-5449 and the test case will fail when
             // talking to older servers. Skip the test case in such cases.
-            String driverVersion = conn.getMetaData().getDriverVersion();
+            String driverVersion =
+                    getConnection().getMetaData().getDriverVersion();
             if (DERBY_5449_PATTERN.matcher(driverVersion).matches()) {
                 return;
             }
         }
 
-        PreparedStatement ps = prepare(conn, "VALUES CAST(? AS INTEGER)");
+        PreparedStatement ps = prepareStatement("VALUES CAST(? AS INTEGER)");
         ps.setBoolean(1, true);
         JDBC.assertSingleValueResultSet(ps.executeQuery(), "1");
         ps.setBoolean(1, false);
         JDBC.assertSingleValueResultSet(ps.executeQuery(), "0");
     }
 
-	/////////////////////////////////////////////////////////////
+    /////////////////////////////////////////////////////////////
+    //
+    //    TEST UDTs
     //
-	//	TEST UDTs
-	//
-	/////////////////////////////////////////////////////////////
-
-	//
-	// Verify the metadata for user defined types.
-	//
-	private	void	udtTest( Connection conn )
-		throws Exception
-	{
+    /////////////////////////////////////////////////////////////
+
+    /**
+     * Verify the metadata for user defined types.
+     */
+    public void testUDT() throws Exception
+    {
         //
         // We must expect the wrong metadata in a network configuration
         // unless both the client and the server are at 10.6 or higher.
         // See DERBY-4491.
         //
         boolean correctBehavior =
-            usingEmbeddedClient() ||
-            (
-             getServerVersion().atLeast( DRB_10_6 ) &&
-             getDriverVersion().atLeast( DRB_10_6 )
-             );
+             getServerVersion().atLeast( DerbyVersion._10_6 ) &&
+             getDriverVersion().atLeast( DerbyVersion._10_6 );
 
         String query = "select aliasinfo from sys.sysaliases";
-        
+
         if ( correctBehavior )
         {
             String aliasInfoClassName = "org.apache.derby.catalog.AliasInfo";
-            
+
             checkRSMD
                 (
-                 conn,
                  query,
                  aliasInfoClassName,
                  15,
@@ -463,7 +473,6 @@ public	class	JDBCDriverTest	extends	Comp
         {
             checkRSMD
                 (
-                 conn,
                  query,
                  "byte[]",
                  65400,
@@ -478,7 +487,7 @@ public	class	JDBCDriverTest	extends	Comp
         if ( serverSupportsUDTs() )
         {
             query = "select a from t_price";
-            PreparedStatement ps = conn.prepareStatement( query );
+            PreparedStatement ps = prepareStatement( query );
             ResultSet rs = ps.executeQuery();
             rs.next();
             Object price = rs.getObject( 1 );
@@ -491,7 +500,6 @@ public	class	JDBCDriverTest	extends	Comp
                 String priceClassName = "org.apache.derbyTesting.functionTests.tests.lang.Price";
                 checkRSMD
                     (
-                     conn,
                      query,
                      priceClassName,
                      15,
@@ -507,7 +515,6 @@ public	class	JDBCDriverTest	extends	Comp
             {
                 checkRSMD
                     (
-                     conn,
                      query,
                      "byte[]",
                      65400,
@@ -516,17 +523,16 @@ public	class	JDBCDriverTest	extends	Comp
                      32700,
                      0
                      );
-                
+
                 assertEquals( "java.lang.String", actualClassName );
             }
 
             query = "insert into t_price( a ) values ( ? )";
-            
+
             if ( correctBehavior )
             {
                 checkPMD
                     (
-                     conn,
                      query,
                      "org.apache.derbyTesting.functionTests.tests.lang.Price",
                      java.sql.Types.JAVA_OBJECT,
@@ -539,7 +545,6 @@ public	class	JDBCDriverTest	extends	Comp
             {
                 checkPMD
                     (
-                     conn,
                      query,
                      "byte[]",
                      java.sql.Types.LONGVARBINARY,
@@ -553,19 +558,23 @@ public	class	JDBCDriverTest	extends	Comp
             // Should only be able to stuff an object into the column if both
             // the client and server are at 10.6 or higher.
             //
-            ps = conn.prepareStatement( query );
+            ps = prepareStatement( query );
             byte[] someBytes = new byte[] { (byte) 1, (byte) 2, (byte) 3 };
             ByteArrayInputStream bais = new ByteArrayInputStream( someBytes );
-            
+
             try {
                 ps.setObject( 1, org.apache.derbyTesting.functionTests.tests.lang.Price.makePrice() );
                 ps.executeUpdate();
 
-                if ( !correctBehavior ) { fail( "setObject( Price ) unexpectedly worked." ); }
+                if ( !correctBehavior ) {
+                    fail( "setObject( Price ) unexpectedly worked." );
+                }
             }
             catch (SQLException se)
             {
-                if ( correctBehavior ) { fail( "setObject( Price ) unexpectedly failed." ); }
+                if ( correctBehavior ) {
+                    fail( "setObject( Price ) unexpectedly failed." );
+                }
             }
             try {
                 ps.setObject( 1, someBytes );
@@ -592,13 +601,12 @@ public	class	JDBCDriverTest	extends	Comp
             ps.close();
         }
     }
-    
+
     /**
      * Check the ResultSetMetaData for a query whose first column is a UDT.
      */
     private void checkRSMD
         (
-         Connection conn,
          String query,
          String expectedClassName,
          int expectedDisplaySize,
@@ -606,9 +614,9 @@ public	class	JDBCDriverTest	extends	Comp
          String expectedSQLTypeName,
          int expectedPrecision,
          int expectedScale
-         ) throws Exception
+         ) throws SQLException
     {
-        PreparedStatement ps = conn.prepareStatement( query );
+        PreparedStatement ps = prepareStatement( query );
         ResultSet rs = ps.executeQuery();
         ResultSetMetaData rsmd = rs.getMetaData();
 
@@ -622,22 +630,21 @@ public	class	JDBCDriverTest	extends	Comp
         rs.close();
         ps.close();
     }
-    
+
     /**
      * Check the ParameterMetaData for a statement whose first parameter is a UDT.
      */
     private void checkPMD
         (
-         Connection conn,
          String query,
          String expectedClassName,
          int expectedJDBCType,
          String expectedSQLTypeName,
          int expectedPrecision,
          int expectedScale
-         ) throws Exception
+         ) throws SQLException
     {
-        PreparedStatement ps = conn.prepareStatement( query );
+        PreparedStatement ps = prepareStatement( query );
         ParameterMetaData pmd = ps.getParameterMetaData();
 
         assertEquals( pmd.getParameterClassName( 1 ), expectedClassName );
@@ -649,222 +656,220 @@ public	class	JDBCDriverTest	extends	Comp
         ps.close();
     }
 
-	/////////////////////////////////////////////////////////////
-	//
-	//	TEST DATATYPES
-	//
-	/////////////////////////////////////////////////////////////
-
-	//
-	// Test that we can declare, insert, and select all datatypes that
-	// are legal on the server. Test the metadata for these datatypes.
-	//
-	private	void	datatypesTest( Connection conn )
-		throws Exception
-	{
-		TypeDescriptor[]	types = ALL_TYPES;
-		String				tableName = ALL_TYPES_TABLE;
-		Object[][]			rows = new Object[][] { makeNullRow( types.length ), ROW_1 };
-		
-		checkDBMetadata( conn, tableName );
-		stuffTable( conn, tableName, types, rows );
-		readTable( conn, tableName, types, rows, null );
-	}
-	
-	//
-	// Verify that we get the correct DatabaseMetaData for a table.
-	//
-	private	void	checkDBMetadata( Connection conn, String tableName )
-		throws Exception
-	{
-		String				normalizedSchema = DEFAULT_USER_NAME.toUpperCase();
-		String				normalizedTable = tableName.toUpperCase();
-		DatabaseMetaData	dbmd = conn.getMetaData();
-
-		ResultSet			rs = dbmd.getColumns
-			( null, normalizedSchema, normalizedTable, "%" );
-
-		println( "Pawing through database metadata for " + normalizedSchema + '.' + normalizedTable );
-
-		while( rs.next() )
-		{
-			String			columnName = rs.getString( "COLUMN_NAME" );
-			int				actualJdbcType = rs.getInt( "DATA_TYPE" );
-			TypeDescriptor	typeDesc = getType( columnName );
-
-			if ( columnName.equals( KEY_COLUMN ) ) { continue; }
-
-			StringBuffer	buffer = new StringBuffer();
-
-			buffer.append( "[ " );
-			buffer.append( rs.getString( "COLUMN_NAME" ) );
-			buffer.append( ",\t" );
-			buffer.append( "type( " + rs.getInt( "DATA_TYPE" ) + " ),\t" );
-			buffer.append( rs.getString( "TYPE_NAME" ) );
-			buffer.append( " ]" );
-
-			println( buffer.toString() );
-			
-			assertEquals( columnName, typeDesc.getJdbcType(), actualJdbcType );
-		}
-
-		close( rs );
-	}
-
-	//
-	// Stuff a table with rows
-	//
-	private	void	stuffTable
-		( Connection conn, String tableName, TypeDescriptor[] types, Object[][] rows )
-		throws Exception
-	{
-		PreparedStatement	ps = makeInsert( conn, tableName, types );
-		int					rowCount = rows.length;
-
-		for ( int i = 0; i < rowCount; i++ )
-		{
-			setRow( ps, i + 1, types, rows[ i ] );
-		}
-		
-		close( ps );
-	}
-
-	private	PreparedStatement	makeInsert
-		( Connection conn, String tableName, TypeDescriptor[] types )
-		throws Exception
-	{
-		StringBuffer	masterBuffer = new StringBuffer();
-		StringBuffer	columnBuffer = new StringBuffer();
-		StringBuffer	valuesBuffer = new StringBuffer();
-		int				columnNumber = 0;
-		int				valuesNumber = 0;
-		int				typeCount = types.length;
-
-		beginColumnList( columnBuffer );
-		beginColumnList( valuesBuffer );
-
-		addColumn( columnBuffer, columnNumber++, doubleQuote( KEY_COLUMN ) );
-		addColumn( valuesBuffer, valuesNumber++, "?" );
-		
-		for ( int i = 0; i < typeCount; i++ )
-		{
-			TypeDescriptor	type = types[ i ];
-			
-			if ( getServerVersion().atLeast( type.getDerbyVersion() ) )
-			{
-				String	typeName = type.getDerbyTypeName();
-				String	columnDesc = doubleQuote( typeName );
-				
-				addColumn( columnBuffer, columnNumber++, columnDesc );
-				addColumn( valuesBuffer, valuesNumber++, "?" );
-			}
-		}
-
-		endColumnList( columnBuffer );
-		endColumnList( valuesBuffer );
-
-		masterBuffer.append( "insert into " + tableName + "\n" );
-		masterBuffer.append( columnBuffer.toString() );
-		masterBuffer.append( "values\n" );
-		masterBuffer.append( valuesBuffer.toString() );
-
-		PreparedStatement	ps = prepare( conn, masterBuffer.toString() );
-
-		return ps;
-	}
-
-	//
-	// Verify that we can select all legal datatypes in a table.
-	//
-	private	void	readTable
-		( Connection conn, String tableName, TypeDescriptor[] types, Object[][] rows, List casts )
-		throws Exception
-	{
-		PreparedStatement	ps = readTableQuery( conn, tableName, types );
-		ResultSet			rs = ps.executeQuery();
+    /////////////////////////////////////////////////////////////
+    //
+    //    TEST DATATYPES
+    //
+    /////////////////////////////////////////////////////////////
+
+    //
+    // Test that we can declare, insert, and select all datatypes that
+    // are legal on the server. Test the metadata for these datatypes.
+    //
+    private void datatypesTest()
+            throws SQLException {
+        TypeDescriptor[]    types = ALL_TYPES;
+        String                tableName = ALL_TYPES_TABLE;
+        Object[][]            rows = new Object[][] { makeNullRow( types.length ), ROW_1 };
+
+        checkDBMetadata(tableName);
+        stuffTable(tableName, types, rows);
+        readTable(tableName, types, rows, null);
+    }
 
-		checkRSMD( rs );
-		close( rs );
+    //
+    // Verify that we get the correct DatabaseMetaData for a table.
+    //
+    private void checkDBMetadata(String tableName)
+        throws SQLException {
+        String defaultUser = TestConfiguration.getCurrent().getUserName();
+        String                normalizedSchema = defaultUser.toUpperCase();
+        String                normalizedTable = tableName.toUpperCase();
+        DatabaseMetaData    dbmd = getConnection().getMetaData();
+
+        ResultSet            rs = dbmd.getColumns
+            ( null, normalizedSchema, normalizedTable, "%" );
+
+        println( "Pawing through database metadata for " + normalizedSchema + '.' + normalizedTable );
+
+        while( rs.next() )
+        {
+            String            columnName = rs.getString( "COLUMN_NAME" );
+            int                actualJdbcType = rs.getInt( "DATA_TYPE" );
+            TypeDescriptor    typeDesc = getType( columnName );
+
+            if ( columnName.equals( KEY_COLUMN ) ) { continue; }
+
+            StringBuilder builder = new StringBuilder();
+
+            builder.append( "[ " ).
+                   append( rs.getString( "COLUMN_NAME" ) ).
+                   append( ",\t" ).
+                   append( "type( " ).
+                   append(rs.getInt( "DATA_TYPE" )).
+                   append( " ),\t" ).
+                   append( rs.getString( "TYPE_NAME" ) ).
+                   append( " ]" );
+
+            println( builder.toString() );
+
+            assertEquals( columnName, typeDesc.getJdbcType(), actualJdbcType );
+        }
+
+        rs.close();
+    }
+
+    //
+    // Stuff a table with rows
+    //
+    private void stuffTable(String tableName, TypeDescriptor[] types,
+                            Object[][] rows)
+            throws SQLException {
+        PreparedStatement    ps = makeInsert(tableName, types);
+        int                    rowCount = rows.length;
+
+        for ( int i = 0; i < rowCount; i++ )
+        {
+            setRow( ps, i + 1, types, rows[ i ] );
+        }
+
+        ps.close();
+    }
+
+    private    PreparedStatement    makeInsert(String tableName,
+                                           TypeDescriptor[] types )
+            throws SQLException {
+        StringBuilder      masterBuilder = new StringBuilder();
+        StringBuilder      columnBuilder = new StringBuilder();
+        StringBuilder      valuesBuilder = new StringBuilder();
+        int                columnNumber = 0;
+        int                valuesNumber = 0;
+        int                typeCount = types.length;
+
+        beginColumnList( columnBuilder );
+        beginColumnList( valuesBuilder );
+
+        addColumn( columnBuilder, columnNumber++, doubleQuote( KEY_COLUMN ) );
+        addColumn( valuesBuilder, valuesNumber++, "?" );
+
+        for ( int i = 0; i < typeCount; i++ )
+        {
+            TypeDescriptor    type = types[ i ];
+
+            if ( getServerVersion().atLeast( type.getDerbyVersion() ) )
+            {
+                String    typeName = type.getDerbyTypeName();
+                String    columnDesc = doubleQuote( typeName );
+
+                addColumn( columnBuilder, columnNumber++, columnDesc );
+                addColumn( valuesBuilder, valuesNumber++, "?" );
+            }
+        }
+
+        endColumnList( columnBuilder );
+        endColumnList( valuesBuilder );
+
+        masterBuilder.append( "insert into " ).
+                     append( tableName ).
+                     append( "\n" ).
+                     append( columnBuilder.toString() ).
+                     append( "values\n" ).
+                     append( valuesBuilder.toString() );
+
+        return prepareStatement(masterBuilder.toString());
+    }
+
+    //
+    // Verify that we can select all legal datatypes in a table.
+    //
+    private void readTable(String tableName, TypeDescriptor[] types,
+                           Object[][] rows, List casts )
+            throws SQLException {
+        PreparedStatement    ps = readTableQuery(tableName, types);
+        ResultSet            rs = ps.executeQuery();
+
+        checkRSMD( rs );
+        rs.close();
         // Execute the statement again for each cast / coercion we check.
         checkRows( ps, types, rows, casts );
 
-		close( ps );
-	}
+        ps.close();
+    }
+
+    //
+    // Make the select query
+    //
+    private PreparedStatement readTableQuery(String tableName,
+                                             TypeDescriptor[] types)
+            throws SQLException {
+        StringBuilder    builder = new StringBuilder();
+        int                columnNumber = 0;
+        int                typeCount = types.length;
+
+        builder.append( "select \n" );
+
+        addColumn( builder, columnNumber++, doubleQuote( KEY_COLUMN ) );
+
+        for ( int i = 0; i < typeCount; i++ )
+        {
+            TypeDescriptor    type = types[ i ];
+
+            if ( getServerVersion().atLeast( type.getDerbyVersion() ) )
+            {
+                String    typeName = type.getDerbyTypeName();
+                String    columnDesc = doubleQuote( typeName );
+
+                addColumn( builder, columnNumber++, columnDesc );
+            }
+        }
+
+        builder.append( "\nfrom " ).
+               append( tableName ).
+               append( "\n" ).
+               append( "order by " ).
+               append(doubleQuote( KEY_COLUMN ) );
+
+        return prepareStatement(builder.toString());
+    }
+
+    //
+    // Verify that we get the correct ResultSetMetaData for all datatypes
+    // which are legal on the server.
+    //
+    private    void    checkRSMD( ResultSet rs )
+        throws SQLException
+    {
+        ResultSetMetaData    rsmd = rs.getMetaData();
+        int                    columnCount = rsmd.getColumnCount();
+        int                    firstTastyColumn = 0;
+
+        println( "ResultSetMetaData:\n" );
+
+        firstTastyColumn++;                // skip uninteresting key column
 
-	//
-	// Make the select query
-	//
-	private	PreparedStatement	readTableQuery
-		( Connection conn, String tableName, TypeDescriptor[] types )
-		throws Exception
-	{
-		StringBuffer	buffer = new StringBuffer();
-		int				columnNumber = 0;
-		int				typeCount = types.length;
-
-		buffer.append( "select \n" );
-
-		addColumn( buffer, columnNumber++, doubleQuote( KEY_COLUMN ) );
-		
-		for ( int i = 0; i < typeCount; i++ )
-		{
-			TypeDescriptor	type = types[ i ];
-			
-			if ( getServerVersion().atLeast( type.getDerbyVersion() ) )
-			{
-				String	typeName = type.getDerbyTypeName();
-				String	columnDesc = doubleQuote( typeName );
-				
-				addColumn( buffer, columnNumber++, columnDesc );
-			}
-		}
-
-		buffer.append( "\nfrom " + tableName + "\n" );
-		buffer.append( "order by " + doubleQuote( KEY_COLUMN ) );
-
-		PreparedStatement	ps = prepare( conn, buffer.toString() );
-
-		return ps;
-	}
-	
-	//
-	// Verify that we get the correct ResultSetMetaData for all datatypes
-	// which are legal on the server.
-	//
-	private	void	checkRSMD( ResultSet rs )
-		throws Exception
-	{
-		ResultSetMetaData	rsmd = rs.getMetaData();
-		int					columnCount = rsmd.getColumnCount();
-		int					firstTastyColumn = 0;
-
-		println( "ResultSetMetaData:\n" );
-		
-		firstTastyColumn++;				// skip uninteresting key column
-
-		for ( int i = firstTastyColumn; i < columnCount; i++ )
-		{
-			StringBuffer		buffer = new StringBuffer();
-			int				columnID = i + 1;
-			String			columnName = rsmd.getColumnName( columnID );
-			TypeDescriptor	typeDesc = getType( columnName );
-			int				expectedType = rsmdTypeKludge( typeDesc.getJdbcType() );
-			int				actualType = rsmd.getColumnType( columnID );
-
-			buffer.append( "[ " );
-			buffer.append( columnName );
-			buffer.append( ", type( " );
-			buffer.append( actualType );
-			buffer.append( " ), " );
-			buffer.append( rsmd.getColumnTypeName( columnID ) );
-			buffer.append( " ]\n" );
-			
-			println( buffer.toString() );
+        for ( int i = firstTastyColumn; i < columnCount; i++ )
+        {
+            StringBuilder        builder = new StringBuilder();
+            int                columnID = i + 1;
+            String            columnName = rsmd.getColumnName( columnID );
+            TypeDescriptor    typeDesc = getType( columnName );
+            int                expectedType = rsmdTypeKludge( typeDesc.getJdbcType() );
+            int                actualType = rsmd.getColumnType( columnID );
+
+            builder.append( "[ " );
+            builder.append( columnName );
+            builder.append( ", type( " );
+            builder.append( actualType );
+            builder.append( " ), " );
+            builder.append( rsmd.getColumnTypeName( columnID ) );
+            builder.append( " ]\n" );
 
-			assertEquals( columnName, expectedType, actualType );
-		}
+            println( builder.toString() );
 
-	}
+            assertEquals( columnName, expectedType, actualType );
+        }
+
+    }
 
     /**
      * Verify that we select the values we originally inserted into a table,
@@ -880,7 +885,7 @@ public	class	JDBCDriverTest	extends	Comp
      */
     private void checkRows(PreparedStatement ps, TypeDescriptor[] types,
                            Object[][] rows, List casts)
-            throws Exception {
+            throws SQLException {
         int typeCount = types.length;
 
         // Iterate over all the types we have defined.
@@ -913,7 +918,7 @@ public	class	JDBCDriverTest	extends	Comp
      */
     private void checkPlainGet(PreparedStatement ps, int columnIndex,
                                TypeDescriptor type, Object[][] rows)
-            throws Exception {
+            throws SQLException {
         String columnName = type.getDerbyTypeName();
         ResultSet rs = ps.executeQuery();
         for (int rowId=0; rowId < rows.length; rowId++) {
@@ -939,7 +944,7 @@ public	class	JDBCDriverTest	extends	Comp
      */
     private void checkCoercions(PreparedStatement ps, TypeDescriptor type,
                                 List casts)
-            throws Exception {
+            throws SQLException {
         String columnName = type.getDerbyTypeName();
         T_CN coercionDesc = COERCIONS[ getCoercionIndex(type.getJdbcType()) ];
         boolean[] coercions = coercionDesc.getCoercions();
@@ -977,209 +982,200 @@ public	class	JDBCDriverTest	extends	Comp
             if (objval == null) {
                 println("\tgetObject() = null");
             } else {
-                StringBuffer buffer = new StringBuffer();
-                buffer.append("\tgetObject() = ");
-                buffer.append(objval.getClass().getName());
-                buffer.append("( ");
-                buffer.append(objval);
-                buffer.append(" )");
-                println(buffer.toString());
+                StringBuilder builder = new StringBuilder();
+                builder.append("\tgetObject() = ");
+                builder.append(objval.getClass().getName());
+                builder.append("( ");
+                builder.append(objval);
+                builder.append(" )");
+                println(builder.toString());
             }
         }
         rs.close();
     }
 
-	//
-	// This kludge compensates for the fact that the DRDA clients report
-	// that NUMERIC columns are DECIMAL. See bug 584.
-	//
-	// In addition, booleans are handled oddly by down-rev clients.
-	//
-	private	int	rsmdTypeKludge( int originalJDbcType )
-	{
-		// The embedded client does the right thing.
-		if ( usingEmbeddedClient() ) { return originalJDbcType; }
-		
-		switch( originalJDbcType )
-		{
-			//This kludge compensates for the fact that the DRDA clients report
-			// that NUMERIC columns are DECIMAL. See bug 584.
-			case Types.NUMERIC:
-				return Types.DECIMAL;
-
-		    default:			return originalJDbcType;
-		}
-	}
-
-	//
-	// Insert a row into the ALL_TYPES table. The row contains all datatypes
-	// that are legal on the server.
-	//
-	private	void	setRow( PreparedStatement ps, int keyValue, TypeDescriptor[] types, Object[] row )
-		throws Exception
-	{
-		int				param = 1;
-		int				typeCount = types.length;
-
-		ps.setInt( param++, keyValue );
-
-		for ( int i = 0; i < typeCount; i++ )
-		{
-			TypeDescriptor	type = types[ i ];
-			Object			value = row[ i ];
-			
-			if ( getServerVersion().atLeast( type.getDerbyVersion() ) )
-			{
-				setParameter( ps, param++, type, value );
-			}
-		}
-
-		ps.execute();
-	}
-
-	private	Object[]	makeNullRow( int rowLength )
-	{
-		return new Object[ rowLength ];
-	}
-
-	//
-	// Index the TypeDescriptors by Derby type name.
-	//
-	private	void	buildTypeMap()
-	{
-		int				typeCount = ALL_TYPES.length;
-
-		for ( int i = 0; i < typeCount; i++ ) { putType( ALL_TYPES[ i ] ); }
-	}
-	private	void	putType( TypeDescriptor type )
-	{
-		_types.put( type.getDerbyTypeName(), type );
-	}
-
-	//
-	// Lookup TypeDescriptors by Derby type name.
-	//
-	private	TypeDescriptor	getType( String typeName )
-	{
-		if ( _types.size() == 0 ) { buildTypeMap(); }
-		
-		return (TypeDescriptor) _types.get( typeName );
-	}
-
-	//
-	// Index legal coercions by jdbc type.
-	//
-	private	void	buildCoercionMap()
-	{
-		int				count = COERCIONS.length;
-
-		for ( int i = 0; i < count; i++ ) { putCoercionIndex( i ); }
-	}
-	private	void	putCoercionIndex( int index )
-	{
-		_coercionIndex.put( new Integer( COERCIONS[ index ].getJdbcType() ), new Integer( index ) );
-	}
-
-	//
-	// Lookup the legal coercions for a given jdbc type.
-	//
-	private	int	getCoercionIndex( int jdbcType )
-	{
-		if ( _coercionIndex.size() == 0 ) { buildCoercionMap(); }
-		
-		return ((Integer) _coercionIndex.get( new Integer( jdbcType ) )).intValue();
-	}
-	
-	/////////////////////////////////////////////////////////////
-	//
-	//	MINIONS
-	//
-	/////////////////////////////////////////////////////////////
-	
-	///////////////////
-	//
-	//	TYPE MANAGEMENT
-	//
-	///////////////////
-	
-	//////////////////
-	//
-	//	SCHEMA MINIONS
-	//
-	//////////////////
-
-	//
-	// Create all the tables needed by our test cases.
-	//
-	private	void	createSchema( Connection conn )
-		throws Exception
-	{
-		createTable( conn, ALL_TYPES_TABLE, ALL_TYPES );
-
-        createUDTObjects( conn );
-        create_derby_2602_objects( conn );
-	}
-
-	//
-	// Create a table modelling an array of datatypes.
-	//
-	private	void	createTable( Connection conn, String tableName, TypeDescriptor[] types )
-		throws Exception
-	{
-		StringBuffer	buffer = new StringBuffer();
-		int				columnNumber = 0;
-		int				typeCount = types.length;
-
-		buffer.append( "create table " + tableName + "\n" );
-		beginColumnList( buffer );
-
-		addColumn( buffer, columnNumber++, doubleQuote( KEY_COLUMN ) + "\tint" );
-		
-		for ( int i = 0; i < typeCount; i++ )
-		{
-			TypeDescriptor	type = types[ i ];
-			
-			if ( getServerVersion().atLeast( type.getDerbyVersion() ) )
-			{
-				String	typeName = type.getDerbyTypeName();
-				String	columnDesc = doubleQuote( typeName ) + '\t' + typeName;
-				
-				addColumn( buffer, columnNumber++, columnDesc );
-			}
-		}
+    //
+    // This kludge compensates for the fact that the DRDA clients report
+    // that NUMERIC columns are DECIMAL. See bug 584.
+    //
+    // In addition, booleans are handled oddly by down-rev clients.
+    //
+    private    int    rsmdTypeKludge( int originalJDbcType )
+    {
+        // The embedded client does the right thing.
+        if ( usingEmbedded()) { return originalJDbcType; }
+
+        switch( originalJDbcType )
+        {
+            //This kludge compensates for the fact that the DRDA clients report
+            // that NUMERIC columns are DECIMAL. See bug 584.
+            case Types.NUMERIC:
+                return Types.DECIMAL;
+
+            default:            return originalJDbcType;
+        }
+    }
+
+    //
+    // Insert a row into the ALL_TYPES table. The row contains all datatypes
+    // that are legal on the server.
+    //
+    private    void    setRow( PreparedStatement ps, int keyValue, TypeDescriptor[] types, Object[] row )
+        throws SQLException
+    {
+        int                param = 1;
+        int                typeCount = types.length;
+
+        ps.setInt( param++, keyValue );
+
+        for ( int i = 0; i < typeCount; i++ )
+        {
+            TypeDescriptor    type = types[ i ];
+            Object            value = row[ i ];
+
+            if ( getServerVersion().atLeast( type.getDerbyVersion() ) )
+            {
+                setParameter( ps, param++, type, value );
+            }
+        }
+
+        ps.execute();
+    }
+
+    private    Object[]    makeNullRow( int rowLength )
+    {
+        return new Object[ rowLength ];
+    }
+
+    //
+    // Index the TypeDescriptors by Derby type name.
+    //
+    private    void    buildTypeMap()
+    {
+        int                typeCount = ALL_TYPES.length;
+
+        for ( int i = 0; i < typeCount; i++ ) { putType( ALL_TYPES[ i ] ); }
+    }
+    private    void    putType( TypeDescriptor type )
+    {
+        _types.put( type.getDerbyTypeName(), type );
+    }
+
+    //
+    // Lookup TypeDescriptors by Derby type name.
+    //
+    private    TypeDescriptor    getType( String typeName )
+    {
+        if ( _types.isEmpty() ) { buildTypeMap(); }
+
+        return (TypeDescriptor) _types.get( typeName );
+    }
+
+    //
+    // Index legal coercions by jdbc type.
+    //
+    private    void    buildCoercionMap()
+    {
+        int                count = COERCIONS.length;
+
+        for ( int i = 0; i < count; i++ ) { putCoercionIndex( i ); }
+    }
+    private    void    putCoercionIndex( int index )
+    {
+        _coercionIndex.put( new Integer( COERCIONS[ index ].getJdbcType() ), new Integer( index ) );
+    }
+
+    //
+    // Lookup the legal coercions for a given jdbc type.
+    //
+    private    int    getCoercionIndex( int jdbcType )
+    {
+        if ( _coercionIndex.isEmpty() ) { buildCoercionMap(); }
+
+        return ((Integer) _coercionIndex.get( new Integer( jdbcType ) )).intValue();
+    }
+
+    /////////////////////////////////////////////////////////////
+    //
+    //    MINIONS
+    //
+    /////////////////////////////////////////////////////////////
+
+    ///////////////////
+    //
+    //    TYPE MANAGEMENT
+    //
+    ///////////////////
+
+    //////////////////
+    //
+    //    SCHEMA MINIONS
+    //
+    //////////////////
+
+    //
+    // Create a table modelling an array of datatypes.
+    //
+    private static void createTable(Connection con, String tableName,
+                                    TypeDescriptor[] types)
+            throws SQLException {
+        StringBuilder    builder = new StringBuilder();
+        int                columnNumber = 0;
+        int                typeCount = types.length;
+
+        builder.append("create table ").append(tableName).append('\n');
+        beginColumnList( builder );
+
+        addColumn( builder, columnNumber++, doubleQuote( KEY_COLUMN ) + "\tint" );
 
-		endColumnList( buffer );
+        for ( int i = 0; i < typeCount; i++ )
+        {
+            TypeDescriptor    type = types[ i ];
+
+            if ( getServerVersion(con).atLeast( type.getDerbyVersion() ) )
+            {
+                String    typeName = type.getDerbyTypeName();
+                String    columnDesc = doubleQuote( typeName ) + '\t' + typeName;
 
-		PreparedStatement	ps = prepare( conn, buffer.toString() );
+                addColumn( builder, columnNumber++, columnDesc );
+            }
+        }
 
-		ps.execute();
+        endColumnList( builder );
 
-		close( ps );
-	}
+        PreparedStatement ps = con.prepareStatement(builder.toString());
+        ps.execute();
+        ps.close();
+    }
 
     //
     // Create an ANSI UDT and a table with that type of column--
     // if the server is at 10.6 or higher.
     //
-    private void createUDTObjects( Connection conn ) throws Exception
-    {
-        if ( !serverSupportsUDTs() ) { return; }
+    private static void createUDTObjects(Connection con)
+            throws SQLException {
+        if ( !serverSupportsUDTs(con) ) { return; }
 
         PreparedStatement ps;
 
-        ps = conn.prepareStatement( "create type price external name 'org.apache.derbyTesting.functionTests.tests.lang.Price' language java\n" );
+        ps = con.prepareStatement("create type price external name " +
+                "'org.apache.derbyTesting.functionTests.tests.lang.Price' " +
+                "language java\n");
         ps.execute();
         ps.close();
 
-        ps = conn.prepareStatement( "create function makePrice( ) returns price language java parameter style java no sql external name 'org.apache.derbyTesting.functionTests.tests.lang.Price.makePrice'\n" );
+        ps = con.prepareStatement("create function makePrice( ) returns price " +
+                "language java parameter style java no sql external name " +
+                "'org.apache.derbyTesting.functionTests.tests.lang.Price.makePrice'\n");
         ps.execute();
         ps.close();
 
-        ps = conn.prepareStatement( "create table t_price( a price )\n" );
+        ps = con.prepareStatement("create table t_price( a price )\n");
         ps.execute();
         ps.close();
 
-        ps = conn.prepareStatement( "insert into t_price( a ) values ( makePrice() )\n" );
+        ps = con.prepareStatement("insert into t_price( a ) " +
+                "values ( makePrice() )\n" );
         ps.execute();
         ps.close();
     }
@@ -1187,339 +1183,211 @@ public	class	JDBCDriverTest	extends	Comp
     //
     // Create a table with a timestamp column.
     //
-    private void create_derby_2602_objects( Connection conn ) throws Exception
-    {
-        PreparedStatement ps;
-
-        ps = conn.prepareStatement( "create table t_2602( a timestamp )\n" );
+    private static void create_derby_2602_objects(Connection con)
+            throws SQLException {
+        PreparedStatement ps = con.prepareStatement(
+                "create table t_2602( a timestamp )\n");
         ps.execute();
         ps.close();
     }
 
 
-	//
-	// Helper methods for declaring a table.
-	//
-	private	void	beginColumnList( StringBuffer buffer )
-	{
-		buffer.append( "(\n" );
-	}
-	private	void	endColumnList( StringBuffer buffer )
-	{
-		buffer.append( "\n)\n" );
-	}
-	private	void	addColumn( StringBuffer buffer, int columnNumber, String text  )
-	{
-		if ( columnNumber > 0 ) { buffer.append( "," ); }
-
-		buffer.append( "\n\t" );
-		buffer.append( text );
-	}
-	
-	//
-	// Drop the tables used by our test cases.
-	//
-	private	void	dropSchema( Connection conn )
-	{
-		dropTable( conn, ALL_TYPES_TABLE );
-        dropUDTObjects( conn );
-        drop_derby_2602_objects( conn );
-	}
+    //
+    // Helper methods for declaring a table.
+    //
+    private static void beginColumnList( StringBuilder builder )
+    {
+        builder.append( "(\n" );
+    }
+
+    private static void endColumnList( StringBuilder builder )
+    {
+        builder.append( "\n)\n" );
+    }
+
+    private static void addColumn( StringBuilder builder, int columnNumber, String text  )
+    {
+        if ( columnNumber > 0 ) { builder.append( "," ); }
+
+        builder.append( "\n\t" );
+        builder.append( text );
+    }
+
+    //
+    // Drop the tables used by our test cases.
+    //
+    private void dropSchema()
+            throws SQLException {
+        dropTable(ALL_TYPES_TABLE);
+        dropUDTObjects();
+        drop_derby_2602_objects();
+    }
 
     //
     // Drop objects needed by UDT tests. We only do this if the server
     // is at 10.6 or higher.
     //
-    private void dropUDTObjects( Connection conn )
+    private void dropUDTObjects()
+            throws SQLException {
+        if (serverSupportsUDTs()) {
+            dropFunction("MAKEPRICE");
+            dropTable("T_PRICE");
+            dropUDT("PRICE");
+        }
+    }
+
+    //
+    // Drop objects needed by DERBY-2602 tests.
+    //
+    private void drop_derby_2602_objects()
+            throws SQLException {
+        dropTable("T_2602");
+    }
+
+    //
+    // Logic for stuffing a data value into a column, given its type.
+    //
+    private    void    setParameter( PreparedStatement ps, int param, TypeDescriptor type, Object value )
+        throws SQLException
     {
-        if ( !serverSupportsUDTs() ) { return; }
+        int        jdbcType = type.getJdbcType();
 
-        dropFunction( conn, "MAKEPRICE" );
-        dropTable( conn, "T_PRICE" );
-        dropUDT( conn, "PRICE" );
+        if ( value != null )
+        {
+            setParameter( ps, param, jdbcType, value );
+            return;
+        }
+        else if ( clientSupports( type ) )
+        {
+            ps.setNull( param, jdbcType );
+
+            return;
+        }
+
+        // client does not support nulls of this type.
+
+        fail( "Unsupported Derby type: " + type.getDerbyTypeName() );
+    }
+
+    // return true if the client supports this datatype
+    private    boolean    clientSupports( TypeDescriptor type )
+            throws SQLException {
+        DerbyVersion firstSupportedVersion = type.getDerbyVersion();
+
+        if ( firstSupportedVersion == null ) { return false; }
+        else { return getDriverVersion().atLeast( firstSupportedVersion ); }
     }
 
     //
-    // Drop objects needed by DERBY-2602 tests.
+    // Get a data value from a column, given its type.
+    //
+    private    Object    getColumn( ResultSet rs, String columnName, TypeDescriptor type )
+        throws SQLException
+    {
+        int            jdbcType = type.getJdbcType();
+
+        return getColumn( rs, columnName, jdbcType );
+    }
+
+    //
+    // SQL code generation minions
+    //
+    private static String doubleQuote( String text )
+    {
+        return '"' + text + '"';
+    }
+
+    /////////////////////////////////////////////////////////////
     //
-    private void drop_derby_2602_objects( Connection conn )
+    //    INNER CLASSES
+    //
+    /////////////////////////////////////////////////////////////
+
+    /**
+     * Description of a legal datatype and the version of Derby
+     * where the datatype first appears.
+     */
+    public    static    final    class    TypeDescriptor
     {
-        dropTable( conn, "T_2602" );
+        private int          _jdbcType;
+        private String       _derbyTypeName;
+        /** The first Derby version which supports this type. */
+        private DerbyVersion _derbyVersion;
+
+        public    TypeDescriptor (
+            int          jdbcType,
+            String       derbyTypeName,
+            DerbyVersion derbyVersion
+        )
+        {
+            _jdbcType = jdbcType;
+            _derbyTypeName = derbyTypeName;
+            _derbyVersion = derbyVersion;
+        }
+
+        public int        getJdbcType()               { return _jdbcType; }
+        public String    getDerbyTypeName()           { return _derbyTypeName; }
+        public DerbyVersion    getDerbyVersion()      { return _derbyVersion; }
     }
 
-	//
-	// Logic for stuffing a data value into a column, given its type.
-	//
-	private	void	setParameter( PreparedStatement ps, int param, TypeDescriptor type, Object value )
-		throws Exception
-	{
-		int		jdbcType = type.getJdbcType();
-
-		if ( value != null )
-		{
-			setParameter( ps, param, jdbcType, value );
-			return;
-		}
-		else if ( clientSupports( type ) )
-		{
-			ps.setNull( param, jdbcType );
-
-			return;
-		}
-
-		// client does not support nulls of this type.
-
-		fail( "Unsupported Derby type: " + type.getDerbyTypeName() );
-	}
-
-	// return true if the client supports this datatype
-	private	boolean	clientSupports( TypeDescriptor type )
-	{
-		Version firstSupportedVersion = type.getDerbyVersion();
-
-		if ( firstSupportedVersion == null ) { return false; }
-		else { return getDriverVersion().atLeast( firstSupportedVersion ); }
-	}
-	
-	//
-	// Get a data value from a column, given its type.
-	//
-	private	Object	getColumn( ResultSet rs, String columnName, TypeDescriptor type )
-		throws Exception
-	{
-		int			jdbcType = type.getJdbcType();
-
-		return getColumn( rs, columnName, jdbcType );
-	}
-
-	//
-	// SQL code generation minions 
-	//
-	private	String	doubleQuote( String text )
-	{
-		return '"' + text + '"';
-	}
-
-	/////////////////////////////////////////////////////////////
-	//
-	//	INNER CLASSES
-	//
-	/////////////////////////////////////////////////////////////
-
-	/**
-	 * <p>
-	 * This helper class describes a legal datatype and the version of Derby
-	 * where the datatype first appears.
-	 * </p>
-	 */
-	public	static	final	class	TypeDescriptor
-	{
-		private	int		_jdbcType;
-		private	String	_derbyTypeName;
-		private	Version	_derbyVersion;		// first derby version which supports this type
-
-		public	TypeDescriptor
-		(
-		    int		jdbcType,
-			String	derbyTypeName,
-			Version	derbyVersion
-		)
-		{
-			_jdbcType = jdbcType;
-			_derbyTypeName = derbyTypeName;
-			_derbyVersion = derbyVersion;
-		}
-
-		public	int		getJdbcType() 					{ return _jdbcType; }
-		public	String	getDerbyTypeName()				{ return _derbyTypeName; }
-		public	Version	getDerbyVersion()				{ return _derbyVersion; }
-	}
-
-	/**
-	 * <p>
-	 * This helper class captures TypeCoercion logic. I have abbreviated it to
-	 * this ugly class name so that the COERCIONS table will fit on a readable screen.
-	 * </p>
-	 */
-	public	static	final	class	T_CN
-	{
-		private	int			_jdbcType;
-		private	boolean[]	_coercions;
-
-		public	T_CN( int jdbcType, boolean[] coercions )
-		{
-			_jdbcType = jdbcType;
-			_coercions = coercions;
-		}
-
-		public	int			getJdbcType() 					{ return _jdbcType; }
-		public	boolean[]	getCoercions() 					{ return _coercions; }
-	}
-	
-	/**
-	 * <p>
-	 * A crude Blob implementation for datatype testing.
-	 * </p>
-	 */
-	public	static	final	class	MyBlob	implements	Blob
-	{
-		private	byte[]	_bytes;
-
-		public	MyBlob( byte[] bytes )
-		{
-			_bytes = bytes;
-		}
-
-		public	InputStream	getBinaryStream()
-		{
-			return new ByteArrayInputStream( _bytes );
-		}
-
-		public	byte[]	getBytes( long position, int length ) { return _bytes; }
-
-		public	long	length() { return (long) _bytes.length; }
-
-		public	long	position( Blob pattern, long start ) { return 0L; }
-		public	long	position( byte[] pattern, long start ) { return 0L; }
-
-		public	boolean	equals( Object other )
-		{
-			if ( other == null ) { return false; }
-			if ( !( other instanceof Blob ) ) { return false; }
-
-			Blob	that = (Blob) other;
-
-			try {
-				if ( this.length() != that.length() ) { return false; }
-
-				InputStream	thisStream = this.getBinaryStream();
-				InputStream	thatStream = that.getBinaryStream();
-
-				while( true )
-				{
-					int		nextByte = thisStream.read();
-
-					if ( nextByte < 0 ) { break; }
-					if ( nextByte != thatStream.read() ) { return false; }
-				}
-			}
-			catch (Exception e)
-			{
-				System.err.println( e.getMessage() );
-				e.printStackTrace();
-				return false;
-			}
-
-			return true;
-		}
-
-        public int setBytes(long arg0, byte[] arg1) throws SQLException {
-            throw new SQLException("not implemented for this test");
-        }
-
-        public int setBytes(long arg0, byte[] arg1, int arg2, int arg3) throws SQLException {
-            throw new SQLException("not implemented for this test");
-        }
-
-        public OutputStream setBinaryStream(long arg0) throws SQLException {
-            throw new SQLException("not implemented for this test");
-        }
-
-        public void truncate(long arg0) throws SQLException {
-            throw new SQLException("not implemented for this test");
-        }
-
-	}
-
-	/**
-	 * <p>
-	 * A crude Clob implementation for datatype testing.
-	 * </p>
-	 */
-	public	static	final	class	MyClob	implements	Clob
-	{
-		private	String	_contents;
-
-		public	MyClob( String contents )
-		{
-			_contents = contents;
-		}
-
-		public	InputStream	getAsciiStream()
-		{
-			try {
-				return new ByteArrayInputStream( _contents.getBytes( "UTF-8" ) );
-			}
-			catch (Exception e) { return null; }
-		}
-
-		public	Reader	getCharacterStream()
-		{
-			return new CharArrayReader( _contents.toCharArray() );
-		}
-
-		public	String	getSubString( long position, int length )
-		{
-			return _contents.substring( (int) position, length );
-		}
-		
-		public	long	length() { return (long) _contents.length(); }
-
-		public	long	position( Clob searchstr, long start ) { return 0L; }
-		public	long	position( String searchstr, long start ) { return 0L; }
-
-		public	boolean	equals( Object other )
-		{
-			if ( other == null ) { return false; }
-			if ( !( other instanceof Clob ) ) { return false; }
-
-			Clob	that = (Clob) other;
-
-			try {
-				if ( this.length() != that.length() ) { return false; }
-			
-				InputStream	thisStream = this.getAsciiStream();
-				InputStream	thatStream = that.getAsciiStream();
-
-				while( true )
-				{
-					int		nextByte = thisStream.read();
-
-					if ( nextByte < 0 ) { break; }
-					if ( nextByte != thatStream.read() ) { return false; }
-				}
-			}
-			catch (Exception e)
-			{
-				System.err.println( e.getMessage() );
-				e.printStackTrace();
-				return false;
-			}
-
-			return true;
-		}
-
-        public int setString(long arg0, String arg1) throws SQLException {
-            throw new SQLException("not implemented for this test");
-        }
-
-        public int setString(long arg0, String arg1, int arg2, int arg3) throws SQLException {
-            throw new SQLException("not implemented for this test");
-        }
-
-        public OutputStream setAsciiStream(long arg0) throws SQLException {
-            throw new SQLException("not implemented for this test");
-        }
-
-        public Writer setCharacterStream(long arg0) throws SQLException {
-            throw new SQLException("not implemented for this test");
-        }
-
-        public void truncate(long arg0) throws SQLException {
-            throw new SQLException("not implemented for this test");
-            
+    /**
+     * Helper class capturing TypeCoercion logic.
+     * <p>
+     * I have abbreviated it to this ugly class name so that the COERCIONS
+     * table will fit on a readable screen.
+     */
+    public    static    final    class    T_CN
+    {
+        private    int            _jdbcType;
+        private    boolean[]    _coercions;
+
+        public    T_CN( int jdbcType, boolean[] coercions )
+        {
+            _jdbcType = jdbcType;
+            _coercions = coercions;
         }
 
-	}
+        public    int          getJdbcType()             { return _jdbcType; }
+        public    boolean[]    getCoercions()            { return _coercions; }
+    }
 
+    /**
+     * Returns a suite with all the available JDBC client driver compatibility
+     * tests.
+     * <p>
+     * JUnit boilerplate which adds as test cases all public methods
+     * whose names start with the string "test" in the named classes.
+     */
+    public static Test suite() {
+        TestSuite testSuite = new TestSuite("JDBCDriverTest suite");
+        testSuite.addTestSuite(JDBCDriverTest.class);
+        return TestConfiguration.defaultExistingServerDecorator(
+                new BaseJDBCTestSetup(testSuite) {
+
+                    protected void setUp() throws Exception {
+                        super.setUp();
+                        Connection con = getConnection();
+                        Statement s = con.createStatement();
+                        // We can't use Connection.getSchema yet.
+                        ResultSet rs = s.executeQuery("values CURRENT SCHEMA");
+                        rs.next();
+                        String schema = rs.getString(1);
+                        rs.close();
+                        s.close();
+                        con.setAutoCommit(false);
+                        // Drop the current schema to clean up. Hopefully this
+                        // is enough to start "reset" the database for each
+                        // client run (running the newest CleanDatabaseTestSetup
+                        // fails on older versions).
+                        JDBC.dropSchema(con.getMetaData(), schema);
+                        con.commit();
+
+                        // Initialize the database for the tests.
+                        con.setAutoCommit(true);
+                        createTable(con, ALL_TYPES_TABLE, ALL_TYPES);
+                        createUDTObjects(con);
+                        create_derby_2602_objects(con);
+                    }
+                });
+    }
 }