Logo Search packages:      
Sourcecode: mysql-connector-java version File versions  Download package

ConnectionTest.java

/*
 Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
 

  The MySQL Connector/J is licensed under the terms of the GPLv2
  <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors.
  There are special exceptions to the terms and conditions of the GPLv2 as it is applied to
  this software, see the FLOSS License Exception
  <http://www.mysql.com/about/legal/licensing/foss-exception.html>.

  This program is free software; you can redistribute it and/or modify it under the terms
  of the GNU General Public License as published by the Free Software Foundation; version 2
  of the License.

  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the GNU General Public License for more details.

  You should have received a copy of the GNU General Public License along with this
  program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth
  Floor, Boston, MA 02110-1301  USA



 */
package testsuite.simple;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.sql.CallableStatement;
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.Savepoint;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;

import testsuite.BaseTestCase;

import com.mysql.jdbc.Driver;
import com.mysql.jdbc.NonRegisteringDriver;
import com.mysql.jdbc.SQLError;
import com.mysql.jdbc.StringUtils;
import com.mysql.jdbc.Util;
import com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource;
import com.mysql.jdbc.log.StandardLogger;

/**
 * Tests java.sql.Connection functionality ConnectionTest.java,v 1.1 2002/12/06
 * 22:01:05 mmatthew Exp
 * 
 * @author Mark Matthews
 */
