mirror of
https://github.com/mariadb-corporation/mariadb-connector-cpp.git
synced 2025-08-03 07:29:01 +00:00
1588 lines
41 KiB
C++
1588 lines
41 KiB
C++
/*
|
|
* Copyright (c) 2009, 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 "PreparedStatement.h"
|
|
#include "Connection.h"
|
|
#include "Warning.h"
|
|
#include "preparedstatementtest.h"
|
|
#include <stdlib.h>
|
|
|
|
#include <memory>
|
|
|
|
namespace testsuite
|
|
{
|
|
namespace classes
|
|
{
|
|
|
|
void preparedstatement::InsertSelectAllTypes()
|
|
{
|
|
logMsg("preparedstatement::InsertSelectAllTypes() - MySQL_PreparedStatement::*");
|
|
|
|
//TODO: Enable it after fixing
|
|
|
|
std::stringstream sql;
|
|
std::vector<columndefinition>::iterator it;
|
|
stmt.reset(con->createStatement());
|
|
bool got_warning=false;
|
|
size_t len;
|
|
|
|
try
|
|
{
|
|
bool blobTestMakesSense= true;
|
|
for (it = columns.end(), it--; it != columns.begin(); it--)
|
|
{
|
|
stmt->execute("DROP TABLE IF EXISTS test");
|
|
sql.str("");
|
|
sql << "CREATE TABLE test(dummy TIMESTAMP, id " << it->sqldef << ")";
|
|
try
|
|
{
|
|
stmt->execute(sql.str());
|
|
sql.str("");
|
|
sql << "... testing '" << it->sqldef << "'";
|
|
logMsg(sql.str());
|
|
}
|
|
catch (sql::SQLException&)
|
|
{
|
|
sql.str("");
|
|
sql << "... skipping '" << it->sqldef << "'";
|
|
logMsg(sql.str());
|
|
continue;
|
|
}
|
|
|
|
pstmt.reset(con->prepareStatement("INSERT INTO test(id) VALUES (?)"));
|
|
if (it->name == "BIT")
|
|
{
|
|
pstmt->setLong(1, std::stoull(it->value));
|
|
}
|
|
else
|
|
{
|
|
pstmt->setString(1, it->value);
|
|
}
|
|
ASSERT_EQUALS(1, pstmt->executeUpdate());
|
|
|
|
pstmt.reset(con->prepareStatement("SELECT id, NULL FROM test"));
|
|
res.reset(pstmt->executeQuery());
|
|
checkResultSetScrolling(res);
|
|
ASSERT(res->next());
|
|
|
|
res.reset();
|
|
res.reset(pstmt->executeQuery());
|
|
checkResultSetScrolling(res);
|
|
ASSERT(res->next());
|
|
|
|
if (it->check_as_string && (res->getString(1) != it->as_string))
|
|
{
|
|
sql.str("");
|
|
sql << "... \t\tWARNING - SQL: '" << it->sqldef << "' - expecting '" << it->as_string << "'";
|
|
sql << " got '" << res->getString(1) << "'";
|
|
logMsg(sql.str());
|
|
got_warning = true;
|
|
}
|
|
|
|
sql::SQLString value = res->getString(1);
|
|
ASSERT_EQUALS(res->getString("id"), String(value.c_str(), value.length()));
|
|
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();
|
|
|
|
try
|
|
{
|
|
ASSERT_EQUALS(res->getDouble("id"), res->getDouble(1));
|
|
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();
|
|
|
|
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();
|
|
|
|
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();
|
|
|
|
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();
|
|
|
|
ASSERT_EQUALS(res->getUInt64("id"), res->getUInt64(1));
|
|
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&)
|
|
{
|
|
}
|
|
}
|
|
catch (sql::SQLException & e)
|
|
{
|
|
//All is good
|
|
if ((e.getErrorCode() != 1264 || e.getSQLState().compare("22003") != 0) && !e.getMessage().startsWith("getDouble not available for data field type"))
|
|
{
|
|
throw e;
|
|
}
|
|
}
|
|
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();
|
|
|
|
/* YEAR is first type after char/bin types(traversing backwards). The way getBlob test is written now,
|
|
it will work correctly only for those types(and maybe some others), and YEAR is firdt type it will not */
|
|
if (it->name == "YEAR")
|
|
{
|
|
blobTestMakesSense= false;
|
|
}
|
|
// TODO - make BLOB
|
|
if (it->check_as_string && blobTestMakesSense)
|
|
{
|
|
{
|
|
std::unique_ptr<std::istream> blob_output_stream(res->getBlob(1));
|
|
len=it->as_string.length();
|
|
std::unique_ptr<char> blob_out(new char[len]);
|
|
blob_output_stream->read(blob_out.get(), len);
|
|
if (it->as_string.compare(0, blob_output_stream->gcount()
|
|
, blob_out.get(), blob_output_stream->gcount()))
|
|
{
|
|
sql.str("");
|
|
sql << "... \t\tWARNING - SQL: '" << it->sqldef << "' - expecting '" << it->as_string << "'";
|
|
sql << " got '" << res->getString(1) << "'";
|
|
logMsg(sql.str());
|
|
got_warning=false;
|
|
}
|
|
}
|
|
|
|
{
|
|
std::unique_ptr<std::istream> blob_output_stream(res->getBlob("id"));
|
|
len=it->as_string.length();
|
|
std::unique_ptr<char> blob_out(new char[len]);
|
|
blob_output_stream->read(blob_out.get(), len);
|
|
if (it->as_string.compare(0, blob_output_stream->gcount()
|
|
, blob_out.get(), blob_output_stream->gcount()))
|
|
{
|
|
sql.str("");
|
|
sql << "... \t\tWARNING - SQL: '" << it->sqldef << "' - expecting '" << it->as_string << "'";
|
|
sql << " got '" << res->getString(1) << "'";
|
|
logMsg(sql.str());
|
|
got_warning=false;
|
|
}
|
|
}
|
|
}
|
|
try
|
|
{
|
|
res->getBlob(0);
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::InvalidArgumentException &)
|
|
{
|
|
}
|
|
|
|
try
|
|
{
|
|
res->getBlob(3);
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::InvalidArgumentException &)
|
|
{
|
|
}
|
|
|
|
res->beforeFirst();
|
|
try
|
|
{
|
|
res->getBlob(1);
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::SQLDataException&)
|
|
{
|
|
}
|
|
res->afterLast();
|
|
try
|
|
{
|
|
res->getBlob(1);
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::SQLDataException&)
|
|
{
|
|
}
|
|
res->first();
|
|
|
|
}
|
|
stmt->execute("DROP TABLE IF EXISTS test");
|
|
if (got_warning)
|
|
FAIL("See warnings");
|
|
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
void preparedstatement::assortedSetType()
|
|
{
|
|
logMsg("preparedstatement::assortedSetType() - MySQL_PreparedStatement::set*");
|
|
|
|
//TODO: Enable it after fixing
|
|
//SKIP("Removed until fixed");
|
|
|
|
std::stringstream sql;
|
|
std::vector<columndefinition>::iterator it;
|
|
stmt.reset(con->createStatement());
|
|
bool got_warning=false;
|
|
|
|
try
|
|
{
|
|
|
|
for (it=columns.end(), it--; it != columns.begin(); it--)
|
|
{
|
|
stmt->execute("DROP TABLE IF EXISTS test");
|
|
sql.str("");
|
|
sql << "CREATE TABLE test(dummy TIMESTAMP, id " << it->sqldef << ")";
|
|
try
|
|
{
|
|
stmt->execute(sql.str());
|
|
sql.str("");
|
|
sql << "... testing '" << it->sqldef << "'";
|
|
logMsg(sql.str());
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
sql.str("");
|
|
sql << "... skipping '" << it->sqldef << "'";
|
|
logMsg(sql.str());
|
|
continue;
|
|
}
|
|
|
|
pstmt.reset(con->prepareStatement("INSERT INTO test(id) VALUES (?)"));
|
|
|
|
if (it->name == "BIT")
|
|
{
|
|
pstmt->setLong(1, std::stoull(it->value));
|
|
ASSERT_EQUALS(1, pstmt->executeUpdate());
|
|
}
|
|
else
|
|
{
|
|
pstmt->setString(1, it->value);
|
|
ASSERT_EQUALS(1, pstmt->executeUpdate());
|
|
|
|
pstmt->clearParameters();
|
|
pstmt->setDateTime(1, it->value);
|
|
ASSERT_EQUALS(1, pstmt->executeUpdate());
|
|
|
|
pstmt->clearParameters();
|
|
pstmt->setBigInt(1, it->value);
|
|
ASSERT_EQUALS(1, pstmt->executeUpdate());
|
|
}
|
|
|
|
|
|
pstmt->clearParameters();
|
|
try
|
|
{
|
|
pstmt->setString(0, "overflow");
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::SQLException&)
|
|
{
|
|
}
|
|
|
|
pstmt->clearParameters();
|
|
try
|
|
{
|
|
pstmt->setString(2, "invalid");
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::SQLException&)
|
|
{
|
|
}
|
|
|
|
pstmt->clearParameters();
|
|
try
|
|
{
|
|
pstmt->setBigInt(0, it->value);
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::SQLException&)
|
|
{
|
|
}
|
|
|
|
pstmt->clearParameters();
|
|
try
|
|
{
|
|
pstmt->setBigInt(2, it->value);
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::SQLException&)
|
|
{
|
|
}
|
|
|
|
pstmt->clearParameters();
|
|
// enum won't accept 0 as a value
|
|
pstmt->setBoolean(1, it->name.compare("ENUM") == 0);
|
|
ASSERT_EQUALS(1, pstmt->executeUpdate());
|
|
|
|
pstmt->clearParameters();
|
|
try
|
|
{
|
|
pstmt->setBoolean(0, false);
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::SQLException&)
|
|
{
|
|
}
|
|
|
|
pstmt->clearParameters();
|
|
try
|
|
{
|
|
pstmt->setBoolean(2, false);
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::SQLException&)
|
|
{
|
|
}
|
|
|
|
pstmt->clearParameters();
|
|
try
|
|
{
|
|
pstmt->setDateTime(0, it->value);
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::SQLException&)
|
|
{
|
|
}
|
|
|
|
pstmt->clearParameters();
|
|
try
|
|
{
|
|
pstmt->setDateTime(2, it->value);
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::SQLException&)
|
|
{
|
|
}
|
|
|
|
pstmt->clearParameters();
|
|
pstmt->setDouble(1, (double) 1.23);
|
|
|
|
if (it->name != "TIMESTAMP" && it->name != "DATETIME" && it->name != "DATE")
|
|
{
|
|
ASSERT_EQUALS(1, pstmt->executeUpdate());
|
|
|
|
pstmt->clearParameters();
|
|
try
|
|
{
|
|
pstmt->setDouble(0, (double)1.23);
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::SQLException&)
|
|
{
|
|
}
|
|
|
|
pstmt->clearParameters();
|
|
try
|
|
{
|
|
pstmt->setDouble(2, (double)1.23);
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::SQLException&)
|
|
{
|
|
}
|
|
|
|
pstmt->clearParameters();
|
|
pstmt->setInt(1, 1);
|
|
ASSERT_EQUALS(1, pstmt->executeUpdate());
|
|
|
|
pstmt->clearParameters();
|
|
try
|
|
{
|
|
pstmt->setInt(0, (int32_t)-1);
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::SQLException&)
|
|
{
|
|
}
|
|
|
|
pstmt->clearParameters();
|
|
try
|
|
{
|
|
pstmt->setInt(2, (int32_t)-1);
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::SQLException&)
|
|
{
|
|
}
|
|
|
|
pstmt->clearParameters();
|
|
pstmt->setUInt(1, (uint32_t)1);
|
|
ASSERT_EQUALS(1, pstmt->executeUpdate());
|
|
|
|
pstmt->clearParameters();
|
|
try
|
|
{
|
|
pstmt->setUInt(0, (uint32_t)1);
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::SQLException&)
|
|
{
|
|
}
|
|
|
|
pstmt->clearParameters();
|
|
try
|
|
{
|
|
pstmt->setUInt(2, (uint32_t)1);
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::SQLException&)
|
|
{
|
|
}
|
|
|
|
pstmt->clearParameters();
|
|
pstmt->setInt64(1, 1);
|
|
ASSERT_EQUALS(1, pstmt->executeUpdate());
|
|
|
|
pstmt->clearParameters();
|
|
pstmt->setUInt64(1, (uint64_t)1);
|
|
ASSERT_EQUALS(1, pstmt->executeUpdate());
|
|
|
|
pstmt->clearParameters();
|
|
try
|
|
{
|
|
pstmt->setUInt64(0, (uint64_t)1);
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::SQLException&)
|
|
{
|
|
}
|
|
|
|
pstmt->clearParameters();
|
|
try
|
|
{
|
|
pstmt->setUInt64(2, (uint64_t)-1);
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::SQLException&)
|
|
{
|
|
}
|
|
}
|
|
|
|
if (it->is_nullable)
|
|
{
|
|
pstmt->clearParameters();
|
|
pstmt->setNull(1, it->ctype);
|
|
ASSERT_EQUALS(1, pstmt->executeUpdate());
|
|
|
|
pstmt->clearParameters();
|
|
try
|
|
{
|
|
pstmt->setNull(0, it->ctype);
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::SQLException&)
|
|
{
|
|
}
|
|
|
|
pstmt->clearParameters();
|
|
try
|
|
{
|
|
pstmt->setNull(2, it->ctype);
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::SQLException&)
|
|
{
|
|
}
|
|
}
|
|
|
|
pstmt->clearParameters();
|
|
pstmt.reset(con->prepareStatement("INSERT INTO test(id) VALUES (?)"));
|
|
std::stringstream blob_input_stream;
|
|
blob_input_stream.str(it->value);
|
|
pstmt->setBlob(1, &blob_input_stream);
|
|
try
|
|
{
|
|
ASSERT_EQUALS(1, pstmt->executeUpdate());
|
|
}
|
|
catch (sql::SQLException & e)
|
|
{
|
|
if (!(e.getErrorCode() == 1265 || e.getErrorCode() == 1406) || (it->name.compare("SET") != 0 && it->name.compare("ENUM") != 0 && it->name.compare("BIT") != 0))
|
|
{
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
pstmt->clearParameters();
|
|
try
|
|
{
|
|
pstmt->setBlob(0, &blob_input_stream);
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::SQLException&)
|
|
{
|
|
}
|
|
|
|
pstmt->clearParameters();
|
|
try
|
|
{
|
|
pstmt->setBlob(2, &blob_input_stream);
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::SQLException&)
|
|
{
|
|
}
|
|
|
|
pstmt.reset(con->prepareStatement("SELECT COUNT(IFNULL(id, 1)) AS _num FROM test"));
|
|
res.reset(pstmt->executeQuery());
|
|
checkResultSetScrolling(res);
|
|
ASSERT(res->next());
|
|
if (res->getInt("_num") != (11 + (int) it->is_nullable))
|
|
{
|
|
sql.str("");
|
|
sql << "....\t\tWARNING, SQL: " << it->sqldef << ", nullable " << std::boolalpha;
|
|
sql << it->is_nullable << ", found " << res->getInt(1) << "columns but";
|
|
sql << " expecting " << (11 + (int) it->is_nullable);
|
|
logMsg(sql.str());
|
|
got_warning=true;
|
|
}
|
|
|
|
}
|
|
stmt->execute("DROP TABLE IF EXISTS test");
|
|
if (got_warning)
|
|
{
|
|
SKIP("There were warnings, but that is due to changes in the test, that made detecting of warnings obsolete");
|
|
}
|
|
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
void preparedstatement::setNull()
|
|
{
|
|
logMsg("preparedstatement::setNull() - MySQL_PreparedStatement::*");
|
|
|
|
std::stringstream sql;
|
|
stmt.reset(con->createStatement());
|
|
|
|
try
|
|
{
|
|
stmt->execute("DROP TABLE IF EXISTS test");
|
|
stmt->execute("CREATE TABLE test(id INT)");
|
|
pstmt.reset(con->prepareStatement("INSERT INTO test(id) VALUES (?)"));
|
|
pstmt->setNull(1, sql::DataType::INTEGER);
|
|
ASSERT_EQUALS(1, pstmt->executeUpdate());
|
|
|
|
pstmt.reset(con->prepareStatement("SELECT id FROM test"));
|
|
res.reset(pstmt->executeQuery());
|
|
checkResultSetScrolling(res);
|
|
ASSERT(res->next());
|
|
ASSERT(res->isNull(1));
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
|
|
try
|
|
{
|
|
stmt->execute("DROP TABLE IF EXISTS test");
|
|
stmt->execute("CREATE TABLE test(id INT NOT NULL)");
|
|
pstmt.reset(con->prepareStatement("INSERT INTO test(id) VALUES (?)"));
|
|
pstmt->setNull(1, sql::DataType::INTEGER);
|
|
pstmt->executeUpdate();
|
|
FAIL("Should fail");
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
}
|
|
|
|
}
|
|
|
|
void preparedstatement::checkClosed()
|
|
{
|
|
logMsg("preparedstatement::checkClosed() - MySQL_PreparedStatement::close()");
|
|
|
|
try
|
|
{
|
|
pstmt.reset(con->prepareStatement("SELECT 1"));
|
|
pstmt->close();
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
|
|
}
|
|
|
|
void preparedstatement::getMetaData()
|
|
{
|
|
logMsg("preparedstatement::getMetaData() - MySQL_PreparedStatement::getMetaData()");
|
|
|
|
std::stringstream sql;
|
|
std::vector<columndefinition>::iterator it;
|
|
stmt.reset(con->createStatement());
|
|
ResultSetMetaData meta_ps;
|
|
ResultSetMetaData meta_st;
|
|
ResultSet res_st;
|
|
bool got_warning=false;
|
|
unsigned int i;
|
|
|
|
try
|
|
{
|
|
|
|
for (it=columns.end(), it--; it != columns.begin(); it--)
|
|
{
|
|
stmt->execute("DROP TABLE IF EXISTS test");
|
|
sql.str("");
|
|
sql << "CREATE TABLE test(dummy TIMESTAMP, id " << it->sqldef << ")";
|
|
try
|
|
{
|
|
stmt->execute(sql.str());
|
|
sql.str("");
|
|
sql << "... testing '" << it->sqldef << "'";
|
|
logMsg(sql.str());
|
|
}
|
|
catch (sql::SQLException &)
|
|
{
|
|
sql.str("");
|
|
sql << "... skipping '" << it->sqldef << "'";
|
|
logMsg(sql.str());
|
|
continue;
|
|
}
|
|
|
|
pstmt.reset(con->prepareStatement("INSERT INTO test(id) VALUES (?)"));
|
|
if (it->name == "BIT")
|
|
{
|
|
pstmt->setLong(1, std::stoull(it->value));
|
|
}
|
|
else
|
|
{
|
|
pstmt->setString(1, it->value);
|
|
}
|
|
ASSERT_EQUALS(1, pstmt->executeUpdate());
|
|
|
|
pstmt.reset(con->prepareStatement("SELECT id, dummy, NULL, -1.1234, 'Warum nicht...' FROM test"));
|
|
res.reset(pstmt->executeQuery());
|
|
meta_ps.reset(res->getMetaData());
|
|
|
|
res_st.reset(stmt->executeQuery("SELECT id, dummy, NULL, -1.1234, 'Warum nicht...' FROM test"));
|
|
meta_st.reset(res->getMetaData());
|
|
|
|
ASSERT_EQUALS(meta_ps->getColumnCount(), meta_st->getColumnCount());
|
|
|
|
for (i=1; i <= meta_ps->getColumnCount(); i++)
|
|
{
|
|
ASSERT_EQUALS(meta_ps->getCatalogName(i), meta_st->getCatalogName(i));
|
|
ASSERT_EQUALS(meta_ps->getColumnDisplaySize(i), meta_st->getColumnDisplaySize(i));
|
|
ASSERT_EQUALS(meta_ps->getColumnLabel(i), meta_st->getColumnLabel(i));
|
|
ASSERT_EQUALS(meta_ps->getColumnName(i), meta_st->getColumnName(i));
|
|
ASSERT_EQUALS(meta_ps->getColumnType(i), meta_st->getColumnType(i));
|
|
ASSERT_EQUALS(meta_ps->getColumnTypeName(i), meta_st->getColumnTypeName(i));
|
|
ASSERT_EQUALS(meta_ps->getPrecision(i), meta_st->getPrecision(i));
|
|
ASSERT_EQUALS(meta_ps->getScale(i), meta_st->getScale(i));
|
|
ASSERT_EQUALS(meta_ps->getSchemaName(i), meta_st->getSchemaName(i));
|
|
ASSERT_EQUALS(meta_ps->getTableName(i), meta_st->getTableName(i));
|
|
ASSERT_EQUALS(meta_ps->isAutoIncrement(i), meta_st->isAutoIncrement(i));
|
|
ASSERT_EQUALS(meta_ps->isCaseSensitive(i), meta_st->isCaseSensitive(i));
|
|
ASSERT_EQUALS(meta_ps->isCurrency(i), meta_st->isCurrency(i));
|
|
ASSERT_EQUALS(meta_ps->isDefinitelyWritable(i), meta_st->isDefinitelyWritable(i));
|
|
ASSERT_EQUALS(meta_ps->isNullable(i), meta_st->isNullable(i));
|
|
ASSERT_EQUALS(meta_ps->isReadOnly(i), meta_st->isReadOnly(i));
|
|
ASSERT_EQUALS(meta_ps->isSearchable(i), meta_st->isSearchable(i));
|
|
ASSERT_EQUALS(meta_ps->isSigned(i), meta_st->isSigned(i));
|
|
ASSERT_EQUALS(meta_ps->isWritable(i), meta_st->isWritable(i));
|
|
}
|
|
|
|
try
|
|
{
|
|
meta_ps->getCatalogName(0);
|
|
FAIL("Invalid argument not detected");
|
|
}
|
|
catch (sql::InvalidArgumentException&)
|
|
{
|
|
}
|
|
|
|
}
|
|
stmt->execute("DROP TABLE IF EXISTS test");
|
|
if (got_warning)
|
|
FAIL("See warnings");
|
|
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
bool preparedstatement::createSP(std::string sp_code)
|
|
{
|
|
try
|
|
{
|
|
stmt.reset(con->createStatement());
|
|
stmt->execute("DROP PROCEDURE IF EXISTS p");
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logMsg(e.what());
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
pstmt.reset(con->prepareStatement(sp_code));
|
|
ASSERT(!pstmt->execute());
|
|
logMsg("... using PS for everything");
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
if (e.getErrorCode() != 1295)
|
|
{
|
|
logErr(e.what());
|
|
std::stringstream msg;
|
|
msg.str("");
|
|
msg << "SQLState: " << e.getSQLState() << ", MySQL error code: " << e.getErrorCode();
|
|
logErr(msg.str());
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
stmt->execute(sp_code);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void preparedstatement::callSP()
|
|
{
|
|
logMsg("preparedstatement::callSP() - MySQL_PreparedStatement::*()");
|
|
std::string sp_code("CREATE PROCEDURE p(OUT ver_param VARCHAR(250)) BEGIN SELECT VERSION() INTO ver_param; END;");
|
|
try
|
|
{
|
|
if (!createSP(sp_code))
|
|
{
|
|
logMsg("... skipping:");
|
|
return;
|
|
}
|
|
|
|
DatabaseMetaData dbmeta(con->getMetaData());
|
|
try
|
|
{
|
|
pstmt.reset(con->prepareStatement("CALL p(@version)"));
|
|
ASSERT(!pstmt->execute());
|
|
ASSERT(!pstmt->execute());
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
if (e.getErrorCode() != 1295)
|
|
{
|
|
logErr(e.what());
|
|
std::stringstream msg;
|
|
msg.str("");
|
|
msg << "SQLState: " << e.getSQLState() << ", MySQL error code: " << e.getErrorCode();
|
|
logErr(msg.str());
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
// PS protocol does not support CALL
|
|
return;
|
|
}
|
|
|
|
pstmt.reset(con->prepareStatement("SELECT @version AS _version"));
|
|
res.reset(pstmt->executeQuery());
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS(dbmeta->getDatabaseProductVersion(), res->getString("_version"));
|
|
|
|
pstmt.reset(con->prepareStatement("SET @version='no_version'"));
|
|
ASSERT(!pstmt->execute());
|
|
pstmt.reset(con->prepareStatement("CALL p(@version)"));
|
|
ASSERT(!pstmt->execute());
|
|
pstmt.reset(con->prepareStatement("SELECT @version AS _version"));
|
|
res.reset(pstmt->executeQuery());
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS(dbmeta->getDatabaseProductVersion(), res->getString("_version"));
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
std::stringstream msg;
|
|
msg.str("");
|
|
msg << "SQLState: " << e.getSQLState() << ", MySQL error code: " << e.getErrorCode();
|
|
logErr(msg.str());
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
void preparedstatement::callSPInOut()
|
|
{
|
|
logMsg("preparedstatement::callSPInOut() - MySQL_PreparedStatement::*()");
|
|
std::string sp_code("CREATE PROCEDURE p(IN ver_in VARCHAR(25), OUT ver_out VARCHAR(25)) BEGIN SELECT ver_in INTO ver_out; END;");
|
|
try
|
|
{
|
|
if (!createSP(sp_code))
|
|
{
|
|
logMsg("... skipping: cannot create SP");
|
|
return;
|
|
}
|
|
try
|
|
{
|
|
cstmt.reset(con->prepareCall("CALL p('myver', @version)"));
|
|
ASSERT(!cstmt->execute());
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
if (e.getErrorCode() != 1295)
|
|
{
|
|
logErr(e.what());
|
|
std::stringstream msg1;
|
|
msg1.str("");
|
|
msg1 << "SQLState: " << e.getSQLState() << ", MySQL error code: " << e.getErrorCode();
|
|
logErr(msg1.str());
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
// PS protocol does not support CALL
|
|
logMsg("... skipping: PS protocol does not support CALL");
|
|
return;
|
|
}
|
|
pstmt.reset(con->prepareStatement("SELECT @version AS _version"));
|
|
res.reset(pstmt->executeQuery());
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS("myver", res->getString("_version"));
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
std::stringstream msg2;
|
|
msg2.str("");
|
|
msg2 << "SQLState: " << e.getSQLState() << ", MySQL error code: " << e.getErrorCode();
|
|
logErr(msg2.str());
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
void preparedstatement::callSPWithPS()
|
|
{
|
|
logMsg("preparedstatement::callSPWithPS() - MySQL_PreparedStatement::*()");
|
|
|
|
try
|
|
{
|
|
std::string sp_code("CREATE PROCEDURE p(IN val VARCHAR(25)) BEGIN SET @sql = CONCAT('SELECT \"', val, '\"'); PREPARE stmt FROM @sql; EXECUTE stmt; DROP PREPARE stmt; END;");
|
|
if (!createSP(sp_code))
|
|
{
|
|
logMsg("... skipping:");
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
cstmt.reset(con->prepareCall("CALL p('abc')"));
|
|
res.reset(cstmt->executeQuery());
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
if (e.getErrorCode() != 1295)
|
|
{
|
|
logErr(e.what());
|
|
std::stringstream msg1;
|
|
msg1.str("");
|
|
msg1 << "SQLState: " << e.getSQLState() << ", MySQL error code: " << e.getErrorCode();
|
|
logErr(msg1.str());
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
// PS interface cannot call this kind of statement
|
|
return;
|
|
}
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS("abc", res->getString(1));
|
|
std::stringstream msg2;
|
|
msg2.str("");
|
|
msg2 << "... val = '" << res->getString(1) << "'";
|
|
logMsg(msg2.str());
|
|
|
|
while(cstmt->getMoreResults())
|
|
{}
|
|
|
|
try
|
|
{
|
|
cstmt.reset(con->prepareCall("CALL p(?)"));
|
|
cstmt->setString(1, "123");
|
|
res.reset(cstmt->executeQuery());
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS("123", res->getString(1));
|
|
ASSERT(!res->next());
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
if (e.getErrorCode() != 1295)
|
|
{
|
|
logErr(e.what());
|
|
std::stringstream msg3;
|
|
msg3.str("");
|
|
msg3 << "SQLState: " << e.getSQLState() << ", MySQL error code: " << e.getErrorCode();
|
|
logErr(msg3.str());
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
// PS interface cannot call this kind of statement
|
|
return;
|
|
}
|
|
res->close();
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
if (e.getErrorCode() != 1295)
|
|
{
|
|
logErr(e.what());
|
|
std::stringstream msg4;
|
|
msg4.str("");
|
|
msg4 << "SQLState: " << e.getSQLState() << ", MySQL error code: " << e.getErrorCode();
|
|
logErr(msg4.str());
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
}
|
|
|
|
void preparedstatement::callSPMultiRes()
|
|
{
|
|
logMsg("preparedstatement::callSPMultiRes() - MySQL_PreparedStatement::*()");
|
|
try
|
|
{
|
|
std::string sp_code("CREATE PROCEDURE p() BEGIN SELECT 1; SELECT 2; SELECT 3; END;");
|
|
if (!createSP(sp_code))
|
|
{
|
|
logMsg("... skipping:");
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
pstmt.reset(con->prepareStatement("CALL p()"));
|
|
ASSERT(pstmt->execute());
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
if (e.getErrorCode() != 1295)
|
|
{
|
|
logErr(e.what());
|
|
std::stringstream msg1;
|
|
msg1.str("");
|
|
msg1 << "SQLState: " << e.getSQLState() << ", MySQL error code: " << e.getErrorCode();
|
|
logErr(msg1.str());
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
// PS interface cannot call this kind of statement
|
|
return;
|
|
}
|
|
|
|
// Should not work prior to MySQL 6.0
|
|
std::stringstream msg2;
|
|
msg2.str("");
|
|
do
|
|
{
|
|
res.reset(pstmt->getResultSet());
|
|
while (res->next())
|
|
{
|
|
msg2 << res->getString(1);
|
|
}
|
|
}
|
|
while (pstmt->getMoreResults());
|
|
|
|
ASSERT_EQUALS("123", msg2.str());
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
std::stringstream msg3;
|
|
msg3.str("");
|
|
msg3 << "SQLState: " << e.getSQLState() << ", MySQL error code: " << e.getErrorCode();
|
|
logErr(msg3.str());
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
void preparedstatement::anonymousSelect()
|
|
{
|
|
logMsg("preparedstatement::anonymousSelect() - MySQL_PreparedStatement::*, MYSQL_PS_Resultset::*");
|
|
|
|
try
|
|
{
|
|
pstmt.reset(con->prepareStatement("SELECT ' ', NULL"));
|
|
res.reset(pstmt->executeQuery());
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS(" ", res->getString(1));
|
|
|
|
std::string mynull(res->getString(2));
|
|
ASSERT(res->isNull(2));
|
|
ASSERT(res->wasNull());
|
|
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
void preparedstatement::crash()
|
|
{
|
|
logMsg("preparedstatement::crash() - MySQL_PreparedStatement::*");
|
|
|
|
try
|
|
{
|
|
stmt.reset(con->createStatement());
|
|
stmt->execute("DROP TABLE IF EXISTS test");
|
|
stmt->execute("CREATE TABLE test(dummy TIMESTAMP, id VARCHAR(1))");
|
|
pstmt.reset(con->prepareStatement("INSERT INTO test(id) VALUES (?)"));
|
|
|
|
pstmt->clearParameters();
|
|
pstmt->setDouble(1, (double) 1.23);
|
|
ASSERT_EQUALS(1, pstmt->executeUpdate());
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
|
|
}
|
|
|
|
void preparedstatement::getWarnings()
|
|
{
|
|
logMsg("preparedstatement::getWarnings() - MySQL_PreparedStatement::get|clearWarnings()");
|
|
|
|
//TODO: Enable it after fixing
|
|
SKIP("Testcase needs to be fixed");
|
|
|
|
std::stringstream msg;
|
|
|
|
stmt.reset(con->createStatement());
|
|
try
|
|
{
|
|
stmt->execute("DROP TABLE IF EXISTS test");
|
|
stmt->execute("CREATE TABLE test(id INT UNSIGNED)");
|
|
|
|
// Generating 2 warnings to make sure we get only the last 1 - won't hurt
|
|
// Lets hope that this will always cause a 1264 or similar warning
|
|
pstmt.reset(con->prepareStatement("INSERT INTO test(id) VALUES (?)"));
|
|
pstmt->setInt(1, -2);
|
|
pstmt->executeUpdate();
|
|
pstmt->setInt(1, -1);
|
|
pstmt->executeUpdate();
|
|
|
|
int count= 0;
|
|
for (const sql::SQLWarning* warn=pstmt->getWarnings(); warn; warn=warn->getNextWarning())
|
|
{
|
|
msg.str("");
|
|
msg << "... ErrorCode = '" << warn->getErrorCode() << "', ";
|
|
msg << "SQLState = '" << warn->getSQLState() << "', ";
|
|
msg << "ErrorMessage = '" << warn->getMessage() << "'";
|
|
logMsg(msg.str());
|
|
|
|
ASSERT((0 != warn->getErrorCode()));
|
|
if (1264 == warn->getErrorCode())
|
|
{
|
|
ASSERT_EQUALS("22003", warn->getSQLState());
|
|
}
|
|
else
|
|
{
|
|
ASSERT(("" != warn->getSQLState()));
|
|
}
|
|
ASSERT(("" != warn->getMessage()));
|
|
|
|
++count;
|
|
}
|
|
|
|
ASSERT_EQUALS(1, count);
|
|
|
|
for (const sql::SQLWarning* warn=pstmt->getWarnings(); warn; warn=warn->getNextWarning())
|
|
{
|
|
msg.str("");
|
|
msg << "... ErrorCode = '" << warn->getErrorCode() << "', ";
|
|
msg << "SQLState = '" << warn->getSQLState() << "', ";
|
|
msg << "ErrorMessage = '" << warn->getMessage() << "'";
|
|
logMsg(msg.str());
|
|
|
|
ASSERT((0 != warn->getErrorCode()));
|
|
if (1264 == warn->getErrorCode())
|
|
{
|
|
ASSERT_EQUALS("22003", warn->getSQLState());
|
|
}
|
|
else
|
|
{
|
|
ASSERT(("" != warn->getSQLState()));
|
|
}
|
|
ASSERT(("" != warn->getMessage()));
|
|
}
|
|
|
|
pstmt->clearWarnings();
|
|
for (const sql::SQLWarning* warn=pstmt->getWarnings(); warn; warn=warn->getNextWarning())
|
|
{
|
|
FAIL("There should be no more warnings!");
|
|
}
|
|
|
|
pstmt->setInt(1, -3);
|
|
pstmt->executeUpdate();
|
|
ASSERT(pstmt->getWarnings() != NULL);
|
|
// Statement without tables access does not reset warnings.
|
|
pstmt.reset(con->prepareStatement("SELECT 1"));
|
|
res.reset(pstmt->executeQuery());
|
|
ASSERT(pstmt->getWarnings() == NULL);
|
|
ASSERT(res->next());
|
|
|
|
// TODO - how to use getNextWarning() ?
|
|
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 preparedstatement::blob()
|
|
{
|
|
logMsg("preparedstatement::blob() - MySQL_PreparedStatement::*");
|
|
|
|
char blob_input[512];
|
|
std::stringstream blob_input_stream;
|
|
std::stringstream msg;
|
|
char blob_output[512];
|
|
int id;
|
|
int offset=0;
|
|
|
|
try
|
|
{
|
|
pstmt.reset(con->prepareStatement("DROP TABLE IF EXISTS test"));
|
|
pstmt->execute();
|
|
|
|
pstmt.reset(con->prepareStatement("CREATE TABLE test(id INT, col1 TINYBLOB, col2 TINYBLOB)"));
|
|
pstmt->execute();
|
|
|
|
// Most basic INSERT/SELECT...
|
|
pstmt.reset(con->prepareStatement("INSERT INTO test(id, col1) VALUES (?, ?)"));
|
|
|
|
for (char ascii_code=CHAR_MIN; ascii_code < CHAR_MAX; ascii_code++)
|
|
{
|
|
blob_output[offset]='\0';
|
|
blob_input[offset++]=ascii_code;
|
|
}
|
|
blob_input[offset]='\0';
|
|
blob_output[offset]='\0';
|
|
for (char ascii_code=CHAR_MAX; ascii_code > CHAR_MIN; ascii_code--)
|
|
{
|
|
blob_output[offset]='\0';
|
|
blob_input[offset++]=ascii_code;
|
|
}
|
|
blob_input[offset]='\0';
|
|
blob_output[offset]='\0';
|
|
|
|
id=1;
|
|
blob_input_stream << blob_input;
|
|
|
|
pstmt->setInt(1, id);
|
|
pstmt->setBlob(2, &blob_input_stream);
|
|
try
|
|
{
|
|
pstmt->setBlob(3, &blob_input_stream);
|
|
FAIL("Invalid index not detected");
|
|
}
|
|
catch (sql::SQLException&)
|
|
{
|
|
}
|
|
|
|
pstmt->execute();
|
|
pstmt.reset(con->prepareStatement("SELECT id, col1 FROM test WHERE id = 1"));
|
|
res.reset(pstmt->executeQuery());
|
|
|
|
ASSERT(res->next());
|
|
|
|
msg.str("");
|
|
msg << "... simple INSERT/SELECT, '" << std::endl << blob_input << std::endl << "' =? '" << std::endl << res->getString(2) << "'";
|
|
logMsg(msg.str());
|
|
|
|
ASSERT_EQUALS(res->getInt(1), id);
|
|
ASSERT_EQUALS(res->getString(2), blob_input_stream.str());
|
|
ASSERT_EQUALS(res->getString(2), blob_input);
|
|
ASSERT_EQUALS(res->getString("col1"), blob_input_stream.str());
|
|
ASSERT_EQUALS(res->getString("col1"), blob_input);
|
|
|
|
std::unique_ptr< std::istream > blob_output_stream(res->getBlob(2));
|
|
blob_output_stream->seekg(std::ios::beg);
|
|
blob_output_stream->get(blob_output, offset + 1);
|
|
ASSERT_EQUALS(blob_input_stream.str(), blob_output);
|
|
|
|
blob_output_stream.reset(res->getBlob("col1"));
|
|
blob_output_stream->seekg(std::ios::beg);
|
|
blob_output_stream->get(blob_output, offset + 1);
|
|
ASSERT_EQUALS(blob_input, blob_output);
|
|
|
|
msg.str("");
|
|
msg << "... second check, '"<< std::endl << blob_input << std::endl << "' =? '" << std::endl << blob_output << "'";
|
|
logMsg(msg.str());
|
|
|
|
ASSERT(!res->next());
|
|
res->close();
|
|
|
|
msg.str("");
|
|
// Data is too long to be stored in a TINYBLOB column
|
|
msg << "... this is more than TINYBLOB can hold: ";
|
|
msg << "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
|
|
pstmt.reset(con->prepareStatement("INSERT INTO test(id, col1) VALUES (?, ?)"));
|
|
id=2;
|
|
pstmt->setInt(1, id);
|
|
pstmt->setBlob(2, &msg);
|
|
try {
|
|
pstmt->execute();
|
|
pstmt.reset(con->prepareStatement("SELECT id, col1 FROM test WHERE id = 2"));
|
|
res.reset(pstmt->executeQuery());
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS(res->getInt(1), id);
|
|
ASSERT_GT((int)(res->getString(2).length()), (int)(msg.str().length()));
|
|
ASSERT(!res->next());
|
|
res->close();
|
|
|
|
msg << "- what has happened to the stream?";
|
|
logMsg(msg.str());
|
|
}
|
|
catch (sql::SQLException & e) {
|
|
// If the server is in the strict mode, inserting too long data causes error
|
|
if (e.getErrorCode() == 1406 && e.getSQLState().compare("22001") == 0) {
|
|
logMsg("The server is in the strict mode - couldn't insert too long stream");
|
|
}
|
|
else {
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
pstmt.reset(con->prepareStatement("DROP TABLE IF EXISTS test"));
|
|
pstmt->execute();
|
|
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
logErr("SQLState: " + std::string(e.getSQLState()));
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
|
|
}
|
|
|
|
void preparedstatement::executeQuery()
|
|
{
|
|
logMsg("preparedstatement::executeQuery() - MySQL_PreparedStatement::executeQuery");
|
|
try
|
|
{
|
|
const sql::SQLString option("defaultPreparedStatementResultType");
|
|
int value=sql::ResultSet::TYPE_FORWARD_ONLY;
|
|
con->setClientOption(option, static_cast<void *> (&value));
|
|
}
|
|
catch (sql::MethodNotImplementedException &/*e*/)
|
|
{
|
|
/* not available */
|
|
return;
|
|
}
|
|
try
|
|
{
|
|
|
|
stmt.reset(con->createStatement());
|
|
stmt->execute("DROP TABLE IF EXISTS test");
|
|
stmt->execute("CREATE TABLE test(id INT UNSIGNED)");
|
|
stmt->execute("INSERT INTO test(id) VALUES (1), (2), (3)");
|
|
|
|
pstmt.reset(con->prepareStatement("SELECT id FROM test ORDER BY id ASC"));
|
|
res.reset(pstmt->executeQuery());
|
|
ASSERT(res->next());
|
|
ASSERT_EQUALS(res->getInt("id"), 1);
|
|
|
|
pstmt.reset(con->prepareStatement("DROP TABLE IF EXISTS test"));
|
|
pstmt->execute();
|
|
}
|
|
catch (sql::SQLException &e)
|
|
{
|
|
logErr(e.what());
|
|
std::stringstream msg;
|
|
msg.str("");
|
|
msg << "SQLState: " << e.getSQLState() << ", MySQL error code: " << e.getErrorCode();
|
|
logErr(msg.str());
|
|
fail(e.what(), __FILE__, __LINE__);
|
|
}
|
|
}
|
|
|
|
} /* namespace preparedstatement */
|
|
} /* namespace testsuite */
|