Logo Search packages:      
Sourcecode: mysql-connector-c++ version File versions

test_common.cpp

/*
   Copyright 2007 - 2008 MySQL AB, 2008 - 2009 Sun Microsystems, Inc.  All rights reserved.

   The MySQL Connector/C++ is licensed under the terms of the GPL
   <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 GPL as it is applied to this software, see the
   FLOSS License Exception
   <http://www.mysql.com/about/legal/licensing/foss-exception.html>.
*/

#include <list>
#include <map>
#include <memory>
#include <iostream>
#include <sstream>
#include <string>
#if !defined(_WIN32) && !defined(_WIN64)
#include <inttypes.h>
#endif

// Portable __FUNCTION__
#ifndef __FUNCTION__
 #ifdef __func__
   #define CPPCONN_FUNC __func__
 #else
   #define CPPCONN_FUNC "(function n/a)"
 #endif
#else
#define CPPCONN_FUNC __FUNCTION__
#endif

#ifndef __LINE__
  #define __LINE__ "(line number n/a)"
#endif

#define ensure(msg, stmt)                       do {total_tests++;if(!(stmt)){printf("\n# Error! line=%d: %s\n# ",__LINE__,msg);total_errors++;throw sql::SQLException("error");} else { printf(".");}} while (0)
#define ensure_equal(msg, op1, op2) do {total_tests++;if((op1)!=(op2)){printf("\n# Error! line=%d: %s\n# ",__LINE__,msg);total_errors++;throw sql::SQLException("error");} else { printf(".");}}while(0)
#define ensure_equal_int(msg, op1, op2)   do {total_tests++;if((op1)!=(op2)){printf("\n# Error! line=%d: %s Op1=%d Op2=%d\n# ",__LINE__,msg,op1,op2);total_errors++;throw sql::SQLException("error");} else { printf(".");}}while(0)
#define ensure_equal_str(msg, op1, op2)   do {total_tests++;if((op1)!=(op2)){printf("\n# Error! line=%d: %s Op1=%s Op2=%s\n# ",__LINE__,msg,op1.c_str(),op2.c_str());total_errors++;throw sql::SQLException("error");} else { printf(".");}}while(0)
#define ensure_equal_int64(msg, op1, op2) do {total_tests++;if((op1)!=(op2)){printf("\n# Error! line=%d: %s Op1=%lld Op2=%lld\n# ",__LINE__,msg,(long long)op1,(long long)op2);total_errors++;throw sql::SQLException("error");} else { printf(".");}}while(0)
#define ensure_equal_uint64(msg, op1, op2)      do {total_tests++;if((op1)!=(op2)){printf("\n# Error! line=%d: %s Op1=%llu Op2=%llu\n# ",__LINE__,msg,(unsigned long long)op1,(unsigned long long)op2);total_errors++;throw sql::SQLException("error");} else { printf(".");}}while(0)

static int total_errors = 0;
static int total_tests = 0;
static int silent = 1;

#define USED_DATABASE "test"

#define ENTER_FUNCTION()            if (!silent) printf("# >>>>   %s\n# ", CPPCONN_FUNC);
#define LEAVE_FUNCTION()            if (!silent) printf("# <<<<   %s\n# ", CPPCONN_FUNC); else printf("\n# ");

#if defined(_WIN32) || defined(_WIN64)
#pragma warning(disable:4251)
#pragma warning(disable:4800)
#endif


extern "C"
{
#if defined(_WIN32) || defined(_WIN64)
#include "my_global.h"
#endif

#include "mysql.h"
}
/* mysql.h introduces bool */
#undef bool

#if defined(_WIN32) || defined(_WIN64)
#pragma warning(disable:4251)
#endif

#include <stdio.h>


#ifndef L64
#ifdef _WIN32
#define L64(x) x##i64
#else
#define L64(x) x##LL
#endif
#endif

#ifndef UL64
#ifdef _WIN32
#define UL64(x) x##ui64
#else
#define UL64(x) x##ULL
#endif
#endif


/* {{{ */
static bool populate_blob_table(std::auto_ptr<sql::Connection> & conn, std::string database)
{
      std::auto_ptr<sql::Statement> stmt(conn->createStatement());
      ensure("stmt is NULL", stmt.get() != NULL);

      stmt->execute("USE " + database);
      stmt->execute("DROP TABLE IF EXISTS test_blob");
      if (true == stmt->execute("CREATE TABLE test_blob (a longblob) ENGINE=MYISAM")) {
            return false;
      }
      return true;
}
/* }}} */


/* {{{ */
static bool populate_insert_data(sql::Statement * stmt)
{
      return stmt->execute("INSERT INTO test_function (a,b,c,d,e) VALUES(1, 111, NULL, '222', 'xyz')");
}
/* }}} */


/* {{{ */
static bool populate_test_table(std::auto_ptr<sql::Connection> & conn, std::string database)
{
      std::auto_ptr<sql::Statement> stmt(conn->createStatement());
      ensure("stmt is NULL", stmt.get() != NULL);

      stmt->execute("USE " + database);
      stmt->execute("DROP TABLE IF EXISTS test_function");
      if (true == stmt->execute("CREATE TABLE test_function (a integer unsigned not null, b integer, c integer default null, d char(10), e varchar(10) character set utf8 collate utf8_bin) ENGINE=MYISAM")) {
            return false;
      }

      if (true == populate_insert_data(stmt.get())) {
            stmt->execute("DROP TABLE test_function");
            return false;
      }
      return true;
}
/* }}} */


/* {{{ */
static bool populate_TX_insert_data(sql::Statement * stmt)
{
      return stmt->execute("INSERT INTO test_function_tx (a,b,c,d,e) VALUES(1, 111, NULL,  '222', 'xyz')");
}
/* }}} */


/* {{{ */
static bool populate_TX_test_table(std::auto_ptr<sql::Connection> & conn, std::string database)
{
      std::auto_ptr<sql::Statement> stmt(conn->createStatement());
      ensure("stmt is NULL", stmt.get() != NULL);

      stmt->execute("USE " + database);
      stmt->execute("DROP TABLE IF EXISTS test_function_tx");
      if (true == stmt->execute("CREATE TABLE test_function_tx(a integer unsigned not null, b integer, c integer default null, d char(10), e varchar(10) character set utf8 collate utf8_bin) engine = innodb")) {
            return false;
      }

      if (true == populate_TX_insert_data(stmt.get())) {
            stmt->execute("DROP TABLE test_function_tx");
            return false;
      }
      stmt->getConnection()->commit();
      return true;
}
/* }}} */


/* {{{ */
static bool populate_test_table_PS(std::auto_ptr<sql::Connection> & conn, std::string database)
{
      std::auto_ptr<sql::Statement> stmt1(conn->createStatement());
      ensure("stmt1 is NULL", stmt1.get() != NULL);
      stmt1->execute("USE " + database);

      std::auto_ptr<sql::PreparedStatement> stmt2(conn->prepareStatement("DROP TABLE IF EXISTS test_function"));
      ensure("stmt2 is NULL", stmt2.get() != NULL);
      stmt2->executeUpdate();

      std::auto_ptr<sql::PreparedStatement> stmt3(conn->prepareStatement("CREATE TABLE test_function(a integer unsigned not null, b integer, c integer default null, d char(10), e varchar(10) character set utf8 collate utf8_bin)"));
      ensure("stmt3 is NULL", stmt3.get() != NULL);
      stmt3->executeUpdate();

      std::auto_ptr<sql::PreparedStatement> stmt4(conn->prepareStatement("INSERT INTO test_function (a,b,c,d,e) VALUES(1, 111, NULL, '222', 'xyz')"));
      ensure("stmt4 is NULL", stmt4.get() != NULL);
      stmt4->executeUpdate();

      return true;
}
/* }}} */


/* {{{ */
static bool populate_TX_test_table_PS(std::auto_ptr<sql::Connection> & conn, std::string database)
{
      std::auto_ptr<sql::Statement> stmt1(conn->createStatement());
      ensure("stmt is NULL", stmt1.get() != NULL);
      stmt1->execute("USE " + database);

      std::auto_ptr<sql::PreparedStatement> stmt2(conn->prepareStatement("DROP TABLE IF EXISTS test_function_tx"));
      ensure("stmt2 is NULL", stmt2.get() != NULL);
      stmt2->executeUpdate();

      std::auto_ptr<sql::PreparedStatement> stmt3(conn->prepareStatement("CREATE TABLE test_function_tx(a integer unsigned not null, b integer, c integer default null, d char(10), e varchar(10) character set utf8 collate utf8_bin) engine = innodb"));
      ensure("stmt3 is NULL", stmt3.get() != NULL);
      stmt3->executeUpdate();

      std::auto_ptr<sql::PreparedStatement> stmt4(conn->prepareStatement("INSERT INTO test_function_tx (a,b,c,d,e) VALUES(1, 111, NULL, '222', 'xyz')"));
      ensure("stmt4 is NULL", stmt4.get() != NULL);
      stmt4->executeUpdate();

      return true;
}
/* }}} */


/* {{{ */
static bool populate_test_table_PS_integers(std::auto_ptr<sql::Connection> & conn, std::string database)
{
      std::auto_ptr<sql::Statement> stmt1(conn->createStatement());
      ensure("stmt1 is NULL", stmt1.get() != NULL);
      stmt1->execute("USE " + database);

      std::auto_ptr<sql::PreparedStatement> stmt2(conn->prepareStatement("DROP TABLE IF EXISTS test_function_int"));
      ensure("stmt2 is NULL", stmt2.get() != NULL);
      stmt2->executeUpdate();

      std::auto_ptr<sql::PreparedStatement> stmt3(conn->prepareStatement("CREATE TABLE test_function_int(i integer, i_uns integer unsigned, b bigint, b_uns bigint unsigned)"));
      ensure("stmt3 is NULL", stmt3.get() != NULL);
      stmt3->executeUpdate();

      return true;
}
/* }}} */