00072 public class ConnectionTest extends BaseTestCase {
      /**
       * Constructor for ConnectionTest.
       * 
       * @param name
       *            the name of the test to run
       */
00079       public ConnectionTest(String name) {
            super(name);
      }

      /**
       * Runs all test cases in this test suite
       * 
       * @param args
       */
00088       public static void main(String[] args) {
            junit.textui.TestRunner.run(ConnectionTest.class);
      }

      /**
       * Tests catalog functionality
       * 
       * @throws Exception
       *             if an error occurs
       */
00098       public void testCatalog() throws Exception {
            String currentCatalog = this.conn.getCatalog();
            this.conn.setCatalog(currentCatalog);
            assertTrue(currentCatalog.equals(this.conn.getCatalog()));
      }

      /**
       * Tests a cluster connection for failover, requires a two-node cluster URL
       * specfied in com.mysql.jdbc.testsuite.ClusterUrl system proeprty.
       * 
       * @throws Exception
       *             DOCUMENT ME!
       */
00111       public void testClusterConnection() throws Exception {
            String url = System.getProperty("com.mysql.jdbc.testsuite.ClusterUrl");

            if ((url != null) && (url.length() > 0)) {
                  Object versionNumObj = getSingleValueWithQuery("SHOW VARIABLES LIKE 'version'");

                  if ((versionNumObj != null)
                              && (versionNumObj.toString().indexOf("cluster") != -1)) {
                        Connection clusterConn = null;
                        Statement clusterStmt = null;

                        try {
                              clusterConn = new NonRegisteringDriver().connect(url, null);

                              clusterStmt = clusterConn.createStatement();
                              clusterStmt
                                          .executeQuery("DROP TABLE IF EXISTS testClusterConn");
                              clusterStmt
                                          .executeQuery("CREATE TABLE testClusterConn (field1 INT) "
                                                      + getTableTypeDecl() + " =ndbcluster");
                              clusterStmt
                                          .executeQuery("INSERT INTO testClusterConn VALUES (1)");

                              clusterConn.setAutoCommit(false);

                              clusterStmt.executeQuery("SELECT * FROM testClusterConn");
                              clusterStmt
                                          .executeUpdate("UPDATE testClusterConn SET field1=4");

                              // Kill the connection
                              String connectionId = getSingleValueWithQuery(
                                          "SELECT CONNECTION_ID()").toString();

                              System.out
                                          .println("Please kill the MySQL server now and press return...");
                              System.in.read();

                              System.out.println("Waiting for TCP/IP timeout...");
                              Thread.sleep(10);

                              System.out.println("Attempting auto reconnect");

                              try {
                                    clusterConn.setAutoCommit(true);
                                    clusterConn.setAutoCommit(false);
                              } catch (SQLException sqlEx) {
                                    System.out.println(sqlEx);
                              }

                              //
                              // Test that this 'new' connection is not read-only
                              //
                              clusterStmt
                                          .executeUpdate("UPDATE testClusterConn SET field1=5");

                              ResultSet rs = clusterStmt
                                          .executeQuery("SELECT * FROM testClusterConn WHERE field1=5");

                              assertTrue("One row should be returned", rs.next());
                        } finally {
                              if (clusterStmt != null) {
                                    clusterStmt
                                                .executeQuery("DROP TABLE IF EXISTS testClusterConn");
                                    clusterStmt.close();
                              }

                              if (clusterConn != null) {
                                    clusterConn.close();
                              }
                        }
                  }
            }
      }

      /**
       * DOCUMENT ME!
       * 
       * @throws Exception
       *             Old test was passing due to
       *             http://bugs.mysql.com/bug.php?id=989 which is fixed for 5.5+
       */
00192       public void testDeadlockDetection() throws Exception {
            try {
                  this.rs = this.stmt
                              .executeQuery("SHOW VARIABLES LIKE 'innodb_lock_wait_timeout'");
                  this.rs.next();

                  int timeoutSecs = this.rs.getInt(2);

                  createTable("t1", "(id INTEGER, x INTEGER) ", "INNODB");
                  this.stmt.executeUpdate("INSERT INTO t1 VALUES(0, 0)");
                  this.conn.setAutoCommit(false);

                  Properties props = new Properties();
                  props.setProperty("includeInnodbStatusInDeadlockExceptions", "true");
                  props.setProperty("includeThreadDumpInDeadlockExceptions", "true");

                  Connection deadlockConn = getConnectionWithProps(props);
                  deadlockConn.setAutoCommit(false);

                  try {
                        this.conn.createStatement().executeQuery(
                                    "SELECT * FROM t1 WHERE id=0 FOR UPDATE");

                        // The following query should hang because con1 is locking the
                        // page
                        deadlockConn.createStatement().executeUpdate(
                                    "UPDATE t1 SET x=2 WHERE id=0");
                  } finally {
                        if (versionMeetsMinimum(5, 5)) {
                              this.conn.commit();
                              deadlockConn.commit();
                        }
                  }

                  Thread.sleep(timeoutSecs * 2 * 1000);
            } catch (SQLException sqlEx) {
                  System.out
                              .println("Caught SQLException due to deadlock/lock timeout");
                  System.out.println("SQLState: " + sqlEx.getSQLState());
                  System.out.println("Vendor error: " + sqlEx.getErrorCode());
                  System.out.println("Message: " + sqlEx.getMessage());

                  //
                  // Check whether the driver thinks it really is deadlock...
                  //
                  assertTrue(SQLError.SQL_STATE_DEADLOCK.equals(sqlEx.getSQLState()));
                  assertTrue(sqlEx.getErrorCode() == 1205);
                  // Make sure INNODB Status is getting dumped into error message

                  if (sqlEx.getMessage().indexOf("PROCESS privilege") != -1) {
                        fail("This test requires user with process privilege");
                  }

                  assertTrue(
                              "Can't find INNODB MONITOR in:\n\n" + sqlEx.getMessage(),
                              sqlEx.getMessage().indexOf("INNODB MONITOR") != -1);
                  
                  assertTrue(
                              "Can't find thread dump in:\n\n" + sqlEx.getMessage(),
                              sqlEx.getMessage().indexOf("testsuite.simple.ConnectionTest.testDeadlockDetection") != -1);
                  
            } finally {
                  this.conn.setAutoCommit(true);
            }
      }

      /**
       * DOCUMENT ME!
       * 
       * @throws Exception
       *             DOCUMENT ME!
       */
00264       public void testCharsets() throws Exception {
            if (versionMeetsMinimum(4, 1)) {
                  Properties props = new Properties();
                  props.setProperty("useUnicode", "true");
                  props.setProperty("characterEncoding", "UTF-8");

                  Connection utfConn = getConnectionWithProps(props);

                  this.stmt = utfConn.createStatement();

                  createTable("t1", "(" + "comment CHAR(32) ASCII NOT NULL,"
                              + "koi8_ru_f CHAR(32) CHARACTER SET koi8r NOT NULL"
                              + ") CHARSET=latin5");

                  this.stmt
                              .executeUpdate("ALTER TABLE t1 CHANGE comment comment CHAR(32) CHARACTER SET latin2 NOT NULL");
                  this.stmt
                              .executeUpdate("ALTER TABLE t1 ADD latin5_f CHAR(32) NOT NULL");
                  this.stmt.executeUpdate("ALTER TABLE t1 CHARSET=latin2");
                  this.stmt
                              .executeUpdate("ALTER TABLE t1 ADD latin2_f CHAR(32) NOT NULL");
                  this.stmt
                              .executeUpdate("ALTER TABLE t1 DROP latin2_f, DROP latin5_f");

                  this.stmt
                              .executeUpdate("INSERT INTO t1 (koi8_ru_f,comment) VALUES ('a','LAT SMALL A')");
                  /*
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('b','LAT SMALL B')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('c','LAT SMALL C')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('d','LAT SMALL D')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('e','LAT SMALL E')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('f','LAT SMALL F')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('g','LAT SMALL G')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('h','LAT SMALL H')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('i','LAT SMALL I')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('j','LAT SMALL J')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('k','LAT SMALL K')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('l','LAT SMALL L')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('m','LAT SMALL M')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('n','LAT SMALL N')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('o','LAT SMALL O')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('p','LAT SMALL P')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('q','LAT SMALL Q')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('r','LAT SMALL R')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('s','LAT SMALL S')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('t','LAT SMALL T')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('u','LAT SMALL U')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('v','LAT SMALL V')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('w','LAT SMALL W')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('x','LAT SMALL X')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('y','LAT SMALL Y')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('z','LAT SMALL Z')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('A','LAT CAPIT A')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('B','LAT CAPIT B')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('C','LAT CAPIT C')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('D','LAT CAPIT D')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('E','LAT CAPIT E')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('F','LAT CAPIT F')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('G','LAT CAPIT G')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('H','LAT CAPIT H')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('I','LAT CAPIT I')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('J','LAT CAPIT J')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('K','LAT CAPIT K')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('L','LAT CAPIT L')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('M','LAT CAPIT M')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('N','LAT CAPIT N')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('O','LAT CAPIT O')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('P','LAT CAPIT P')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('Q','LAT CAPIT Q')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('R','LAT CAPIT R')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('S','LAT CAPIT S')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('T','LAT CAPIT T')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('U','LAT CAPIT U')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('V','LAT CAPIT V')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('W','LAT CAPIT W')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('X','LAT CAPIT X')"); this.stmt.executeUpdate("INSERT
                   * INTO t1 (koi8_ru_f,comment) VALUES ('Y','LAT CAPIT Y')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES ('Z','LAT CAPIT Z')");
                   */

                  String cyrillicSmallA = "\u0430";
                  this.stmt
                              .executeUpdate("INSERT INTO t1 (koi8_ru_f,comment) VALUES ('"
                                          + cyrillicSmallA + "','CYR SMALL A')");

                  /*
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL BE')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL VE')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL GE')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL DE')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL IE')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL IO')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL ZHE')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL ZE')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL I')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL KA')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL EL')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL EM')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL EN')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL O')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL PE')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL ER')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL ES')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL TE')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL U')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL EF')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL HA')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL TSE')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL CHE')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL SHA')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL SCHA')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL HARD SIGN')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL YERU')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL SOFT SIGN')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL E')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL YU')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR SMALL YA')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT A')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT BE')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT VE')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT GE')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT DE')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT IE')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT IO')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT ZHE')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT ZE')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT I')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT KA')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT EL')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT EM')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT EN')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT O')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT PE')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT ER')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT ES')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT TE')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT U')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT EF')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT HA')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT TSE')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT CHE')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT SHA')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT SCHA')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT HARD SIGN')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT YERU')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT SOFT SIGN')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT E')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT YU')");
                   * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
                   * VALUES (_koi8r'?��','CYR CAPIT YA')");
                   */

                  this.stmt
                              .executeUpdate("ALTER TABLE t1 ADD utf8_f CHAR(32) CHARACTER SET utf8 NOT NULL");
                  this.stmt
                              .executeUpdate("UPDATE t1 SET utf8_f=CONVERT(koi8_ru_f USING utf8)");
                  this.stmt.executeUpdate("SET CHARACTER SET koi8r");
                  // this.stmt.executeUpdate("SET CHARACTER SET UTF8");
                  this.rs = this.stmt.executeQuery("SELECT * FROM t1");

                  ResultSetMetaData rsmd = this.rs.getMetaData();

                  int numColumns = rsmd.getColumnCount();

                  for (int i = 0; i < numColumns; i++) {
                        System.out.print(rsmd.getColumnName(i + 1));
                        System.out.print("\t\t");
                  }

                  System.out.println();

                  while (this.rs.next()) {
                        System.out.println(this.rs.getString(1) + "\t\t"
                                    + this.rs.getString(2) + "\t\t" + this.rs.getString(3));

                        if (this.rs.getString(1).equals("CYR SMALL A")) {
                              this.rs.getString(2);
                        }
                  }

                  System.out.println();

                  this.stmt.executeUpdate("SET NAMES utf8");
                  this.rs = this.stmt.executeQuery("SELECT _koi8r 0xC1;");

                  rsmd = this.rs.getMetaData();

                  numColumns = rsmd.getColumnCount();

                  for (int i = 0; i < numColumns; i++) {
                        System.out.print(rsmd.getColumnName(i + 1));
                        System.out.print("\t\t");
                  }

                  System.out.println();

                  while (this.rs.next()) {
                        System.out.println(this.rs.getString(1).equals("\u0430")
                                    + "\t\t");
                        System.out.println(new String(this.rs.getBytes(1), "KOI8_R"));

                  }

                  char[] c = new char[] { 0xd0b0 };

                  System.out.println(new String(c));
                  System.out.println("\u0430");
            }
      }

      /**
       * Tests isolation level functionality
       * 
       * @throws Exception
       *             if an error occurs
       */
00568       public void testIsolationLevel() throws Exception {
            if (versionMeetsMinimum(4, 0)) {
                  String[] isoLevelNames = new String[] {
                              "Connection.TRANSACTION_NONE",
                              "Connection.TRANSACTION_READ_COMMITTED",
                              "Connection.TRANSACTION_READ_UNCOMMITTED",
                              "Connection.TRANSACTION_REPEATABLE_READ",
                              "Connection.TRANSACTION_SERIALIZABLE" };

                  int[] isolationLevels = new int[] { Connection.TRANSACTION_NONE,
                              Connection.TRANSACTION_READ_COMMITTED,
                              Connection.TRANSACTION_READ_UNCOMMITTED,
                              Connection.TRANSACTION_REPEATABLE_READ,
                              Connection.TRANSACTION_SERIALIZABLE };

                  DatabaseMetaData dbmd = this.conn.getMetaData();

                  for (int i = 0; i < isolationLevels.length; i++) {
                        if (dbmd.supportsTransactionIsolationLevel(isolationLevels[i])) {
                              this.conn.setTransactionIsolation(isolationLevels[i]);

                              assertTrue(
                                          "Transaction isolation level that was set ("
                                                      + isoLevelNames[i]
                                                      + ") was not returned, nor was a more restrictive isolation level used by the server",
                                          this.conn.getTransactionIsolation() == isolationLevels[i]
                                                      || this.conn.getTransactionIsolation() > isolationLevels[i]);
                        }
                  }
            }
      }

      /**
       * Tests the savepoint functionality in MySQL.
       * 
       * @throws Exception
       *             if an error occurs.
       */
00606       public void testSavepoint() throws Exception {
            if (!isRunningOnJdk131()) {
                  DatabaseMetaData dbmd = this.conn.getMetaData();

                  if (dbmd.supportsSavepoints()) {
                        System.out.println("Testing SAVEPOINTs");

                        try {
                              this.conn.setAutoCommit(true);

                              createTable("testSavepoints", "(field1 int)", "InnoDB");

                              // Try with named save points
                              this.conn.setAutoCommit(false);
                              this.stmt
                                          .executeUpdate("INSERT INTO testSavepoints VALUES (1)");

                              Savepoint afterInsert = this.conn
                                          .setSavepoint("afterInsert");
                              this.stmt
                                          .executeUpdate("UPDATE testSavepoints SET field1=2");

                              Savepoint afterUpdate = this.conn
                                          .setSavepoint("afterUpdate");
                              this.stmt.executeUpdate("DELETE FROM testSavepoints");

                              assertTrue("Row count should be 0",
                                          getRowCount("testSavepoints") == 0);
                              this.conn.rollback(afterUpdate);
                              assertTrue("Row count should be 1",
                                          getRowCount("testSavepoints") == 1);
                              assertTrue(
                                          "Value should be 2",
                                          "2".equals(getSingleValue("testSavepoints",
                                                      "field1", null).toString()));
                              this.conn.rollback(afterInsert);
                              assertTrue(
                                          "Value should be 1",
                                          "1".equals(getSingleValue("testSavepoints",
                                                      "field1", null).toString()));
                              this.conn.rollback();
                              assertTrue("Row count should be 0",
                                          getRowCount("testSavepoints") == 0);

                              // Try with 'anonymous' save points
                              this.conn.rollback();

                              this.stmt
                                          .executeUpdate("INSERT INTO testSavepoints VALUES (1)");
                              afterInsert = this.conn.setSavepoint();
                              this.stmt
                                          .executeUpdate("UPDATE testSavepoints SET field1=2");
                              afterUpdate = this.conn.setSavepoint();
                              this.stmt.executeUpdate("DELETE FROM testSavepoints");

                              assertTrue("Row count should be 0",
                                          getRowCount("testSavepoints") == 0);
                              this.conn.rollback(afterUpdate);
                              assertTrue("Row count should be 1",
                                          getRowCount("testSavepoints") == 1);
                              assertTrue(
                                          "Value should be 2",
                                          "2".equals(getSingleValue("testSavepoints",
                                                      "field1", null).toString()));
                              this.conn.rollback(afterInsert);
                              assertTrue(
                                          "Value should be 1",
                                          "1".equals(getSingleValue("testSavepoints",
                                                      "field1", null).toString()));
                              this.conn.rollback();

                              this.conn.releaseSavepoint(this.conn.setSavepoint());
                        } finally {
                              this.conn.setAutoCommit(true);
                        }
                  } else {
                        System.out.println("MySQL version does not support SAVEPOINTs");
                  }
            }
      }

      /**
       * Tests the ability to set the connection collation via properties.
       * 
       * @throws Exception
       *             if an error occurs or the test fails
       */
00693       public void testNonStandardConnectionCollation() throws Exception {
            if (versionMeetsMinimum(4, 1)) {
                  String collationToSet = "utf8_bin";
                  String characterSet = "utf-8";

                  Properties props = new Properties();
                  props.setProperty("connectionCollation", collationToSet);
                  props.setProperty("characterEncoding", characterSet);

                  Connection collConn = null;
                  Statement collStmt = null;
                  ResultSet collRs = null;

                  try {
                        collConn = getConnectionWithProps(props);

                        collStmt = collConn.createStatement();

                        collRs = collStmt
                                    .executeQuery("SHOW VARIABLES LIKE 'collation_connection'");

                        assertTrue(collRs.next());
                        assertTrue(collationToSet.equalsIgnoreCase(collRs.getString(2)));
                  } finally {
                        if (collConn != null) {
                              collConn.close();
                        }
                  }
            }
      }

      public void testDumpQueriesOnException() throws Exception {
            Properties props = new Properties();
            props.setProperty("dumpQueriesOnException", "true");
            String bogusSQL = "SELECT 1 TO BAZ";
            Connection dumpConn = getConnectionWithProps(props);

            try {
                  dumpConn.createStatement().executeQuery(bogusSQL);
            } catch (SQLException sqlEx) {
                  assertTrue(sqlEx.getMessage().indexOf(bogusSQL) != -1);
            }

            try {
                  ((com.mysql.jdbc.Connection) dumpConn).clientPrepareStatement(
                              bogusSQL).executeQuery();
            } catch (SQLException sqlEx) {
                  assertTrue(sqlEx.getMessage().indexOf(bogusSQL) != -1);
            }

            try {
                  createTable("testDumpQueriesOnException", "(field1 int UNIQUE)");
                  this.stmt
                              .executeUpdate("INSERT INTO testDumpQueriesOnException VALUES (1)");

                  PreparedStatement pStmt = dumpConn
                              .prepareStatement("INSERT INTO testDumpQueriesOnException VALUES (?)");
                  pStmt.setInt(1, 1);
                  pStmt.executeUpdate();
            } catch (SQLException sqlEx) {
                  assertTrue(sqlEx.getMessage().indexOf(
                              "INSERT INTO testDumpQueriesOnException") != -1);
            }

            try {
                  dumpConn.prepareStatement(bogusSQL);
            } catch (SQLException sqlEx) {
                  assertTrue(sqlEx.getMessage().indexOf(bogusSQL) != -1);
            }
      }

      /**
       * Tests functionality of the ConnectionPropertiesTransform interface.
       * 
       * @throws Exception
       *             if the test fails.
       */
00770       public void testConnectionPropertiesTransform() throws Exception {
            String transformClassName = SimpleTransformer.class.getName();

            Properties props = new Properties();

            props.setProperty(NonRegisteringDriver.PROPERTIES_TRANSFORM_KEY,
                        transformClassName);

            NonRegisteringDriver driver = new NonRegisteringDriver();

            Properties transformedProps = driver
                        .parseURL(BaseTestCase.dbUrl, props);

            assertTrue("albequerque".equals(transformedProps
                        .getProperty(NonRegisteringDriver.HOST_PROPERTY_KEY)));
      }

      /**
       * Tests functionality of using URLs in 'LOAD DATA LOCAL INFILE' statements.
       * 
       * @throws Exception
       *             if the test fails.
       */
00793       public void testLocalInfileWithUrl() throws Exception {
            File infile = File.createTempFile("foo", "txt");
            infile.deleteOnExit();
            String url = infile.toURL().toExternalForm();
            FileWriter output = new FileWriter(infile);
            output.write("Test");
            output.flush();
            output.close();

            createTable("testLocalInfileWithUrl", "(field1 LONGTEXT)");

            Properties props = new Properties();
            props.setProperty("allowUrlInLocalInfile", "true");

            Connection loadConn = getConnectionWithProps(props);
            Statement loadStmt = loadConn.createStatement();

            try {
                  loadStmt.executeQuery("LOAD DATA LOCAL INFILE '" + url
                              + "' INTO TABLE testLocalInfileWithUrl");
            } catch (SQLException sqlEx) {
                  sqlEx.printStackTrace();

                  throw sqlEx;
            }

            this.rs = this.stmt
                        .executeQuery("SELECT * FROM testLocalInfileWithUrl");
            assertTrue(this.rs.next());
            assertTrue("Test".equals(this.rs.getString(1)));
            int count = this.stmt
                        .executeUpdate("DELETE FROM testLocalInfileWithUrl");
            assertTrue(count == 1);

            StringBuffer escapedPath = new StringBuffer();
            String path = infile.getCanonicalPath();

            for (int i = 0; i < path.length(); i++) {
                  char c = path.charAt(i);

                  if (c == '\\') {
                        escapedPath.append('\\');
                  }

                  escapedPath.append(c);
            }

            loadStmt.executeQuery("LOAD DATA LOCAL INFILE '"
                        + escapedPath.toString()
                        + "' INTO TABLE testLocalInfileWithUrl");
            this.rs = this.stmt
                        .executeQuery("SELECT * FROM testLocalInfileWithUrl");
            assertTrue(this.rs.next());
            assertTrue("Test".equals(this.rs.getString(1)));

            try {
                  loadStmt.executeQuery("LOAD DATA LOCAL INFILE 'foo:///' INTO TABLE testLocalInfileWithUrl");
            } catch (SQLException sqlEx) {
                  assertTrue(sqlEx.getMessage() != null);
                  assertTrue(sqlEx.getMessage().indexOf("FileNotFoundException") != -1);
            }
      }

      public void testLocalInfileDisabled() throws Exception {
            createTable("testLocalInfileDisabled", "(field1 varchar(255))");

            File infile = File.createTempFile("foo", "txt");
            infile.deleteOnExit();
            String url = infile.toURL().toExternalForm();
            FileWriter output = new FileWriter(infile);
            output.write("Test");
            output.flush();
            output.close();

            Connection loadConn = getConnectionWithProps(new Properties());

            try {
                  // have to do this after connect, otherwise it's the server
                  // that's enforcing it
                  ((com.mysql.jdbc.Connection) loadConn)
                              .setAllowLoadLocalInfile(false);
                  try {
                        loadConn.createStatement().execute(
                                    "LOAD DATA LOCAL INFILE '" + infile.getCanonicalPath()
                                                + "' INTO TABLE testLocalInfileDisabled");
                        fail("Should've thrown an exception.");
                  } catch (SQLException sqlEx) {
                        assertEquals(SQLError.SQL_STATE_GENERAL_ERROR,
                                    sqlEx.getSQLState());
                  }

                  assertFalse(loadConn.createStatement()
                              .executeQuery("SELECT * FROM testLocalInfileDisabled")
                              .next());
            } finally {
                  loadConn.close();
            }
      }

      public void testServerConfigurationCache() throws Exception {
            Properties props = new Properties();

            props.setProperty("cacheServerConfiguration", "true");
            props.setProperty("profileSQL", "true");
            props.setProperty("logFactory", "com.mysql.jdbc.log.StandardLogger");

            Connection conn1 = getConnectionWithProps(props);

            // eliminate side-effects when not run in isolation
            StandardLogger.bufferedLog = new StringBuffer();

            Connection conn2 = getConnectionWithProps(props);

            StandardLogger.saveLogsToBuffer();

            assertTrue("Configuration wasn't cached", StandardLogger.bufferedLog
                        .toString().indexOf("SHOW VARIABLES") == -1);

            if (versionMeetsMinimum(4, 1)) {
                  assertTrue(
                              "Configuration wasn't cached",
                              StandardLogger.bufferedLog.toString().indexOf(
                                          "SHOW COLLATION") == -1);

            }
      }

      /**
       * Tests whether or not the configuration 'useLocalSessionState' actually
       * prevents non-needed 'set autocommit=', 'set session transaction isolation
       * ...' and 'show variables like tx_isolation' queries.
       * 
       * @throws Exception
       *             if the test fails.
       */
00928       public void testUseLocalSessionState() throws Exception {
            Properties props = new Properties();

            props.setProperty("useLocalSessionState", "true");
            props.setProperty("profileSQL", "true");
            props.setProperty("logFactory", "com.mysql.jdbc.log.StandardLogger");

            Connection conn1 = getConnectionWithProps(props);
            conn1.setAutoCommit(true);
            conn1.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);

            StandardLogger.saveLogsToBuffer();
            StandardLogger.bufferedLog.setLength(0);

            conn1.setAutoCommit(true);
            conn1.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
            conn1.getTransactionIsolation();

            String logAsString = StandardLogger.bufferedLog.toString();

            assertTrue(logAsString.indexOf("SET SESSION") == -1
                        && logAsString.indexOf("SHOW VARIABLES LIKE 'tx_isolation'") == -1
                        && logAsString.indexOf("SET autocommit=") == -1);
      }

      /**
       * Tests whether re-connect with non-read-only connection can happen.
       * 
       * @throws Exception
       *             if the test fails.
       */
