/* * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. * 2020 MariaDB Corporation AB * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2.0, as * published by the Free Software Foundation. * * This program is also distributed with certain software (including * but not limited to OpenSSL) that is licensed under separate terms, * as designated in a particular file or component or in included license * documentation. The authors of MySQL hereby grant you an * additional permission to link the program and your derivative works * with the separately licensed software that they have included with * MySQL. * * Without limiting anything contained in the foregoing, this file, * which is part of MySQL Connector/C++, is also subject to the * Universal FOSS Exception, version 1.0, a copy of which can be found at * http://oss.oracle.com/licenses/universal-foss-exception. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License, version 2.0, for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #ifndef _WIN32 #include #endif #include "tests_config.h" /* __FUNCTION__/__func__ is not portable. We do not promise that our example definition covers each and every compiler. If not, it is up to you to find a different definition for your setup. */ #if __STDC_VERSION__ < 199901L # if __GNUC__ >= 2 # define CPPCONN_FUNC __FUNCTION__ # else # define CPPCONN_FUNC "(function n/a)" # endif #elif defined(_MSC_VER) # if _MSC_VER < 1300 # define CPPCONN_FUNC "(function n/a)" # else # define CPPCONN_FUNC __FUNCTION__ # endif #elif (defined __func__) # define CPPCONN_FUNC __func__ #else # define CPPCONN_FUNC "(function n/a)" #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 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" //{ //#include "mysql.h" //} //#undef bool #if defined(_WIN32) || defined(_WIN64) #pragma warning(disable:4251) #endif #include #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::unique_ptr & conn, std::string database) { std::unique_ptr 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::unique_ptr & conn, std::string database) { std::unique_ptr 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::unique_ptr & conn, std::string database) { std::unique_ptr 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::unique_ptr & conn, std::string database) { std::unique_ptr stmt1(conn->createStatement()); ensure("stmt1 is NULL", stmt1.get() != NULL); stmt1->execute("USE " + database); std::unique_ptr stmt2(conn->prepareStatement("DROP TABLE IF EXISTS test_function")); ensure("stmt2 is NULL", stmt2.get() != NULL); stmt2->executeUpdate(); std::unique_ptr 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::unique_ptr 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::unique_ptr & conn, std::string database) { std::unique_ptr stmt1(conn->createStatement()); ensure("stmt is NULL", stmt1.get() != NULL); stmt1->execute("USE " + database); std::unique_ptr stmt2(conn->prepareStatement("DROP TABLE IF EXISTS test_function_tx")); ensure("stmt2 is NULL", stmt2.get() != NULL); stmt2->executeUpdate(); std::unique_ptr 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::unique_ptr 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::unique_ptr & conn, std::string database) { std::unique_ptr stmt1(conn->createStatement()); ensure("stmt1 is NULL", stmt1.get() != NULL); stmt1->execute("USE " + database); std::unique_ptr stmt2(conn->prepareStatement("DROP TABLE IF EXISTS test_function_int")); ensure("stmt2 is NULL", stmt2.get() != NULL); stmt2->executeUpdate(); std::unique_ptr 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::unique_ptr & 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.getSQLStateCStr()); printf("# "); ++total_errors; } LEAVE_FUNCTION(); } /* }}} */ /* {{{ */ static void test_connection_0(std::unique_ptr & conn) { ENTER_FUNCTION(); try { char buff[64]; std::unique_ptr stmt1(conn->createStatement()); ensure("stmt1 is NULL", stmt1.get() != NULL); std::unique_ptr 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 */ } catch (std::system_error& se) { std::cout << "System error occured: " << se.what() << '(' << se.code() << ')' << std::endl; } try { std::unique_ptr rset2(stmt1->executeQuery("SELECT CONNECTION_ID()")); ensure("no exception", false); } catch (sql::SQLException &) { ensure("Exception correctly thrown", true); } ensure("connection is open", conn->isClosed() == true); // W/out auto-reconnect, it's supposed to be closed at this point? } 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.getSQLStateCStr()); printf("# "); ++total_errors; } LEAVE_FUNCTION(); } /* }}} */ /* {{{ */ static void test_connection_1(std::unique_ptr & conn, std::string database) { ENTER_FUNCTION(); try { std::unique_ptr 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::unique_ptr 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::unique_ptr savepoint(conn->setSavepoint(savepointName)); populate_TX_insert_data(stmt1.get()); std::unique_ptr 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::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } LEAVE_FUNCTION(); } /* }}} */ /* {{{ */ static void test_connection_2(std::unique_ptr & conn, std::string database) { ENTER_FUNCTION(); try { std::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } } LEAVE_FUNCTION(); } /* }}} */ /* {{{ */ static void test_connection_3(std::unique_ptr & 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.getSQLStateCStr()); printf("# "); ++total_errors; } LEAVE_FUNCTION(); } /* }}} */ /* {{{ */ static void test_statement_0(std::unique_ptr & conn) { ENTER_FUNCTION(); try { std::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } LEAVE_FUNCTION(); } /* }}} */ /* {{{ Test simple update statement against statement object */ static void test_statement_1(std::unique_ptr & conn, std::unique_ptr & conn2, std::string database) { ENTER_FUNCTION(); try { std::unique_ptr 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::unique_ptr 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.getSQLStateCStr()); 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::unique_ptr & conn, std::unique_ptr & conn2, std::string database) { ENTER_FUNCTION(); try { std::unique_ptr 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::unique_ptr 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.getSQLStateCStr()); 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::unique_ptr & conn, std::unique_ptr & conn2, std::string database) { ENTER_FUNCTION(); try { std::unique_ptr 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::unique_ptr 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.getSQLStateCStr()); ++total_errors; printf("# "); } /* Clean */ std::unique_ptr 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.getSQLStateCStr()); 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::unique_ptr & conn, std::unique_ptr & conn2, std::string database) { ENTER_FUNCTION(); try { std::unique_ptr 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::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } /* Clean */ std::unique_ptr 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.getSQLStateCStr()); 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::unique_ptr & conn, std::unique_ptr & conn2, std::string database) { ENTER_FUNCTION(); try { std::unique_ptr 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::unique_ptr 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::unique_ptr 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.getSQLStateCStr()); 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::unique_ptr & conn, std::unique_ptr & conn2, std::string database) { ENTER_FUNCTION(); try { std::unique_ptr 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.getSQLStateCStr()); ++total_errors; } /* Clean */ std::unique_ptr 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.getSQLStateCStr()); 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::unique_ptr & conn, std::unique_ptr & conn2, std::string database) { ENTER_FUNCTION(); try { std::unique_ptr 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::unique_ptr 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.getSQLStateCStr()); 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::unique_ptr & conn, std::unique_ptr & conn2) { ENTER_FUNCTION(); try { std::unique_ptr 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.getSQLStateCStr()); 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::unique_ptr & conn) { ENTER_FUNCTION(); try { std::unique_ptr 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.getSQLStateCStr()); 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::unique_ptr & conn) { ENTER_FUNCTION(); try { std::unique_ptr 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.getSQLStateCStr()); 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::unique_ptr & conn) { ENTER_FUNCTION(); try { std::unique_ptr 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.getSQLStateCStr()); 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::unique_ptr & conn, std::unique_ptr & conn2, std::string database) { ENTER_FUNCTION(); try { std::unique_ptr 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::unique_ptr rset(stmt->getResultSet()); ensure("rset is NULL", rset.get() != NULL); /* Clean */ std::unique_ptr 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.getSQLStateCStr()); 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::unique_ptr & conn, std::unique_ptr & conn2, std::string database) { ENTER_FUNCTION(); try { std::unique_ptr 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::unique_ptr rset(stmt->getResultSet()); ensure("rset is not NULL", rset.get() == NULL); /* Clean */ std::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } catch (...) { printf("\n# ERR: Caught unknown exception at %s::%d\n", CPPCONN_FUNC, __LINE__); printf("# "); ++total_errors; } LEAVE_FUNCTION(); } /* }}} */ /* {{{ Test metadata usage after result set has been closed */ static void test_statement_10(std::unique_ptr & conn, std::unique_ptr & conn2, std::string database) { ENTER_FUNCTION(); try { std::unique_ptr stmt(conn->createStatement()); ensure("stmt is NULL", stmt.get() != NULL); ensure("Data not populated", true == populate_test_table(conn, database)); std::unique_ptr res(stmt->executeQuery("SELECT * FROM test_function")); ensure("ResultSet is empty", res->rowsCount() > 0); sql::ResultSetMetaData * meta = res->getMetaData(); ensure("Error while reading a row ", res->next()); ensure_equal_str("Table name differs", meta->getTableName(1), std::string("test_function")); res->close(); try { ensure_equal_str("Table name differs", meta->getTableName(1), std::string("test_function")); ensure("Exception not correctly thrown", true/*false*/); //TODO: check if metadata should not return anything, if rs is closed } catch (sql::SQLException &/*e*/) { // exception correctly thrown } /* Clean */ std::unique_ptr 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.getSQLStateCStr()); 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::unique_ptr & conn) { ENTER_FUNCTION(); try { std::unique_ptr stmt(conn->createStatement()); ensure("AutoCommit", conn.get() == stmt->getConnection()); std::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } LEAVE_FUNCTION(); } /* }}} */ /* {{{ */ static void test_result_set_1(std::unique_ptr & conn) { ENTER_FUNCTION(); try { std::unique_ptr stmt1(conn->createStatement()); ensure("stmt1 is NULL", stmt1.get() != NULL); stmt1->setResultSetType(sql::ResultSet::TYPE_SCROLL_INSENSITIVE); std::unique_ptr rset1(stmt1->executeQuery("SELECT 1")); ensure("res1 is NULL", rset1.get() != NULL); std::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } LEAVE_FUNCTION(); } /* }}} */ /* {{{ */ static void test_result_set_2(std::unique_ptr & conn, std::string database) { ENTER_FUNCTION(); try { std::unique_ptr stmt1(conn->createStatement()); ensure("stmt1 is NULL", stmt1.get() != NULL); ensure("Data not populated", true == populate_test_table(conn, database)); std::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } LEAVE_FUNCTION(); } /* }}} */ /* {{{ */ static void test_result_set_3(std::unique_ptr & conn, std::string database) { ENTER_FUNCTION(); try { std::unique_ptr 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::unique_ptr 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::unique_ptr 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::unique_ptr 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::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } LEAVE_FUNCTION(); } /* }}} */ /* {{{ Test commit and rollback (autocommit on) */ static void test_result_set_4(std::unique_ptr & conn, std::string database) { ENTER_FUNCTION(); try { std::unique_ptr 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::unique_ptr 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::unique_ptr 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::unique_ptr 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::unique_ptr 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::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } LEAVE_FUNCTION(); } /* }}} */ /* {{{ Test multistatement off - send two queries in one call */ static void test_result_set_5(std::unique_ptr & conn) { ENTER_FUNCTION(); try { std::unique_ptr stmt1(conn->createStatement()); ensure("stmt1 is NULL", stmt1.get() != NULL); try { std::unique_ptr 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.getSQLStateCStr()); 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.getSQLStateCStr()); printf("# "); ++total_errors; } } /* {{{ Test out of bound extraction of data */ static void test_result_set_6(std::unique_ptr & conn, std::string database) { ENTER_FUNCTION(); try { std::unique_ptr 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::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } LEAVE_FUNCTION(); } /* }}} */ /* {{{ Test out of bound extraction of data - PS version */ static void test_result_set_7(std::unique_ptr & conn, std::string database) { ENTER_FUNCTION(); try { ensure("Data not populated", true == populate_TX_test_table(conn, database)); std::unique_ptr 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::unique_ptr rset1(stmt1->executeQuery()); ensure("res1 is NULL", rset1.get() != NULL); test_result_set_check_out_of_bound(rset1.get()); std::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } LEAVE_FUNCTION(); } /* }}} */ /* {{{ Test commit and rollback (autocommit on) - PS version */ static void test_result_set_8(std::unique_ptr & conn, std::string database) { ENTER_FUNCTION(); try { int count_full_before; std::unique_ptr 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::unique_ptr stmt1(conn->prepareStatement("SELECT COUNT(*) FROM test_function_tx")); std::unique_ptr 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::unique_ptr 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::unique_ptr stmt3(conn->prepareStatement("SELECT COUNT(*) FROM test_function_tx")); std::unique_ptr 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::unique_ptr stmt4(conn->prepareStatement("SELECT COUNT(*) FROM test_function_tx")); std::unique_ptr 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::unique_ptr 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::unique_ptr stmt6(conn->prepareStatement("SELECT COUNT(*) FROM test_function_tx")); std::unique_ptr 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::unique_ptr 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::unique_ptr stmt8(conn->prepareStatement("SELECT COUNT(*) FROM test_function_tx")); std::unique_ptr 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::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } LEAVE_FUNCTION(); } /* }}} */ /* {{{ Test multistatement off - send two queries in one call - PS version */ static void test_result_set_9(std::unique_ptr & conn) { ENTER_FUNCTION(); try { try { std::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } LEAVE_FUNCTION(); } /* }}} */ /* {{{ Test multiresults - SP with normal and prepared statement */ static void test_result_set_10(std::unique_ptr & conn, std::string database) { ENTER_FUNCTION(); try { std::unique_ptr 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::unique_ptr stmt1(conn->createStatement()); stmt1->execute("DROP PROCEDURE IF EXISTS CPP1"); stmt1->execute("CREATE PROCEDURE CPP1() SELECT 42"); std::unique_ptr stmt2(conn->prepareStatement("CALL CPP1()")); stmt2->execute(); std::unique_ptr 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::unique_ptr rset2(stmt2->getResultSet()); ensure("res2 is not NULL", rset2.get() == NULL); /* drop procedure is not supported for preparing */ stmt1->execute("DROP PROCEDURE CPP1"); } { std::unique_ptr stmt1(conn->createStatement()); stmt1->execute("DROP PROCEDURE IF EXISTS CPP1"); stmt1->execute("CREATE PROCEDURE CPP1() SELECT 42"); stmt1->execute("CALL CPP1()"); std::unique_ptr 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::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } LEAVE_FUNCTION(); } /* }}} */ /* {{{ getMetadata() */ static void test_result_set_11(std::unique_ptr & conn, std::string database) { ENTER_FUNCTION(); try { std::unique_ptr 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::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } LEAVE_FUNCTION(); } /* }}} */ #if 0 /* {{{ General test 0 */ static void test_general_0(std::unique_ptr & conn) { ENTER_FUNCTION(); try { sql::DatabaseMetaData * meta = conn->getMetaData(); std::unique_ptr rset(meta->getSchemata()); while (rset->next()) { std::unique_ptr 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.getSQLStateCStr()); ++total_errors; } LEAVE_FUNCTION(); } /* }}} */ /* {{{ General test 1 */ static void test_general_1(std::unique_ptr & conn) { ENTER_FUNCTION(); try { std::unique_ptr 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::unique_ptr prepStmt(conn->prepareStatement("INSERT INTO test.product (idproduct, name) VALUES(?, ?)")); prepStmt->setInt(1, 1); prepStmt->setString(2, "The answer is 42"); prepStmt->executeUpdate(); std::unique_ptr 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::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } LEAVE_FUNCTION(); } /* }}} */ #endif /* {{{ */ static void test_prep_statement_0(std::unique_ptr & conn) { ENTER_FUNCTION(); try { try { std::unique_ptr stmt(conn->prepareStatement("SELECT 1")); stmt->execute(); std::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } try { std::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } /* Bind but don't execute. There should be no leak */ try { std::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } /* Bind two different types for the same column. There should be no leak */ try { std::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } /* Execute without fetching the result set. The connector should clean the wire */ try { std::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } #if 0 /* Bind one parameter less than needed - NULL should be sent to the server . Check also multibyte fetching. */ try { std::unique_ptr stmt(conn->prepareStatement("SELECT ? as \"Здравей_МySQL\" , ?, ?")); stmt->setInt(3, 42); stmt->setString(1, "Здравей МySQL! Как си?"); stmt->execute(); std::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } #endif /* try double ::execute() */ try { std::unique_ptr stmt(conn->prepareStatement("SELECT ?")); stmt->setString(1, "Hello World"); for (int i = 0; i < 100; ++i) { std::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } /* Test clearParameters() */ { try { std::unique_ptr stmt(conn->prepareStatement("SELECT ?")); stmt->setInt(1, 13); std::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } try { std::unique_ptr stmt(conn->prepareStatement("SELECT ?")); stmt->setInt(1, 13); stmt->clearParameters(); std::unique_ptr rs(stmt->executeQuery()); ensure("Exception not thrown", false); } catch (sql::SQLException &) {} } /* try clearParameters() call */ { std::unique_ptr stmt(conn->prepareStatement("SELECT ?, ?, ?, NULL")); try { stmt->setInt(3, 42); stmt->setString(1, "Hello MYSQL"); stmt->setDouble(2, 1.25); std::unique_ptr rset(stmt->executeQuery()); ensure("No result set", rset.get() != NULL); ensure("Result set is empty", rset->next() != false); ensure("Non empty string returned for NULL", rset->getString(4).length() == 0); ensure("wasNull() not properly set for NULL", rset->wasNull()); ensure("isNull() is wrong", rset->isNull(4)); ensure("Incorrect value for col 4", !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()); long double col2= rset->getDouble(2); printf("# Column 2 value(long double) is: %Lf\n", col2); ensure("Incorrect value for col 3", col2 == 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.getSQLStateCStr()); printf("# "); ++total_errors; } } try { std::unique_ptr stmt(conn->prepareStatement("SELECT ?")); stmt->setInt(1, 1); stmt->execute(); std::unique_ptr 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.getSQLStateCStr()); printf("# "); ++total_errors; } LEAVE_FUNCTION(); } /* }}} */ /* {{{ Test simple update statement against statement object */ static void test_prep_statement_1(std::unique_ptr & conn, std::unique_ptr & conn2, const std::string & database) { ENTER_FUNCTION(); try { std::unique_ptr 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::unique_ptr 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::unique_ptr rset(stmt1->getResultSet()); /* Clean */ std::unique_ptr stmt2(conn2->createStatement()); ensure("stmt2 is NULL", stmt2.get() != NULL); stmt2->execute("USE " + database); std::unique_ptr 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.getSQLStateCStr()); 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::unique_ptr & conn, std::string database) { ENTER_FUNCTION(); try { populate_test_table_PS_integers(conn, database); try { std::unique_ptr stmt(conn->prepareStatement("SELECT '1")); ensure("ERR: Exception not thrown", false); } catch (sql::SQLException &) {} /* USE still cannot be prepared */ try { std::unique_ptr 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.getSQLStateCStr()); 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::unique_ptr & conn, std::unique_ptr & 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::unique_ptr 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(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(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::unique_ptr 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::unique_ptr 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::unique_ptr 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::unique_ptr 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::unique_ptr stmt4(conn2->createStatement()); ensure("stmt4 is NULL", stmt4.get() != NULL); stmt4->execute("USE " + database); std::unique_ptr 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.getSQLStateCStr()); 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::unique_ptr & conn, std::string database) { ENTER_FUNCTION(); try { populate_blob_table(conn, database); /* USE still cannot be prepared */ std::unique_ptr use_stmt(conn->createStatement()); use_stmt->execute("USE " + database); std::unique_ptr 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::unique_ptr stmt2(conn->createStatement()); stmt2->execute("SELECT * FROM test_blob"); std::unique_ptr 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::unique_ptr 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.getSQLStateCStr()); 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::unique_ptr root_conn(get_connection(host, user, pass)); std::unique_ptr 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::unique_ptr user_conn(get_connection(host, plain_user, "pass")); std::unique_ptr user_conn_meta(user_conn->getMetaData()); std::unique_ptr 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.getSQLStateCStr()); 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.getSQLStateCStr()); printf("# "); ++total_errors; } catch (...) { printf("\n# ERR: Caught unknown exception at %s::%d\n", CPPCONN_FUNC, __LINE__); printf("# "); ++total_errors; } LEAVE_FUNCTION(); } */ /* {{{ Invoke as many "not implemented" methods as possible for better code coverage (and to make sure we keep CHANGES current) */ static void test_not_implemented_connection(std::unique_ptr & conn) { ENTER_FUNCTION(); std::string bar("bar"); int int_array[] = {1, 2, 3}; sql::SQLString string_array[] = {"a", "b", "c"}; try { try { ++total_tests; conn->isReadOnly(); ensure("Exception not thrown", true); } catch (sql::MethodNotImplementedException &) {} // setHoldability(int /* holdability */) try { ++total_tests; conn->setHoldability(1); ensure("Exception not thrown", true); } catch (sql::MethodNotImplementedException &) {} // setReadOnly(bool /* readOnly */) try { ++total_tests; conn->setReadOnly(true); ensure("Exception not thrown", true); } catch (sql::MethodNotImplementedException &) {} // setSavepoint() try { ++total_tests; conn->setSavepoint(); ensure("Exception not thrown", true); } catch (sql::MethodNotImplementedException &) {} } 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.getSQLStateCStr()); 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_not_implemented_statement(std::unique_ptr & conn, const std::string & database) { ENTER_FUNCTION(); std::string bar("foo"); std::unique_ptr stmt(conn->createStatement()); stmt->execute("USE " + database); try { // cancel() try { ++total_tests; stmt->cancel(); ensure("Exception not thrown", true); } catch (sql::MethodNotImplementedException &) {} // getFetchSize() try { ++total_tests; stmt->getFetchSize(); ensure("Exception not thrown", true); } catch (sql::MethodNotImplementedException &) {} // setFetchSize(unsigned int) try { ++total_tests; stmt->setFetchSize(1); ensure("Exception not thrown", true); } catch (sql::MethodNotImplementedException &) {} // getMaxFieldSize() try { ++total_tests; stmt->getMaxFieldSize(); ensure("Exception not thrown", true); } catch (sql::MethodNotImplementedException &) {} // getMaxRows() try { ++total_tests; stmt->getMaxRows(); ensure("Exception not thrown", true); } catch (sql::MethodNotImplementedException &) {} // setCursorName(const std::string &) try { ++total_tests; stmt->setCursorName(bar); ensure("ERR: Exception not thrown", false); } catch (sql::SQLFeatureNotSupportedException&) {} // setEscapeProcessing(bool) try { ++total_tests; stmt->setEscapeProcessing(true); ensure("Exception not thrown", true); } catch (sql::MethodNotImplementedException &) {} // setMaxFieldSize(unsigned int) try { ++total_tests; stmt->setMaxFieldSize(1); ensure("Exception not thrown", true); } catch (sql::MethodNotImplementedException &) {} // setMaxRows(unsigned int) try { ++total_tests; stmt->setMaxRows(1); ensure("Exception not thrown", true); } catch (sql::MethodNotImplementedException &) {} } 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.getSQLStateCStr()); 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_not_implemented_conn_meta(std::unique_ptr & conn) { ENTER_FUNCTION(); std::string bar("foo"); sql::DatabaseMetaData * conn_meta = conn->getMetaData(); try { // getURL() try { ++total_tests; conn_meta->getURL(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // locatorsUpdateCopy() try { ++total_tests; conn_meta->locatorsUpdateCopy(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // supportsIntegrityEnhancementFacility() try { ++total_tests; conn_meta->supportsIntegrityEnhancementFacility(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // supportsResultSetConcurrency(int /* type */, int /* concurrency */) try { ++total_tests; conn_meta->supportsResultSetConcurrency(1, 2); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} } 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.getSQLStateCStr()); 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_not_implemented_ps(std::unique_ptr & conn, const std::string & database) { ENTER_FUNCTION(); std::string bar("jedervernunft"); std::unique_ptr stmt(conn->createStatement()); stmt->execute("USE " + database); std::unique_ptr ps1(conn->prepareStatement("SELECT 1")); std::unique_ptr ps2(conn->prepareStatement("SELECT ?")); ps2->setInt(1, 2); try { // execute(const std::string&) try { ++total_tests; ps1->execute(bar); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // executeQuery(const std::string&) try { ++total_tests; ps1->executeQuery(bar); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // executeUpdate(const std::string&) try { ++total_tests; ps1->executeUpdate(bar); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // cancel() try { ++total_tests; ps2->cancel(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getFetchSize() try { ++total_tests; ps2->getFetchSize(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // setFetchSize(unsigned int) try { ++total_tests; ps2->setFetchSize(1); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // setQueryTimeout(unsigned int) try { ++total_tests; ps2->setQueryTimeout(1); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getMaxFieldSize() try { ++total_tests; ps2->getMaxFieldSize(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getMaxRows() try { ++total_tests; ps2->getMaxRows(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getQueryTimeout() try { ++total_tests; ps2->getQueryTimeout(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getUpdateCount() try { ++total_tests; ps2->getUpdateCount(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // setCursorName(const std::string &) try { ++total_tests; ps2->setCursorName(bar); ensure("ERR: Exception not thrown", false); } catch (sql::SQLFeatureNotSupportedException &) {} // setEscapeProcessing(bool) try { ++total_tests; ps2->setEscapeProcessing(true); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // setMaxFieldSize(unsigned int) try { ++total_tests; ps2->setMaxFieldSize(1); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // setMaxRows(unsigned int) try { ++total_tests; ps2->setMaxRows(1); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} } 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.getSQLStateCStr()); 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_not_implemented_resultset(std::unique_ptr & conn) { ENTER_FUNCTION(); std::string bar("foo"); std::unique_ptr stmt(conn->createStatement()); std::unique_ptr res(stmt->executeQuery("SELECT 1 AS 'a'")); try { // cancelRowUpdates() try { ++total_tests; res->cancelRowUpdates(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getConcurrency() try { ++total_tests; res->getConcurrency(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getCursorName() try { ++total_tests; res->getCursorName(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getFetchDirection() try { ++total_tests; res->getFetchDirection(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getFetchSize() try { ++total_tests; res->getFetchSize(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getHoldability() try { ++total_tests; res->getHoldability(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getRowId(unsigned int) try { ++total_tests; res->getRowId(1); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getRowId(const std::string &) try { ++total_tests; res->getRowId(bar); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // insertRow() try { ++total_tests; res->insertRow(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // moveToCurrentRow() try { ++total_tests; res->moveToCurrentRow(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // moveToInsertRow() try { ++total_tests; res->moveToInsertRow(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // refreshRow() try { ++total_tests; res->refreshRow(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // rowDeleted() try { ++total_tests; res->rowDeleted(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // rowInserted() try { ++total_tests; res->rowInserted(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // rowUpdated() try { ++total_tests; res->rowUpdated(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // setFetchSize(size_t /* rows */) try { ++total_tests; res->setFetchSize(1); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} } 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.getSQLStateCStr()); 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_not_implemented_ps_resultset(std::unique_ptr & conn) { ENTER_FUNCTION(); std::string bar("foo"); std::unique_ptr stmt(conn->prepareStatement("SELECT 1 AS 'a'")); std::unique_ptr res(stmt->executeQuery()); try { // cancelRowUpdates() try { ++total_tests; res->cancelRowUpdates(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getConcurrency() try { ++total_tests; res->getConcurrency(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getCursorName() try { ++total_tests; res->getCursorName(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getFetchDirection() try { ++total_tests; res->getFetchDirection(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getFetchSize() try { ++total_tests; res->getFetchSize(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getHoldability() try { ++total_tests; res->getHoldability(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getRowId(unsigned int) try { ++total_tests; res->getRowId(1); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getRowId(const std::string &) try { ++total_tests; res->getRowId(bar); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // insertRow() try { ++total_tests; res->insertRow(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // moveToCurrentRow() try { ++total_tests; res->moveToCurrentRow(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // moveToInsertRow() try { ++total_tests; res->moveToInsertRow(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // refreshRow() try { ++total_tests; res->refreshRow(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // rowDeleted() try { ++total_tests; res->rowDeleted(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // rowInserted() try { ++total_tests; res->rowInserted(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // rowUpdated() try { ++total_tests; res->rowUpdated(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // setFetchSize(size_t /* rows */) try { ++total_tests; res->setFetchSize(1); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} } 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.getSQLStateCStr()); 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_not_implemented_cs_resultset(std::unique_ptr & conn) { ENTER_FUNCTION(); std::string bar("foo"); sql::DatabaseMetaData * conn_meta = conn->getMetaData(); try { std::unique_ptr res(conn_meta->getSchemaObjectTypes()); try { // cancelRowUpdates() try { ++total_tests; res->cancelRowUpdates(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getConcurrency() try { ++total_tests; res->getConcurrency(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getCursorName() try { ++total_tests; res->getCursorName(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getFetchDirection() try { ++total_tests; res->getFetchDirection(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getFetchSize() try { ++total_tests; res->getFetchSize(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getHoldability() try { ++total_tests; res->getHoldability(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getRowId(unsigned int) try { ++total_tests; res->getRowId(1); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getRowId(const std::string &) try { ++total_tests; res->getRowId(bar); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // insertRow() try { ++total_tests; res->insertRow(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // moveToCurrentRow() try { ++total_tests; res->moveToCurrentRow(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // moveToInsertRow() try { ++total_tests; res->moveToInsertRow(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // refreshRow() try { ++total_tests; res->refreshRow(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // rowDeleted() try { ++total_tests; res->rowDeleted(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // rowInserted() try { ++total_tests; res->rowInserted(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // rowUpdated() try { ++total_tests; res->rowUpdated(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // setFetchSize(size_t /* rows */) try { ++total_tests; res->setFetchSize(1); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} } 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.getSQLStateCStr()); printf("# "); ++total_errors; } catch (...) { printf("\n# ERR: Caught unknown exception at %s::%d\n", CPPCONN_FUNC, __LINE__); printf("# "); ++total_errors; } } catch (sql::SQLFeatureNotImplementedException& e) { LEAVE_FUNCTION(); return; } LEAVE_FUNCTION(); } /* }}} */ static void test_not_implemented_rs_meta(std::unique_ptr & conn) { ENTER_FUNCTION(); std::string bar("foo"); std::unique_ptr stmt(conn->createStatement()); std::unique_ptr res(stmt->executeQuery("SELECT 1 AS 'a'")); try { try { ++total_tests; res->cancelRowUpdates(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} } 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.getSQLStateCStr()); 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_not_implemented_cs_rs_meta(std::unique_ptr & conn) { ENTER_FUNCTION(); std::string bar("foo"); sql::DatabaseMetaData * conn_meta = conn->getMetaData(); std::unique_ptr res(conn_meta->getTableTypes()); sql::ResultSetMetaData * meta = res->getMetaData(); try { // getColumnDisplaySize(unsigned int columnIndex) try { ++total_tests; meta->getColumnDisplaySize(1); res->cancelRowUpdates(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getPrecision(unsigned int columnIndex) try { ++total_tests; meta->getPrecision(1); res->cancelRowUpdates(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} // getScale(unsigned int columnIndex) try { ++total_tests; meta->getScale(1); res->cancelRowUpdates(); ensure("ERR: Exception not thrown", false); } catch (sql::MethodNotImplementedException &) {} } 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.getSQLStateCStr()); 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); std::unique_ptr conn, conn2; int last_error_total = 0; int i; const std::string user(argc >=3 ? argv[2] : TEST_DEFAULT_LOGIN); const std::string pass(argc >=4 ? argv[3] : TEST_DEFAULT_PASSWD); const std::string database(argc >=5 ? argv[4] : TEST_DEFAULT_DB); 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] : TEST_DEFAULT_HOST); 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.getSQLStateCStr()); 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::unique_ptr stmt(conn->createStatement()); stmt->execute("SHOW ENGINES"); { std::unique_ptr rset(stmt->getResultSet()); int found = 0; while (rset->next()) { std::string engine(rset->getString("Engine")), support(rset->getString("Support")); std::cout << "# " << engine << "::" << support << std::endl; if (engine == "InnoDB" && (support == "YES" || 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.getSQLStateCStr()); 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)); conn2.reset(get_connection(host, user, pass)); test_statement_10(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); conn.reset(get_connection(host, user, pass)); test_not_implemented_connection(conn); conn.reset(NULL); conn.reset(get_connection(host, user, pass)); test_not_implemented_statement(conn, database); conn.reset(NULL); /*conn.reset(get_connection(host, user, pass)); test_not_implemented_conn_meta(conn); conn.reset(NULL); conn.reset(get_connection(host, user, pass)); test_not_implemented_ps(conn, database); conn.reset(NULL); conn.reset(get_connection(host, user, pass)); test_not_implemented_resultset(conn); conn.reset(NULL); conn.reset(get_connection(host, user, pass)); test_not_implemented_ps_resultset(conn); conn.reset(NULL); conn.reset(get_connection(host, user, pass)); test_not_implemented_cs_resultset(conn); conn.reset(NULL); conn.reset(get_connection(host, user, pass)); test_not_implemented_rs_meta(conn); conn.reset(NULL); conn.reset(get_connection(host, user, pass)); test_not_implemented_cs_rs_meta(conn); conn.reset(NULL);*/ 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 */