Package testsuite.simple

Source Code of testsuite.simple.CallableStatementTest

/*
Copyright (c) 2002, 2012, 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.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ParameterMetaData;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Properties;

import testsuite.BaseTestCase;

import com.mysql.jdbc.SQLError;
import com.mysql.jdbc.log.StandardLogger;

/**
* Tests callable statement functionality.
*
* @author Mark Matthews
* @version $Id: CallableStatementTest.java,v 1.1.2.1 2005/05/13 18:58:37
*          mmatthews Exp $
*/
public class CallableStatementTest extends BaseTestCase {
  /**
   * DOCUMENT ME!
   *
   * @param name
   */
  public CallableStatementTest(String name) {
    super(name);
  }

  /**
   * Tests functioning of inout parameters
   *
   * @throws Exception
   *             if the test fails
   */

  public void testInOutParams() throws Exception {
    if (versionMeetsMinimum(5, 0)) {
      CallableStatement storedProc = null;

      createProcedure("testInOutParam",
          "(IN p1 VARCHAR(255), INOUT p2 INT)\n" + "begin\n"
              + " DECLARE z INT;\n" + "SET z = p2 + 1;\n"
              + "SET p2 = z;\n" + "SELECT p1;\n"
              + "SELECT CONCAT('zyxw', p1);\n" + "end\n");

      storedProc = this.conn.prepareCall("{call testInOutParam(?, ?)}");

      storedProc.setString(1, "abcd");
      storedProc.setInt(2, 4);
      storedProc.registerOutParameter(2, Types.INTEGER);

      storedProc.execute();

      assertEquals(5, storedProc.getInt(2));

    }
  }