00959       public void testFailoverConnection() throws Exception {

            if (!isServerRunningOnWindows()) { // windows sockets don't
                                                                  // work for this test
                  Properties props = new Properties();
                  props.setProperty("autoReconnect", "true");
                  props.setProperty("failOverReadOnly", "false");

                  Properties urlProps = new NonRegisteringDriver().parseURL(
                              this.dbUrl, null);

                  String host = urlProps.getProperty(Driver.HOST_PROPERTY_KEY);
                  String port = urlProps.getProperty(Driver.PORT_PROPERTY_KEY);

                  props.setProperty(Driver.HOST_PROPERTY_KEY + ".1", host);
                  props.setProperty(Driver.PORT_PROPERTY_KEY + ".1", port);
                  props.setProperty(Driver.HOST_PROPERTY_KEY + ".2", host);
                  props.setProperty(Driver.PORT_PROPERTY_KEY + ".2", port);
                  props.setProperty(Driver.NUM_HOSTS_PROPERTY_KEY, "2");

                  Connection failoverConnection = null;

                  try {
                        failoverConnection = getConnectionWithProps(props);

                        String originalConnectionId = getSingleIndexedValueWithQuery(
                                    failoverConnection, 1, "SELECT connection_id()")
                                    .toString();
                        System.out.println("Original Connection Id = "
                                    + originalConnectionId);

                        assertTrue("Connection should not be in READ_ONLY state",
                                    !failoverConnection.isReadOnly());

                        // Kill the connection
                        this.stmt.executeUpdate("KILL " + originalConnectionId);

                        // This takes a bit to occur

                        Thread.sleep(3000);

                        try {
                              failoverConnection.createStatement().executeQuery(
                                          "SELECT 1");
                              fail("We expect an exception here, because the connection should be gone until the reconnect code picks it up again");
                        } catch (SQLException sqlEx) {
                              ; // do-nothing
                        }

                        // Tickle re-connect

                        failoverConnection.setAutoCommit(true);

                        String newConnectionId = getSingleIndexedValueWithQuery(
                                    failoverConnection, 1, "SELECT connection_id()")
                                    .toString();
                        System.out.println("new Connection Id = " + newConnectionId);

                        assertTrue(
                                    "We should have a new connection to the server in this case",
                                    !newConnectionId.equals(originalConnectionId));
                        assertTrue("Connection should not be read-only",
                                    !failoverConnection.isReadOnly());
                  } finally {
                        if (failoverConnection != null) {
                              failoverConnection.close();
                        }
                  }
            }
      }

      public void testCannedConfigs() throws Exception {
            String url = "jdbc:mysql:///?useConfigs=clusterBase";

            Properties cannedProps = new NonRegisteringDriver().parseURL(url, null);

            assertTrue("true".equals(cannedProps.getProperty("autoReconnect")));
            assertTrue("false".equals(cannedProps.getProperty("failOverReadOnly")));
            assertTrue("true".equals(cannedProps
                        .getProperty("roundRobinLoadBalance")));

            // this will fail, but we test that too
            url = "jdbc:mysql:///?useConfigs=clusterBase,clusterBase2";

            try {
                  cannedProps = new NonRegisteringDriver().parseURL(url, null);
                  fail("should've bailed on that one!");
            } catch (SQLException sqlEx) {
                  assertTrue(SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE
                              .equals(sqlEx.getSQLState()));
            }
      }

      public void testUseOldUTF8Behavior() throws Exception {

            Properties props = new Properties();
            props.setProperty("useOldUTF8Behavior", "true");
            props.setProperty("useUnicode", "true");
            props.setProperty("characterEncoding", "UTF-8");
            props.setProperty("logFactory", "com.mysql.jdbc.log.StandardLogger");
            props.setProperty("profileSQL", "true");
            StandardLogger.saveLogsToBuffer();
            StandardLogger.bufferedLog.setLength(0);

            try {
                  getConnectionWithProps(props);

                  assertTrue(StringUtils.indexOfIgnoreCase(
                              StandardLogger.bufferedLog.toString(), "SET NAMES utf8") == -1);
            } finally {
                  StandardLogger.bufferedLog = null;
            }
      }

      /**
       * Checks implementation of 'dontTrackOpenResources' property.
       * 
       * @throws Exception
       *             if the test fails.
       */