/* {{{ */
static void test_autocommit(std::auto_ptr<sql::Connection> & conn)
{
      ENTER_FUNCTION();
      try {
            conn->setAutoCommit(1);
            ensure("AutoCommit", conn->getAutoCommit() == true);

            conn->setAutoCommit(0);
            ensure("AutoCommit", conn->getAutoCommit() == false);
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ */
static void test_connection_0(std::auto_ptr<sql::Connection> & conn)
{
      ENTER_FUNCTION();
      try {
            char buff[64];

            std::auto_ptr<sql::Statement> stmt1(conn->createStatement());
            ensure("stmt1 is NULL", stmt1.get() != NULL);
            std::auto_ptr<sql::ResultSet> rset1(stmt1->executeQuery("SELECT CONNECTION_ID()"));
            ensure("res1 is NULL", rset1.get() != NULL);

            ensure("res1 is empty", rset1->next() != false);

            ensure("connection is closed", !conn->isClosed());

            sprintf(buff, "KILL %d", rset1->getInt(1));

            try {
                  stmt1->execute(buff);
            } catch (sql::SQLException &) {
                  /*
                    If this is mac, we will get an error.
                    MySQL on Mac closes the connection without sending response
                  */
            }
            try {
                  std::auto_ptr<sql::ResultSet> rset2(stmt1->executeQuery("SELECT CONNECTION_ID()"));
                  ensure("no exception", false);
            } catch (sql::SQLException &) {
                  ensure("Exception correctly thrown", true);
            }
            ensure("connection is open", conn->isClosed() == false);
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ */
static void test_connection_1(std::auto_ptr<sql::Connection> & conn, std::string database)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt1(conn->createStatement());
            ensure("stmt1 is NULL", stmt1.get() != NULL);
            ensure("connection is closed", !conn->isClosed());
            conn->setAutoCommit(false);

            ensure("Data not populated", true == populate_TX_test_table(conn, database));

            std::auto_ptr<sql::ResultSet> rset1(stmt1->executeQuery("SELECT COUNT(*) FROM test_function_tx"));
            ensure("res1 is NULL", rset1.get() != NULL);
            ensure("res1 is empty", rset1->next() != false);
            int count_full_before = rset1->getInt(1);
            ensure_equal_int("res1 has more rows ", rset1->next(), false);

            std::string savepointName("firstSavePoint");
            std::auto_ptr<sql::Savepoint> savepoint(conn->setSavepoint(savepointName));

            populate_TX_insert_data(stmt1.get());
            std::auto_ptr<sql::ResultSet> rset2(stmt1->executeQuery("SELECT COUNT(*) FROM test_function_tx"));
            ensure("res2 is NULL", rset2.get() != NULL);
            ensure_equal_int("res2 is empty", rset2->next(), true);
            int count_full_after = rset2->getInt(1);
            ensure_equal_int("res2 has more rows ", rset2->next(), false);
            ensure_equal_int("wrong number of rows", count_full_after, (count_full_before * 2));

            conn->rollback(savepoint.get());
            std::auto_ptr<sql::ResultSet> rset3(stmt1->executeQuery("SELECT COUNT(*) FROM test_function_tx"));
            ensure("res3 is NULL", rset3.get() != NULL);
            ensure_equal_int("res3 is empty", rset3->next(), true);
            int count_full_after_rollback = rset3->getInt(1);
            ensure_equal_int("res3 has more rows ", rset3->next(), false);
            ensure_equal_int("wrong number of rows", count_full_after_rollback, count_full_before);

            conn->releaseSavepoint(savepoint.get());
            try {
                  /* The second call should throw an exception */
                  conn->releaseSavepoint(savepoint.get());
                  total_errors++;
            } catch (sql::SQLException &) {}

            /* Clean */
            stmt1->execute("USE " + database);
            stmt1->execute("DROP TABLE test_function_tx");
      } catch (sql::MethodNotImplementedException &) {
            printf("\n# SKIP: RELEASE SAVEPOINT not available in this MySQL version\n");
            printf("# ");
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ */
static void test_connection_2(std::auto_ptr<sql::Connection> & conn, std::string database)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt(conn->createStatement());
            ensure("stmt1 is NULL", stmt.get() != NULL);

            ensure("Wrong catalog", conn->getCatalog() == "def" || conn->getCatalog() == "");
            stmt->execute("USE " + database);
            std::string newCatalog(conn->getSchema());
            ensure(std::string("Wrong catalog '" + newCatalog + "'/'" + database + "'").c_str(), newCatalog == std::string(database));

            try {
                  conn->setCatalog(std::string("doesnt_actually_exist"));
                        // printf("\n# ERR: Accepting invalid catalog");
                  // total_errors++;
            } catch (sql::SQLException &) {}
            conn->setSchema(std::string("information_schema"));
            std::string newCatalog2(conn->getSchema());
            ensure("Wrong catalog", newCatalog2 == std::string("information_schema"));
      } catch (sql::SQLException &e) {
            /* Error: 1049 SQLSTATE: 42000  (ER_BAD_DB_ERROR)  - information_schema not available */
            if (e.getErrorCode() != 1049) {
                  printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
                  printf("# ");
                  total_errors++;
            }
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ */
static void test_connection_3(std::auto_ptr<sql::Connection> & conn, std::string user)
{
      ENTER_FUNCTION();
      try {
            sql::DatabaseMetaData * meta = conn->getMetaData();
            ensure("getUserName() failed", user == meta->getUserName().substr(0, user.length()));
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ */
static void test_statement_0(std::auto_ptr<sql::Connection> & conn)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt(conn->createStatement());
            ensure("AutoCommit", conn.get() == stmt->getConnection());
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ Test simple update statement against statement object */
static void test_statement_1(std::auto_ptr<sql::Connection> & conn, std::auto_ptr<sql::Connection> & conn2, std::string database)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt(conn->createStatement());
            ensure("stmt is NULL", stmt.get() != NULL);

            ensure("Data not populated", true == populate_test_table(conn, database));
            if (false == stmt->execute("SELECT * FROM test_function"))
                  ensure("False returned for SELECT", false);

            /* Clean */
            std::auto_ptr<sql::Statement> stmt2(conn2->createStatement());
            ensure("stmt is NULL", stmt2.get() != NULL);
            stmt2->execute("USE " + database);
            stmt2->execute("DROP TABLE test_function");
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      } catch (...) {
            printf("\n# ERR: Caught unknown exception at %s::%d\n", CPPCONN_FUNC, __LINE__);
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ Test simple query against statement object */
static void test_statement_2(std::auto_ptr<sql::Connection> & conn, std::auto_ptr<sql::Connection> & conn2, std::string database)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt(conn->createStatement());
            ensure("stmt is NULL", stmt.get() != NULL);

            ensure("Data not populated", true == populate_test_table(conn, database));
            if (false == stmt->execute("SELECT * FROM test_function"))
                  ensure("False returned for SELECT", false);

            /* Clean */
            std::auto_ptr<sql::Statement> stmt2(conn2->createStatement());
            ensure("stmt is NULL", stmt2.get() != NULL);
            stmt2->execute("USE " + database);
            stmt2->execute("DROP TABLE test_function");
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      } catch (...) {
            printf("\n# ERR: Caught unknown exception at %s::%d\n", CPPCONN_FUNC, __LINE__);
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ Test executeQuery() - returning a result set*/
static void test_statement_3(std::auto_ptr<sql::Connection> & conn, std::auto_ptr<sql::Connection> & conn2, std::string database)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt(conn->createStatement());
            ensure("stmt is NULL", stmt.get() != NULL);

            ensure("Data not populated", true == populate_test_table(conn, database));
            /* Get a result set */
            try {
                  std::auto_ptr<sql::ResultSet> rset(stmt->executeQuery("SELECT * FROM test_function"));
                  ensure("NULL returned for result set", rset.get() != NULL);
            } catch (sql::SQLException &e) {
                  printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
                  total_errors++;
                  printf("# ");
            }

            /* Clean */
            std::auto_ptr<sql::Statement> stmt2(conn2->createStatement());
            ensure("stmt is NULL", stmt2.get() != NULL);
            stmt2->execute("USE " + database);
            stmt2->execute("DROP TABLE test_function");
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      } catch (...) {
            printf("\n# ERR: Caught unknown exception at %s::%d\n", CPPCONN_FUNC, __LINE__);
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ Test executeQuery() - returning empty result set */
static void test_statement_4(std::auto_ptr<sql::Connection> & conn, std::auto_ptr<sql::Connection> & conn2, std::string database)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt(conn->createStatement());
            ensure("stmt is NULL", stmt.get() != NULL);

            ensure("Data not populated", true == populate_test_table(conn, database));
            /* Get a result set */
            try {
                  std::auto_ptr<sql::ResultSet> rset(stmt->executeQuery("SELECT * FROM test_function WHERE 1=2"));
                  ensure("NULL returned for result set", rset.get() != NULL);
                  ensure_equal_int("Non-empty result set", false, rset->next());

            } catch (sql::SQLException &e) {
                  printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
                  printf("# ");
                  total_errors++;
            }

            /* Clean */
            std::auto_ptr<sql::Statement> stmt2(conn2->createStatement());
            ensure("stmt is NULL", stmt2.get() != NULL);
            stmt2->execute("USE " + database);
            stmt2->execute("DROP TABLE test_function");
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      } catch (...) {
            printf("\n# ERR: Caught unknown exception at %s::%d\n", CPPCONN_FUNC, __LINE__);
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ Test executeQuery() - use it for inserting, should generate an exception */
static void test_statement_5(std::auto_ptr<sql::Connection> & conn, std::auto_ptr<sql::Connection> & conn2, std::string database)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt(conn->createStatement());
            ensure("stmt is NULL", stmt.get() != NULL);

            ensure("Data not populated", true == populate_test_table(conn, database));
            /* Get a result set */
            try {
                  std::auto_ptr<sql::ResultSet> rset(stmt->executeQuery("INSERT INTO test_function VALUES(2,200)"));
                  ensure("NULL returned for result set", rset.get() == NULL);
                  ensure_equal_int("Non-empty result set", false, rset->next());
            } catch (sql::SQLException &) {
            } catch (...) {
                  printf("\n# ERR: Caught unknown exception at %s::%d\n", CPPCONN_FUNC, __LINE__);
                  printf("# ");
                  total_errors++;
            }
            /* Clean */
            std::auto_ptr<sql::Statement> stmt2(conn2->createStatement());
            ensure("stmt is NULL", stmt2.get() != NULL);
            stmt2->execute("USE " + database);
            stmt2->execute("DROP TABLE test_function");
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      } catch (...) {
            printf("\n# ERR: Caught unknown exception at %s::%d\n", CPPCONN_FUNC, __LINE__);
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ Test executeUpdate() - check the returned value */
static void test_statement_6(std::auto_ptr<sql::Connection> & conn, std::auto_ptr<sql::Connection> & conn2, std::string database)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt(conn->createStatement());
            ensure("stmt is NULL", stmt.get() != NULL);

            ensure("Data not populated", true == populate_test_table(conn, database));
            /* Get a result set */
            try {
                  ensure("Number of updated rows", stmt->executeUpdate("UPDATE test_function SET a = 123") == 1);
            } catch (sql::SQLException &e) {
                  printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
                  total_errors++;
            }

            /* Clean */
            std::auto_ptr<sql::Statement> stmt2(conn2->createStatement());
            ensure("stmt is NULL", stmt2.get() != NULL);
            stmt2->execute("USE " + database);
            stmt2->execute("DROP TABLE test_function");
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      } catch (...) {
            printf("\n# ERR: Caught unknown exception at %s::%d\n", CPPCONN_FUNC, __LINE__);
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ Test executeUpdate() - execute a SELECT, should get an exception */
static void test_statement_7(std::auto_ptr<sql::Connection> & conn, std::auto_ptr<sql::Connection> & conn2, std::string database)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt(conn->createStatement());
            ensure("stmt is NULL", stmt.get() != NULL);

            ensure("Data not populated", true == populate_test_table(conn, database));
            /* Get a result set */
            try {
                  stmt->executeUpdate("SELECT * FROM test_function");
                  ensure("No exception thrown", false);
            } catch (sql::SQLException &) {
            } catch (...) {
                  printf("\n# ERR: Incorrectly sql::SQLException ist not thrown\n");
                  printf("# ");
                  total_errors++;
            }

            /* Clean */
            std::auto_ptr<sql::Statement> stmt2(conn2->createStatement());
            ensure("stmt is NULL", stmt2.get() != NULL);
            stmt2->execute("USE " + database);
            stmt2->execute("DROP TABLE test_function");
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      } catch (...) {
            printf("\n# ERR: Caught unknown exception at %s::%d\n", CPPCONN_FUNC, __LINE__);
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


#if 0
/* {{{ Test getFetchSize() - should return int value */
/* XXX: Test fails because getFetchSize() is not implemented*/
static void test_statement_xx(std::auto_ptr<sql::Connection> & conn, std::auto_ptr<sql::Connection> & conn2)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt(conn->createStatement());
            ensure("stmt is NULL", stmt.get() != NULL);

            ensure("fetchSize is negative", stmt->getFetchSize() > 0);
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      } catch (...) {
            printf("\n# ERR: Caught unknown exception at %s::%d\n", CPPCONN_FUNC, __LINE__);
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */

/* {{{ Test setFetchSize() - set and get the value */
/* XXX: Doesn't pass because setFetchSize() is unimplemented */
static void test_statement_xx(std::auto_ptr<sql::Connection> & conn)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt(conn->createStatement());
            ensure("stmt is NULL", stmt.get() != NULL);

            int setFetchSize = 50;

            stmt->setFetchSize(setFetchSize);

            ensure_equal("Non-equal", setFetchSize, stmt->getFetchSize());
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      } catch (...) {
            printf("\n# ERR: Caught unknown exception at %s::%d\n", CPPCONN_FUNC, __LINE__);
            printf("# ");
            total_errors++;
      }
}
/* }}} */


/* {{{ Test setFetchSize() - set negative value and expect an exception */
/* XXX: Doesn't pass because setFetchSize() is unimplemented */
static void test_statement_xx(std::auto_ptr<sql::Connection> & conn)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt(conn->createStatement());
            ensure("stmt is NULL", stmt.get() != NULL);

            try {
                  stmt->setFetchSize(-1);
                  ensure("No exception", false);
            } catch (sql::InvalidArgumentException) {
                  printf("INFO: Caught sql::InvalidArgumentException\n");
            }
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      } catch (...) {
            printf("\n# ERR: Caught unknown exception at %s::%d\n", CPPCONN_FUNC, __LINE__);
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ Test setQueryTimeout() - set negative value and expect an exception */
/* XXX: Doesn't pass because setQueryTimeout() is unimplemented */
static void test_statement_xx(std::auto_ptr<sql::Connection> & conn)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt(conn->createStatement());
            ensure("stmt is NULL", stmt.get() != NULL);

            try {
                  stmt->setQueryTimeout(-1);
                  printf("\n# ERR:No exception\n");
            } catch (sql::InvalidArgumentException &) {}
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      } catch (...) {
            printf("\n# ERR: Caught unknown exception at %s::%d\n", CPPCONN_FUNC, __LINE__);
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */
#endif


/* {{{ Test getResultSet() - execute() a query and get the result set */
static void test_statement_8(std::auto_ptr<sql::Connection> & conn, std::auto_ptr<sql::Connection> & conn2, std::string database)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt(conn->createStatement());
            ensure("stmt is NULL", stmt.get() != NULL);

            ensure("Data not populated", true == populate_test_table(conn, database));

            ensure("sql::Statement::execute returned false", true == stmt->execute("SELECT * FROM test_function"));

            std::auto_ptr<sql::ResultSet> rset(stmt->getResultSet());
            ensure("rset is NULL", rset.get() != NULL);

            /* Clean */
            std::auto_ptr<sql::Statement> stmt2(conn2->createStatement());
            ensure("stmt is NULL", stmt2.get() != NULL);
            stmt2->execute("USE " + database);
            stmt2->execute("DROP TABLE test_function");
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      } catch (...) {
            printf("\n# ERR: Caught unknown exception at %s::%d\n", CPPCONN_FUNC, __LINE__);
            printf("# ");
            total_errors++;
      }
}
/* }}} */


/* {{{ Test getResultSet() - execute() an update query and get the result set - should be empty */
static void test_statement_9(std::auto_ptr<sql::Connection> & conn, std::auto_ptr<sql::Connection> & conn2, std::string database)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt(conn->createStatement());
            ensure("stmt is NULL", stmt.get() != NULL);

            ensure("Data not populated", true == populate_test_table(conn, database));

            ensure("sql::Statement::execute returned true", false == stmt->execute("UPDATE test_function SET a = 222"));

            std::auto_ptr<sql::ResultSet> rset(stmt->getResultSet());
            ensure("rset is not NULL", rset.get() == NULL);

            /* Clean */
            std::auto_ptr<sql::Statement> stmt2(conn2->createStatement());
            ensure("stmt is NULL", stmt2.get() != NULL);
            stmt2->execute("USE " + database);
            stmt2->execute("DROP TABLE test_function");
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      } catch (...) {
            printf("\n# ERR: Caught unknown exception at %s::%d\n", CPPCONN_FUNC, __LINE__);
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ */
static void test_result_set_0(std::auto_ptr<sql::Connection> & conn)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt(conn->createStatement());
            ensure("AutoCommit", conn.get() == stmt->getConnection());

            std::auto_ptr<sql::ResultSet> result(stmt->setResultSetType(sql::ResultSet::TYPE_SCROLL_INSENSITIVE)->executeQuery("SELECT 1, 2, 3"));

            ensure_equal_int("isFirst", result->isFirst(), false);

            ensure_equal_int("isLast", result->isLast(), false);
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ */
static void test_result_set_1(std::auto_ptr<sql::Connection> & conn)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt1(conn->createStatement());
            ensure("stmt1 is NULL", stmt1.get() != NULL);
            stmt1->setResultSetType(sql::ResultSet::TYPE_SCROLL_INSENSITIVE);

            std::auto_ptr<sql::ResultSet> rset1(stmt1->executeQuery("SELECT 1"));
            ensure("res1 is NULL", rset1.get() != NULL);

            std::auto_ptr<sql::ResultSet> rset2(stmt1->executeQuery("SELECT 1"));
            ensure("res2 is NULL", rset2.get() != NULL);

            ensure("res1 is empty", rset1->next() != false);
            ensure("res2 is empty", rset2->next() != false);
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ */
static void test_result_set_2(std::auto_ptr<sql::Connection> & conn, std::string database)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt1(conn->createStatement());
            ensure("stmt1 is NULL", stmt1.get() != NULL);

            ensure("Data not populated", true == populate_test_table(conn, database));

            std::auto_ptr<sql::ResultSet> rset1(stmt1->executeQuery("SELECT 1"));
            ensure("res1 is NULL", rset1.get() != NULL);
            ensure_equal_int("res1 is empty", rset1->next(), true);
            ensure_equal_int("res1 is empty", rset1->next(), false);

            ensure("No rows updated", stmt1->executeUpdate("UPDATE test_function SET a = 2") > 0);

            stmt1->execute("DROP TABLE test_function");
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ */
static void test_result_set_3(std::auto_ptr<sql::Connection> & conn, std::string database)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt1(conn->createStatement());
            ensure("stmt1 is NULL", stmt1.get() != NULL);

            ensure_equal("sql::Connection differs", conn.get(), stmt1->getConnection());
            int old_commit_mode = conn->getAutoCommit();
            conn->setAutoCommit(0);

            ensure("Data not populated", true == populate_TX_test_table(conn, database));

            std::auto_ptr<sql::ResultSet> rset1(stmt1->executeQuery("SELECT COUNT(*) FROM test_function_tx"));
            ensure("res1 is NULL", rset1.get() != NULL);
            ensure("res1 is empty", rset1->next() != false);
            int count_full_before = rset1->getInt(1);
            ensure("res1 has more rows ", rset1->next() == false);

            /* Let's delete and then rollback */
            ensure_equal("Deleted less rows",
                                                      stmt1->executeUpdate("DELETE FROM test_function_tx WHERE 1"),
                                                      count_full_before);

            std::auto_ptr<sql::ResultSet> rset2(stmt1->executeQuery("SELECT COUNT(*) FROM test_function_tx"));
            ensure("res2 is NULL", rset2.get() != NULL);
            ensure("res2 is empty", rset2->next() != false);
            ensure("Table not empty after delete", rset2->getInt(1) == 0);
            ensure("res2 has more rows ", rset2->next() == false);

            stmt1->getConnection()->rollback();

            std::auto_ptr<sql::ResultSet> rset3(stmt1->executeQuery("SELECT COUNT(*) FROM test_function_tx"));
            ensure("res3 is NULL", rset3.get() != NULL);
            ensure("res3 is empty", rset3->next() != false);
            int count_full_after = rset3->getInt(1);
            ensure("res3 has more rows ", rset3->next() == false);

            ensure("Rollback didn't work", count_full_before == count_full_after);

            /* Now let's delete and then commit */
            ensure_equal("Deleted less rows",
                                                      stmt1->executeUpdate("DELETE FROM test_function_tx WHERE 1"),
                                                      count_full_before);
            stmt1->getConnection()->commit();

            std::auto_ptr<sql::ResultSet> rset4(stmt1->executeQuery("SELECT COUNT(*) FROM test_function_tx"));
            ensure("res4 is NULL", rset4.get() != NULL);
            ensure("res4 is empty", rset4->next() != false);
            ensure("Table not empty after delete", rset4->getInt(1) == 0);
            ensure("res4 has more rows ", rset4->next() == false);

            stmt1->execute("DROP TABLE test_function_tx");

            conn->setAutoCommit(old_commit_mode);
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ Test commit and rollback (autocommit on) */
static void test_result_set_4(std::auto_ptr<sql::Connection> & conn, std::string database)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt1(conn->createStatement());
            ensure("stmt1 is NULL", stmt1.get() != NULL);

            ensure_equal("sql::Connection differs", conn.get(), stmt1->getConnection());

            int old_commit_mode = conn->getAutoCommit();
            conn->setAutoCommit(true);
            ensure_equal_int("Data not populated", true, populate_TX_test_table(conn, database));


            std::auto_ptr<sql::ResultSet> rset1(stmt1->executeQuery("SELECT COUNT(*) FROM test_function_tx"));
            ensure("res1 is NULL", rset1.get() != NULL);
            ensure_equal_int("res1 is empty", rset1->next(), true);
            int count_full_before = rset1->getInt(1);
            ensure_equal_int("res1 has more rows ", rset1->next(), false);

            /* Let's delete and then rollback */
            ensure_equal_int("Deleted less rows",
                                                      stmt1->executeUpdate("DELETE FROM test_function_tx WHERE 1"),
                                                      count_full_before);

            std::auto_ptr<sql::ResultSet> rset2(stmt1->executeQuery("SELECT COUNT(*) FROM test_function_tx"));
            ensure("res2 is NULL", rset2.get() != NULL);
            ensure_equal_int("res2 is empty", rset2->next(), true);
            ensure_equal_int("Table not empty after delete", rset2->getInt(1), 0);
            ensure_equal_int("res2 has more rows ", rset2->next(), false);

            /* In autocommit on, this is a no-op */
            stmt1->getConnection()->rollback();

            std::auto_ptr<sql::ResultSet> rset3(stmt1->executeQuery("SELECT COUNT(*) FROM test_function_tx"));
            ensure("res3 is NULL", rset3.get() != NULL);
            ensure_equal_int("res3 is empty", rset3->next(), true);
            ensure_equal_int("Rollback didn't work", rset3->getInt(1), 0);
            ensure_equal_int("res3 has more rows ", rset3->next(), false);

            ensure("Data not populated", true == populate_TX_test_table(conn, database));

            /* Now let's delete and then commit */
            ensure_equal("Deleted less rows",
                                                      stmt1->executeUpdate("DELETE FROM test_function_tx WHERE 1"),
                                                      count_full_before);
            /* In autocommit on, this is a no-op */
            stmt1->getConnection()->commit();

            std::auto_ptr<sql::ResultSet> rset4(stmt1->executeQuery("SELECT COUNT(*) FROM test_function_tx"));
            ensure("res4 is NULL", rset4.get() != NULL);
            ensure_equal_int("res4 is empty", rset4->next(), true);
            ensure_equal_int("Table not empty after delete", rset4->getInt(1), 0);
            ensure_equal_int("res4 has more rows ", rset4->next(), false);

            conn->setAutoCommit(false);
            ensure("Data not populated", true == populate_TX_test_table(conn, database));
            ensure_equal("Deleted less rows",
                                                      stmt1->executeUpdate("DELETE FROM test_function_tx WHERE 1"),
                                                      count_full_before);
            /* In autocommit iff, this is an op */
            stmt1->getConnection()->rollback();
            std::auto_ptr<sql::ResultSet> rset5(stmt1->executeQuery("SELECT COUNT(*) FROM test_function_tx"));
            ensure("res5 is NULL", rset5.get() != NULL);
            ensure_equal_int("res5 is empty", rset5->next(), true);
            ensure_equal_int("Table empty after delete", rset5->getInt(1), count_full_before);
            ensure_equal_int("res5 has more rows ", rset5->next(), false);

            stmt1->execute("DROP TABLE test_function_tx");

            conn->setAutoCommit(old_commit_mode);
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ Test multistatement off - send two queries in one call */
static void test_result_set_5(std::auto_ptr<sql::Connection> & conn)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt1(conn->createStatement());
            ensure("stmt1 is NULL", stmt1.get() != NULL);

            try {
                  std::auto_ptr<sql::ResultSet> rset1(stmt1->executeQuery("SELECT COUNT(*) FROM test_function_tx; DELETE FROM test_function_tx"));
                  ensure("ERR: Exception not thrown", false);
            } catch (sql::SQLException &) {}
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


static void test_result_set_check_out_of_bound(sql::ResultSet *rset1)
{
      ensure("res1 is empty", rset1->next() != false);
      try {
            rset1->getInt(0);
            ensure("ERR: No sql::InvalidArgumentException thrown", false);
      } catch (sql::InvalidArgumentException &) {}
      try {
            rset1->getInt(123);
            ensure("ERR: No sql::InvalidArgumentException thrown", false);
      } catch (sql::InvalidArgumentException &) {}
      try {
            rset1->getInt("no_such_column");
            ensure("ERR: No sql::InvalidArgumentException thrown", false);
      } catch (sql::InvalidArgumentException &) {}
      try {
            rset1->getString(0);
            ensure("ERR: No sql::InvalidArgumentException thrown", false);
      } catch (sql::InvalidArgumentException &) {}
      try {
            rset1->getString(123);
            ensure("ERR: No sql::InvalidArgumentException thrown", false);
      } catch (sql::InvalidArgumentException &) {}
      try {
            rset1->getString("no_such_column");
            ensure("ERR: No sql::InvalidArgumentException thrown", false);
      } catch (sql::InvalidArgumentException &) {}
      try {
            rset1->getDouble(0);
            ensure("ERR: No sql::InvalidArgumentException thrown", false);
      } catch (sql::InvalidArgumentException &) {}
      try {
            rset1->getDouble(123);
            ensure("ERR: No sql::InvalidArgumentException thrown", false);
      } catch (sql::InvalidArgumentException &) {}
      try {
            rset1->getDouble("no_such_column");
            ensure("ERR: No sql::InvalidArgumentException thrown", false);
      } catch (sql::InvalidArgumentException &) {}
      try {
            rset1->getInt(rset1->getInt(1) + 1000);
            ensure("ERR: No sql::InvalidArgumentException thrown", false);
      } catch (sql::InvalidArgumentException &) {}
      try {
            rset1->isNull(0);
            ensure("ERR: No sql::InvalidArgumentException thrown", false);
      } catch (sql::InvalidArgumentException &) {}
      try {
            rset1->isNull(123);
            ensure("ERR: No sql::InvalidArgumentException thrown", false);
      } catch (sql::InvalidArgumentException &) {}
      try {
            rset1->isNull("no_such_column");
            ensure("ERR: No sql::InvalidArgumentException thrown", false);
      } catch (sql::InvalidArgumentException &) {}
      try {

            ensure_equal_int("res1 has more rows ", rset1->getInt(1), 1);
            ensure_equal_int("res1 has more rows ", rset1->getInt("count of rows"), 1);

//          ensure("res1 has more rows ", rset1->getDouble(1) - 1 < 0.1);
//          ensure("res1 has more rows ", rset1->getDouble("count of rows") - 1 < 0.1);
//          with libmysq we don't support these conversions,  on the fly :(
//          ensure("res1 has more rows ", rset1->getString(1).compare("1"));
//          ensure("res1 has more rows ", rset1->getString("count of rows").compare("1"));

            ensure_equal_int("c is not null", rset1->isNull(1), false);

            ensure_equal_int("res1 has more rows ", rset1->next(), false);
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      }
}


/* {{{ Test out of bound extraction of data */
static void test_result_set_6(std::auto_ptr<sql::Connection> & conn, std::string database)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt1(conn->createStatement());
            ensure("stmt1 is NULL", stmt1.get() != NULL);

            ensure_equal("sql::Connection differs", conn.get(), stmt1->getConnection());

            ensure("Data not populated", true == populate_TX_test_table(conn, database));

            std::auto_ptr<sql::ResultSet> rset1(stmt1->executeQuery("SELECT COUNT(*) AS 'count of rows' FROM test_function_tx"));
            ensure("res1 is NULL", rset1.get() != NULL);

            test_result_set_check_out_of_bound(rset1.get());

            stmt1->execute("DROP TABLE test_function_tx");
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ Test out of bound extraction of data - PS version */
static void test_result_set_7(std::auto_ptr<sql::Connection> & conn, std::string database)
{
      ENTER_FUNCTION();
      try {
            ensure("Data not populated", true == populate_TX_test_table(conn, database));

            std::auto_ptr<sql::PreparedStatement> stmt1(conn->prepareStatement("SELECT COUNT(*) AS 'count of rows' FROM test_function_tx"));
            ensure("stmt1 is NULL", stmt1.get() != NULL);
            ensure_equal("sql::Connection differs", conn.get(), stmt1->getConnection());

            std::auto_ptr<sql::ResultSet> rset1(stmt1->executeQuery());
            ensure("res1 is NULL", rset1.get() != NULL);

            test_result_set_check_out_of_bound(rset1.get());

            std::auto_ptr<sql::PreparedStatement> stmt2(conn->prepareStatement("DROP TABLE test_function_tx"));
            stmt2->execute();
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ Test commit and rollback (autocommit on) - PS version */
static void test_result_set_8(std::auto_ptr<sql::Connection> & conn, std::string database)
{
      ENTER_FUNCTION();
      try {
            int count_full_before;
            std::auto_ptr<sql::PreparedStatement> stmt0(conn->prepareStatement("SELECT 1"));
            ensure("stmt0 is NULL", stmt0.get() != NULL);

            ensure_equal("sql::Connection differs", conn.get(), stmt0->getConnection());

            int old_commit_mode = conn->getAutoCommit();
            conn->setAutoCommit(true);
            ensure("Data not populated", true == populate_TX_test_table_PS(conn, database));

            std::auto_ptr<sql::PreparedStatement> stmt1(conn->prepareStatement("SELECT COUNT(*) FROM test_function_tx"));
            std::auto_ptr<sql::ResultSet> rset1(stmt1->executeQuery());
            ensure("res1 is NULL", rset1.get() != NULL);
            ensure_equal_int("res1 is empty", rset1->next(), true);
            count_full_before = rset1->getInt(1);
            ensure_equal_int("res1 has more rows ", rset1->next(), false);

            std::auto_ptr<sql::PreparedStatement> stmt2(conn->prepareStatement("DELETE FROM test_function_tx WHERE 1"));
            /* Let's delete and then rollback */
            ensure_equal_int("Deleted less rows", stmt2->executeUpdate(), count_full_before);

            std::auto_ptr<sql::PreparedStatement> stmt3(conn->prepareStatement("SELECT COUNT(*) FROM test_function_tx"));
            std::auto_ptr<sql::ResultSet> rset2(stmt3->executeQuery());
            ensure("res2 is NULL", rset2.get() != NULL);
            ensure_equal_int("res2 is empty", rset2->next(), true);
            ensure_equal_int("Table not empty after delete", rset2->getInt(1), 0);
            ensure_equal_int("res2 has more rows ", rset2->next(), false);

            /* In autocommit on, this is a no-op */
            stmt1->getConnection()->rollback();

            std::auto_ptr<sql::PreparedStatement> stmt4(conn->prepareStatement("SELECT COUNT(*) FROM test_function_tx"));
            std::auto_ptr<sql::ResultSet> rset3(stmt4->executeQuery());
            ensure("res3 is NULL", rset3.get() != NULL);
            ensure_equal_int("res3 is empty", rset3->next(), true);
            ensure_equal_int("Rollback didn't work", rset3->getInt(1), 0);
            ensure_equal_int("res3 has more rows ", rset3->next(), false);

            ensure("Data not populated", true == populate_TX_test_table_PS(conn, database));

            std::auto_ptr<sql::PreparedStatement> stmt5(conn->prepareStatement("DELETE FROM test_function_tx WHERE 1"));
            /* Let's delete and then rollback */
            ensure_equal_int("Deleted less rows", stmt5->executeUpdate(), count_full_before);

            /* In autocommit on, this is a no-op */
            stmt1->getConnection()->commit();

            std::auto_ptr<sql::PreparedStatement> stmt6(conn->prepareStatement("SELECT COUNT(*) FROM test_function_tx"));
            std::auto_ptr<sql::ResultSet> rset4(stmt6->executeQuery());
            ensure("res4 is NULL", rset4.get() != NULL);
            ensure_equal_int("res4 is empty", rset4->next(), true);
            ensure_equal_int("Rollback didn't work", rset4->getInt(1), 0);
            ensure_equal_int("res4 has more rows ", rset4->next(), false);

            conn->setAutoCommit(false);
            ensure("Data not populated", true == populate_TX_test_table_PS(conn, database));
            std::auto_ptr<sql::PreparedStatement> stmt7(conn->prepareStatement("DELETE FROM test_function_tx WHERE 1"));
            /* Let's delete and then rollback */
            ensure("Deleted less rows", stmt7->executeUpdate() == count_full_before);
            /* In autocommit iff, this is an op */
            stmt1->getConnection()->rollback();

            std::auto_ptr<sql::PreparedStatement> stmt8(conn->prepareStatement("SELECT COUNT(*) FROM test_function_tx"));
            std::auto_ptr<sql::ResultSet> rset5(stmt8->executeQuery());
            ensure("res5 is NULL", rset5.get() != NULL);
            ensure_equal_int("res5 is empty", rset5->next(), true);
            ensure_equal_int("Rollback didn't work", rset5->getInt(1), 0);
            ensure_equal_int("res5 has more rows ", rset5->next(), false);

            std::auto_ptr<sql::PreparedStatement> stmt9(conn->prepareStatement("DROP TABLE test_function_tx"));
            stmt1->execute();

            conn->setAutoCommit(old_commit_mode);
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ Test multistatement off - send two queries in one call - PS version */
static void test_result_set_9(std::auto_ptr<sql::Connection> & conn)
{
      ENTER_FUNCTION();
      try {

            try {
                  std::auto_ptr<sql::PreparedStatement> stmt1(conn->prepareStatement("SELECT COUNT(*) FROM test_function_tx; DELETE FROM test_function_tx"));
                  ensure("ERR: Exception not thrown", false);
            } catch (sql::SQLException &) {}
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ Test multiresults - SP with normal and prepared statement */
static void test_result_set_10(std::auto_ptr<sql::Connection> & conn, std::string database)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt0(conn->createStatement());
            ensure("stmt0 is NULL", stmt0.get() != NULL);
            stmt0->execute("USE " + database);

#if 0
      /* Doesn't work with libmysql - a limitation of the library, might work with mysqlnd if it lies under */
            {
                  /* Create procedure is not supported for preparing */
                  std::auto_ptr<sql::Statement> stmt1(conn->createStatement());
                  stmt1->execute("DROP PROCEDURE IF EXISTS CPP1");
                  stmt1->execute("CREATE PROCEDURE CPP1() SELECT 42");

                  std::auto_ptr<sql::PreparedStatement> stmt2(conn->prepareStatement("CALL CPP1()"));
                  stmt2->execute();

                  std::auto_ptr<sql::ResultSet> rset1(stmt2->getResultSet());
                  ensure("res1 is NULL", rset1.get() != NULL);
                  ensure_equal_int("res1 is empty", rset1->next(), true);
                  eensure_equal_intsure("Wrong data", rset1->getInt(1), 42);
                  ensure_equal_int("res1 has more rows ", rset1->next(), false);

                  /* Here comes the status result set*/
                  std::auto_ptr<sql::ResultSet> rset2(stmt2->getResultSet());
                  ensure("res2 is not NULL", rset2.get() == NULL);

                  /* drop procedure is not supported for preparing */
                  stmt1->execute("DROP PROCEDURE CPP1");
            }

            {
                  std::auto_ptr<sql::Statement> stmt1(conn->createStatement());
                  stmt1->execute("DROP PROCEDURE IF EXISTS CPP1");
                  stmt1->execute("CREATE PROCEDURE CPP1() SELECT 42");

                  stmt1->execute("CALL CPP1()");
                  std::auto_ptr<sql::ResultSet> rset1(stmt1->getResultSet());
                  ensure("res1 is NULL", rset1.get() != NULL);
                  ensure_equal_int("res1 is empty", rset1->next(), true);
                  ensure_equal_int("Wrong data", rset1->getInt(1), 42);
                  ensure_equal_int("res1 has more rows ", rset1->next(), false);

                  /* Here comes the status result set*/
                  std::auto_ptr<sql::ResultSet> rset2(stmt1->getResultSet());
                  ensure_equal_int("res2 is not NULL", rset2.get(), NULL);

                  stmt1->execute("DROP PROCEDURE CPP1");
            }
#endif
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ getMetadata() */
static void test_result_set_11(std::auto_ptr<sql::Connection> & conn, std::string database)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt1(conn->createStatement());
            ensure("stmt1 is NULL", stmt1.get() != NULL);
            stmt1->setResultSetType(sql::ResultSet::TYPE_SCROLL_INSENSITIVE);

            ensure("Data not populated", true == populate_test_table(conn, database));

            std::auto_ptr<sql::ResultSet> rset1(stmt1->executeQuery("SELECT * FROM test_function"));
            ensure("res1 is NULL", rset1.get() != NULL);
            ensure("res1 is empty", rset1->next() != false);
            stmt1->execute("set @old_charset_res=@@session.character_set_results");
            stmt1->execute("set character_set_results=NULL");
            sql::ResultSetMetaData * meta1 = rset1->getMetaData();
            ensure("column name differs", !meta1->getColumnName(1).compare("a"));
            ensure("column name differs", !meta1->getColumnName(2).compare("b"));
            ensure("column name differs", !meta1->getColumnName(3).compare("c"));
            ensure("column name differs", !meta1->getColumnName(4).compare("d"));
            ensure("column name differs", !meta1->getColumnName(5).compare("e"));

            ensure_equal_int("bad case sensitivity", meta1->isCaseSensitive(1), false);
            ensure_equal_int("bad case sensitivity", meta1->isCaseSensitive(2), false);
            ensure_equal_int("bad case sensitivity", meta1->isCaseSensitive(3), false);
            ensure_equal_int("bad case sensitivity", meta1->isCaseSensitive(4), false);
//          ensure_equal_int("bad case sensitivity", meta1->isCaseSensitive(5), true);

            ensure_equal_int("bad case sensitivity", meta1->isCurrency(1), false);
            ensure_equal_int("bad case sensitivity", meta1->isCurrency(2), false);
            ensure_equal_int("bad case sensitivity", meta1->isCurrency(3), false);
            ensure_equal_int("bad case sensitivity", meta1->isCurrency(4), false);
            ensure_equal_int("bad case sensitivity", meta1->isCurrency(5), false);
            stmt1->execute("set character_set_results=@old_charset_res");

            try {
                  meta1->getColumnName(0);
                  meta1->isCaseSensitive(0);
                  meta1->isCurrency(0);
                  ensure("Exception not correctly thrown", false);
            } catch (sql::SQLException &) {
                  ensure("Exception correctly thrown", true);
            }
            try {
                  meta1->getColumnName(100);
                  meta1->isCaseSensitive(100);
                  meta1->isCurrency(100);
                  ensure("Exception not correctly thrown", false);
            } catch (sql::SQLException &) {
                  ensure("Exception correctly thrown", true);
            }
            /*
                  a integer unsigned not null,
                  b integer,
                  c integer default null,
                  d char(10),
                  e varchar(10) character set utf8 collate utf8_bin
            */


      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */

#if 0
/* {{{ General test 0 */
static void test_general_0(std::auto_ptr<sql::Connection> & conn)
{
      ENTER_FUNCTION();
      try {
            sql::DatabaseMetaData * meta = conn->getMetaData();
            std::auto_ptr<sql::ResultSet> rset(meta->getSchemata());

            while (rset->next()) {
                  std::auto_ptr<sql::ResultSet> rset2(meta->getSchemaObjects("", rset->getString("schema_name")));

                  while (rset2->next())  {
                        rset2->getString("object_type").c_str();
                        rset2->getString("name").c_str();
                        rset2->getString("ddl").c_str();
                  }
            }
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ General test 1 */
static void test_general_1(std::auto_ptr<sql::Connection> & conn)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::Statement> stmt(conn->createStatement());

            stmt->execute("DROP TABLE IF EXISTS test.product");
            stmt->execute("CREATE TABLE test.product(idproduct INT NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(80))");

            conn->setAutoCommit(0);


            std::auto_ptr<sql::PreparedStatement> prepStmt(conn->prepareStatement("INSERT INTO test.product (idproduct, name) VALUES(?, ?)"));
            prepStmt->setInt(1, 1);
            prepStmt->setString(2, "The answer is 42");
            prepStmt->executeUpdate();

            std::auto_ptr<sql::ResultSet> rset1(stmt->executeQuery("SELECT * FROM test.product"));

            ensure_equal_int("Empty result set", rset1->next(), true);
            ensure("Wrong data", !rset1->getString(2).compare("The answer is 42"));
            ensure("Wrong data", !rset1->getString("name").compare("The answer is 42"));
            ensure_equal_int("Non-Empty result set", rset1->next(), false);

            conn->rollback();

            std::auto_ptr<sql::ResultSet> rset2(stmt->executeQuery("SELECT * FROM test.product"));

            ensure_equal_int("Non-Empty result set", rset1->next(), false);

            stmt->execute("DROP TABLE IF EXISTS test.product");
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */
#endif

/* {{{ */
static void test_prep_statement_0(std::auto_ptr<sql::Connection> & conn)
{
      ENTER_FUNCTION();
      try {
            try {
                  std::auto_ptr<sql::PreparedStatement> stmt(conn->prepareStatement("SELECT 1"));
                  stmt->execute();
                  std::auto_ptr<sql::ResultSet> rset1(stmt->getResultSet());
            } catch (sql::SQLException &e) {
                  printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
                  printf("# ");
                  total_errors++;
            }

            try {
                  std::auto_ptr<sql::PreparedStatement> stmt(conn->prepareStatement("SELECT ?"));
            } catch (sql::SQLException &e) {
                  printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
                  printf("# ");
                  total_errors++;
            }

            /* Bind but don't execute. There should be no leak */
            try {
                  std::auto_ptr<sql::PreparedStatement> stmt(conn->prepareStatement("SELECT ?, ?, ?"));
                  stmt->setInt(1, 1);
            } catch (sql::SQLException &e) {
                  printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
                  printf("# ");
                  total_errors++;
            }

            /* Bind two different types for the same column. There should be no leak */
            try {
                  std::auto_ptr<sql::PreparedStatement> stmt(conn->prepareStatement("SELECT ?"));
                  stmt->setString(1, "Hello MySQL");
                  stmt->setInt(1, 42);
                  stmt->execute();
            } catch (sql::SQLException &e) {
                  printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
                  printf("# ");
                  total_errors++;
            }

            /* Execute without fetching the result set. The connector should clean the wire */
            try {
                  std::auto_ptr<sql::PreparedStatement> stmt(conn->prepareStatement("SELECT ?, ?, ?, ?"));
                  stmt->setInt(1, 1);
                  stmt->setDouble(2, 2.25);
                  stmt->setString(3, "Здрасти МySQL");
                  stmt->setDateTime(4, "2006-11-10 16:17:18");
                  stmt->execute();
            } catch (sql::SQLException &e) {
                  printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
                  printf("# ");
                  total_errors++;
            }

#if 0
            /* Bind one parameter less than needed - NULL should be sent to the server . Check also multibyte fetching. */
            try {
                  std::auto_ptr<sql::PreparedStatement> stmt(conn->prepareStatement("SELECT ? as \"Здравей_МySQL\" , ?, ?"));
                  stmt->setInt(3, 42);
                  stmt->setString(1, "Здравей МySQL! Как си?");
                  stmt->execute();
                  std::auto_ptr<sql::ResultSet> rset(stmt->getResultSet());
                  ensure("No result set", rset.get() != NULL);
                  ensure("Result set is empty", rset->next() != false);
                  ensure("Incorrect value for col 1", rset->getInt(2) == 0 && true == rset->wasNull());

                  ensure("Incorrect value for col 0", !rset->getString(1).compare("Здравей МySQL! Как си?") && false == rset->wasNull());
                  ensure("Incorrect value for col 0", !rset->getString("Здравей_МySQL").compare("Здравей МySQL! Как си?") && false == rset->wasNull());

                  ensure("Incorrect value for col 2", rset->getInt(3) == 42 && false == rset->wasNull());
                  ensure("Incorrect value for col 2", !rset->getString(3).compare("42") && false == rset->wasNull());
            } catch (sql::SQLException &e) {
                  printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
                  printf("# ");
                  total_errors++;
            }
#endif
            /* try double ::execute() */
            try {
                  std::auto_ptr<sql::PreparedStatement> stmt(conn->prepareStatement("SELECT ?"));
                  stmt->setString(1, "Hello World");
                  for (int i = 0; i < 100; i++) {
                        std::auto_ptr<sql::ResultSet> rset(stmt->executeQuery());
                  }
            } catch (sql::SQLException &e) {
                  printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
                  printf("# ");
                  total_errors++;
            }

            /* Test clearParameters() */
            {
                  try {
                        std::auto_ptr<sql::PreparedStatement> stmt(conn->prepareStatement("SELECT ?"));
                        stmt->setInt(1, 13);
                        std::auto_ptr<sql::ResultSet> rs(stmt->executeQuery());
                  } catch (sql::SQLException &e) {
                        printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
                        printf("# ");
                        total_errors++;
                  }
                  try {
                        std::auto_ptr<sql::PreparedStatement> stmt(conn->prepareStatement("SELECT ?"));
                        stmt->setInt(1, 13);
                        stmt->clearParameters();
                        std::auto_ptr<sql::ResultSet> rs(stmt->executeQuery());
                        ensure("Exception not thrown", false);
                  } catch (sql::SQLException &) {}
            }

            /* try clearParameters() call */
            {
                  std::auto_ptr<sql::PreparedStatement> stmt(conn->prepareStatement("SELECT ?, ?, ?, NULL"));
                  try {
                        stmt->setInt(3, 42);
                        stmt->setString(1, "Hello MYSQL");
                        stmt->setDouble(2, 1.25);
                        std::auto_ptr<sql::ResultSet> rset(stmt->executeQuery());
                        ensure("No result set", rset.get() != NULL);
                        ensure("Result set is empty", rset->next() != false);
                        ensure("Incorrect value for col 1", !rset->getString(4).compare("") && true == rset->wasNull());

                        ensure("Incorrect value for col 0", !rset->getString(1).compare("Hello MYSQL") && false == rset->wasNull());

                        ensure("Incorrect value for col 2", rset->getInt(3) == 42 && false == rset->wasNull());
//                      ensure("Incorrect value for col 2", !rset->getString(3).compare("42") && false == rset->wasNull());

                        ensure("Incorrect value for col 3", rset->getDouble(2) == 1.25 && false == rset->wasNull());
                  } catch (sql::SQLException &e) {
                        printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
                        printf("# ");
                        total_errors++;
                  }
            }
            try {
                  std::auto_ptr<sql::PreparedStatement> stmt(conn->prepareStatement("SELECT ?"));
                  stmt->setInt(1, 1);
                  stmt->execute();
                  std::auto_ptr<sql::ResultSet> rset(stmt->getResultSet());
            } catch (sql::SQLException &) {
                  printf("\n# ERR: Caught sql::SQLException at %s::%d\n", CPPCONN_FUNC, __LINE__);
                  printf("# ");
                  total_errors++;
            }

      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ Test simple update statement against statement object */
static void test_prep_statement_1(std::auto_ptr<sql::Connection> & conn, std::auto_ptr<sql::Connection> & conn2, const std::string & database)
{
      ENTER_FUNCTION();
      try {
            std::auto_ptr<sql::PreparedStatement> stmt0(conn->prepareStatement("SELECT 1, 2, 3"));
            ensure("stmt0 is NULL", stmt0.get() != NULL);

            ensure("Data not populated", true == populate_test_table_PS(conn, database));

            std::auto_ptr<sql::PreparedStatement> stmt1(conn->prepareStatement("SELECT * FROM test_function"));
            ensure("stmt1 is NULL", stmt1.get() != NULL);
            if (false == stmt1->execute()) {
                  ensure("False returned for SELECT", false);
            }
            std::auto_ptr<sql::ResultSet> rset(stmt1->getResultSet());

            /* Clean */
            std::auto_ptr<sql::Statement> stmt2(conn2->createStatement());
            ensure("stmt2 is NULL", stmt2.get() != NULL);
            stmt2->execute("USE " + database);

            std::auto_ptr<sql::PreparedStatement> stmt3(conn2->prepareStatement("DROP TABLE test_function"));
            ensure("stmt3 is NULL", stmt3.get() != NULL);
            stmt3->execute();
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      } catch (...) {
            printf("\n# ERR: Caught unknown exception at %s::%d\n", CPPCONN_FUNC, __LINE__);
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ Test simple update statement against statement object */
static void test_prep_statement_2(std::auto_ptr<sql::Connection> & conn, std::string database)
{
      ENTER_FUNCTION();
      try {
            populate_test_table_PS_integers(conn, database);

            try {
                  std::auto_ptr<sql::PreparedStatement> stmt(conn->prepareStatement("SELECT '1"));
                  ensure("ERR: Exception not thrown", false);
            } catch (sql::SQLException &) {}

            /* USE still cannot be prepared */
            try {
                  std::auto_ptr<sql::PreparedStatement> stmt(conn->prepareStatement("USE " + database));
                  ensure("ERR: Exception not thrown", false);
            } catch (sql::SQLException &) {}

      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      } catch (...) {
            printf("\n# ERR: Caught unknown exception at %s::%d\n", CPPCONN_FUNC, __LINE__);
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ Test simple update statement against statement object */
static void test_prep_statement_3(std::auto_ptr<sql::Connection> & conn, std::auto_ptr<sql::Connection> & conn2, const std::string & database)
{
      ENTER_FUNCTION();
      try {
            int64_t     r1_c1 = L64(2147483646),
                        r1_c2 = L64(2147483650),
                        r1_c3 = L64(9223372036854775806),
                        r2_c1 = L64(2147483647),
                        r2_c2 = L64(2147483649),
                        r2_c3 = L64(9223372036854775807);

            uint64_t r1_c4 = UL64(9223372036854775810),
                         r2_c4 = UL64(18446744073709551615);

            ensure("Data not populated", true == populate_test_table_PS_integers(conn, database));

            std::auto_ptr<sql::PreparedStatement> stmt1(conn->prepareStatement("INSERT INTO test_function_int (i, i_uns, b, b_uns) VALUES(?,?,?,?)"));
            ensure("stmt0 is NULL", stmt1.get() != NULL);
            stmt1->clearParameters();
            stmt1->setInt(1, static_cast<int>(r1_c1));
            stmt1->setInt64(2, r1_c2);
            stmt1->setInt64(3, r1_c3);
            stmt1->setUInt64(4, r1_c4);
            ensure("True returned for INSERT", false == stmt1->execute());
            stmt1->clearParameters();
            stmt1->setInt(1, static_cast<int>(r2_c1));
            stmt1->setInt64(2, r2_c2);
            stmt1->setInt64(3, r2_c3);
            stmt1->setUInt64(4, r2_c4);
            ensure("True returned for INSERT", false == stmt1->execute());

            {
                  std::auto_ptr<sql::PreparedStatement> stmt2(conn->prepareStatement("SELECT i, i_uns, b, b_uns FROM test_function_int"));
                  ensure("stmt1 is NULL", stmt2.get() != NULL);
                  ensure("False returned for SELECT", stmt2->execute());

                  std::auto_ptr<sql::ResultSet> rset(stmt2->getResultSet());

                  ensure("No first line", rset->next());
                  ensure_equal_int64("Different data", rset->getInt("i"), r1_c1);
                  ensure_equal_int64("Different data", rset->getInt(1), r1_c1);

                  ensure_equal_int64("Different data", rset->getInt64("i_uns"), r1_c2);
                  ensure_equal_int64("Different data", rset->getInt64(2), r1_c2);

                  ensure_equal_int64("Different data", rset->getInt64("b"), r1_c3);
                  ensure_equal_int64("Different data", rset->getInt64(3), r1_c3);

                  ensure_equal_uint64("Different data", rset->getUInt64("b_uns"), r1_c4);
                  ensure_equal_uint64("Different data", rset->getUInt64(4), r1_c4);

                  ensure("No second line", rset->next());

                  ensure_equal_int64("Different data", rset->getInt("i"), r2_c1);
                  ensure_equal_int64("Different data", rset->getInt(1), r2_c1);

                  ensure_equal_int64("Different data", rset->getInt64("i_uns"), r2_c2);
                  ensure_equal_int64("Different data", rset->getInt64(2), r2_c2);

                  ensure_equal_int64("Different data", rset->getInt64("b"), r2_c3);
                  ensure_equal_int64("Different data", rset->getInt64(3), r2_c3);

                  ensure_equal_uint64("Different data", rset->getUInt64("b_uns"), r2_c4);
                  ensure_equal_uint64("Different data", rset->getUInt64(4), r2_c4);

                  ensure("Too many lines", rset->next() == false);
            }

            {
                  std::auto_ptr<sql::Statement> stmt2(conn->createStatement());
                  ensure("stmt1 is NULL", stmt2.get() != NULL);
                  ensure("False returned for SELECT", stmt2->execute("SELECT i, i_uns, b, b_uns FROM test_function_int"));

                  std::auto_ptr<sql::ResultSet> rset(stmt2->getResultSet());

                  ensure("No first line", rset->next());
                  ensure_equal_int64("Different data", rset->getInt("i"), r1_c1);
                  ensure_equal_int64("Different data", rset->getInt(1), r1_c1);

                  ensure_equal_int64("Different data", rset->getInt64("i_uns"), r1_c2);
                  ensure_equal_int64("Different data", rset->getInt64(2), r1_c2);

                  ensure_equal_int64("Different data", rset->getInt64("b"), r1_c3);
                  ensure_equal_int64("Different data", rset->getInt64(3), r1_c3);

                  ensure_equal_uint64("Different data", rset->getUInt64("b_uns"), r1_c4);
                  ensure_equal_uint64("Different data", rset->getUInt64(4), r1_c4);

                  ensure("No second line", rset->next());

                  ensure_equal_int64("Different data", rset->getInt("i"), r2_c1);
                  ensure_equal_int64("Different data", rset->getInt(1), r2_c1);

                  ensure_equal_int64("Different data", rset->getInt64("i_uns"), r2_c2);
                  ensure_equal_int64("Different data", rset->getInt64(2), r2_c2);

                  ensure_equal_int64("Different data", rset->getInt64("b"), r2_c3);
                  ensure_equal_int64("Different data", rset->getInt64(3), r2_c3);

                  ensure_equal_uint64("Different data", rset->getUInt64("b_uns"), r2_c4);
                  ensure_equal_uint64("Different data", rset->getUInt64(4), r2_c4);

                  ensure("Too many lines", rset->next() == false);
            }

            /* Clean */
            std::auto_ptr<sql::Statement> stmt4(conn2->createStatement());
            ensure("stmt4 is NULL", stmt4.get() != NULL);
            stmt4->execute("USE " + database);

            std::auto_ptr<sql::PreparedStatement> stmt5(conn2->prepareStatement("DROP TABLE test_function_int"));
            ensure("stmt5 is NULL", stmt5.get() != NULL);
            stmt5->execute();
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      } catch (...) {
            printf("\n# ERR: Caught unknown exception at %s::%d\n", CPPCONN_FUNC, __LINE__);
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */


/* {{{ Tests blob with PS */
static void test_prep_statement_blob(std::auto_ptr<sql::Connection> & conn, std::string database)
{
      ENTER_FUNCTION();
      try {
            populate_blob_table(conn, database);
            /* USE still cannot be prepared */
            std::auto_ptr<sql::Statement> use_stmt(conn->createStatement());
            use_stmt->execute("USE " + database);

            std::auto_ptr<sql::PreparedStatement> stmt(conn->prepareStatement("INSERT INTO test_blob VALUES(?)"));
            std::string value("A\0B", sizeof("A\0B") - 1);
            std::istringstream tmp_blob(value);
            stmt->setBlob(1, &tmp_blob);
            stmt->execute();


            std::auto_ptr<sql::Statement> stmt2(conn->createStatement());
            stmt2->execute("SELECT * FROM test_blob");
            std::auto_ptr<sql::ResultSet> rset2(stmt2->getResultSet());
            ensure("res2 is NULL", rset2.get() != NULL);
            ensure_equal_int("res2 is empty", rset2->next(), true);
            ensure_equal_str("Wrong data", rset2->getString(1), value);

            std::auto_ptr<std::istream> blob(rset2->getBlob(1));
            std::string::iterator it;
            for (it = value.begin() ; it < value.end(); it++) {
                  if ((blob->rdstate() & std::istream::eofbit)) {
                        ensure("premature eof", 0);
                  }
                  char ch;
                  blob->get(ch);
                  if ((blob->rdstate() & std::istream::badbit) != 0) {
                        ensure("badbit set", false);
                  } else if ((blob->rdstate() & std::istream::failbit) != 0) {
                        if ((blob->rdstate() & std::istream::eofbit) == 0) {
                              ensure("failbit set without eof being set", false);
                        }
                  }
                  if (*it != ch) {
                        ensure("character differ", false);
                  }
            }
            ensure("BLOB doesn't match, has more data", (blob->rdstate() & std::istream::eofbit) == 0);

            ensure_equal_int("res2 has more rows ", rset2->next(), false);

            stmt2->execute("DELETE FROM test_blob WHERE 1");
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      } catch (...) {
            printf("\n# ERR: Caught unknown exception at %s::%d\n", CPPCONN_FUNC, __LINE__);
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}
/* }}} */

#define DEBUG_TABLE_PRIVS 0

/* {{{ Tests getTablePrivileges */
/* TODO - broken
static void test_get_table_privileges_1(const std::string & host, const std::string & user, const std::string & pass)
{
      ENTER_FUNCTION();
      int a;
      char buf[20] = "p";
      snprintf(buf+1, sizeof(buf) - 2, "%u", ((unsigned int) &a) % 10000);

      std::string plain_user(std::string("tu").append(buf));
      std::string plain_user_w_host(std::string("").append(plain_user).
#if A0
                                          append("@%"));
#else
                                          append("@localhost"));
#endif

      std::string plain_user_db(std::string("test_someuser_db").append(buf));
      std::string plain_user_table("table1");
      std::string create_db(std::string("CREATE DATABASE `").append(plain_user_db).append("`"));
      std::string create_table(std::string("CREATE TABLE `").append(plain_user_db).append("`.`").append(plain_user_table).append("`(a int)"));
      std::string create_user(std::string("CREATE USER ").append(plain_user_w_host).append(" IDENTIFIED BY 'pass'"));
      std::string grant_user1(std::string("GRANT ALL ON `").append(plain_user_db).append("`.`").
                                          append(plain_user_table).append("` TO ").append(plain_user_w_host));
      std::string grant_user2(std::string("GRANT DELETE ON `").append(plain_user_db).append("`.`").
                                          append(plain_user_table).append("` TO ").append(plain_user_w_host));
      std::string grant_user3(std::string("GRANT SELECT, INSERT ON `").append(plain_user_db).append("`.`").
                                          append(plain_user_table).append("` TO ").append(plain_user_w_host));
      std::string drop_user(std::string("DROP USER ").append(plain_user_w_host));
      std::string drop_db(std::string("DROP DATABASE `").append(plain_user_db).append("`"));

      std::list< std::string > grantsList;
      grantsList.push_back(grant_user1);
      grantsList.push_back(grant_user2);
      grantsList.push_back(grant_user3);

      std::list< std::list< std::string > > expectedPrivilegesList;
      std::list< std::string > expectedPrivileges1;
      expectedPrivileges1.push_back(std::string("ALTER"));
      expectedPrivileges1.push_back(std::string("DELETE"));
      expectedPrivileges1.push_back(std::string("DROP"));
      expectedPrivileges1.push_back(std::string("INDEX"));
      expectedPrivileges1.push_back(std::string("INSERT"));
      expectedPrivileges1.push_back(std::string("LOCK TABLES"));
      expectedPrivileges1.push_back(std::string("SELECT"));
      expectedPrivileges1.push_back(std::string("UPDATE"));
      expectedPrivilegesList.push_back(expectedPrivileges1);

      std::list< std::string > expectedPrivileges2;
      expectedPrivileges2.push_back(std::string("DELETE"));
      expectedPrivilegesList.push_back(expectedPrivileges2);

      std::list< std::string > expectedPrivileges3;
      expectedPrivileges3.push_back(std::string("SELECT"));
      expectedPrivileges3.push_back(std::string("INSERT"));
      expectedPrivilegesList.push_back(expectedPrivileges3);

      std::list< std::string >::const_iterator grantsList_it = grantsList.begin();
      std::list< std::list< std::string > >::const_iterator expectedPrivilegesList_it = expectedPrivilegesList.begin();

      try {
            std::auto_ptr<sql::Connection> root_conn(get_connection(host, user, pass));
            std::auto_ptr<sql::Statement> root_stmt(root_conn->createStatement());
#if DEBUG_TABLE_PRIVS
            std::cout << std::endl << plain_user_w_host << std::endl;
#endif
            for (; grantsList_it != grantsList.end(); grantsList_it++, expectedPrivilegesList_it++) {
                  root_stmt->execute(create_db);
                  root_stmt->execute(create_table);
                  root_stmt->execute(create_user);
                  root_stmt->execute(*grantsList_it);
                   Put it in a block, so the connection will be closed before we start dropping the user and the table
                  try {

                        std::auto_ptr<sql::Connection> user_conn(get_connection(host, plain_user, "pass"));
                        std::auto_ptr<sql::DatabaseMetaData> user_conn_meta(user_conn->getMetaData());
                        std::auto_ptr<sql::ResultSet> res(user_conn_meta->getTablePrivileges("", "%", "%"));


#if DEBUG_TABLE_PRIVS
                        printf("\tTABLE_CAT\tTABLE_SCHEM\tTABLE_NAME\tGRANTOR\tGRANTEE\tPRIVILEGE\tIS_GRANTABLE\n");
#endif
                        unsigned int found = 0, rows = 0;
                        while (res->next()) {
#if DEBUG_TABLE_PRIVS
                              for (int i = 1; i < 8; i++) printf("\t[%s]", res->getString(i).c_str());
                              printf("\n");
#endif
                              std::list< std::string >::const_iterator it = expectedPrivilegesList_it->begin();
                              for (;it != expectedPrivilegesList_it->end(); it++) {
                                    if (!it->compare(res->getString("PRIVILEGE"))) {
                                          found++;
                                    }
//                                  ensure_equal("Bad TABLE_CAT", std::string(""), res->getString("TABLE_CAT"));
//                                  ensure_equal("Bad TABLE_SCHEM", plain_user_db, res->getString("TABLE_SCHEM"));
//                                  ensure_equal("Bad TABLE_NAME", plain_user_table, res->getString("TABLE_NAME"));
//                                  ensure_equal("Bad GRANTEE", plain_user_w_host, res->getString("GRANTEE"));
                              }
                              rows++;
                        }
#if DEBUG_TABLE_PRIVS
                        std::cout << "Found:" << found << " Rows:" << rows << "\n";
#endif
                        ensure_equal_int("Bad PRIVILEGE data(1)", found, expectedPrivilegesList_it->size());
                        ensure_equal_int("Bad PRIVILEGE data(2)", found, rows);
                  } catch (sql::SQLException &e) {
                        printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
                        printf("# ");
                        total_errors++;
                  } catch (...) {
                        printf("\n# ERR: Caught unknown exception at %s::%d\n", CPPCONN_FUNC, __LINE__);
                        printf("# ");
                        total_errors++;
                  }
                  root_stmt->execute(drop_user);
                  root_stmt->execute(drop_db);
            }
      } catch (sql::SQLException &e) {
            printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
            printf("# ");
            total_errors++;
      } catch (...) {
            printf("\n# ERR: Caught unknown exception at %s::%d\n", CPPCONN_FUNC, __LINE__);
            printf("# ");
            total_errors++;
      }
      LEAVE_FUNCTION();
}

*/


/* {{{ */
int run_tests(int argc, const char **argv)
{

      printf("1..%d\n#\n", loops);
#ifndef DRIVER_TEST
      printf("# Client version: %s\n", mysql_get_client_info());
#endif

      std::auto_ptr<sql::Connection> conn, conn2;
      int last_error_total = 0;
      int i;

      const std::string user(argc >=3? argv[2]:"root");
      const std::string pass(argc >=4? argv[3]:"root");
      const std::string database(argc >=5? argv[4]:USED_DATABASE);

      for (i = 0 ; i < loops; i++) {
            last_error_total = total_errors;
                printf("# 0 - total_errors %d, last_error_total = %d\n", total_errors, last_error_total);
            const std::string host(argc >=2? argv[1]:"tcp://127.0.0.1");
            std::cout << "# Host=" << host << std::endl;
                std::cout << "# User=" << user << std::endl;

                std::string connect_method("unknown");
                if (host.find("tcp://", (size_t)0) != std::string::npos) {
                  connect_method = "tcp";
                } else if (host.find("unix://", (size_t)0) != std::string::npos) {
                  connect_method = "socket";
                }

            printf("#---------------  %d -----------------\n", i + 1);
            printf("# ");

            try {
                  conn.reset(get_connection(host, user, pass));
            } catch (sql::SQLException &e) {
                  printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
                  printf("not ok\n");
                  return 1;
            }
            /* XXX : Doing upcast, not the best thing, but tests getMySQLVariable */
//          ensure("Testing getSessionVariable",
//                            0 == ((sql::mysql::MySQL_Connection *) conn)->getSessionVariable("version").compare(
//                                              mysql_get_server_info(((sql::mysql::MySQL_Connection *) conn)->getMySQLHandle())
//                                                                                                                                        )
//                );
//          printf("\n");
//          printf("# Server %s\n", ((sql::mysql::MySQL_Connection *) conn)->getSessionVariable("version").c_str());
//          printf("# ");

            try {
                  std::auto_ptr<sql::Statement> stmt(conn->createStatement());
                  stmt->execute("SHOW ENGINES");
                  {
                        std::auto_ptr<sql::ResultSet> rset(stmt->getResultSet());
                        int found = 0;
                        while (rset->next()) {
                              if (rset->getString("Engine") == "InnoDB" && (rset->getString("Support") == "YES" || rset->getString("Support") == "DEFAULT")) {
                                    found = 1;
                                    break;
                              }
                        }
                        if (found == 0) {
                              printf("\n#ERR: InnoDB Storage engine not available or disabled\n");
                              printf("not ok\n");
                              return 1;
                        }
                  }

                  stmt->execute("USE " + database);
            } catch (sql::SQLException &e) {
                  printf("\n# ERR: Caught sql::SQLException at %s::%d  [%s] (%d/%s)\n", CPPCONN_FUNC, __LINE__, e.what(), e.getErrorCode(), e.getSQLState());
                  printf("# ");
                  return 1;
            }
            conn.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            test_connection_0(conn);
            conn.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            test_connection_1(conn, database);
            conn.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            test_connection_2(conn, database);
            conn.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            test_connection_3(conn, user);
            conn.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            test_autocommit(conn);
            conn.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            test_statement_0(conn);
            conn.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            conn2.reset(get_connection(host, user, pass));
            test_statement_1(conn, conn2, database);
            conn.reset(NULL);
            conn2.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            conn2.reset(get_connection(host, user, pass));
            test_statement_2(conn, conn2, database);
            conn.reset(NULL);
            conn2.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            conn2.reset(get_connection(host, user, pass));
            test_statement_3(conn, conn2, database);
            conn.reset(NULL);
            conn2.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            conn2.reset(get_connection(host, user, pass));
            test_statement_4(conn, conn2, database);
            conn.reset(NULL);
            conn2.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            conn2.reset(get_connection(host, user, pass));
            test_statement_5(conn, conn2, database);
            conn.reset(NULL);
            conn2.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            conn2.reset(get_connection(host, user, pass));
            test_statement_6(conn, conn2, database);
            conn.reset(NULL);
            conn2.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            conn2.reset(get_connection(host, user, pass));
            test_statement_7(conn, conn2, database);
            conn.reset(NULL);
            conn2.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            conn2.reset(get_connection(host, user, pass));
            test_statement_8(conn, conn2, database);
            conn.reset(NULL);
            conn2.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            conn2.reset(get_connection(host, user, pass));
            test_statement_9(conn, conn2, database);
            conn.reset(NULL);
            conn2.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            test_result_set_0(conn);
            conn.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            test_result_set_1(conn);
            conn.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            test_result_set_2(conn, database);
            conn.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            test_result_set_3(conn, database);
            conn.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            test_result_set_4(conn, database);
            conn.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            test_result_set_5(conn);
            conn.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            test_result_set_6(conn, database);
            conn.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            test_result_set_7(conn, database);
            conn.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            test_result_set_8(conn, database);
            conn.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            test_result_set_9(conn);
            conn.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            test_result_set_10(conn, database);
            conn.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            test_result_set_11(conn, database);
            conn.reset(NULL);
#if 0
            test_general_0(conn); delete conn;
            test_general_1(conn); delete conn;
#endif
            conn.reset(get_connection(host, user, pass));
            test_prep_statement_0(conn);
            conn.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            conn2.reset(get_connection(host, user, pass));
            test_prep_statement_1(conn, conn2, database);
            conn.reset(NULL);
            conn2.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            test_prep_statement_2(conn, database);
            conn.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            conn2.reset(get_connection(host, user, pass));
            test_prep_statement_3(conn, conn2, database);
            conn.reset(NULL);
            conn2.reset(NULL);

            conn.reset(get_connection(host, user, pass));
            test_prep_statement_blob(conn, database);
            conn.reset(NULL);

//          test_get_table_privileges_1(host, user, pass);

            printf("\n#---------------  %d -----------------\n", i + 1);
            if ((total_errors - last_error_total) == 0) {
                  printf("ok %d - %s_%s_loop%d\n", i + 1, TEST_COMMON_TAP_NAME, connect_method.c_str(), i + 1);
            } else {
                  printf("not ok %d - %s_%s_loop%d\n", i + 1, TEST_COMMON_TAP_NAME, connect_method.c_str(), i + 1);
            }


      }
      printf("\n# Loops=%2d Tests= %4d Failures= %3d \n", loops, total_tests, total_errors);

      return 0;
}
/* }}} */


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: noet sw=4 ts=4 fdm=marker
 * vim<600: noet sw=4 ts=4
 */

Generated by  Doxygen 1.6.0   Back to index