Files
mariadb-connector-cpp/test/unit/classes/resultset.cpp
Lawrin Novitsky 2704acd7f4 CONCPP-46 Addition - fix of the build with gcc on macos
Some travis congig fixes for macos

Errors and warnings.
Fix of one testcase failing aginst 10.2
2020-11-15 23:57:16 +01:00

1308 lines
34 KiB
C++

/*
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
*
* 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 "Warning.h"
#include <sstream>
#include <cstdlib>
#include <stdlib.h>
#include "ResultSet.h"
#include "Types.h"
#include "Connection.h"
#include "resultsettest.h"
namespace testsuite
{
namespace classes
{
static const sql::SQLString id("id");
void resultset::getInt()
{
bool on_off=true;
//con->setClientOption("clientTrace", &on_off);
// Message for --verbose output
logMsg("resultset::getInt - MySQL_ResultSet::getInt*");
try
{
stmt.reset(con->createStatement());
stmt->execute("DROP TABLE IF EXISTS test");
stmt->execute("CREATE TABLE test(i integer, i_uns integer unsigned, b bigint, b_uns bigint unsigned)");
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);
pstmt.reset(con->prepareStatement("INSERT INTO test(i, i_uns, b, b_uns) VALUES(?,?,?,?)"));
ASSERT(pstmt.get() != NULL);
pstmt->clearParameters();
pstmt->setInt(1, static_cast<int> (r1_c1));
pstmt->setInt64(2, r1_c2);
pstmt->setInt64(3, r1_c3);
pstmt->setUInt64(4, r1_c4);
ASSERT_EQUALS(false, pstmt->execute());
pstmt->clearParameters();
pstmt->setInt(1, static_cast<int> (r2_c1));
pstmt->setInt64(2, r2_c2);
pstmt->setInt64(3, r2_c3);
pstmt->setUInt64(4, r2_c4);
ASSERT_EQUALS(false, pstmt->execute());
pstmt.reset(con->prepareStatement("SELECT i, i_uns, b, b_uns FROM test"));
ASSERT(pstmt.get() != NULL);
ASSERT(pstmt->execute());
res.reset(pstmt->getResultSet());
checkResultSetScrolling(res);
ASSERT(res->next());
ASSERT_EQUALS(r1_c1, (int64_t) res->getInt("i"));
ASSERT_EQUALS(r1_c1, (int64_t) res->getInt(1));
ASSERT_EQUALS(r1_c2, res->getInt64("i_uns"));
ASSERT_EQUALS(r1_c2, res->getInt64(2));
ASSERT_EQUALS(r1_c3, res->getInt64("b"));
ASSERT_EQUALS(r1_c3, res->getInt64(3));
ASSERT_EQUALS(r1_c4, res->getUInt64("b_uns"));
ASSERT_EQUALS(r1_c4, res->getUInt64(4));
ASSERT(res->next());
ASSERT_EQUALS(r2_c1, (int64_t) res->getInt("i"));
ASSERT_EQUALS(r2_c1, (int64_t) res->getInt(1));
ASSERT_EQUALS(r2_c2, res->getInt64("i_uns"));
ASSERT_EQUALS(r2_c2, res->getInt64(2));
ASSERT_EQUALS(r2_c3, res->getInt64("b"));
ASSERT_EQUALS(r2_c3, res->getInt64(3));
ASSERT_EQUALS(r2_c4, res->getUInt64("b_uns"));
ASSERT_EQUALS(r2_c4, res->getUInt64(4));
ASSERT_EQUALS(res->next(), false);
res.reset(stmt->executeQuery("SELECT i, i_uns, b, b_uns FROM test"));
checkResultSetScrolling(res);
ASSERT(res->next());
ASSERT_EQUALS(r1_c1, (int64_t) res->getInt("i"));
ASSERT_EQUALS(r1_c1, (int64_t) res->getInt(1));
ASSERT_EQUALS(r1_c2, res->getInt64("i_uns"));
ASSERT_EQUALS(r1_c2, res->getInt64(2));
ASSERT_EQUALS(r1_c3, res->getInt64("b"));
ASSERT_EQUALS(r1_c3, res->getInt64(3));
ASSERT_EQUALS(r1_c4, res->getUInt64("b_uns"));
ASSERT_EQUALS(r1_c4, res->getUInt64(4));
ASSERT(res->next());
ASSERT_EQUALS(r2_c1, (int64_t) res->getInt("i"));
ASSERT_EQUALS(r2_c1, (int64_t) res->getInt(1));
ASSERT_EQUALS(r2_c2, res->getInt64("i_uns"));
ASSERT_EQUALS(r2_c2, res->getInt64(2));
ASSERT_EQUALS(r2_c3, res->getInt64("b"));
ASSERT_EQUALS(r2_c3, res->getInt64(3));
ASSERT_EQUALS(r2_c4, res->getUInt64("b_uns"));
ASSERT_EQUALS(r2_c4, res->getUInt64(4));
ASSERT_EQUALS(res->next(), false);
stmt->execute("DROP TABLE IF EXISTS test");
}
catch (sql::SQLException &e)
{
logErr(e.what());
logErr("SQLState: " + std::string(e.getSQLState()));
fail(e.what(), __FILE__, __LINE__);
}
on_off=false;
//con->setClientOption("clientTrace", &on_off);
}
void resultset::getTypes()
{
logMsg("resultset::getTypes - MySQL_ResultSet::get*");
std::vector<columndefinition>::iterator it;
std::stringstream msg;
bool got_warning=false;
ResultSet pres;
std::string ps_value;
std::string::size_type len_st;
std::string::size_type len_ps;
try
{
stmt.reset(con->createStatement());
logMsg("... looping over all kinds of column types");
for (it = columns.begin(); it != columns.end(); it++)
{
stmt->execute("DROP TABLE IF EXISTS test");
msg.str("");
msg << "CREATE TABLE test(dummy TIMESTAMP, id " << it->sqldef << ")";
try
{
stmt->execute(msg.str());
msg.str("");
msg << "... testing " << it->sqldef << ", value = '" << it->value << "'";
logMsg(msg.str());
}
catch (sql::SQLException&)
{
msg.str("");
msg << "... skipping " << it->sqldef;
logMsg(msg.str());
continue;
}
msg.str("");
switch (it->ctype)
{
case sql::DataType::BIT:
msg << "INSERT INTO test(id) VALUES (" << it->value << ")";
break;
default:
msg << "INSERT INTO test(id) VALUES (\"" << it->value << "\")";
}
try
{
stmt->execute(msg.str());
ASSERT_EQUALS(1, (int)stmt->getUpdateCount());
}
catch (sql::SQLException & e)
{
logErr(e.what());
logErr("SQLState: " + std::string(e.getSQLState()));
logErr("SqlDef: " + it->sqldef);
fail(e.what(), __FILE__, __LINE__);
}
res.reset(stmt->executeQuery("SELECT id, NULL FROM test"));
checkResultSetScrolling(res);
ASSERT(res->next());
pstmt.reset(con->prepareStatement("SELECT id, NULL FROM test"));
pstmt->clearParameters();
pres.reset(pstmt->executeQuery());
checkResultSetScrolling(pres);
ASSERT(pres->next());
if (it->check_as_string)
{
logMsg("... checking string value");
if (it->as_string != res->getString(id))
{
msg.str("");
msg << "... expecting '" << it->as_string << "', got '" << res->getString(id) << "'";
logMsg(msg.str());
got_warning = true;
}
}
ASSERT(res->getString(id).compare(res->getString(1)) == 0);
try
{
res->getString(0);
FAIL("Invalid argument not detected");
}
catch (sql::InvalidArgumentException&)
{
}
try
{
res->getString(3);
FAIL("Invalid argument not detected");
}
catch (sql::InvalidArgumentException&)
{
}
res->beforeFirst();
try
{
res->getString(1);
FAIL("Invalid argument not detected");
}
catch (sql::SQLDataException&)
{
}
res->afterLast();
try
{
res->getString(1);
FAIL("Invalid argument not detected");
}
catch (sql::SQLDataException&)
{
}
res->first();
ASSERT_EQUALS(res->getBoolean(id), res->getBoolean(1));
try
{
res->getBoolean(0);
FAIL("Invalid argument not detected");
}
catch (sql::InvalidArgumentException&)
{
}
try
{
res->getBoolean(3);
FAIL("Invalid argument not detected");
}
catch (sql::InvalidArgumentException&)
{
}
res->beforeFirst();
try
{
res->getBoolean(1);
FAIL("Invalid argument not detected");
}
catch (sql::SQLDataException&)
{
}
res->afterLast();
try
{
res->getBoolean(1);
FAIL("Invalid argument not detected");
}
catch (sql::SQLDataException&)
{
}
res->first();
// Comparing prepared statement resultset and statement resultset
if (it->check_as_string && (pres->getString(id) != res->getString(id)))
{
if (it->sqldef.find("ZEROFILL", 0) == std::string::npos)
{
ps_value = pres->getString(id);
len_st = res->getString(id).length();
len_ps = ps_value.length();
if (len_ps > len_st)
{
// Something like 1.01000 vs. 1.01 ?
std::string::size_type i;
for (i = len_st; i < len_ps; i++)
{
if (ps_value.at(i) != '0')
break;
}
if (i < (len_ps - 1))
{
got_warning = true;
msg.str("");
msg << "... \t\tWARNING - getString(), PS: '" << pres->getString(id) << "'";
msg << ", Statement: '" << res->getString(id) << "'";
logMsg(msg.str());
}
}
}
}
try
{
ASSERT_EQUALS(res->getDouble(id), res->getDouble(1));
}
catch (sql::SQLException & e)
{
if ((it->name.compare("DATE") != 0 && it->name.compare("DATETIME") != 0 && it->name.compare("TIMESTAMP") != 0 && it->name.compare("TIME") != 0 &&
it->name.compare("CHAR") != 0 && it->name.compare("BINARY") != 0 && it->name.compare("VARCHAR") != 0 && it->name.compare("VARBINARY") != 0 &&
it->name.compare("TINYBLOB") != 0 && it->name.compare("TINYTEXT") != 0 && it->name.compare("TEXT") != 0 && it->name.compare("BLOB") != 0 &&
it->name.compare("MEDIUMTEXT") != 0 && it->name.compare("MEDIUMBLOB") != 0 && it->name.compare("LONGBLOB") != 0 &&
it->name.compare("LONGTEXT") != 0 && it->name.compare("ENUM") && it->name.compare("SET"))
|| (!e.getMessage().startsWith("getDouble not available for data field type Types::") && !e.getMessage().startsWith("Incorrect format ")))
{
throw e;
}
try
{
res->getInt(id);
FAIL("getInt shouldn't be available for this type");
}
catch (sql::SQLException&)
{
}
try
{
pres->getDouble(id);
FAIL("getInt shouldn't be available for this type");
}
catch (sql::SQLException&)
{
}
try
{
pres->getInt(id);
FAIL("getInt shouldn't be available for this type");
}
catch (sql::SQLException&)
{
}
// There is not sense to continue for this type further
continue;
}
try
{
res->getDouble(0);
FAIL("Invalid argument not detected");
}
catch (sql::InvalidArgumentException&)
{
}
try
{
res->getDouble(3);
FAIL("Invalid argument not detected");
}
catch (sql::InvalidArgumentException&)
{
}
res->beforeFirst();
try
{
res->getDouble(1);
FAIL("Invalid argument not detected");
}
catch (sql::SQLDataException&)
{
}
res->afterLast();
try
{
res->getDouble(1);
FAIL("Invalid argument not detected");
}
catch (sql::SQLDataException&)
{
}
res->first();
int64_t intValue = 0;
bool isNumber = true, inIntRange = true, inUintRange = !it->is_negative, inInt64Range = true;
try
{
if (it->is_negative)
{
intValue = std::stoll(it->value.c_str());
}
else
{
intValue = static_cast<int64_t>(std::stoull(it->value.c_str()));
}
}
catch (...)
{
isNumber = false;
}
if ((!it->is_negative && intValue < 0) || intValue < INT32_MIN || intValue > INT32_MAX)
{
inIntRange = false;
try
{
res->getInt(1);
FAIL("Overflow of int value is not detected");
}
catch (sql::SQLException & e)
{
//All is good
ASSERT_EQUALS(1264, e.getErrorCode());
ASSERT_EQUALS("22003", e.getSQLState());
}
if (intValue >= 0 && intValue <= UINT32_MAX)
{
ASSERT_EQUALS(res->getUInt(1), res->getUInt(id));
}
else
{
inUintRange = false;
if (!it->is_negative && intValue < 0)// i.e. value is in fact uint64_t
{
try
{
res->getLong(1); //getInt64 is the same
FAIL("Overflow of int64 value is not detected");
}
catch (sql::SQLException & e)
{
//All is good
ASSERT_EQUALS(1264, e.getErrorCode());
ASSERT_EQUALS("22003", e.getSQLState());
}
}
else
{
ASSERT_EQUALS(res->getInt64(1), res->getInt64(id));
}
}
}
else
{
ASSERT_EQUALS(res->getInt(1), res->getInt(id));
}
try
{
res->getInt(0);
FAIL("Invalid argument not detected");
}
catch (sql::InvalidArgumentException&)
{
}
try
{
res->getInt(3);
FAIL("Invalid argument not detected");
}
catch (sql::InvalidArgumentException&)
{
}
res->beforeFirst();
try
{
res->getInt(1);
FAIL("Invalid argument not detected");
}
catch (sql::SQLDataException&)
{
}
res->afterLast();
try
{
res->getInt(1);
FAIL("Invalid argument not detected");
}
catch (sql::SQLDataException&)
{
}
res->first();
if (it->is_negative || !inUintRange)
{
try
{
ASSERT_EQUALS(res->getUInt(1), res->getUInt(id));
FAIL("Range error(negative value) has not been detected");
}
catch (sql::SQLException & e)
{
ASSERT_EQUALS(1264, e.getErrorCode());
ASSERT_EQUALS("22003", e.getSQLState());
}
}
else
{
ASSERT_EQUALS(res->getUInt(1), res->getUInt(id));
}
try
{
res->getUInt(0);
FAIL("Invalid argument not detected");
}
catch (sql::InvalidArgumentException &)
{
}
try
{
res->getUInt(3);
FAIL("Invalid argument not detected");
}
catch (sql::InvalidArgumentException &)
{
}
res->beforeFirst();
try
{
res->getUInt(1);
FAIL("Invalid argument not detected");
}
catch (sql::SQLDataException&)
{
}
res->afterLast();
try
{
res->getUInt(1);
FAIL("Invalid argument not detected");
}
catch (sql::SQLDataException&)
{
}
res->first();
// intValue >= 0 means it's in int64 range
if (it->is_negative || intValue >= 0)
{
ASSERT_EQUALS(res->getInt64(id), res->getInt64(1));
}
try
{
res->getInt64(0);
FAIL("Invalid argument not detected");
}
catch (sql::InvalidArgumentException &)
{
}
try
{
res->getInt64(3);
FAIL("Invalid argument not detected");
}
catch (sql::InvalidArgumentException &)
{
}
res->beforeFirst();
try
{
res->getInt64(1);
FAIL("Invalid argument not detected");
}
catch (sql::SQLDataException&)
{
}
res->afterLast();
try
{
res->getInt64(1);
FAIL("Invalid argument not detected");
}
catch (sql::SQLDataException&)
{
}
res->first();
if (it->is_negative)
{
try
{
ASSERT_EQUALS(res->getUInt64(1), res->getUInt64(id));
FAIL("Range error(negative value) has not been detected");
}
catch (sql::SQLException & e)
{
ASSERT_EQUALS(1264, e.getErrorCode());
ASSERT_EQUALS("22003", e.getSQLState());
}
}
else
{
ASSERT_EQUALS(res->getUInt64(1), res->getUInt64(id));
}
try
{
res->getUInt64(0);
FAIL("Invalid argument not detected");
}
catch (sql::InvalidArgumentException &)
{
}
try
{
res->getUInt64(3);
FAIL("Invalid argument not detected");
}
catch (sql::InvalidArgumentException &)
{
}
res->beforeFirst();
try
{
res->getUInt64(1);
FAIL("Invalid argument not detected");
}
catch (sql::SQLDataException&)
{
}
res->afterLast();
try
{
res->getUInt64(1);
FAIL("Invalid argument not detected");
}
catch (sql::SQLDataException&)
{
}
res->first();
try
{
if (!fuzzyEquals(pres->getDouble(id), res->getDouble(id), 0.001))
{
msg.str("");
msg << "... \t\tWARNING - getDouble(), PS: '" << pres->getDouble(id) << "'";
msg << ", Statement: '" << res->getDouble(id) << "'";
msg << ", Difference: '" << (pres->getDouble(id) - res->getDouble(id)) << "'";
logMsg(msg.str());
got_warning = true;
}
}
catch (sql::SQLException & e)
{
if (it->name.compare("DATE") != 0 || !e.getMessage().startsWith("getDouble not available for data field type Types::"))
{
throw e;
}
}
if (inIntRange && (pres->getInt(id) != res->getInt(id)))
{
msg.str("");
msg << "... \t\tWARNING - getInt(), PS: '" << pres->getInt(id) << "'";
msg << ", Statement: '" << res->getInt(id) << "'";
logMsg(msg.str());
got_warning=true;
}
if (!it->is_negative && (pres->getUInt64(id) != res->getUInt64(id)))
{
msg.str("");
msg << "... \t\tWARNING - getUInt64(), PS: '" << pres->getUInt64(id) << "'";
msg << ", Statement: '" << res->getUInt64(id) << "'";
logMsg(msg.str());
got_warning=true;
}
if (inUintRange)
{
ASSERT_EQUALS(pres->getUInt(id), res->getUInt(id));
}
if ((it->is_negative || intValue >= 0) && pres->getInt64(id) != res->getInt64(id))
{
msg.str("");
msg << "... \t\tWARNING - getInt64(), PS: '" << pres->getInt64(id) << "'";
msg << ", Statement: '" << res->getInt64(id) << "'";
logMsg(msg.str());
got_warning=true;
}
// ASSERT_EQUALS(pres->getInt64(id), res->getInt64(id));
if (!it->is_negative && (pres->getUInt64(id) != res->getUInt64(id)))
{
msg.str("");
msg << "... \t\tWARNING - getUInt64(), PS: '" << pres->getUInt64(id) << "'";
msg << ", Statement: '" << res->getUInt64(id) << "'";
logMsg(msg.str());
got_warning=true;
}
// ASSERT_EQUALS(pres->getUInt64(id), res->getUInt64(id));
ASSERT_EQUALS(pres->getBoolean(id), res->getBoolean(1));
}
if (got_warning)
FAIL("See warnings!");
stmt->execute("DROP TABLE IF EXISTS test");
}
catch (sql::SQLException &e)
{
logErr(e.what());
logErr("SQLState: " + std::string(e.getSQLState()));
fail(e.what(), __FILE__, __LINE__);
}
}
void resultset::getTypesMinorIssues()
{
logMsg("resultset::getTypesMinorIssues - MySQL_ResultSet::get*");
std::vector<columndefinition>::iterator it;
std::stringstream msg;
bool got_warning=false;
bool got_minor_warning=false;
ResultSet pres;
std::string ps_value;
std::string::size_type len_st;
std::string::size_type len_ps;
try
{
stmt.reset(con->createStatement());
logMsg("... looping over all kinds of column types");
for (it=columns.begin(); it != columns.end(); it++)
{
stmt->execute("DROP TABLE IF EXISTS test");
msg.str("");
msg << "CREATE TABLE test(dummy TIMESTAMP, id " << it->sqldef << ")";
try
{
stmt->execute(msg.str());
msg.str("");
msg << "... testing " << it->sqldef << ", value = '" << it->value << "'";
logMsg(msg.str());
}
catch (sql::SQLException &)
{
msg.str("");
msg << "... skipping " << it->sqldef;
logMsg(msg.str());
continue;
}
msg.str("");
switch(it->ctype)
{
case sql::DataType::BIT:
msg << "INSERT INTO test(id) VALUES (" << it->value << ")";
break;
default:
msg << "INSERT INTO test(id) VALUES (\"" << it->value << "\")";
}
try
{
stmt->execute(msg.str());
ASSERT_EQUALS(1, (int)stmt->getUpdateCount());
}
catch (sql::SQLException &e)
{
logErr(e.what());
logErr("SQLState: " + std::string(e.getSQLState()));
logErr("SqlDef: " + it->sqldef);
fail(e.what(), __FILE__, __LINE__);
}
res.reset(stmt->executeQuery("SELECT id, NULL FROM test"));
checkResultSetScrolling(res);
ASSERT(res->next());
pstmt.reset(con->prepareStatement("SELECT id, NULL FROM test"));
pstmt->clearParameters();
pres.reset(pstmt->executeQuery());
checkResultSetScrolling(pres);
ASSERT(pres->next());
if (it->check_as_string && (it->as_string != res->getString(id)))
{
msg.str("");
msg << "... expecting '" << it->as_string << "', got '" << res->getString(id) << "'";
logMsg(msg.str());
got_warning=true;
}
// Comparing prepared statement resultset and statement resultset
if (pres->getString(id) != res->getString(id))
{
if (it->sqldef.find("ZEROFILL", 0) == std::string::npos)
{
bool is_minor=false;
ps_value=pres->getString(id);
len_st=res->getString(id).length();
len_ps=ps_value.length();
if (len_ps > len_st)
{
// Something like 1.01000 vs. 1.01 ?
std::string::size_type i;
for (i=len_st; i < len_ps; i++)
{
if (ps_value.at(i) != '0')
break;
}
if (i < (len_ps - 1))
{
got_warning=true;
}
else
{
is_minor=true;
got_minor_warning=true;
}
}
if (!it->check_as_string)
{
is_minor=true;
got_minor_warning=true;
}
else
{
got_warning=true;
}
msg.str("");
if (is_minor)
{
msg << "... \t\tMINOR WARNING - getString(), PS: '" << pres->getString(id) << "'";
}
else
{
msg << "... \t\tWARNING - getString(), PS: '" << pres->getString(id) << "'";
}
msg << ", Statement: '" << res->getString(id) << "'";
logMsg(msg.str());
}
}
}
if (got_warning)
FAIL("See --verbose warnings!");
/*
* We decided to ignore the differences. It is
* about number formatting only. Any application using C/C++
* will apply their own formatting style anyway.
* No simple fix came to our mind. If we ever have an
* idea we should fix it. Meanwhile: won't fix.
*/
if (got_minor_warning && false)
{
FAIL("TODO - see MINOR WARNING when using --verbose");
}
stmt->execute("DROP TABLE IF EXISTS test");
}
catch (sql::SQLException &e)
{
logErr(e.what());
logErr("SQLState: " + std::string(e.getSQLState()));
fail(e.what(), __FILE__, __LINE__);
}
}
#ifdef INCLUDE_NOT_IMPLEMENTED_METHODS
void resultset::notImplemented()
{
logMsg("resultset::notImplemented - MySQL_ResultSet::*");
try
{
stmt.reset(con->createStatement());
stmt->execute("DROP TABLE IF EXISTS test");
stmt->execute("CREATE TABLE test(id INT)");
ASSERT_EQUALS(1, stmt->executeUpdate("INSERT INTO test(id) VALUES (1)"));
res.reset(stmt->executeQuery("SELECT id FROM test"));
doNotImplemented();
pstmt.reset(con->prepareStatement("SELECT id FROM test"));
res.reset(pstmt->executeQuery());
doNotImplemented();
stmt->execute("DROP TABLE IF EXISTS test");
}
catch (sql::SQLException &e)
{
logErr(e.what());
logErr("SQLState: " + std::string(e.getSQLState()));
fail(e.what(), __FILE__, __LINE__);
}
}
void resultset::doNotImplemented()
{
try
{
res->getWarnings();
}
catch (sql::MethodNotImplementedException)
{
}
try
{
res->clearWarnings();
}
catch (sql::MethodNotImplementedException)
{
}
try
{
res->insertRow();
}
catch (sql::MethodNotImplementedException)
{
}
try
{
res->moveToCurrentRow();
}
catch (sql::MethodNotImplementedException)
{
}
try
{
res->moveToInsertRow();
}
catch (sql::MethodNotImplementedException)
{
}
try
{
res->refreshRow();
}
catch (sql::MethodNotImplementedException)
{
}
try
{
res->rowDeleted();
}
catch (sql::MethodNotImplementedException)
{
}
try
{
res->rowInserted();
}
catch (sql::MethodNotImplementedException)
{
}
try
{
res->rowUpdated();
}
catch (sql::MethodNotImplementedException)
{
}
}
#endif
void resultset::fetchBigint()
{
std::stringstream msg;
logMsg("resultset::fetchBigint - MySQL_ResultSet::*");
try
{
stmt.reset(con->createStatement());
stmt->execute("DROP TABLE IF EXISTS test");
stmt->execute("CREATE TABLE test(id BIGINT UNSIGNED)");
stmt->execute("INSERT INTO test(id) VALUES (18446744073709551615)");
res.reset(stmt->executeQuery("SELECT id FROM test"));
#ifdef INCLUDE_NOT_IMPLEMENTED_METHODS
doNotImplemented();
#endif
pstmt.reset(con->prepareStatement("SELECT id FROM test"));
res.reset(pstmt->executeQuery());
res->next();
msg.str("");
msg << "... PS: id = " << res->getDouble(1);
logMsg(msg.str());
res.reset(stmt->executeQuery("SELECT id FROM test"));
res->next();
msg.str("");
msg << "... Statement: id = " << res->getDouble(1);
logMsg(msg.str());
stmt->execute("DROP TABLE IF EXISTS test");
}
catch (sql::SQLException &e)
{
logErr(e.what());
logErr("SQLState: " + std::string(e.getSQLState()));
fail(e.what(), __FILE__, __LINE__);
}
}
void resultset::fetchBitAsInt()
{
std::stringstream msg;
logMsg("resultset::fetchBitAsInt - MySQL_ResultSet::*");
try
{
logMsg("... BIT(0) - non-PS");
stmt.reset(con->createStatement());
stmt->execute("DROP TABLE IF EXISTS test");
stmt->execute("CREATE TABLE test(id BIT(1))");
stmt->execute("INSERT INTO test(id) VALUES (0)");
stmt->execute("INSERT INTO test(id) VALUES (1)");
res.reset(stmt->executeQuery("SELECT id, CAST(id AS SIGNED) AS bit_as_signed FROM test ORDER BY id"));
while (res->next())
{
ASSERT_EQUALS(res->getInt(id), res->getInt("bit_as_signed"));
ASSERT_EQUALS(res->getInt(id), res->getInt(1));
}
logMsg("... BIT(0) - PS");
pstmt.reset(con->prepareStatement("SELECT id, CAST(id AS SIGNED) AS bit_as_signed FROM test ORDER BY id"));
res.reset(pstmt->executeQuery());
while (res->next())
{
ASSERT_EQUALS(res->getInt(id), res->getInt("bit_as_signed"));
ASSERT_EQUALS(res->getInt(id), res->getInt(1));
}
uint64_t c1=UL64(4294967295),
c2=UL64(18446744073709551615);
logMsg("... BIT(32), BIT(64) - non-PS");
stmt->execute("DROP TABLE IF EXISTS test");
stmt->execute("CREATE TABLE test(col1 BIT(32), col2 BIT(64))");
stmt->execute("INSERT INTO test(col1, col2) VALUES(b'11111111111111111111111111111111', b'1111111111111111111111111111111111111111111111111111111111111111')");
res.reset(stmt->executeQuery("SELECT col1, CAST(col1 AS UNSIGNED) AS col1_as_unsigned, col2, CAST(col2 AS UNSIGNED) AS col2_as_unsigned FROM test"));
ASSERT(res->next());
ASSERT_EQUALS(c1, res->getUInt64(1));
ASSERT_EQUALS(res->getUInt64("col1_as_unsigned"), res->getUInt64(1));
ASSERT_EQUALS(c2, res->getUInt64("col2"));
ASSERT_EQUALS(res->getUInt64("col2_as_unsigned"), res->getUInt64("col2"));
logMsg("... BIT(32), BIT(64) - PS");
stmt->execute("DELETE FROM test");
pstmt.reset(con->prepareStatement("INSERT INTO test(col1, col2) VALUES(?,?)"));
pstmt->clearParameters();
pstmt->setUInt64(1, c1);
pstmt->setUInt64(2, c2);
ASSERT_EQUALS(false, pstmt->execute());
pstmt.reset(con->prepareStatement("SELECT col1, CAST(col1 AS UNSIGNED) AS col1_as_unsigned, col2, CAST(col2 AS UNSIGNED) AS col2_as_unsigned FROM test"));
res.reset(pstmt->executeQuery());
ASSERT(res->next());
ASSERT_EQUALS(c1, res->getUInt64(1));
ASSERT_EQUALS(res->getUInt64("col1_as_unsigned"), res->getUInt64(1));
ASSERT_EQUALS(c2, res->getUInt64("col2"));
ASSERT_EQUALS(res->getUInt64("col2_as_unsigned"), res->getUInt64("col2"));
stmt->execute("DROP TABLE IF EXISTS test");
}
catch (sql::SQLException &e)
{
logErr(e.what());
logErr("SQLState: " + std::string(e.getSQLState()));
fail(e.what(), __FILE__, __LINE__);
}
}
void resultset::getResultSetType()
{
sql::ConnectOptionsMap connection_properties;
logMsg("resultset::getResultSetType - MySQL_ResultSet::*");
SKIP("defaultStatementResultType connection option is not supported")
try
{
/* user comes from the unit testing framework */
connection_properties["user"]= user;
connection_properties["password"]= passwd;
connection_properties.erase("defaultStatementResultType");
{
logMsg("... testing defaultStatementResultType");
connection_properties["defaultStatementResultType"]= std::to_string(sql::ResultSet::TYPE_FORWARD_ONLY);
try
{
created_objects.clear();
con.reset(driver->connect(url, connection_properties));
}
catch (sql::SQLException &e)
{
fail(e.what(), __FILE__, __LINE__);
}
stmt.reset(con->createStatement());
ASSERT_EQUALS(stmt->getResultSetType(), sql::ResultSet::TYPE_FORWARD_ONLY);
pstmt.reset(con->prepareStatement("SELECT 1"));
/* NOTE: no bug - PS supports TYPE_SCROLL_INSENSITIVE only and we
are setting StatementResultType not PreparedStatementResultType */
res.reset(pstmt->executeQuery());
ASSERT_EQUALS(pstmt->getResultSetType(), sql::ResultSet::TYPE_FORWARD_ONLY);// sql::ResultSet::TYPE_SCROLL_INSENSITIVE);
connection_properties.erase("defaultStatementResultType");
connection_properties["defaultStatementResultType"]= std::to_string(sql::ResultSet::TYPE_SCROLL_INSENSITIVE);
try
{
created_objects.clear();
con.reset(driver->connect(url, connection_properties));
}
catch (sql::SQLException &e)
{
fail(e.what(), __FILE__, __LINE__);
}
stmt.reset(con->createStatement());
ASSERT_EQUALS(stmt->getResultSetType(), sql::ResultSet::TYPE_SCROLL_INSENSITIVE);
pstmt.reset(con->prepareStatement("SELECT 1"));
res.reset(pstmt->executeQuery());
ASSERT_EQUALS(pstmt->getResultSetType(), sql::ResultSet::TYPE_SCROLL_INSENSITIVE);
connection_properties.erase("defaultStatementResultType");
connection_properties["defaultStatementResultType"]= std::to_string(sql::ResultSet::TYPE_SCROLL_SENSITIVE);
try
{
created_objects.clear();
try
{
con.reset(driver->connect(url, connection_properties));
FAIL("Bug or API change - TYPE_SCROLL_SENSITIVE is unsupported");
stmt.reset(con->createStatement());
ASSERT_EQUALS(stmt->getResultSetType(), sql::ResultSet::TYPE_SCROLL_SENSITIVE);
pstmt.reset(con->prepareStatement("SELECT 1"));
res.reset(pstmt->executeQuery());
ASSERT_EQUALS(pstmt->getResultSetType(), sql::ResultSet::TYPE_SCROLL_INSENSITIVE);
}
catch (sql::SQLException &e)
{
logMsg("... expected exception because TYPE_SCROLL_SENSITIVE is unsupported!");
logMsg(e.what());
}
}
catch (sql::SQLException &e)
{
fail(e.what(), __FILE__, __LINE__);
}
}
connection_properties.erase("defaultStatementResultType");
}
catch (sql::SQLException &e)
{
logErr(e.what());
logErr("SQLState: " + std::string(e.getSQLState()));
fail(e.what(), __FILE__, __LINE__);
}
}
void resultset::JSON_support()
{
std::stringstream msg;
logMsg("resultset::JSON_support - MySQL_ResultSet::*");
if (getServerVersion(con) < 102007)
{
SKIP("Server does not support JSON");
}
try
{
stmt.reset(con->createStatement());
stmt->execute("DROP TABLE IF EXISTS test");
stmt->execute("CREATE TABLE test(id INT, jval JSON)");
stmt->execute("INSERT INTO test(id, jval) VALUES(1, '[1]')");
#ifdef INCLUDE_NOT_IMPLEMENTED_METHODS
doNotImplemented();
#endif
pstmt.reset(con->prepareStatement("SELECT * FROM test"));
res.reset(pstmt->executeQuery());
res->next();
msg.str("");
ASSERT_EQUALS(1, res->getInt(1));
msg << "... PS: id = " << res->getInt(1);
ASSERT_EQUALS("[1]", res->getString(2));
msg << "... PS: jval = " << res->getString(2);
logMsg(msg.str());
res.reset(stmt->executeQuery("SELECT * FROM test"));
res->next();
msg.str("");
ASSERT_EQUALS(1, res->getInt(1));
msg << "... Statement: id = " << res->getInt(1);
ASSERT_EQUALS("[1]", res->getString(2));
msg << "... Statement: jval = " << res->getString(2);
logMsg(msg.str());
stmt->execute("DROP TABLE IF EXISTS test");
}
catch (sql::SQLException &e)
{
logErr(e.what());
logErr("SQLState: " + std::string(e.getSQLState()));
fail(e.what(), __FILE__, __LINE__);
}
}
} /* namespace resultset */
} /* namespace testsuite */