01079       public void testDontTrackOpenResources() throws Exception {
            Properties props = new Properties();

            props.setProperty("dontTrackOpenResources", "true");
            Connection noTrackConn = null;
            Statement noTrackStatement = null;
            PreparedStatement noTrackPstmt = null;
            ResultSet rs2 = null;

            try {
                  noTrackConn = getConnectionWithProps(props);
                  noTrackStatement = noTrackConn.createStatement();
                  noTrackPstmt = noTrackConn.prepareStatement("SELECT 1");
                  rs2 = noTrackPstmt.executeQuery();
                  rs2.next();

                  this.rs = noTrackStatement.executeQuery("SELECT 1");
                  this.rs.next();

                  noTrackConn.close();

                  // Under 'strict' JDBC requirements, these calls should fail
                  // (and _do_ if dontTrackOpenResources == false)

                  this.rs.getString(1);
                  rs2.getString(1);
            } finally {
                  if (rs2 != null) {
                        rs2.close();
                  }

                  if (noTrackStatement != null) {
                        noTrackStatement.close();
                  }

                  if (noTrackConn != null && !noTrackConn.isClosed()) {
                        noTrackConn.close();
                  }
            }
      }

      public void testPing() throws SQLException {
            Connection conn2 = getConnectionWithProps((String) null);

            ((com.mysql.jdbc.Connection) conn2).ping();
            conn2.close();

            try {
                  ((com.mysql.jdbc.Connection) conn2).ping();
                  fail("Should have failed with an exception");
            } catch (SQLException sqlEx) {
                  // ignore for now
            }

            //
            // This feature caused BUG#8975, so check for that too!

            Properties props = new Properties();
            props.setProperty("autoReconnect", "true");

            getConnectionWithProps(props);
      }

      public void testSessionVariables() throws Exception {
            String getInitialWaitTimeout = getMysqlVariable("wait_timeout");

            int newWaitTimeout = Integer.parseInt(getInitialWaitTimeout) + 10000;

            Properties props = new Properties();
            props.setProperty("sessionVariables", "wait_timeout=" + newWaitTimeout);
            props.setProperty("profileSQL", "true");

            Connection varConn = getConnectionWithProps(props);

            assertTrue(!getInitialWaitTimeout.equals(getMysqlVariable(varConn,
                        "wait_timeout")));
      }

      /**
       * Tests setting profileSql on/off in the span of one connection.
       * 
       * @throws Exception
       *             if an error occurs.
       */
