mirror of
https://github.com/mariadb-corporation/mariadb-connector-cpp.git
synced 2025-08-11 23:32:23 +00:00

Some travis congig fixes for macos Errors and warnings. Fix of one testcase failing aginst 10.2
1308 lines
34 KiB
C++
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 */
|