/*
 *
 * Derby - Class BaseJDBCTestCase
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, 
 * software distributed under the License is distributed on an 
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
 * either express or implied. See the License for the specific 
 * language governing permissions and limitations under the License.
 */
package org.apache.derbyTesting.junit;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.PrintStream;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.net.URL;
import java.sql.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import junit.framework.AssertionFailedError;
import junit.framework.Test;

import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
import org.apache.derby.iapi.sql.execute.RunTimeStatistics;
import org.apache.derby.impl.jdbc.EmbedConnection;
import org.apache.derby.tools.ij;
import org.apache.derbyTesting.functionTests.util.TestNullOutputStream;


/**
 * Base class for JDBC JUnit tests.
 * A method for getting a default connection is provided, along with methods
 * for telling if a specific JDBC client is used.
 */
public abstract class BaseJDBCTestCase
    extends BaseTestCase {

    private static final boolean ORDERED = true;
    private static final boolean UNORDERED = false;

    /**
     * Maintain a single connection to the default
     * database, opened at the first call to getConnection.
     * Typical setup will just require a single connection.
     * @see BaseJDBCTestCase#getConnection()
     */
    private Connection conn;
    
    /**
     * Maintain a list of statement objects that
     * were returned by utility methods and close
     * them at teardown.
     */
    private List<Statement> statements;

    /**
     * Maintain a list of connection objects that
     * were returned by utility methods and close
     * them at teardown.
     */
    private List<Connection> connections;
    
    /**
     * Create a test case with the given name.
     *
     * @param name of the test case.
     */
    public BaseJDBCTestCase(String name) {
        super(name);
    }
    
    /**
     * Obtain the connection to the default database.
     * This class maintains a single connection returned
     * by this class, it is opened on the first call to
     * this method. Subsequent calls will return the same
     * connection object unless it has been closed. In that
     * case a new connection object will be returned.
     * <P>
     * The tearDown method will close the connection if
     * it is open.
     * <BR>
     * The connection will be initialized by calling initializeConnection.
     * A sub-class may provide an implementation of initializeConnection
     * to ensure its connections are in a consistent state that is different
     * to the default.
     * @see #openDefaultConnection()
     */
    public Connection getConnection() throws SQLException
    {
        if (conn != null)
        {
            if (!conn.isClosed())
                return conn;
            conn = null;
        }
        return conn = openDefaultConnection();
    }
    
    /**
     * Allow a sub-class to initialize a connection to provide
     * consistent connection state for its tests. Called once
     * for each time these method calls open a connection:
     * <UL>
     * <LI> getConnection()
     * <LI> openDefaultConnection()
     * <LI> openConnection(database)
     * <LI> getDefaultConnection(String connAttrs)
     * </UL>
     * Default action is to not modify the connection's state from
     * the initialization provided by the data source.
     * @param conn Connection to be intialized
     * @throws SQLException Error setting the initial state.
     */
    protected void initializeConnection(Connection conn) throws SQLException
    {
    }
    
    /**
     * Utility method to create a Statement using the connection
     * returned by getConnection.
     * The returned statement object will be closed automatically
     * at tearDown() but may be closed earlier by the test if required.
     * @return Statement object from getConnection.createStatement()
     * @throws SQLException
     */
    public Statement createStatement() throws SQLException
    {
        Statement s = getConnection().createStatement();
        addStatement(s);
        return s;
    }
    
    /**
     * Add a statement into the list we will close
     * at tearDown.
     */
    private void addStatement(Statement s)
    {
        if (statements == null)
            statements = new ArrayList<Statement>();
        statements.add(s);
    }
    
    /**
     * Add connection to the list. We will close at tearDown
     * @param c
     */
    private void addConnection(Connection c)
    {
        if (connections == null)
            connections = new ArrayList<Connection>();
        connections.add(c);     
    }
    
    /**
     * Close a statement and remove it from the list of statements to close
     * at tearDown(). Useful for test cases that create a large number of
     * statements that are only used for a short time, as the memory footprint
     * may become big if all the statements are held until tearDown().
     *
     * @param s the statement to close and forget
     * @throws SQLException if closing the statement fails
     */
    public void closeStatement(Statement s) throws SQLException {
        s.close();
        if (statements != null) {
            statements.remove(s);
        }
    }

    /**
     * Utility method to create a Statement using the connection
     * returned by getConnection.
     * The returned statement object will be closed automatically
     * at tearDown() but may be closed earlier by the test if required.
     * @return Statement object from
     * getConnection.createStatement(resultSetType, resultSetConcurrency)
     * @throws SQLException
     */
    public Statement createStatement(int resultSetType,
            int resultSetConcurrency) throws SQLException
    {
        Statement s =
            getConnection().createStatement(resultSetType, resultSetConcurrency);
        addStatement(s);
        return s;
    }

    /**
     * Utility method to create a Statement using the connection
     * returned by getConnection.
     * @return Statement object from
     * getConnection.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability)
     * @throws SQLException
     */
    public Statement createStatement(int resultSetType,
            			int resultSetConcurrency,
	    			int resultSetHoldability) throws SQLException
    {
        return getConnection().createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
    }

    /**
     * Utility method to create a PreparedStatement using the connection
     * returned by getConnection.
     * The returned statement object will be closed automatically
     * at tearDown() but may be closed earlier by the test if required.
     * @return Statement object from
     * getConnection.prepareStatement(sql)
     * @throws SQLException
     */
    public PreparedStatement prepareStatement(String sql) throws SQLException
    {
        PreparedStatement ps = getConnection().prepareStatement(sql);
        addStatement(ps);
        return ps;
    }
    
    /**
     * Utility method to create a PreparedStatement using the connection
     * returned by getConnection with result set type and concurrency.
     * The returned statement object will be closed automatically
     * at tearDown() but may be closed earlier by the test if required.
     * @return Statement object from
     * getConnection.prepareStatement(sql)
     * @throws SQLException
     */
    public PreparedStatement prepareStatement(String sql,
            int resultSetType, int resultSetConcurrency) throws SQLException
    {
        PreparedStatement ps = getConnection().prepareStatement(sql,
                resultSetType, resultSetConcurrency);
        addStatement(ps);
        return ps;
    }
    /**
     * Utility method to create a PreparedStatement using the connection
     * returned by getConnection with result set type and concurrency.
     * The returned statement object will be closed automatically
     * at tearDown() but may be closed earlier by the test if required.
     * @return Statement object from
     * getConnection.prepareStatement(sql)
     * @throws SQLException
     */
    public PreparedStatement prepareStatement(String sql,
            int resultSetType, int resultSetConcurrency,
            int resultSetHoldability) throws SQLException
    {
        PreparedStatement ps = getConnection().prepareStatement(sql,
                resultSetType, resultSetConcurrency, resultSetHoldability);
        addStatement(ps);
        return ps;
    }
    /**
     * Utility method to create a PreparedStatement using the connection
     * returned by getConnection and a flag that signals the driver whether
     * the auto-generated keys produced by this Statement object should be
     * made available for retrieval.
     * The returned statement object will be closed automatically
     * at tearDown() but may be closed earlier by the test if required.
     * @return Statement object from
     * prepareStatement(sql, autoGeneratedKeys)
     * @throws SQLException
     */
    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
        throws SQLException
    {
        PreparedStatement ps =
            getConnection().prepareStatement(sql, autoGeneratedKeys);
        
        addStatement(ps);
        return ps;
    }    

    /**
     * Utility method to create a PreparedStatement using the connection
     * returned by getConnection and an array of column indexes that
     * indicates which auto-generated keys produced by this Statement
     * object should be made available for retrieval.
     * The returned statement object will be closed automatically
     * at tearDown() but may be closed earlier by the test if required.
     *
     * @return Statement object from:
     *     prepareStatement(sql, columnIndexes)
     *
     * @throws SQLException
     */
    public PreparedStatement prepareStatement(String sql,
        int [] columnIndexes) throws SQLException
    {
        PreparedStatement ps =
            getConnection().prepareStatement(sql, columnIndexes);
        addStatement(ps);
        return ps;
    }

    /**
     * Utility method to create a PreparedStatement using the connection
     * returned by getConnection and an array of column names that
     * indicates which auto-generated keys produced by this Statement
     * object should be made available for retrieval.
     * The returned statement object will be closed automatically
     * at tearDown() but may be closed earlier by the test if required.
     *
     * @return Statement object from:
     *     prepareStatement(sql, columnNames)
     *
     * @throws SQLException
     */
    public PreparedStatement prepareStatement(String sql,
        String [] columnNames) throws SQLException
    {
        PreparedStatement ps =
            getConnection().prepareStatement(sql, columnNames);
        addStatement(ps);
        return ps;
     }

    /**
     * Utility method to create a CallableStatement using the connection
     * returned by getConnection.
     * The returned statement object will be closed automatically
     * at tearDown() but may be closed earlier by the test if required.
     * @return Statement object from
     * getConnection().prepareCall(sql)
     * @throws SQLException
     */
    public CallableStatement prepareCall(String sql) throws SQLException
    {
        CallableStatement cs =
            getConnection().prepareCall(sql);
        addStatement(cs);
        return cs;
 
    }

    /**
     * Utility method to create a CallableStatement using the connection
     * returned by getConnection.
     * The returned statement object will be closed automatically
     * at tearDown() but may be closed earlier by the test if required.
     * @return Statement object from
     * getConnection().prepareCall(sql, resultSetType, resultSetConcurrency)
     * @throws SQLException
     */
    public CallableStatement prepareCall(String sql,
					int resultSetType, 
					int resultSetConcurrency) throws SQLException
    {
        CallableStatement cs = getConnection().prepareCall(sql, resultSetType,
                resultSetConcurrency);
        addStatement(cs);
        return cs;
    }

    /**
     * Utility method to create a CallableStatement using the connection
     * returned by getConnection.
     * The returned statement object will be closed automatically
     * at tearDown() but may be closed earlier by the test if required.
     * @return Statement object from
     * getConnection().prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability)
     * @throws SQLException
     */
    public CallableStatement prepareCall(String sql,
                                        int resultSetType,
                                        int resultSetConcurrency,
					 int resultSetHoldability) throws SQLException
    {
        CallableStatement cs = getConnection().prepareCall(sql,
                resultSetType, resultSetConcurrency, resultSetHoldability);
        addStatement(cs);
        return cs;
    }
    
    /**
     * Utility method to set auto commit behaviour.
     * @param commit false if autoCommit should be disabled.
     */
    public void setAutoCommit(boolean commit) throws SQLException {
    	getConnection().setAutoCommit(commit);
    }
    /**
     * Utility method to commit using the connection
     * returned by getConnection.
     * @throws SQLException
     */
    public void commit() throws SQLException
    {
        getConnection().commit();
    }  
    
    /**
     * Utility method to rollback using the connection
     * returned by getConnection.
     * @throws SQLException
     */
    public void rollback() throws SQLException
    {
        getConnection().rollback();
    } 

    /**
     * <p>
     * Run the bare test, including {@code setUp()} and {@code tearDown()}.
     * </p>
     *
     * <p>
     * Subclasses that want to override {@code runBare()}, should override
     * this method instead. Overriding this method shouldn't be necessary
     * except in very special cases. Override {@code setUp()} and
     * {@code tearDown()} instead if possible.
     * </p>
     *
     * <p>
     * The overridden method would typically want to call
     * {@code super.runBareOverridable()} to actually run the test.
     * </p>
     */
    protected void runBareOverridable() throws Throwable {
        super.runBare();
    }

    /**
     * <p>
     * Run the bare test, including {@code setUp()} and {@code tearDown()},
     * and finally verify that the cached connection has been released.
     * </p>
     *
     * <p>
     * This method is final to prevent subclasses from accidentally bypassing
     * the assert that checks if the cached connection has been released.
     * Subclasses that want to override the method, should override
     * {@link #runBareOverridable()} instead.
     * </p>
     */
    public final void runBare() throws Throwable {
        runBareOverridable();
        // It's quite common to forget to call super.tearDown() when
        // overriding tearDown() in sub-classes.
        assertNull(
            "Connection should be null by now. " +
            "Missing call to super.tearDown()?", conn);
    }

    /**
     * Tear down this fixture, sub-classes should call
     * super.tearDown(). This cleans up and closes the connection
     * if it is open and any statement objects returned through
     * the utility methods.
     */
    protected void tearDown()
    throws java.lang.Exception
    {
        if (statements != null) {
            for (Statement s : statements) {
                s.close();
            }
            // Allow gc'ing of all those statements.
            statements = null;
        }
        if (connections != null) {
            for (Connection c : connections) {
                JDBC.cleanup(c);
            }
            // Allow gc'ing of all those connections.
            connections = null;
        }
        conn = null;
    }

    /**
     * Open a connection to the default database.
     * If the database does not exist, it will be created.
     * A default username and password will be used for the connection.
     * 
     * The connection will be initialized by calling initializeConnection.
     * A sub-class may provide an implementation of initializeConnection
     * to ensure its connections are in a consistent state that is different
     * to the default.
     *
     * @return connection to default database.
     * @see TestConfiguration#openDefaultConnection()
     * @see BaseJDBCTestCase#initializeConnection(Connection)
     */
    public Connection openDefaultConnection()
        throws SQLException {
        Connection conn =  getTestConfiguration().openDefaultConnection();
        addConnection(conn);
        initializeConnection(conn);
        return conn;
    }


    /**
     * Open a connection to the default database for the given configuration.
     * If the database does not exist, it will be created.  A default username
     * and password will be used for the connection.
     *
     * The connection will be initialized by calling initializeConnection.
     * A sub-class may provide an implementation of initializeConnection
     * to ensure its connections are in a consistent state that is different
     * to the default.
     * @param tc test configuration to use
     * @return connection to default database for the configuration
     * @see TestConfiguration#openDefaultConnection()
     * @see BaseJDBCTestCase#initializeConnection(Connection)
     */
    public Connection openDefaultConnection(TestConfiguration tc)
        throws SQLException {
        Connection conn =  tc.openDefaultConnection();
        addConnection(conn);
        initializeConnection(conn);
        return conn;
    }

    /**
     * Open a connection to the current default database using the
     * specified user name and password.
     * <BR>
     * This connection is not
     * automatically closed on tearDown, the test fixture must
     * ensure the connection is closed.
     * 
     * The connection will be initialized by calling initializeConnection.
     * A sub-class may provide an implementation of initializeConnection
     * to ensure its connections are in a consistent state that is different
     * to the default.
     * @see BaseJDBCTestCase#initializeConnection(Connection)
     */
    public Connection openDefaultConnection(String user, String password)
    throws SQLException
    {
        Connection conn =  getTestConfiguration().openDefaultConnection(user,
                password);
        addConnection(conn);
        initializeConnection(conn);
        return conn;        
    }
    
    /**
     * Open a connection to the current default database using the
     * specified user name. The password is a function of
     * the user name and the password token setup by the
     * builtin authentication decorators.
     * <BR>
     * If the fixture is not wrapped in one of the decorators
     * that setup BUILTIN authentication then the password
     * is a function of the user name and the empty string
     * as the password token. This mode is not recommended.
     * 
     * <BR>
     * This connection is not
     * automaticaly closed on tearDown, the test fixture must
     * ensure the connection is closed.
     * <BR>
     * The connection will be initialized by calling initializeConnection.
     * A sub-class may provide an implementation of initializeConnection
     * to ensure its connections are in a consistent state that is different
     * to the default.
     * 
     * @see DatabasePropertyTestSetup#builtinAuthentication(Test, String[], String)
     * @see TestConfiguration#sqlAuthorizationDecorator(Test, String[], String)
     * @see BaseJDBCTestCase#initializeConnection(Connection)
     */
    public Connection openUserConnection(String user) throws SQLException
    {
        return openDefaultConnection(user,
                getTestConfiguration().getPassword(user));
    }
    
    /**
     * Open a connection to the specified database.
     * If the database does not exist, it will be created.
     * A default username and password will be used for the connection.
     * Requires that the test has been decorated with a
     * additionalDatabaseDecorator with the matching name.
     * <BR>
     * The connection will be initialized by calling initializeConnection.
     * A sub-class may provide an implementation of initializeConnection
     * to ensure its connections are in a consistent state that is different
     * to the default.
     * @return connection to default database.
     * @see TestConfiguration#additionalDatabaseDecorator(Test, String)
     * @see BaseJDBCTestCase#initializeConnection(Connection)
     */
    public Connection openConnection(String databaseName)
        throws SQLException {
        Connection conn =  getTestConfiguration().openConnection(databaseName);
        addConnection(conn);
        initializeConnection(conn);
        return conn;
    }
    
    /**
     * Run a SQL script through ij discarding the output
     * using this object's default connection. Intended for
     * setup scripts.
     * @throws UnsupportedEncodingException 
     * @throws SQLException 
     */
    public int runScript(InputStream script, String encoding)
        throws UnsupportedEncodingException, SQLException
    {
        // Sink output.
        OutputStream sink = new TestNullOutputStream();
        
        // Use the same encoding as the input for the output.    
        return ij.runScript(getConnection(), script, encoding,
                sink, encoding);       
    }
    
    /**
     * Run a SQL script through ij discarding the output
     * using this object's default connection. Intended for
     * setup scripts.
     * @return Number of errors executing the script
     * @throws UnsupportedEncodingException 
     * @throws PrivilegedActionException
     * @throws SQLException 
     */
    public int runScript(String resource,String encoding)
        throws UnsupportedEncodingException, SQLException,
        PrivilegedActionException,IOException
    {
        
        URL sql = getTestResource(resource);
        assertNotNull("SQL script missing: " + resource, sql);
        InputStream sqlIn = openTestResource(sql);
        Connection conn = getConnection();
        int numErrors = runScript(sqlIn,encoding);
        sqlIn.close();
        
        if (!conn.isClosed() && !conn.getAutoCommit())
            conn.commit();
        
        return numErrors;
    }
    
    /**
     * Run a set of SQL commands from a String discarding the output.
     * Commands are separated by a semi-colon. Connection used
     * is this objects default connection.
     * @param sqlCommands
     * @return Number of errors executing the script.
     * @throws UnsupportedEncodingException
     * @throws SQLException
     */
    public int runSQLCommands(String sqlCommands)
        throws UnsupportedEncodingException, SQLException
    {
        byte[] raw = sqlCommands.getBytes("UTF-8");
        ByteArrayInputStream in = new ByteArrayInputStream(raw);
        
        return runScript(in, "UTF-8");
    }
    
    /**
     * Tell if the client is embedded.
     *
     * @return <code>true</code> if using the embedded client
     *         <code>false</code> otherwise.
     */
     public static boolean usingEmbedded() {
         return TestConfiguration.getCurrent().getJDBCClient().isEmbedded();
     }
    
    /**
    * Tell if the client is DerbyNetClient.
    *
    * @return <code>true</code> if using the DerbyNetClient client
    *         <code>false</code> otherwise.
    */
    public static boolean usingDerbyNetClient() {
        return TestConfiguration.getCurrent().getJDBCClient().isDerbyNetClient();
    }
    
    /**
    * Tell if the client is DB2Client.
    *
    * @return <code>true</code> if using the DB2 client driver,
    *         <code>false</code> otherwise.
    */
    public static boolean usingDB2Client() {
        return TestConfiguration.getCurrent().getJDBCClient().isDB2Client();
    }
    
    /**
     * Get the value of a database property using the default connection 
     * @param propertyName Property key
     * @return null if the property is not set at the database level,
     * otherwise the value of the property.
     * @throws SQLException
     */
    public String getDatabaseProperty(String propertyName) throws SQLException
    {
        PreparedStatement ps =  prepareStatement(
             "VALUES SYSCS_UTIL.SYSCS_GET_DATABASE_PROPERTY(?)");
        
        ps.setString(1, propertyName);
        ResultSet rs = ps.executeQuery();
        
        rs.next();

        String val = rs.getString(1);

        rs.close();
        closeStatement(ps);

        return val;
    }

    /**
     * Assert equality between two <code>Blob</code> objects.
     * If both input references are <code>null</code>, they are considered
     * equal. The same is true if both blobs have <code>null</code>-streams.
     *
     * @param b1 first <code>Blob</code>.
     * @param b2 second <code>Blob</code>.
     * @throws AssertionFailedError if blobs are not equal.
     * @throws IOException if reading or closing a stream fails
     * @throws SQLException if obtaining a stream fails
     */
    public static void assertEquals(Blob b1, Blob b2)
            throws IOException, SQLException {
        if (b1 == null || b2 == null) {
            assertNull("Blob b2 is null, b1 is not", b1);
            assertNull("Blob b1 is null, b2 is not", b2);
            return;
        }
        assertEquals("Blobs have different lengths",
                     b1.length(), b2.length());
        InputStream is1 = b1.getBinaryStream();
        InputStream is2 = b2.getBinaryStream();

        if (is1 == null || is2 == null) {
            assertNull("Blob b2 has null-stream, blob b1 doesn't", is1);
            assertNull("Blob b1 has null-stream, blob b2 doesn't", is2);
            return;
        }
        
        // wrap buffered stream around the binary stream
        is1 = new BufferedInputStream(is1);
        is2 = new BufferedInputStream(is2);
 
        long index = 1;
        int by1 = is1.read();
        int by2 = is2.read();
        do {
            // Avoid string concatenation for every byte in the stream.
            if (by1 != by2) {
                assertEquals("Blobs differ at index " + index,
                        by1, by2);
            }
            index++;
            by1 = is1.read();
            by2 = is2.read();
        } while ( by1 != -1 || by2 != -1);
        is1.close();
        is2.close();
    }

    /**
     * Assert equality between two <code>Clob</code> objects.
     * If both input references are <code>null</code>, they are considered
     * equal. The same is true if both clobs have <code>null</code>-streams.
     *
     * @param c1 first <code>Clob</code>.
     * @param c2 second <code>Clob</code>.
     * @throws AssertionFailedError if clobs are not equal.
     * @throws IOException if reading or closing a stream fails
     * @throws SQLException if obtaining a stream fails
     */
    public static void assertEquals(Clob c1, Clob c2)
            throws IOException, SQLException {
        if (c1 == null || c2 == null) {
            assertNull("Clob c2 is null, c1 is not", c1);
            assertNull("Clob c1 is null, c2 is not", c2);
            return;
        }
        assertEquals("Clobs have different lengths",
                     c1.length(), c2.length());
        Reader r1 = c1.getCharacterStream();
        assertNotNull(r1); // java.sql.Blob object cannot represent NULL
        Reader r2 = c2.getCharacterStream();
        assertNotNull(r2); // java.sql.Blob object cannot represent NULL

        // wrap buffered reader around the character stream
        r1 = new BufferedReader(r1);
        r2 = new BufferedReader(r2);

        long index = 1;
        int ch1 = r1.read();
        int ch2 = r2.read();
        do {
            // Avoid string concatenation for every char in the stream.
            if (ch1 != ch2) {
                assertEquals("Clobs differ at index " + index,
                        ch1, ch2);
            }
            index++;
            ch1 = r1.read();
            ch2 = r2.read();
        } while (ch1 != -1 || ch2 != -1);
        r1.close();
        r2.close();
    }

    /**
     * Assert equality between two <code>java.sql.Time</code> objects.
     * If both input references are <code>null</code>, they are considered
     * equal.
     *
     * @param msg String with message to supply with AssertionFailedError
     * @param t1 first java.sql.Time object.
     * @param t2 second java.sql.Time object.
     * @throws AssertionFailedError if Time objects are not equal.
     */
    public static void assertEquals(String msg, Time t1, Time t2) {
        if(null == t1 && null == t2) {
            return;
        }
        assertNotNull(msg, t1);
        assertNotNull(msg, t2);
        assertEquals(msg, t1.toString(), t2.toString());
    }
    
    /**
     * Assert that SQLState is as expected.  If the SQLState for
     * the top-level exception doesn't match, look for nested
     * exceptions and, if there are any, see if they have the
     * desired SQLState.
     *
     * @param message message to print on failure.
     * @param expected the expected SQLState.
     * @param exception the exception to check the SQLState of.
     */
    public static void assertSQLState(String message, 
                                      String expected, 
                                      SQLException exception) {
        // Make sure exception is not null. We want to separate between a
        // null-exception object, and a null-SQLState.
        assertNotNull("Exception cannot be null when asserting on SQLState", 
                      exception);
        
        try {
            String state = exception.getSQLState();
            
            if ( state != null )
                assertTrue("The exception's SQL state must be five characters long",
                        state.length() == 5);
            
            if ( expected != null )
                assertTrue("The expected SQL state must be five characters long",
                    expected.length() == 5);
            
            assertEquals(message, expected, state);
        } catch (AssertionFailedError e) {
            
            // Save the SQLException
            e.initCause(exception);

            if (usingDB2Client())
            {
                /* For JCC the error message is a series of tokens representing
                 * different things like SQLSTATE, SQLCODE, nested SQL error
                 * message, and nested SQL state.  Based on observation it
                 * appears that the last token in the message is the SQLSTATE
                 * of the nested exception, and it's preceded by a colon.
                 * So using that (hopefully consistent?) rule, try to find
                 * the target SQLSTATE.
                 */
                String msg = exception.getMessage();
                if (!msg.substring(msg.lastIndexOf(":")+1)
                    .trim().equals(expected))
                {
                    throw e;
                }
            }
            else
            {
                // Check nested exceptions to see if any of them is
                // the one we're looking for.
                exception = exception.getNextException();
                if (exception != null)
                    assertSQLState(message, expected, exception);
                else
                    throw e;
            }
        }
    }

    /**
     * Assert that a warning is chained to the connection.
     *
     * @param conn  the connection
     * @param expected the expected SQLState of the warning
     */
    public static void assertWarning( Connection conn, String expected )
        throws SQLException
    {
        SQLWarning  firstWarning = conn.getWarnings();
        assertNotNull( firstWarning );

        for ( SQLWarning warning = firstWarning; warning != null; warning = warning.getNextWarning() )
        {
            if ( expected.equals( warning.getSQLState() ) ) { return; }
        }

        fail( "Expected to see a SQLWarning with the SQLState " + expected );
    }


    /**
     * Assert that SQLState is as expected.
     *
     * @param expected the expected SQLState.
     * @param exception the exception to check the SQLState of.
     */
    public static void assertSQLState(String expected, SQLException exception) {
        assertSQLState("Unexpected SQL state.", expected, exception);
    }

    /**
     * Assert that the error code is as expected.
     *
     * @param expected the expected error code
     * @param exception the exception to check
     * @throws AssertionFailedError if the error code is wrong
     */
    public static void assertErrorCode(int expected, SQLException exception) {
        assertNotNull("Exception should not be null", exception);
        int actual = exception.getErrorCode();
        if (actual != expected) {
            fail("Expected error code " + expected + ", got " + actual,
                 exception);
        }
    }

    /**
     * Assert that the SQL statement does not compile and throws
     * a SQLException with the expected state.
     * 
     * @param sqlState expected sql state.
     * @param sql the SQL to compile.
     */
    public void assertCompileError(String sqlState, String sql) {

        try {
            PreparedStatement pSt = prepareStatement(sql);
            if (usingDB2Client())
            {
                /* For JCC the prepares are deferred until execution,
                 * so we have to actually execute in order to see the
                 * expected error.  Note that we don't need to worry
                 * about binding the parameters (if any); the compile
                 * error should occur before the execution-time error
                 * about unbound parameters.
                 */
                try {
                    pSt.execute();
                } finally {
                    pSt.close();
                }
            }
            fail("expected compile error: " + sqlState);
        } catch (SQLException se) {
            assertSQLState(sqlState, se);
        }
    }
    
    /**
     * Check the table using SYSCS_UTIL.SYSCS_CHECK_TABLE.
     */
    public void assertCheckTable(String table) throws SQLException
    {
        PreparedStatement ps = prepareStatement(
                "VALUES SYSCS_UTIL.SYSCS_CHECK_TABLE(?, ?)");
        
        ps.setString(1, getTestConfiguration().getUserName());
        ps.setString(2, table);
        
        ResultSet rs = ps.executeQuery();
        JDBC.assertSingleValueResultSet(rs, "1");
        ps.close();
    }
    
    /**
     * Assert that the number of rows in a table is an expected value.
     * Query uses a SELECT COUNT(*) FROM "table".
     * 
     * @param table Name of table in current schema, will be quoted
     * @param rowCount Number of rows expected in the table
     * @throws SQLException Error accessing the database.
     */
    protected void assertTableRowCount(String table, int rowCount) throws SQLException
    {
        assertEscapedTableRowCount(JDBC.escape(table), rowCount);
    }

    /**
     * Assert that the number of rows in a table is an expected value.
     * Query uses a SELECT COUNT(*) FROM table.
     * 
     * @param escapedTableName Escaped name of table, will be used as-is.
     * @param rowCount Number of rows expected in the table
     * @throws SQLException Error accessing the database.
     */
    private void assertEscapedTableRowCount(String escapedTableName, int rowCount)
       throws SQLException
    {
    
        Statement s = createStatement();
        ResultSet rs = s.executeQuery(
                "SELECT COUNT(*) FROM " + escapedTableName);
        rs.next();
        assertEquals(escapedTableName + " row count:",
            rowCount, rs.getInt(1));
        rs.close();
        s.close();
    }

    /**
     * Clear the contents of the statement cache. Useful if a test case
     * needs to make sure that a statement is actually compiled and not
     * just fetched from the statement cache.
     *
     * @throws SQLException if a database error happens
     */
    protected final void emptyStatementCache() throws SQLException {
        Statement s = createStatement();
        s.execute("CALL SYSCS_UTIL.SYSCS_EMPTY_STATEMENT_CACHE()");
        closeStatement(s);
    }

    /**
     * Execute a DROP TABLE command using the passed in tableName as-is
     * and the default connection.
     * If the DROP TABLE fails because the table does not exist then
     * the exception is ignored.
     * @param tableName Table to be dropped.
     * @throws SQLException
     */
    public final void dropTable(String tableName) throws SQLException
    {
       dropTable(getConnection(), tableName);
    }
    
    /**
     * Execute a DROP TABLE command using the passed in tableName as-is.
     * If the DROP TABLE fails because the table does not exist then
     * the exception is ignored.
     * @param conn Connection to execute the DROP TABLE
     * @param tableName Table to be dropped.
     * @throws SQLException
     */
    public static void dropTable(Connection conn, String tableName) throws SQLException
    {
        Statement statement = conn.createStatement();
        String dropSQL = "DROP TABLE " + tableName;
        try { 
            
            statement.executeUpdate(dropSQL); 
        } catch (SQLException e) {
            assertSQLState("42Y55", e);
        }
        finally {
            statement.close();
        }
    }

    /**
     * Execute a DROP VIEW command using the passed in viewName as-is
     * and the default connection.
     * If the DROP VIEW fails because the view does not exist then
     * the exception is ignored.
     * @param viewName Table to be dropped.
     * @throws SQLException
     */
    public final void dropView(String viewName) throws SQLException
    {
       dropView(getConnection(), viewName);
    }
    
    /**
     * Execute a DROP VIEW command using the passed in viewName as-is.
     * If the DROP VIEW fails because the view does not exist then
     * the exception is ignored.
     * @param conn Connection to execute the DROP VIEW
     * @param viewName Table to be dropped.
     * @throws SQLException
     */
    public static void dropView(Connection conn, String viewName) throws SQLException
    {
        Statement statement = conn.createStatement();
        String dropSQL = "DROP VIEW " + viewName;
        try { 
            
            statement.executeUpdate(dropSQL); 
        } catch (SQLException e) {
            assertSQLState("42Y55", e);
        }
        finally {
            statement.close();
        }
    }

    /**
     * Assert that the query fails (either in compilation,
     * execution, or retrieval of results--doesn't matter)
     * and throws a SQLException with the expected states.
     *
     * Assumption is that 'query' does *not* have parameters
     * that need binding and thus can be executed using a
     * simple Statement.execute() call.
     *
     * If there are extra chained SQLExceptions that are 
     * not in sqlStates, this method will not fail.
     * 
     * @param sqlStates  expected sql states.
     * @param st Statement object on which to execute.
     * @param query the query to compile and execute.
     */
    public static void assertStatementError(String[] sqlStates,
            Statement st, String query) {
        assertStatementErrorMinion(sqlStates, ORDERED, st, query);
    }

    /**
     * Assert that the query fails (either in compilation,
     * execution, or retrieval of results--doesn't matter)
     * and throws a SQLException with the expected states.
     *
     * Assumption is that 'query' does *not* have parameters
     * that need binding and thus can be executed using a
     * simple Statement.execute() call.
     *
     * If there are extra chained SQLExceptions that are
     * not in sqlStates, this method will not fail.
     *
     * @param sqlStates  expected sql states.
     * @param st Statement object on which to execute.
     * @param query the query to compile and execute.
     */
    public static void assertStatementErrorUnordered(String[] sqlStates,
            Statement st, String query) {
        assertStatementErrorMinion(sqlStates, UNORDERED, st, query);
    }

    /**
     * Asserts that the given statement fails (compilation, execution or
     * retrieval of results) and throws an {@code SQLException} with the
     * expected (chained) states.
     *
     * @param sqlStates the expected states
     * @param orderedStates whether or not the states are expected in the
     *      specified order or not
     * @param st the statement used to execute the query
     * @param query the query to execute
     */
    private static void assertStatementErrorMinion(
            String[] sqlStates, boolean orderedStates,
            Statement st, String query) {
        ArrayList<String> statesBag = null;
        if (!orderedStates) {
            statesBag = new ArrayList<String>(Arrays.asList(sqlStates));
        }
        try {
            boolean haveRS = st.execute(query);
            fetchAndDiscardAllResults(st, haveRS);
            String errorMsg = "Expected error(s) '" ;
            for (int i = 0; i < sqlStates.length;i++)
                errorMsg += " " + sqlStates[i];
            errorMsg += "' but no error was thrown.";            
            fail(errorMsg);            
        } catch (SQLException se) {
            int count = 0;
            do {
                if (orderedStates) {
                    assertSQLState(sqlStates[count], se);
                } else {
                    String state = se.getSQLState();
                    assertTrue("Unexpected state: " + state,
                            statesBag.remove(state));
                    // Run through assertSQLStates too, to catch invalid states.
                    assertSQLState(state, se);
                }
                count++;
                se = se.getNextException();
            } while (se != null && count < sqlStates.length);
            // We must have at least as many exceptions as 
            // we expected.
            assertEquals("Got " +
                    count + " exceptions. Expected at least"+
                    sqlStates.length,count,sqlStates.length);
            
        }
    }

    /**
     * Assert that the query fails with a single error
     *  
     * @param sqlState  Expected SQLState of exception
     * @param st         
     * @param query
     * @see #assertStatementError(String[], Statement, String)
     */
    public static void assertStatementError(String sqlState, Statement st, String query) {
        assertStatementError(new String[] {sqlState},st,query);
    }
        
    /**
     * Assert that that a commit fails with the given error
     * @param sqlState state
     * @param c        the connection
     */
    public static void assertCommitError(String sqlState, Connection c) {
        try {
            c.commit();
            fail();
        } catch (SQLException e) {
            assertSQLState(sqlState, e);
        }
    }
   
    /**
     * Assert that the query fails (either in compilation,
     * execution, or retrieval of results--doesn't matter)
     * and throws a SQLException with the expected state
     * and error code
     *
     * Assumption is that 'query' does *not* have parameters
     * that need binding and thus can be executed using a
     * simple Statement.execute() call.
     * 
     * @param sqlState expected sql state.
     * @param errorCode expected error code.
     * @param st Statement object on which to execute.
     * @param query the query to compile and execute.
     */
    public static void assertStatementError(String sqlState, int errorCode, Statement st, String query) {
        try {
            boolean haveRS = st.execute(query);
            fetchAndDiscardAllResults(st, haveRS);
            fail("Expected error '" + sqlState +
                "' but no error was thrown.");
        } catch (SQLException se) {
            assertSQLState(sqlState, se);
            assertErrorCode(errorCode, se);
        }
        
    }

    /**
     * Assert that the query fails (either in execution, or retrieval of
     * results--doesn't matter) and throws a SQLException with the expected
     * state and error code
     *
     * Parameters must have been already bound, if any.
     *
     * @param sqlState expected sql state.
     * @param ps PreparedStatement query object to execute.
     */
    public static void assertPreparedStatementError(String sqlState,
                                                    PreparedStatement ps) {
        try {
            boolean haveRS = ps.execute();
            fetchAndDiscardAllResults(ps, haveRS);
            fail("Expected error '" + sqlState +
                "' but no error was thrown.");
        } catch (SQLException se) {
            assertSQLState(sqlState, se);
        }
    }

    /**
     * Assert that execution of the received PreparedStatement
     * object fails (either in execution or when retrieving
     * results) and throws a SQLException with the expected
     * state.
     * 
     * Assumption is that "pSt" is either a PreparedStatement
     * or a CallableStatement that has already been prepared
     * and whose parameters (if any) have already been bound.
     * Thus the only thing left to do is to call "execute()"
     * and look for the expected SQLException.
     * 
     * @param sqlState expected sql state.
     * @param pSt A PreparedStatement or CallableStatement on
     *  which to call "execute()".
     */
    public static void assertStatementError(String sqlState,
        PreparedStatement pSt)
    {
        try {
            boolean haveRS = pSt.execute();
            fetchAndDiscardAllResults(pSt, haveRS);
            fail("Expected error '" + sqlState +
                "' but no error was thrown.");
        } catch (SQLException se) {
            assertSQLState(sqlState, se);
        }
    }


    /**
     * Executes the Callable statement that is expected to fail and verifies
     * that it throws the expected SQL exception.
     * @param expectedSE The expected SQL exception
     * @param callSQL The SQL to execute
     * @throws SQLException
     */
    public void assertCallError(String expectedSE, String callSQL)
    throws SQLException
    {
        try {
            CallableStatement cs = prepareCall(callSQL);
            cs.execute();
            fail("FAIL - SQL expected to throw exception");
        } catch (SQLException se) {
            assertSQLState(expectedSE, se);
        }
    }
    /**
     * Perform a fetch on the ResultSet with an expected failure
     * 
     * @param sqlState Expected SQLState
     * @param rs   ResultSet upon which next() will be called
     */
    public static void assertNextError(String sqlState,ResultSet rs)
    {
    	try {
    		rs.next();
    		fail("Expected error on next()");
    	}catch (SQLException se){
    		assertSQLState(sqlState,se);
    	}
    }
    
    /**
     * Perform getInt(position) with expected error
     * @param position  position argument to pass to getInt
     * @param sqlState  sqlState of expected error
     * @param rs ResultSet upon which to call getInt(position)
     */
    public static void assertGetIntError(int position, String sqlState, ResultSet rs)
    {
    	try {
    		rs.getInt(position);
    		fail("Expected exception " + sqlState);
    	} catch (SQLException se){
    		assertSQLState(sqlState,se);
    	}
    			
    	
    }
    /**
     * Take a Statement object and a SQL statement, execute it
     * via the "executeUpdate()" method, and assert that the
     * resultant row count matches the received row count.
     *
     * Assumption is that 'sql' does *not* have parameters
     * that need binding and that it can be executed using a
     * simple Statement.executeUpdate() call.
     * 
     * @param st Statement object on which to execute.
     * @param expectedRC Expected row count.
     * @param sql SQL to execute.
     */
    public static void assertUpdateCount(Statement st,
        int expectedRC, String sql) throws SQLException
    {
        assertEquals("Update count does not match:",
            expectedRC, st.executeUpdate(sql));
    }

    /**
     * Assert that a call to "executeUpdate()" on the received
     * PreparedStatement object returns a row count that matches
     * the received row count.
     *
     * Assumption is that "pSt" is either a PreparedStatement
     * or a CallableStatement that has already been prepared
     * and whose parameters (if any) have already been bound.
     * Also assumes the statement's SQL is such that a call
     * executeUpdate() is allowed.  Thus the only thing left
     * to do is to call the "executeUpdate" method.
     * 
     * @param pSt The PreparedStatement on which to execute.
     * @param expectedRC The expected row count.
     */
    public static void assertUpdateCount(PreparedStatement pSt,
        int expectedRC) throws SQLException
    {
        assertEquals("Update count does not match:",
            expectedRC, pSt.executeUpdate());
    }

    /**
     * Get the last SQLException in chain.
     * @param sqle <code>SQLException</code>
     * @return the last exception in the chain.
     */
    public SQLException getLastSQLException(SQLException sqle) {
        SQLException current = sqle;
        SQLException next = sqle.getNextException();
        while (next != null) {
            current = next;
            next = next.getNextException();
        }
        return current;
    }

    /**
     * Take the received Statement--on which a query has been
     * executed--and fetch all rows of all result sets (if any)
     * returned from execution.  The rows themselves are
     * discarded.  This is useful when we expect there to be
     * an error when processing the results but do not know
     * (or care) at what point the error occurs.
     *
     * @param st An already-executed statement from which
     *  we get the result set to process (if there is one).
     * @param haveRS Whether or not the the statement's
     *  first result is a result set (as opposed to an
     *  update count).
     */
    private static void fetchAndDiscardAllResults(Statement st,
        boolean haveRS) throws SQLException
    {
        ResultSet rs = null;
        while (haveRS || (st.getUpdateCount() != -1))
        {
            // If we have a result set, iterate through all
            // of the rows.
            if (haveRS)
                JDBC.assertDrainResults(st.getResultSet(), -1);
            haveRS = st.getMoreResults();
        }
    }

    /**
     * Assert that the two (2) passed-in SQLException's are equals and
     * not just '=='.
     *
     * @param se1 first SQLException to compare
     * @param se2 second SQLException to compare
     */
    public static void assertSQLExceptionEquals(SQLException se1,
                                                SQLException se2) {
        // Ensure non-null SQLException's are being passed.
        assertNotNull(
            "Passed-in SQLException se1 cannot be null",
            se1);
        assertNotNull(
            "Passed-in SQLException se2 cannot be null",
            se2);

        // Now verify that the passed-in SQLException's are of the same type
        assertEquals("SQLException class types are different",
                     se1.getClass().getName(), se2.getClass().getName());

        // Here we check that the detailed message of both
        // SQLException's is the same
        assertEquals(
                "Detailed messages of the SQLException's are different",
                 se1.getMessage(), se2.getMessage());

        // Check that getCause() returns the same value on the two exceptions.
        Throwable se1Cause = se1.getCause();
        Throwable se2Cause = se2.getCause();
        if (se1Cause == null) {
            assertNull(se2Cause);
        } else {
            assertThrowableEquals(se1Cause, se2Cause);
        }

        // Check that the two exceptions have the same next exception.
        if (se1.getNextException() == null) {
            assertNull(se2.getNextException());
        } else {
            assertSQLExceptionEquals(se1.getNextException(),
                                     se2.getNextException());
        }
    }

    /**
     * Compares two JDBC types to see if they are equivalent.
     * DECIMAL and NUMERIC and DOUBLE and FLOAT are considered
     * equivalent.
     * @param expectedType Expected jdbctype from java.sql.Types
     * @param type         Actual type from metadata
     */
    public static void assertEquivalentDataType(int expectedType, int type)
    {
     if (expectedType == type)
         return;
     if (expectedType == java.sql.Types.DECIMAL && 
                 type == java.sql.Types.NUMERIC)
         return;
     if (expectedType == java.sql.Types.NUMERIC && 
             type == java.sql.Types.DECIMAL)
         return;
     if (expectedType == java.sql.Types.DOUBLE && 
                 type == java.sql.Types.FLOAT)
         return;
     if (expectedType == java.sql.Types.FLOAT && 
             type == java.sql.Types.DOUBLE)
     return;
     fail("types:" + expectedType + " and " + type + " are not equivalent");
     
    }
  
    /**
     * Attempts to obtain the client-side transaction counter from the given
     * connection, which is internal state information.
     * <p>
     * <em>NOTE:</em> Use with care, accesses internal state.
     *
     * @param conn the connection
     * @return Internal client transaction id.
     * @throws SQLException if the given connection is an embedded connection,
     *      or if invoking the required method fails
     **/
    public static int getClientTransactionID(Connection conn)
            throws SQLException {
        try {
            Method m = conn.getClass().getMethod(
                    "getTransactionID", new Class[] {});
            return ((Integer) m.invoke(conn, new Object[] {} )).intValue();
        } catch (Exception e) {
            SQLException se = new SQLException(e.getMessage());
            se.initCause(e);
            throw se;
        }
    }

    /**
     * Return estimated row count for runtime statistics.  
     * Requires caller first turned on RuntimeStatistics, executed a query and closed the ResultSet.
     * 
     * For client calls we just return as we can't find out this information.
     * @param conn
     * @param expectedCount
     * @throws SQLException
     */
    public static void checkEstimatedRowCount(Connection conn, double expectedCount) throws SQLException {
        if (! (conn instanceof EmbedConnection))
	    { return; }
	
        EmbedConnection econn = (EmbedConnection) conn;
        LanguageConnectionContext   lcc = (LanguageConnectionContext) getLanguageConnectionContext( econn );
        RunTimeStatistics rts = lcc.getRunTimeStatisticsObject();
        assertNotNull(" RuntimeStatistics is null. Did you call SYSCS_UTIL.SYSCS_SET_RUNTIMESTATISTICS(1)?",rts);
        assertEquals((long) expectedCount, (long) rts.getEstimatedRowCount());
	}

    /**
     * Check consistency of all tables
     * 
     * @param conn
     * @throws SQLException
     */
    protected void  checkAllConsistency(
            Connection  conn)
    throws SQLException
    {
        Statement s = createStatement();

        ResultSet rs = 
            s.executeQuery(
                    "select schemaname, tablename, SYSCS_UTIL.SYSCS_CHECK_TABLE(schemaname, tablename) " + 
            "from sys.systables a,  sys.sysschemas b where a.schemaid = b.schemaid");

        int table_count = 0;

        while (rs.next())
        {
            table_count++;

            if (rs.getInt(3) != 1)
            {
                assertEquals("Bad return from consistency check of " +
                        rs.getString(1) + "." + rs.getString(2),1,rs.getInt(3));

            }
        }
        assertTrue("Something wrong with consistency check query, found only " +
                table_count + " tables.",table_count >= 5);

        rs.close();
        s.close();

        conn.commit();
    }

    protected static void dumpRs(ResultSet s, PrintStream out)
            throws SQLException
    {
        if (s == null) {
            out.println("<NULL>");
            return;
        }

        ResultSetMetaData rsmd = s.getMetaData();

        // Get the number of columns in the result set
        int numCols = rsmd.getColumnCount();

        if (numCols <= 0) {
            out.println("(no columns!)");
            return;
        }

        StringBuilder heading = new StringBuilder("\t ");
        StringBuilder underline = new StringBuilder("\t ");

        int len;
        // Display column headings
        for (int i=1; i<=numCols; i++) {
            if (i > 1) {
                heading.append(",");
                underline.append(" ");
            }

            len = heading.length();
            heading.append(rsmd.getColumnLabel(i));
            len = heading.length() - len;

            for (int j = len; j > 0; j--) {
                underline.append("-");
            }
        }

        out.println(heading.toString());
        out.println(underline.toString());


        StringBuilder row = new StringBuilder();
        // Display data, fetching until end of the result set
        while (s.next()) {
            row.append("\t{");
            // Loop through each column, getting the
            // column data and displaying
            for (int i=1; i<=numCols; i++) {
                if (i > 1) row.append(",");
                row.append(s.getString(i));
            }

            row.append("}\n");
        }

        out.println(row.toString());
        s.close();
    }

    public static void dumpRs(ResultSet s) throws SQLException {
        dumpRs(s, System.out);
    }

    // helper methods moved from GeneratedColumnsHelper

    /**
     * Run good DDL.
     * @throws SQLException 
     */
    protected void    goodStatement( Connection conn, String command ) throws SQLException
    {
        PreparedStatement    ps = chattyPrepare( conn, command );

        ps.execute();
        ps.close();
    }
    
    /**
     * Run a good update statement with an expected row count.
     * @throws SQLException 
     */
    protected void    goodUpdate( Connection conn, String update, int expectedRowCount ) throws SQLException
    {
        PreparedStatement    ps = chattyPrepare( conn, update );

        int actualRowCount = ps.executeUpdate();
        ps.close();

        println( "Expecting to touch " + expectedRowCount + " rows." );
        assertEquals( expectedRowCount, actualRowCount );
    }
    
    /**
     * Assert that the statement returns the correct results.
     */
    protected void assertResults( Connection conn, String query, String[][] rows, boolean trimResults )
        throws SQLException
    {
        PreparedStatement   ps = chattyPrepare( conn, query );
        ResultSet                   rs = ps.executeQuery();

        assertResults( rs, rows, trimResults );

        rs.close();
        ps.close();
    }
        
    /**
     * Assert that the ResultSet returns the desired rows.
     */
    protected void assertResults( ResultSet rs, String[][] rows, boolean trimResults )
        throws SQLException
    {
        int     rowCount = rows.length;

        for ( int i = 0; i < rowCount; i++ )
        {
            String[]    row = rows[ i ];
            int             columnCount = row.length;

            assertTrue( rs.next() );

            for ( int j = 0; j < columnCount; j++ )
            {
                String  expectedValue =  row[ j ];
                //println( "(row, column ) ( " + i + ", " +  j + " ) should be " + expectedValue );
                String  actualValue = null;
                int         column = j+1;

                actualValue = rs.getString( column );
                if ( rs.wasNull() ) { actualValue = null; }

                if ( (actualValue != null) && trimResults ) { actualValue = actualValue.trim(); }
                
                assertEquals( (expectedValue == null), rs.wasNull() );
                
                if ( expectedValue == null )    { assertNull( actualValue ); }
                else { assertEquals(expectedValue, actualValue); }
            }
        }

        assertFalse( rs.next() );
    }

	protected	static	ResultSet	executeQuery( Statement stmt, String text )
		throws SQLException
	{
		println( "Executing '" + text + "'" );

        return stmt.executeQuery( text );
	}

    /**
     * Prepare a statement and report its sql text.
     */
    protected PreparedStatement   chattyPrepare( Connection conn, String text )
        throws SQLException
    {
        println( "Preparing statement:\n\t" + text );
        
        return conn.prepareStatement( text );
    }

    /**
     * Prepare a callable statement and report its sql text.
     */
    protected CallableStatement   chattyPrepareCall( Connection conn, String text )
        throws SQLException
    {
        println( "Preparing callable statement:\n\t" + text );
        
        return conn.prepareCall( text );
    }

    /**
     * Assert that the statement text, when compiled, raises an exception
     */
    protected void    expectCompilationError( String sqlState, String query )
    {
        println( "\nExpecting " + sqlState + " when preparing:\n\t" + query );

        assertCompileError( sqlState, query );
    }

    /**
     * Assert that the statement text, when compiled, raises an exception
     */
    protected void    expectCompilationError( Connection conn, String sqlState, String query )
    {
        println( "\nExpecting " + sqlState + " when preparing:\n\t" + query );

        PreparedStatement ps = null;

        try {
            ps = conn.prepareStatement( query );
        } catch (SQLException se )
        {
            assertSQLState( sqlState, se );

            return;
        }

        fail( "Expected SQL state: " + sqlState );
    }

    /**
     * Assert that the statement text, when executed, raises an error.
     */
    protected void    expectExecutionError( Connection conn, String sqlState, String query )
        throws Exception
    {
        println( "\nExpecting " + sqlState + " when executing:\n\t"  );
        PreparedStatement   ps = chattyPrepare( conn, query );

        assertStatementError( sqlState, ps );
        ps.close();
    }
    
	/**
	  * Gets the LanguageConnectionContext for this connection. You might think that
      * this method could take an EmbedConnection as its argument and return a
      * LanguageConnectionContext. That, however, makes the compatibility tests blow up.
      * With those stronger types, the test lookup machinery in junit.framework.TestSuite
      * can't resolve the signature of this private method. That is because the engine jar is
      * not on the client-only classpath used by the compatibility tests. Now you know.
	  */
	private static Object	getLanguageConnectionContext( Connection conn )
	{
        final EmbedConnection   econn = (EmbedConnection) conn;
        return AccessController.doPrivileged
            (
             new PrivilegedAction<LanguageConnectionContext>()
             {
                 public LanguageConnectionContext run()
                 {
                     return econn.getLanguageConnection();
                 }
             }
             );
	}


} // End class BaseJDBCTestCase