01163       public void testSetProfileSql() throws Exception {
            ((com.mysql.jdbc.Connection) this.conn).setProfileSql(false);
            stmt.executeQuery("SELECT 1");
            ((com.mysql.jdbc.Connection) this.conn).setProfileSql(true);
            stmt.executeQuery("SELECT 1");
      }

      public void testCreateDatabaseIfNotExist() throws Exception {
            if (isAdminConnectionConfigured()) {
                  Properties props = new Properties();
                  props.setProperty("createDatabaseIfNotExist", "true");
                  props.setProperty(NonRegisteringDriver.DBNAME_PROPERTY_KEY,
                              "testcreatedatabaseifnotexists");

                  Connection newConn = getAdminConnectionWithProps(props);
                  newConn.createStatement().executeUpdate(
                              "DROP DATABASE testcreatedatabaseifnotexists");
            }
      }

      /**
       * Tests if gatherPerfMetrics works.
       * 
       * @throws Exception
       *             if the test fails
       */
01189       public void testGatherPerfMetrics() throws Exception {
            if (versionMeetsMinimum(4, 1)) {
                  try {
                        Properties props = new Properties();
                        props.put("autoReconnect", "true");
                        props.put("relaxAutoCommit", "true");
                        props.put("logSlowQueries", "true");
                        props.put("slowQueryThresholdMillis", "2000");
                        // these properties were reported as the cause of
                        // NullPointerException
                        props.put("gatherPerfMetrics", "true");
                        props.put("reportMetricsIntervalMillis", "3000");

                        Connection conn1 = getConnectionWithProps(props);
                        Statement stmt1 = conn1.createStatement();
                        ResultSet rs1 = stmt1.executeQuery("SELECT 1");
                        rs1.next();
                        conn1.close();
                  } catch (NullPointerException e) {
                        e.printStackTrace();
                        fail();
                  }
            }
      }

      /**
       * Tests if useCompress works.
       * 
       * @throws Exception
       *             if the test fails
       */
