Return-Path: X-Original-To: apmail-db-derby-commits-archive@www.apache.org Delivered-To: apmail-db-derby-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id EE691DD50 for ; Thu, 28 Jun 2012 11:58:53 +0000 (UTC) Received: (qmail 45261 invoked by uid 500); 28 Jun 2012 11:58:53 -0000 Delivered-To: apmail-db-derby-commits-archive@db.apache.org Received: (qmail 45239 invoked by uid 500); 28 Jun 2012 11:58:53 -0000 Mailing-List: contact derby-commits-help@db.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: "Derby Development" List-Id: Delivered-To: mailing list derby-commits@db.apache.org Received: (qmail 45229 invoked by uid 99); 28 Jun 2012 11:58:53 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 28 Jun 2012 11:58:53 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 28 Jun 2012 11:58:43 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 34FF42388A3D; Thu, 28 Jun 2012 11:58:21 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: 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/ Date: Thu, 28 Jun 2012 11:58:19 -0000 To: derby-commits@db.apache.org From: kristwaa@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20120628115821.34FF42388A3D@eris.apache.org> 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; + /** - *

- * This JUnit test verifies the compatibility of Derby clients and - * servers across Derby version levels and supported VMs. - *

- * + * 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 - // - ///////////////////////////////////////////////////////////// - - /** - *

- * 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 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 ); } - } - - /** - *

- * Main test of jdbc drivers. - *

- */ - 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); } + /** - *

* Vet boolean results. - *

*/ - 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 - // - ///////////////////////////////////////////////////////////// - - /** - *

- * This helper class describes a legal datatype and the version of Derby - * where the datatype first appears. - *

- */ - 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; } - } - - /** - *

- * 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. - *

- */ - 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; } - } - - /** - *

- * A crude Blob implementation for datatype testing. - *

- */ - 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"); - } - - } - - /** - *

- * A crude Clob implementation for datatype testing. - *

- */ - 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. + *

+ * 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. + *

+ * 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); + } + }); + } }