  public void testBatch() throws Exception {
    if (versionMeetsMinimum(5, 0)) {
      Connection batchedConn = null;

      try {
        createTable("testBatchTable", "(field1 INT)");
        createProcedure("testBatch", "(IN foo VARCHAR(15))\n"
            + "begin\n"
            + "INSERT INTO testBatchTable VALUES (foo);\n"
            + "end\n");

        executeBatchedStoredProc(this.conn);

        batchedConn = getConnectionWithProps("logger=StandardLogger,rewriteBatchedStatements=true,profileSQL=true");

        StringBuffer outBuf = new StringBuffer();
        StandardLogger.bufferedLog = outBuf;
        executeBatchedStoredProc(batchedConn);
        String[] log = outBuf.toString().split(";");
        assertTrue(log.length > 20);
      } finally {
        StandardLogger.bufferedLog = null;

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

  private void executeBatchedStoredProc(Connection c) throws Exception {
    this.stmt.executeUpdate("TRUNCATE TABLE testBatchTable");

    CallableStatement storedProc = c.prepareCall("{call testBatch(?)}");

    try {
      int numBatches = 300;

      for (int i = 0; i < numBatches; i++) {
        storedProc.setInt(1, i + 1);
        storedProc.addBatch();
      }

      int[] counts = storedProc.executeBatch();

      assertEquals(numBatches, counts.length);

      for (int i = 0; i < numBatches; i++) {
        assertEquals(1, counts[i]);
      }

      this.rs = this.stmt
          .executeQuery("SELECT field1 FROM testBatchTable ORDER BY field1 ASC");

      for (int i = 0; i < numBatches; i++) {
        assertTrue(this.rs.next());
        assertEquals(i + 1, this.rs.getInt(1));
      }
    } finally {

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

  /**
   * Tests functioning of output parameters.
   *
   * @throws Exception
   *             if the test fails.
   */
  public void testOutParams() throws Exception {
    if (versionMeetsMinimum(5, 0)) {
      CallableStatement storedProc = null;

      createProcedure("testOutParam", "(x int, out y int)\n" + "begin\n"
          + "declare z int;\n" + "set z = x+1, y = z;\n" + "end\n");

      storedProc = this.conn.prepareCall("{call testOutParam(?, ?)}");

      storedProc.setInt(1, 5);
      storedProc.registerOutParameter(2, Types.INTEGER);

      storedProc.execute();

      System.out.println(storedProc);

      int indexedOutParamToTest = storedProc.getInt(2);

      if (!isRunningOnJdk131()) {
        int namedOutParamToTest = storedProc.getInt("y");

        assertTrue("Named and indexed parameter are not the same",
            indexedOutParamToTest == namedOutParamToTest);
        assertTrue("Output value not returned correctly",
            indexedOutParamToTest == 6);

        // Start over, using named parameters, this time
        storedProc.clearParameters();
        storedProc.setInt("x", 32);
        storedProc.registerOutParameter("y", Types.INTEGER);

        storedProc.execute();

        indexedOutParamToTest = storedProc.getInt(2);
        namedOutParamToTest = storedProc.getInt("y");

        assertTrue("Named and indexed parameter are not the same",
            indexedOutParamToTest == namedOutParamToTest);
        assertTrue("Output value not returned correctly",
            indexedOutParamToTest == 33);

        try {
          storedProc.registerOutParameter("x", Types.INTEGER);
          assertTrue(
              "Should not be able to register an out parameter on a non-out parameter",
              true);
        } catch (SQLException sqlEx) {
          if (!SQLError.SQL_STATE_ILLEGAL_ARGUMENT.equals(sqlEx
              .getSQLState())) {
            throw sqlEx;
          }
        }

        try {
          storedProc.getInt("x");
          assertTrue(
              "Should not be able to retreive an out parameter on a non-out parameter",
              true);
        } catch (SQLException sqlEx) {
          if (!SQLError.SQL_STATE_COLUMN_NOT_FOUND.equals(sqlEx
              .getSQLState())) {
            throw sqlEx;
          }
        }
      }

      try {
        storedProc.registerOutParameter(1, Types.INTEGER);
        assertTrue(
            "Should not be able to register an out parameter on a non-out parameter",
            true);
      } catch (SQLException sqlEx) {
        if (!SQLError.SQL_STATE_ILLEGAL_ARGUMENT.equals(sqlEx
            .getSQLState())) {
          throw sqlEx;
        }
      }
    }
  }

  /**
   * Tests functioning of output parameters.
   *
   * @throws Exception
   *             if the test fails.
   */
  public void testResultSet() throws Exception {
    if (versionMeetsMinimum(5, 0)) {
      CallableStatement storedProc = null;

      createTable("testSpResultTbl1", "(field1 INT)");
      this.stmt
          .executeUpdate("INSERT INTO testSpResultTbl1 VALUES (1), (2)");
      createTable("testSpResultTbl2", "(field2 varchar(255))");
      this.stmt
          .executeUpdate("INSERT INTO testSpResultTbl2 VALUES ('abc'), ('def')");

      createProcedure(
          "testSpResult",
          "()\n"
              + "BEGIN\n"
              + "SELECT field2 FROM testSpResultTbl2 WHERE field2='abc';\n"
              + "UPDATE testSpResultTbl1 SET field1=2;\n"
              + "SELECT field2 FROM testSpResultTbl2 WHERE field2='def';\n"
              + "end\n");

      storedProc = this.conn.prepareCall("{call testSpResult()}");

      storedProc.execute();

      this.rs = storedProc.getResultSet();

      ResultSetMetaData rsmd = this.rs.getMetaData();

      assertTrue(rsmd.getColumnCount() == 1);
      assertTrue("field2".equals(rsmd.getColumnName(1)));
      assertTrue(rsmd.getColumnType(1) == Types.VARCHAR);

      assertTrue(this.rs.next());

      assertTrue("abc".equals(this.rs.getString(1)));

      // TODO: This does not yet work in MySQL 5.0
      // assertTrue(!storedProc.getMoreResults());
      // assertTrue(storedProc.getUpdateCount() == 2);
      assertTrue(storedProc.getMoreResults());

      ResultSet nextResultSet = storedProc.getResultSet();

      rsmd = nextResultSet.getMetaData();

      assertTrue(rsmd.getColumnCount() == 1);
      assertTrue("field2".equals(rsmd.getColumnName(1)));
      assertTrue(rsmd.getColumnType(1) == Types.VARCHAR);

      assertTrue(nextResultSet.next());

      assertTrue("def".equals(nextResultSet.getString(1)));

      nextResultSet.close();

      this.rs.close();

      storedProc.execute();
    }
  }

  /**
   * Tests parsing of stored procedures
   *
   * @throws Exception
   *             if an error occurs.
   */
  public void testSPParse() throws Exception {

    if (versionMeetsMinimum(5, 0)) {

      @SuppressWarnings("unused")
      CallableStatement storedProc = null;

      createProcedure("testSpParse", "(IN FOO VARCHAR(15))\n" + "BEGIN\n"
          + "SELECT 1;\n" + "end\n");

      storedProc = this.conn.prepareCall("{call testSpParse()}");

    }
  }

  /**
   * Tests parsing/execution of stored procedures with no parameters...
   *
   * @throws Exception
   *             if an error occurs.
   */
  public void testSPNoParams() throws Exception {

    if (versionMeetsMinimum(5, 0)) {

      CallableStatement storedProc = null;

      createProcedure("testSPNoParams", "()\n" + "BEGIN\n"
          + "SELECT 1;\n" + "end\n");

      storedProc = this.conn.prepareCall("{call testSPNoParams()}");
      storedProc.execute();

    }
  }

  /**
   * Tests parsing of stored procedures
   *
   * @throws Exception
   *             if an error occurs.
   */
  public void testSPCache() throws Exception {
    if (isRunningOnJdk131()) {
      return; // no support for LRUCache
    }

    if (versionMeetsMinimum(5, 0)) {

      CallableStatement storedProc = null;

      createProcedure("testSpParse", "(IN FOO VARCHAR(15))\n" + "BEGIN\n"
          + "SELECT 1;\n" + "end\n");

      int numIterations = 10;

      long startTime = System.currentTimeMillis();

      for (int i = 0; i < numIterations; i++) {
        storedProc = this.conn.prepareCall("{call testSpParse(?)}");
        storedProc.close();
      }

      long elapsedTime = System.currentTimeMillis() - startTime;

      System.out.println("Standard parsing/execution: " + elapsedTime
          + " ms");

      storedProc = this.conn.prepareCall("{call testSpParse(?)}");
      storedProc.setString(1, "abc");
      this.rs = storedProc.executeQuery();

      assertTrue(this.rs.next());
      assertTrue(this.rs.getInt(1) == 1);

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

      Connection cachedSpConn = getConnectionWithProps(props);

      startTime = System.currentTimeMillis();

      for (int i = 0; i < numIterations; i++) {
        storedProc = cachedSpConn.prepareCall("{call testSpParse(?)}");
        storedProc.close();
      }

      elapsedTime = System.currentTimeMillis() - startTime;

      System.out.println("Cached parse stage: " + elapsedTime + " ms");

      storedProc = cachedSpConn.prepareCall("{call testSpParse(?)}");
      storedProc.setString(1, "abc");
      this.rs = storedProc.executeQuery();

      assertTrue(this.rs.next());
      assertTrue(this.rs.getInt(1) == 1);

    }
  }

  public void testOutParamsNoBodies() throws Exception {
    if (versionMeetsMinimum(5, 0)) {
      CallableStatement storedProc = null;

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

      Connection spConn = getConnectionWithProps(props);

      createProcedure("testOutParam", "(x int, out y int)\n" + "begin\n"
          + "declare z int;\n" + "set z = x+1, y = z;\n" + "end\n");

      storedProc = spConn.prepareCall("{call testOutParam(?, ?)}");

      storedProc.setInt(1, 5);
      storedProc.registerOutParameter(2, Types.INTEGER);

      storedProc.execute();

      int indexedOutParamToTest = storedProc.getInt(2);

      assertTrue("Output value not returned correctly",
          indexedOutParamToTest == 6);

      storedProc.clearParameters();
      storedProc.setInt(1, 32);
      storedProc.registerOutParameter(2, Types.INTEGER);

      storedProc.execute();

      indexedOutParamToTest = storedProc.getInt(2);

      assertTrue("Output value not returned correctly",
          indexedOutParamToTest == 33);
    }
  }

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

  /**
   * Tests the new parameter parser that doesn't require "BEGIN" or "\n" at
   * end of parameter declaration
   *
   * @throws Exception
   */
  public void testParameterParser() throws Exception {

    if (!versionMeetsMinimum(5, 0)) {
      return;
    }

    CallableStatement cstmt = null;

    try {

      createTable("t1",
          "(id   char(16) not null default '', data int not null)");
      createTable("t2", "(s   char(16),  i   int,  d   double)");

      createProcedure("foo42",
          "() insert into test.t1 values ('foo', 42);");
      this.conn.prepareCall("{CALL foo42()}");
      this.conn.prepareCall("{CALL foo42}");

      createProcedure("bar",
          "(x char(16), y int, z DECIMAL(10)) insert into test.t1 values (x, y);");
      cstmt = this.conn.prepareCall("{CALL bar(?, ?, ?)}");

      if (!isRunningOnJdk131()) {
        ParameterMetaData md = cstmt.getParameterMetaData();
        assertEquals(3, md.getParameterCount());
        assertEquals(Types.CHAR, md.getParameterType(1));
        assertEquals(Types.INTEGER, md.getParameterType(2));
        assertEquals(Types.DECIMAL, md.getParameterType(3));
      }

      createProcedure("p", "() label1: WHILE @a=0 DO SET @a=1; END WHILE");
      this.conn.prepareCall("{CALL p()}");

      createFunction("f", "() RETURNS INT NO SQL return 1; ");
      cstmt = this.conn.prepareCall("{? = CALL f()}");

      if (!isRunningOnJdk131()) {
        ParameterMetaData md = cstmt.getParameterMetaData();
        assertEquals(Types.INTEGER, md.getParameterType(1));
      }
    } finally {
      if (cstmt != null) {
        cstmt.close();
      }
    }
  }
}
TOP

Related Classes of testsuite.simple.CallableStatementTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.