01220       public void testUseCompress() throws Exception {

            // Original test
            // Properties props = new Properties();
            // props.put("useCompression", "true");
            // props.put("traceProtocol", "true");
            // Connection conn1 = getConnectionWithProps(props);
            // Statement stmt1 = conn1.createStatement();
            // ResultSet rs1 = stmt1.executeQuery("SELECT VERSION()");
            // rs1.next();
            // rs1.getString(1);
            // stmt1.close();
            // conn1.close();

            File testBlobFile = null;
            int requiredSize = 0;

            Properties props = new Properties();
            props.put("useCompression", "true");
            Connection conn1 = getConnectionWithProps(props);

            Statement stmt1 = conn1.createStatement();
            // Get real value
            this.rs = stmt1
                        .executeQuery("SHOW VARIABLES LIKE 'max_allowed_packet'");
            this.rs.next();
            // Create smaller than maximum allowed BLOB for testing
            requiredSize = this.rs.getInt(2) / 8;
            System.out.println("Required size: " + requiredSize);
            this.rs.close();

            // http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html#sysvar_max_allowed_packet
            // setting GLOBAL variable during test is not ok
            // The protocol limit for max_allowed_packet is 1GB.
            if (testBlobFile == null || testBlobFile.length() != requiredSize) {
                  if (testBlobFile != null && testBlobFile.length() != requiredSize) {
                        testBlobFile.delete();
                  }

                  testBlobFile = File.createTempFile("cmj-testblob", ".dat");
                  testBlobFile.deleteOnExit();

                  cleanupTempFiles(testBlobFile, "cmj-testblob");

                  BufferedOutputStream bOut = new BufferedOutputStream(
                              new FileOutputStream(testBlobFile));

                  int dataRange = Byte.MAX_VALUE - Byte.MIN_VALUE;

                  for (int i = 0; i < requiredSize; i++) {
                        bOut.write((byte) ((Math.random() * dataRange) + Byte.MIN_VALUE));
                  }

                  bOut.flush();
                  bOut.close();
            }

            createTable("BLOBTEST",
                        "(pos int PRIMARY KEY auto_increment, blobdata LONGBLOB)");
            BufferedInputStream bIn = new BufferedInputStream(new FileInputStream(
                        testBlobFile));

            this.pstmt = conn1
                        .prepareStatement("INSERT INTO BLOBTEST(blobdata) VALUES (?)");
            this.pstmt.setBinaryStream(1, bIn, (int) testBlobFile.length());
            this.pstmt.execute();
            this.pstmt.clearParameters();

            this.rs = stmt1.executeQuery("SELECT blobdata from BLOBTEST LIMIT 1");
            this.rs.next();

            if (bIn != null) {
                  bIn.close();
            }
      }

      /**
       * Tests feature of "localSocketAddress", by enumerating local IF's and
       * trying each one in turn. This test might take a long time to run, since
       * we can't set timeouts if we're using localSocketAddress. We try and keep
       * the time down on the testcase by spawning the checking of each interface
       * off into separate threads.
       * 
       * @throws Exception
       *             if the test can't use at least one of the local machine's
       *             interfaces to make an outgoing connection to the server.
       */
01307       public void testLocalSocketAddress() throws Exception {
            if (isRunningOnJdk131()) {
                  return;
            }

            Enumeration allInterfaces = NetworkInterface.getNetworkInterfaces();

            SpawnedWorkerCounter counter = new SpawnedWorkerCounter();

            List allChecks = new ArrayList();

            while (allInterfaces.hasMoreElements()) {
                  NetworkInterface intf = (NetworkInterface) allInterfaces
                              .nextElement();

                  Enumeration allAddresses = intf.getInetAddresses();

                  allChecks.add(new LocalSocketAddressCheckThread(allAddresses,
                              counter));
            }

            counter.setWorkerCount(allChecks.size());

            for (Iterator it = allChecks.iterator(); it.hasNext();) {
                  LocalSocketAddressCheckThread t = (LocalSocketAddressCheckThread) it
                              .next();
                  t.start();
            }

            // Wait for tests to complete....
            synchronized (counter) {

                  while (counter.workerCount > 0 /* safety valve */) {

                        counter.wait();

                        if (counter.workerCount == 0) {
                              System.out.println("Done!");
                              break;
                        }
                  }
            }

            boolean didOneWork = false;
            boolean didOneFail = false;

            for (Iterator it = allChecks.iterator(); it.hasNext();) {
                  LocalSocketAddressCheckThread t = (LocalSocketAddressCheckThread) it
                              .next();

                  if (t.atLeastOneWorked) {
                        didOneWork = true;

                        break;
                  } else {
                        if (!didOneFail) {
                              didOneFail = true;
                        }
                  }
            }

            assertTrue(
                        "At least one connection was made with the localSocketAddress set",
                        didOneWork);

            NonRegisteringDriver d = new NonRegisteringDriver();

            String hostname = d.host(d.parseURL(dbUrl, null));

            if (!hostname.startsWith(":") && !hostname.startsWith("localhost")) {

                  int indexOfColon = hostname.indexOf(":");

                  if (indexOfColon != -1) {
                        hostname = hostname.substring(0, indexOfColon);
                  }

                  boolean isLocalIf = false;

                  isLocalIf = (null != NetworkInterface.getByName(hostname));

                  if (!isLocalIf) {
                        try {
                              isLocalIf = (null != NetworkInterface
                                          .getByInetAddress(InetAddress.getByName(hostname)));
                        } catch (Throwable t) {
                              isLocalIf = false;
                        }
                  }

                  if (!isLocalIf) {
                        assertTrue(
                                    "At least one connection didn't fail with localSocketAddress set",
                                    didOneFail);
                  }
            }
      }

01405       class SpawnedWorkerCounter {
            private int workerCount = 0;

            synchronized void setWorkerCount(int i) {
                  workerCount = i;
            }

            synchronized void decrementWorkerCount() {
                  workerCount--;
                  notify();
            }
      }

01418       class LocalSocketAddressCheckThread extends Thread {
            boolean atLeastOneWorked = false;
            Enumeration allAddresses = null;
            SpawnedWorkerCounter counter = null;

            LocalSocketAddressCheckThread(Enumeration e, SpawnedWorkerCounter c) {
                  allAddresses = e;
                  counter = c;
            }

            public void run() {

                  while (allAddresses.hasMoreElements()) {
                        InetAddress addr = (InetAddress) allAddresses.nextElement();

                        try {
                              Properties props = new Properties();
                              props.setProperty("localSocketAddress",
                                          addr.getHostAddress());
                              props.setProperty("connectTimeout", "2000");
                              getConnectionWithProps(props).close();

                              atLeastOneWorked = true;

                              break;
                        } catch (SQLException sqlEx) {
                              // ignore, we're only seeing if one of these tests succeeds
                        }
                  }

                  counter.decrementWorkerCount();
            }
      }

      public void testUsageAdvisorTooLargeResultSet() throws Exception {
            Connection uaConn = null;

            PrintStream stderr = System.err;

            StringBuffer logBuf = new StringBuffer();

            StandardLogger.bufferedLog = logBuf;

            try {
                  Properties props = new Properties();
                  props.setProperty("useUsageAdvisor", "true");
                  props.setProperty("resultSetSizeThreshold", "4");
                  props.setProperty("logger", "StandardLogger");

                  uaConn = getConnectionWithProps(props);

                  assertTrue(
                              "Result set threshold message not present",
                              logBuf.toString().indexOf(
                                          "larger than \"resultSetSizeThreshold\" of 4 rows") != -1);
            } finally {
                  System.setErr(stderr);

                  if (uaConn != null) {
                        uaConn.close();
                  }
            }
      }

      public void testUseLocalSessionStateRollback() throws Exception {
            if (!versionMeetsMinimum(6, 0, 0)) {
                  return;
            }

            Properties props = new Properties();
            props.setProperty("useLocalSessionState", "true");
            props.setProperty("useLocalTransactionState", "true");
            props.setProperty("profileSQL", "true");

            StringBuffer buf = new StringBuffer();
            StandardLogger.bufferedLog = buf;

            createTable("testUseLocalSessionState", "(field1 varchar(32))",
                        "InnoDB");

            Connection localStateConn = null;
            Statement localStateStmt = null;

            try {
                  localStateConn = getConnectionWithProps(props);
                  localStateStmt = localStateConn.createStatement();

                  localStateConn.setAutoCommit(false);
                  localStateStmt
                              .executeUpdate("INSERT INTO testUseLocalSessionState VALUES ('abc')");
                  localStateConn.rollback();
                  localStateConn.rollback();
                  localStateStmt
                              .executeUpdate("INSERT INTO testUseLocalSessionState VALUES ('abc')");
                  localStateConn.commit();
                  localStateConn.commit();
                  localStateStmt.close();
            } finally {
                  StandardLogger.bufferedLog = null;

                  if (localStateStmt != null) {
                        localStateStmt.close();
                  }

                  if (localStateConn != null) {
                        localStateConn.close();
                  }
            }

            int rollbackCount = 0;
            int rollbackPos = 0;

            String searchIn = buf.toString();

            while (rollbackPos != -1) {
                  rollbackPos = searchIn.indexOf("rollback", rollbackPos);

                  if (rollbackPos != -1) {
                        rollbackPos += "rollback".length();
                        rollbackCount++;
                  }
            }

            assertEquals(1, rollbackCount);

            int commitCount = 0;
            int commitPos = 0;

            // space is important here, we don't want to count "autocommit"
            while (commitPos != -1) {
                  commitPos = searchIn.indexOf(" commit", commitPos);

                  if (commitPos != -1) {
                        commitPos += " commit".length();
                        commitCount++;
                  }
            }

            assertEquals(1, commitCount);
      }

      /**
       * Checks if setting useCursorFetch to "true" automatically enables
       * server-side prepared statements.
       */

01564       public void testCouplingOfCursorFetch() throws Exception {
            if (!versionMeetsMinimum(5, 0)) {
                  return;
            }

            Connection fetchConn = null;

            try {
                  Properties props = new Properties();
                  props.setProperty("useServerPrepStmts", "false"); // force the issue
                  props.setProperty("useCursorFetch", "true");
                  fetchConn = getConnectionWithProps(props);

                  String classname = "com.mysql.jdbc.ServerPreparedStatement";

                  if (Util.isJdbc4()) {
                        classname = "com.mysql.jdbc.JDBC4ServerPreparedStatement";
                  }

                  assertEquals(classname, fetchConn.prepareStatement("SELECT 1")
                              .getClass().getName());
            } finally {
                  if (fetchConn != null) {
                        fetchConn.close();
                  }
            }
      }

      public void testInterfaceImplementation() throws Exception {
            testInterfaceImplementation(getConnectionWithProps((Properties) null));
            MysqlConnectionPoolDataSource cpds = new MysqlConnectionPoolDataSource();
            cpds.setUrl(dbUrl);
            testInterfaceImplementation(cpds.getPooledConnection().getConnection());
      }

      private void testInterfaceImplementation(Connection connToCheck)
                  throws Exception {
            Method[] dbmdMethods = java.sql.DatabaseMetaData.class.getMethods();

            // can't do this statically, as we return different
            // implementations depending on JDBC version
            DatabaseMetaData dbmd = connToCheck.getMetaData();

            checkInterfaceImplemented(dbmdMethods, dbmd.getClass(), dbmd);

            Statement stmtToCheck = connToCheck.createStatement();

            checkInterfaceImplemented(java.sql.Statement.class.getMethods(),
                        stmtToCheck.getClass(), stmtToCheck);

            PreparedStatement pStmtToCheck = connToCheck
                        .prepareStatement("SELECT 1");
            ParameterMetaData paramMd = pStmtToCheck.getParameterMetaData();

            checkInterfaceImplemented(
                        java.sql.PreparedStatement.class.getMethods(),
                        pStmtToCheck.getClass(), pStmtToCheck);
            checkInterfaceImplemented(
                        java.sql.ParameterMetaData.class.getMethods(),
                        paramMd.getClass(), paramMd);

            pStmtToCheck = ((com.mysql.jdbc.Connection) connToCheck)
                        .serverPrepareStatement("SELECT 1");

            checkInterfaceImplemented(
                        java.sql.PreparedStatement.class.getMethods(),
                        pStmtToCheck.getClass(), pStmtToCheck);
            ResultSet toCheckRs = connToCheck.createStatement().executeQuery(
                        "SELECT 1");
            checkInterfaceImplemented(java.sql.ResultSet.class.getMethods(),
                        toCheckRs.getClass(), toCheckRs);
            toCheckRs = connToCheck.createStatement().executeQuery("SELECT 1");
            checkInterfaceImplemented(
                        java.sql.ResultSetMetaData.class.getMethods(), toCheckRs
                                    .getMetaData().getClass(), toCheckRs.getMetaData());

            if (versionMeetsMinimum(5, 0, 0)) {
                  createProcedure("interfaceImpl",
                              "(IN p1 INT)\nBEGIN\nSELECT 1;\nEND");

                  CallableStatement cstmt = connToCheck
                              .prepareCall("{CALL interfaceImpl(?)}");

                  checkInterfaceImplemented(
                              java.sql.CallableStatement.class.getMethods(),
                              cstmt.getClass(), cstmt);
            }
            checkInterfaceImplemented(java.sql.Connection.class.getMethods(),
                        connToCheck.getClass(), connToCheck);
      }

      private void checkInterfaceImplemented(Method[] interfaceMethods,
                  Class implementingClass, Object invokeOn)
                  throws NoSuchMethodException {
            for (int i = 0; i < interfaceMethods.length; i++) {
                  Method toFind = interfaceMethods[i];
                  Method toMatch = implementingClass.getMethod(toFind.getName(),
                              toFind.getParameterTypes());
                  assertNotNull(toFind.toString(), toMatch);
                  Class paramTypes[] = toFind.getParameterTypes();

                  Object[] args = new Object[paramTypes.length];
                  fillPrimitiveDefaults(paramTypes, args, paramTypes.length);

                  try {
                        toMatch.invoke(invokeOn, args);
                  } catch (IllegalArgumentException e) {

                  } catch (IllegalAccessException e) {

                  } catch (InvocationTargetException e) {

                  } catch (java.lang.AbstractMethodError e) {
                        throw e;
                  }
            }
      }

      public void testNonVerifyServerCert() throws Exception {
            getConnectionWithProps("useSSL=true,verifyServerCertificate=false,requireSSL=true");
      }

      public void testSelfDestruct() throws Exception {
            Connection selfDestructingConn = getConnectionWithProps("selfDestructOnPingMaxOperations=2");

            boolean failed = false;

            for (int i = 0; i < 20; i++) {
                  selfDestructingConn.createStatement().executeQuery("SELECT 1");

                  try {
                        selfDestructingConn.createStatement().executeQuery(
                                    "/* ping */ SELECT 1");
                  } catch (SQLException sqlEx) {
                        String sqlState = sqlEx.getSQLState();

                        assertEquals("08S01", sqlState);

                        failed = true;

                        break;
                  }
            }

            if (!failed) {
                  fail("Connection should've self-destructed");
            }

            failed = false;

            selfDestructingConn = getConnectionWithProps("selfDestructOnPingSecondsLifetime=1");

            long begin = System.currentTimeMillis();

            for (int i = 0; i < 20; i++) {
                  selfDestructingConn.createStatement().executeQuery(
                              "SELECT SLEEP(1)");

                  try {
                        selfDestructingConn.createStatement().executeQuery(
                                    "/* ping */ SELECT 1");
                  } catch (SQLException sqlEx) {
                        String sqlState = sqlEx.getSQLState();

                        assertEquals("08S01", sqlState);

                        failed = true;

                        break;
                  }
            }

            if (!failed) {
                  fail("Connection should've self-destructed");
            }
      }

      public void testLifecyleInterceptor() throws Exception {
            createTable("testLifecycleInterceptor", "(field1 int)", "InnoDB");
            Connection liConn = null;

            try {
                  liConn = getConnectionWithProps("connectionLifecycleInterceptors=testsuite.simple.TestLifecycleInterceptor");
                  liConn.setAutoCommit(false);

                  liConn.createStatement().executeUpdate(
                              "INSERT INTO testLifecycleInterceptor VALUES (1)");
                  liConn.commit();
                  assertEquals(TestLifecycleInterceptor.transactionsBegun, 1);
                  assertEquals(TestLifecycleInterceptor.transactionsCompleted, 1);
                  liConn.createStatement().executeQuery(
                              "SELECT * FROM testLifecycleInterceptor");
                  assertEquals(TestLifecycleInterceptor.transactionsBegun, 2);
                  // implicit commit
                  liConn.createStatement().executeUpdate(
                              "CREATE TABLE testLifecycleFoo (field1 int)");
                  assertEquals(TestLifecycleInterceptor.transactionsCompleted, 2);
            } finally {
                  if (liConn != null) {
                        liConn.createStatement().executeUpdate(
                                    "DROP TABLE IF EXISTS testLifecycleFoo");
                        liConn.close();
                  }
            }

      }

      public void testNewHostParsing() throws Exception {
            Properties parsedProps = new NonRegisteringDriver().parseURL(dbUrl,
                        null);
            String host = parsedProps
                        .getProperty(NonRegisteringDriver.HOST_PROPERTY_KEY);
            String port = parsedProps
                        .getProperty(NonRegisteringDriver.PORT_PROPERTY_KEY);
            String user = parsedProps
                        .getProperty(NonRegisteringDriver.USER_PROPERTY_KEY);
            String password = parsedProps
                        .getProperty(NonRegisteringDriver.PASSWORD_PROPERTY_KEY);
            String database = parsedProps
                        .getProperty(NonRegisteringDriver.DBNAME_PROPERTY_KEY);

            String newUrl = String
                        .format("jdbc:mysql://address=(protocol=tcp)(host=%s)(port=%s)(user=%s)(password=%s)/%s",
                                    host, port, user != null ? user : "",
                                    password != null ? password : "", database);

            try {
                  getConnectionWithProps(newUrl, new Properties());
            } catch (SQLException sqlEx) {
                  throw new RuntimeException("Failed to connect with URL " + newUrl,
                              sqlEx);
            }
      }

      public void testCompression() throws Exception {
            Connection compressedConn = getConnectionWithProps("useCompression=true,maxAllowedPacket=33554432");
            Statement compressedStmt = compressedConn.createStatement();
            compressedStmt.setFetchSize(Integer.MIN_VALUE);
            this.rs = compressedStmt
                        .executeQuery("select repeat('a', 256 * 256 * 256 - 5)");
            this.rs.next();
            String str = rs.getString(1);

            assertEquals((256 * 256 * 256 - 5), str.length());

            for (int i = 0; i < str.length(); i++) {
                  if (str.charAt(i) != 'a') {
                        fail();
                  }
            }
      }
      
      public void testIsLocal() throws Exception {
            Properties parsedProps = new NonRegisteringDriver().parseURL(dbUrl, null);
            String host = parsedProps.getProperty(NonRegisteringDriver.HOST_PROPERTY_KEY, "localhost");
            
            if (host.equals("localhost") || host.equals("127.0.0.1")) {
                  // we can actually test this
                  assertTrue(((com.mysql.jdbc.ConnectionImpl) this.conn).isServerLocal());
            }
            
      }
}

Generated by  Doxygen 1.6.0   Back to index