mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2025-01-31 18:07:14 +01:00
4a6bfc086c
Switched to POCO library for unified platform/library interface. Deprecated the external module API. It was creating more problems than solving. Removed most built-in libraries in favor of system libraries for easier maintenance. Cleaned and secured code with help from static analyzers.
4013 lines
131 KiB
C++
4013 lines
131 KiB
C++
//
|
|
// SQLExecutor.cpp
|
|
//
|
|
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
|
// and Contributors.
|
|
//
|
|
// SPDX-License-Identifier: BSL-1.0
|
|
//
|
|
|
|
|
|
#include "CppUnit/TestCase.h"
|
|
#include "SQLExecutor.h"
|
|
#include "Poco/String.h"
|
|
#include "Poco/Format.h"
|
|
#include "Poco/Tuple.h"
|
|
#include "Poco/Nullable.h"
|
|
#include "Poco/Any.h"
|
|
#include "Poco/Dynamic/Var.h"
|
|
#include "Poco/DateTime.h"
|
|
#include "Poco/Stopwatch.h"
|
|
#include "Poco/NumberFormatter.h"
|
|
#include "Poco/Thread.h"
|
|
#include "Poco/Logger.h"
|
|
#include "Poco/Message.h"
|
|
#include "Poco/RefCountedObject.h"
|
|
#include "Poco/AutoPtr.h"
|
|
#include "Poco/SharedPtr.h"
|
|
#include "Poco/Exception.h"
|
|
#include "Poco/Data/Date.h"
|
|
#include "Poco/Data/Time.h"
|
|
#include "Poco/Data/LOB.h"
|
|
#include "Poco/Data/StatementImpl.h"
|
|
#include "Poco/Data/RecordSet.h"
|
|
#include "Poco/Data/RowIterator.h"
|
|
#include "Poco/Data/RowFilter.h"
|
|
#include "Poco/Data/BulkExtraction.h"
|
|
#include "Poco/Data/BulkBinding.h"
|
|
#include "Poco/Data/SQLChannel.h"
|
|
#include "Poco/Data/Transaction.h"
|
|
#include "Poco/Data/ODBC/Connector.h"
|
|
#include "Poco/Data/ODBC/Utility.h"
|
|
#include "Poco/Data/ODBC/Diagnostics.h"
|
|
#include "Poco/Data/ODBC/Error.h"
|
|
#include "Poco/Data/ODBC/Preparator.h"
|
|
#include "Poco/Data/ODBC/ODBCException.h"
|
|
#include "Poco/Data/ODBC/ODBCStatementImpl.h"
|
|
#include "Poco/UnicodeConverter.h"
|
|
#include "Poco/UTFString.h"
|
|
#include <sqltypes.h>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <iterator>
|
|
|
|
|
|
using namespace Poco::Data::Keywords;
|
|
using Poco::Data::Session;
|
|
using Poco::Data::Statement;
|
|
using Poco::Data::RecordSet;
|
|
using Poco::Data::Column;
|
|
using Poco::Data::Row;
|
|
using Poco::Data::RowFilter;
|
|
using Poco::Data::RowIterator;
|
|
using Poco::Data::SQLChannel;
|
|
using Poco::Data::LimitException;
|
|
using Poco::Data::BindingException;
|
|
using Poco::Data::CLOB;
|
|
using Poco::Data::Date;
|
|
using Poco::Data::Time;
|
|
using Poco::Data::Transaction;
|
|
using Poco::Data::NotConnectedException;
|
|
using Poco::Data::ODBC::Utility;
|
|
using Poco::Data::ODBC::Preparator;
|
|
using Poco::Data::ODBC::ConnectionException;
|
|
using Poco::Data::ODBC::StatementException;
|
|
using Poco::Data::ODBC::DataTruncatedException;
|
|
using Poco::Data::ODBC::StatementError;
|
|
using Poco::format;
|
|
using Poco::Tuple;
|
|
using Poco::Nullable;
|
|
using Poco::Any;
|
|
using Poco::AnyCast;
|
|
using Poco::Dynamic::Var;
|
|
using Poco::DateTime;
|
|
using Poco::Stopwatch;
|
|
using Poco::NumberFormatter;
|
|
using Poco::AutoPtr;
|
|
using Poco::Thread;
|
|
using Poco::Logger;
|
|
using Poco::Message;
|
|
using Poco::NotFoundException;
|
|
using Poco::InvalidAccessException;
|
|
using Poco::InvalidArgumentException;
|
|
using Poco::NotImplementedException;
|
|
using Poco::BadCastException;
|
|
using Poco::RangeException;
|
|
using Poco::TimeoutException;
|
|
using Poco::UnicodeConverter;
|
|
using Poco::UTF16String;
|
|
using Poco::UTF32String;
|
|
|
|
struct Person
|
|
{
|
|
std::string lastName;
|
|
std::string firstName;
|
|
std::string address;
|
|
int age;
|
|
Person(){age = 0;}
|
|
Person(const std::string& ln, const std::string& fn, const std::string& adr, int a):lastName(ln), firstName(fn), address(adr), age(a)
|
|
{
|
|
}
|
|
bool operator==(const Person& other) const
|
|
{
|
|
return lastName == other.lastName && firstName == other.firstName && address == other.address && age == other.age;
|
|
}
|
|
|
|
bool operator < (const Person& p) const
|
|
{
|
|
if (age < p.age)
|
|
return true;
|
|
if (lastName < p.lastName)
|
|
return true;
|
|
if (firstName < p.firstName)
|
|
return true;
|
|
return (address < p.address);
|
|
}
|
|
|
|
const std::string& operator () () const
|
|
/// This method is required so we can extract data to a map!
|
|
{
|
|
// we choose the lastName as the key
|
|
return lastName;
|
|
}
|
|
};
|
|
|
|
|
|
struct RefCountedPerson : public Poco::RefCountedObject
|
|
{
|
|
std::string lastName;
|
|
std::string firstName;
|
|
std::string address;
|
|
int age;
|
|
RefCountedPerson(){age = 0;}
|
|
RefCountedPerson(const std::string& ln, const std::string& fn, const std::string& adr, int a):lastName(ln), firstName(fn), address(adr), age(a)
|
|
{
|
|
}
|
|
bool operator==(const Person& other) const
|
|
{
|
|
return lastName == other.lastName && firstName == other.firstName && address == other.address && age == other.age;
|
|
}
|
|
|
|
bool operator < (const RefCountedPerson& p) const
|
|
{
|
|
if (age < p.age)
|
|
return true;
|
|
if (lastName < p.lastName)
|
|
return true;
|
|
if (firstName < p.firstName)
|
|
return true;
|
|
return (address < p.address);
|
|
}
|
|
|
|
const std::string& operator () () const
|
|
/// This method is required so we can extract data to a map!
|
|
{
|
|
// we choose the lastName as the key
|
|
return lastName;
|
|
}
|
|
|
|
private:
|
|
RefCountedPerson(const RefCountedPerson &);
|
|
RefCountedPerson& operator = (const RefCountedPerson&);
|
|
};
|
|
|
|
|
|
namespace Poco {
|
|
namespace Data {
|
|
|
|
|
|
template <>
|
|
class TypeHandler<Person>
|
|
{
|
|
public:
|
|
static void bind(std::size_t pos,
|
|
const Person& obj,
|
|
AbstractBinder::Ptr pBinder,
|
|
AbstractBinder::Direction dir = AbstractBinder::PD_IN)
|
|
{
|
|
// the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))
|
|
poco_assert_dbg (!pBinder.isNull());
|
|
pBinder->bind(pos++, obj.lastName, dir);
|
|
pBinder->bind(pos++, obj.firstName, dir);
|
|
pBinder->bind(pos++, obj.address, dir);
|
|
pBinder->bind(pos++, obj.age, dir);
|
|
}
|
|
|
|
static void prepare(std::size_t pos, const Person& obj, AbstractPreparator::Ptr pPrepare)
|
|
{
|
|
// the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))
|
|
poco_assert_dbg (!pPrepare.isNull());
|
|
pPrepare->prepare(pos++, obj.lastName);
|
|
pPrepare->prepare(pos++, obj.firstName);
|
|
pPrepare->prepare(pos++, obj.address);
|
|
pPrepare->prepare(pos++, obj.age);
|
|
}
|
|
|
|
static std::size_t size()
|
|
{
|
|
return 4;
|
|
}
|
|
|
|
static void extract(std::size_t pos, Person& obj, const Person& defVal, AbstractExtractor::Ptr pExt)
|
|
{
|
|
poco_assert_dbg (!pExt.isNull());
|
|
if (!pExt->extract(pos++, obj.lastName))
|
|
obj.lastName = defVal.lastName;
|
|
if (!pExt->extract(pos++, obj.firstName))
|
|
obj.firstName = defVal.firstName;
|
|
if (!pExt->extract(pos++, obj.address))
|
|
obj.address = defVal.address;
|
|
if (!pExt->extract(pos++, obj.age))
|
|
obj.age = defVal.age;
|
|
}
|
|
|
|
private:
|
|
TypeHandler(const TypeHandler&);
|
|
TypeHandler& operator=(const TypeHandler&);
|
|
};
|
|
|
|
|
|
template <>
|
|
class TypeHandler<RefCountedPerson>
|
|
{
|
|
public:
|
|
static void bind(std::size_t pos,
|
|
const RefCountedPerson& obj,
|
|
AbstractBinder::Ptr pBinder,
|
|
AbstractBinder::Direction dir = AbstractBinder::PD_IN)
|
|
{
|
|
// the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))
|
|
poco_assert_dbg (!pBinder.isNull());
|
|
pBinder->bind(pos++, obj.lastName, dir);
|
|
pBinder->bind(pos++, obj.firstName, dir);
|
|
pBinder->bind(pos++, obj.address, dir);
|
|
pBinder->bind(pos++, obj.age, dir);
|
|
}
|
|
|
|
static void prepare(std::size_t pos, RefCountedPerson& obj, AbstractPreparator::Ptr pPrepare)
|
|
{
|
|
// the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))
|
|
poco_assert_dbg (!pPrepare.isNull());
|
|
pPrepare->prepare(pos++, obj.lastName);
|
|
pPrepare->prepare(pos++, obj.firstName);
|
|
pPrepare->prepare(pos++, obj.address);
|
|
pPrepare->prepare(pos++, obj.age);
|
|
}
|
|
|
|
static std::size_t size()
|
|
{
|
|
return 4;
|
|
}
|
|
|
|
static void extract(std::size_t pos, RefCountedPerson& obj, const RefCountedPerson& defVal, AbstractExtractor::Ptr pExt)
|
|
{
|
|
poco_assert_dbg (!pExt.isNull());
|
|
if (!pExt->extract(pos++, obj.lastName))
|
|
obj.lastName = defVal.lastName;
|
|
if (!pExt->extract(pos++, obj.firstName))
|
|
obj.firstName = defVal.firstName;
|
|
if (!pExt->extract(pos++, obj.address))
|
|
obj.address = defVal.address;
|
|
if (!pExt->extract(pos++, obj.age))
|
|
obj.age = defVal.age;
|
|
}
|
|
|
|
private:
|
|
TypeHandler(const TypeHandler&);
|
|
TypeHandler& operator=(const TypeHandler&);
|
|
};
|
|
|
|
|
|
} } // namespace Poco::Data
|
|
|
|
|
|
const std::string SQLExecutor::MULTI_INSERT =
|
|
"INSERT INTO Test VALUES ('1', 2, 3.5);"
|
|
"INSERT INTO Test VALUES ('2', 3, 4.5);"
|
|
"INSERT INTO Test VALUES ('3', 4, 5.5);"
|
|
"INSERT INTO Test VALUES ('4', 5, 6.5);"
|
|
"INSERT INTO Test VALUES ('5', 6, 7.5);";
|
|
|
|
const std::string SQLExecutor::MULTI_SELECT =
|
|
"SELECT * FROM Test WHERE First = '1';"
|
|
"SELECT * FROM Test WHERE First = '2';"
|
|
"SELECT * FROM Test WHERE First = '3';"
|
|
"SELECT * FROM Test WHERE First = '4';"
|
|
"SELECT * FROM Test WHERE First = '5';";
|
|
|
|
|
|
SQLExecutor::SQLExecutor(const std::string& name, Poco::Data::Session* pSession):
|
|
CppUnit::TestCase(name),
|
|
_pSession(pSession)
|
|
{
|
|
}
|
|
|
|
|
|
SQLExecutor::~SQLExecutor()
|
|
{
|
|
}
|
|
|
|
|
|
void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
|
|
const std::string& tableCreateString,
|
|
SQLExecutor::DataBinding bindMode,
|
|
SQLExecutor::DataExtraction extractMode,
|
|
bool doTime,
|
|
const std::string& blobPlaceholder)
|
|
{
|
|
SQLRETURN rc;
|
|
SQLHENV henv = SQL_NULL_HENV;
|
|
SQLHDBC hdbc = SQL_NULL_HDBC;
|
|
SQLHSTMT hstmt = SQL_NULL_HSTMT;
|
|
|
|
// Environment begin
|
|
rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
|
|
poco_odbc_check_env (rc, henv);
|
|
rc = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, 0);
|
|
poco_odbc_check_env (rc, henv);
|
|
|
|
// Connection begin
|
|
rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
|
|
poco_odbc_check_dbc (rc, hdbc);
|
|
|
|
SQLCHAR connectOutput[1024] = {0};
|
|
SQLSMALLINT result;
|
|
rc = SQLDriverConnect(hdbc
|
|
, NULL
|
|
,(SQLCHAR*) dbConnString.c_str()
|
|
,(SQLSMALLINT) SQL_NTS
|
|
, connectOutput
|
|
, sizeof(connectOutput)
|
|
, &result
|
|
, SQL_DRIVER_NOPROMPT);
|
|
poco_odbc_check_dbc (rc, hdbc);
|
|
|
|
// retrieve datetime type information for this DBMS
|
|
rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
rc = SQLGetTypeInfo(hstmt, SQL_TYPE_TIMESTAMP);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
rc = SQLFetch(hstmt);
|
|
assertTrue (SQL_SUCCEEDED(rc) || SQL_NO_DATA == rc);
|
|
|
|
SQLULEN dateTimeColSize = 0;
|
|
SQLSMALLINT dateTimeDecDigits = 0;
|
|
if (SQL_SUCCEEDED(rc))
|
|
{
|
|
SQLLEN ind = 0;
|
|
rc = SQLGetData(hstmt, 3, SQL_C_SLONG, &dateTimeColSize, sizeof(SQLINTEGER), &ind);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
rc = SQLGetData(hstmt, 14, SQL_C_SSHORT, &dateTimeDecDigits, sizeof(SQLSMALLINT), &ind);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
assertTrue (sizeof(SQL_TIMESTAMP_STRUCT) <= dateTimeColSize);
|
|
}
|
|
else if (SQL_NO_DATA == rc)
|
|
std::cerr << '[' << name() << ']' << " Warning: no SQL_TYPE_TIMESTAMP data type info returned by driver." << std::endl;
|
|
|
|
rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
// Statement begin
|
|
rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
std::string sql = "DROP TABLE Test";
|
|
SQLCHAR* pStr = (SQLCHAR*) sql.c_str();
|
|
SQLExecDirect(hstmt, pStr, (SQLINTEGER) sql.length());
|
|
//no return code check - ignore drop errors
|
|
|
|
// create table and go
|
|
sql = tableCreateString;
|
|
pStr = (SQLCHAR*) sql.c_str();
|
|
rc = SQLPrepare(hstmt, pStr, (SQLINTEGER) sql.length());
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
rc = SQLExecute(hstmt);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
sql = format("INSERT INTO Test VALUES (?,?,%s,?,?,?)", blobPlaceholder);
|
|
pStr = (SQLCHAR*) sql.c_str();
|
|
rc = SQLPrepare(hstmt, pStr, (SQLINTEGER) sql.length());
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
std::string str[3] = { "11111111111", "222222222222222222222222", "333333333333333333333333333" };
|
|
int fourth = 4;
|
|
float fifth = 1.5;
|
|
SQL_TIMESTAMP_STRUCT sixth;
|
|
sixth.year = 1965;
|
|
sixth.month = 6;
|
|
sixth.day = 18;
|
|
sixth.hour = 5;
|
|
sixth.minute = 34;
|
|
sixth.second = 58;
|
|
// Fraction support is limited to milliseconds due to MS SQL Server limitation
|
|
// see http://support.microsoft.com/kb/263872
|
|
sixth.fraction = 997000000;
|
|
|
|
SQLLEN li[3] = { SQL_NTS, SQL_NTS, 0 };
|
|
SQLINTEGER size = (SQLINTEGER) str[0].size();
|
|
|
|
if (SQLExecutor::PB_AT_EXEC == bindMode)
|
|
li[0] = SQL_LEN_DATA_AT_EXEC(size);
|
|
|
|
rc = SQLBindParameter(hstmt,
|
|
(SQLUSMALLINT) 1,
|
|
SQL_PARAM_INPUT,
|
|
SQL_C_CHAR,
|
|
SQL_LONGVARCHAR,
|
|
(SQLUINTEGER) size,
|
|
0,
|
|
(SQLPOINTER) str[0].c_str(),
|
|
size,
|
|
&li[0]);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
size = (SQLINTEGER) str[1].size();
|
|
if (SQLExecutor::PB_AT_EXEC == bindMode)
|
|
li[1] = SQL_LEN_DATA_AT_EXEC(size);
|
|
else li[1] = SQL_NTS;
|
|
|
|
rc = SQLBindParameter(hstmt,
|
|
(SQLUSMALLINT) 2,
|
|
SQL_PARAM_INPUT,
|
|
SQL_C_CHAR,
|
|
SQL_LONGVARCHAR,
|
|
(SQLUINTEGER) size,
|
|
0,
|
|
(SQLPOINTER) str[1].c_str(),
|
|
size,
|
|
&li[1]);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
size = (SQLINTEGER) str[2].size();
|
|
if (SQLExecutor::PB_AT_EXEC == bindMode)
|
|
li[2] = SQL_LEN_DATA_AT_EXEC(size);
|
|
else li[2] = size;
|
|
|
|
rc = SQLBindParameter(hstmt,
|
|
(SQLUSMALLINT) 3,
|
|
SQL_PARAM_INPUT,
|
|
SQL_C_BINARY,
|
|
SQL_LONGVARBINARY,
|
|
(SQLUINTEGER) size,
|
|
0,
|
|
(SQLPOINTER) str[2].data(),
|
|
size,
|
|
&li[2]);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
rc = SQLBindParameter(hstmt,
|
|
(SQLUSMALLINT) 4,
|
|
SQL_PARAM_INPUT,
|
|
SQL_C_SLONG,
|
|
SQL_INTEGER,
|
|
0,
|
|
0,
|
|
(SQLPOINTER) &fourth,
|
|
0,
|
|
0);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
rc = SQLBindParameter(hstmt,
|
|
(SQLUSMALLINT) 5,
|
|
SQL_PARAM_INPUT,
|
|
SQL_C_FLOAT,
|
|
SQL_REAL,
|
|
0,
|
|
1,
|
|
(SQLPOINTER) &fifth,
|
|
0,
|
|
0);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
SQLSMALLINT dataType = 0;
|
|
SQLULEN parameterSize = 0;
|
|
SQLSMALLINT decimalDigits = 0;
|
|
SQLSMALLINT nullable = 0;
|
|
rc = SQLDescribeParam(hstmt, 6, &dataType, ¶meterSize, &decimalDigits, &nullable);
|
|
if (SQL_SUCCEEDED(rc))
|
|
{
|
|
if (parameterSize)
|
|
dateTimeColSize = parameterSize;
|
|
if (decimalDigits)
|
|
dateTimeDecDigits = decimalDigits;
|
|
}
|
|
else
|
|
std::cerr << '[' << name() << ']' << " Warning: could not get SQL_TYPE_TIMESTAMP parameter description." << std::endl;
|
|
|
|
rc = SQLBindParameter(hstmt,
|
|
(SQLUSMALLINT) 6,
|
|
SQL_PARAM_INPUT,
|
|
SQL_C_TYPE_TIMESTAMP,
|
|
SQL_TYPE_TIMESTAMP,
|
|
dateTimeColSize,
|
|
dateTimeDecDigits,
|
|
(SQLPOINTER) &sixth,
|
|
0,
|
|
0);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
rc = SQLExecute(hstmt);
|
|
assertTrue (SQL_NEED_DATA == rc || SQL_SUCCEEDED(rc));
|
|
|
|
if (SQL_NEED_DATA == rc)
|
|
{
|
|
SQLPOINTER pParam = 0;
|
|
while (SQL_NEED_DATA == (rc = SQLParamData(hstmt, &pParam)))
|
|
{
|
|
SQLINTEGER dataSize = 0;
|
|
// Data size should be ignored for non-null,
|
|
// non-variable length fields, but SQLite ODBC
|
|
// driver insists on it always being the actual
|
|
// data length
|
|
|
|
if (pParam == (SQLPOINTER) str[0].c_str())
|
|
dataSize = (SQLINTEGER) str[0].size();
|
|
else if (pParam == (SQLPOINTER) str[1].c_str())
|
|
dataSize = (SQLINTEGER) str[1].size();
|
|
else if (pParam == (SQLPOINTER) str[2].c_str())
|
|
dataSize = (SQLINTEGER) str[2].size();
|
|
else if (pParam == (SQLPOINTER) &fourth)
|
|
dataSize = (SQLINTEGER) sizeof(fourth);
|
|
else if (pParam == (SQLPOINTER) &fifth)
|
|
dataSize = (SQLINTEGER) sizeof(fifth);
|
|
else if (pParam == (SQLPOINTER) &sixth)
|
|
dataSize = (SQLINTEGER) sizeof(sixth);
|
|
|
|
assertTrue (0 != dataSize);
|
|
rc = SQLPutData(hstmt, pParam, dataSize);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
}
|
|
}
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
sql = "SELECT * FROM Test";
|
|
pStr = (SQLCHAR*) sql.c_str();
|
|
rc = SQLPrepare(hstmt, pStr, (SQLINTEGER) sql.length());
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
char chr[3][50] = {{ 0 }};
|
|
SQLLEN lengths[6] = { 0 };
|
|
fourth = 0;
|
|
fifth = 0.0f;
|
|
std::memset(&sixth, 0, sizeof(sixth));
|
|
|
|
if (SQLExecutor::DE_BOUND == extractMode)
|
|
{
|
|
rc = SQLBindCol(hstmt,
|
|
(SQLUSMALLINT) 1,
|
|
SQL_C_CHAR,
|
|
(SQLPOINTER) chr[0],
|
|
(SQLINTEGER) sizeof(chr[0]),
|
|
&lengths[0]);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
rc = SQLBindCol(hstmt,
|
|
(SQLUSMALLINT) 2,
|
|
SQL_C_CHAR,
|
|
(SQLPOINTER) chr[1],
|
|
(SQLINTEGER) sizeof(chr[1]),
|
|
&lengths[1]);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
rc = SQLBindCol(hstmt,
|
|
(SQLUSMALLINT) 3,
|
|
SQL_C_BINARY,
|
|
(SQLPOINTER) chr[2],
|
|
(SQLINTEGER) sizeof(chr[2]),
|
|
&lengths[2]);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
rc = SQLBindCol(hstmt,
|
|
(SQLUSMALLINT) 4,
|
|
SQL_C_SLONG,
|
|
(SQLPOINTER) &fourth,
|
|
(SQLINTEGER) 0,
|
|
&lengths[3]);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
rc = SQLBindCol(hstmt,
|
|
(SQLUSMALLINT) 5,
|
|
SQL_C_FLOAT,
|
|
(SQLPOINTER) &fifth,
|
|
(SQLINTEGER) 0,
|
|
&lengths[4]);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
rc = SQLBindCol(hstmt,
|
|
(SQLUSMALLINT) 6,
|
|
SQL_C_TYPE_TIMESTAMP,
|
|
(SQLPOINTER) &sixth,
|
|
(SQLINTEGER) 0,
|
|
&lengths[5]);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
}
|
|
|
|
rc = SQLExecute(hstmt);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
rc = SQLFetch(hstmt);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
if (SQLExecutor::DE_MANUAL == extractMode)
|
|
{
|
|
SQLLEN len = lengths[0] = 0;
|
|
while (SQL_SUCCESS_WITH_INFO == (rc = SQLGetData(hstmt,
|
|
(SQLUSMALLINT) 1,
|
|
SQL_C_CHAR,
|
|
chr[0] + len,
|
|
sizeof(chr[0]) - len,
|
|
&lengths[0])))
|
|
{
|
|
len += lengths[0];
|
|
if (!lengths[0] || len >= sizeof(chr[1]))
|
|
break;
|
|
}
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
len = lengths[1] = 0;
|
|
while (SQL_SUCCESS_WITH_INFO == (rc = SQLGetData(hstmt,
|
|
(SQLUSMALLINT) 2,
|
|
SQL_C_CHAR,
|
|
chr[1] + len,
|
|
sizeof(chr[1]) - len,
|
|
&lengths[1])))
|
|
{
|
|
len += lengths[1];
|
|
if (!lengths[1] || len >= sizeof(chr[1]))
|
|
break;
|
|
}
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
len = lengths[2] = 0;
|
|
while (SQL_SUCCESS_WITH_INFO == (rc = SQLGetData(hstmt,
|
|
(SQLUSMALLINT) 3,
|
|
SQL_C_BINARY,
|
|
chr[2] + len,
|
|
sizeof(chr[2]) - len,
|
|
&lengths[2])))
|
|
{
|
|
len += lengths[1];
|
|
if (!lengths[2] || len >= sizeof(chr[2]))
|
|
break;
|
|
}
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
rc = SQLGetData(hstmt,
|
|
(SQLUSMALLINT) 4,
|
|
SQL_C_SLONG,
|
|
&fourth,
|
|
0,
|
|
&lengths[3]);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
rc = SQLGetData(hstmt,
|
|
(SQLUSMALLINT) 5,
|
|
SQL_C_FLOAT,
|
|
&fifth,
|
|
0,
|
|
&lengths[4]);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
rc = SQLGetData(hstmt,
|
|
(SQLUSMALLINT) 6,
|
|
SQL_C_TYPE_TIMESTAMP,
|
|
&sixth,
|
|
0,
|
|
&lengths[5]);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
}
|
|
|
|
assertTrue (0 == std::strncmp(str[0].c_str(), chr[0], str[0].size()));
|
|
assertTrue (0 == std::strncmp(str[1].c_str(), chr[1], str[1].size()));
|
|
assertTrue (0 == std::strncmp(str[2].c_str(), chr[2], str[2].size()));
|
|
assertTrue (4 == fourth);
|
|
assertTrue (1.5 == fifth);
|
|
|
|
assertTrue (1965 == sixth.year);
|
|
assertTrue (6 == sixth.month);
|
|
assertTrue (18 == sixth.day);
|
|
if (doTime)
|
|
{
|
|
assertTrue (5 == sixth.hour);
|
|
assertTrue (34 == sixth.minute);
|
|
if (sixth.fraction) // MySQL rounds fraction
|
|
{
|
|
assertTrue (58 == sixth.second);
|
|
assertTrue (997000000 == sixth.fraction);
|
|
}
|
|
else
|
|
{
|
|
assertTrue (59 == sixth.second);
|
|
}
|
|
}
|
|
|
|
rc = SQLCloseCursor(hstmt);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
sql = "DROP TABLE Test";
|
|
pStr = (SQLCHAR*) sql.c_str();
|
|
rc = SQLExecDirect(hstmt, pStr, (SQLINTEGER) sql.length());
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
// Connection end
|
|
rc = SQLDisconnect(hdbc);
|
|
poco_odbc_check_dbc (rc, hdbc);
|
|
rc = SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
|
|
poco_odbc_check_dbc (rc, hdbc);
|
|
|
|
// Environment end
|
|
rc = SQLFreeHandle(SQL_HANDLE_ENV, henv);
|
|
poco_odbc_check_env (rc, henv);
|
|
}
|
|
|
|
|
|
void SQLExecutor::bareboneODBCMultiResultTest(const std::string& dbConnString,
|
|
const std::string& tableCreateString,
|
|
SQLExecutor::DataBinding bindMode,
|
|
SQLExecutor::DataExtraction extractMode,
|
|
const std::string& insert,
|
|
const std::string& select)
|
|
{
|
|
SQLRETURN rc;
|
|
SQLHENV henv = SQL_NULL_HENV;
|
|
SQLHDBC hdbc = SQL_NULL_HDBC;
|
|
SQLHSTMT hstmt = SQL_NULL_HSTMT;
|
|
|
|
// Environment begin
|
|
rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
rc = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, 0);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
// Connection begin
|
|
rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
SQLCHAR connectOutput[512] = {0};
|
|
SQLSMALLINT result;
|
|
rc = SQLDriverConnect(hdbc
|
|
, NULL
|
|
,(SQLCHAR*) dbConnString.c_str()
|
|
,(SQLSMALLINT) SQL_NTS
|
|
, connectOutput
|
|
, sizeof(connectOutput)
|
|
, &result
|
|
, SQL_DRIVER_NOPROMPT);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
// Statement begin
|
|
rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
std::string sql = "DROP TABLE Test";
|
|
SQLCHAR* pStr = (SQLCHAR*) sql.c_str();
|
|
SQLExecDirect(hstmt, pStr, (SQLINTEGER) sql.length());
|
|
//no return code check - ignore drop errors
|
|
|
|
// create table and go
|
|
sql = tableCreateString;
|
|
pStr = (SQLCHAR*) sql.c_str();
|
|
rc = SQLPrepare(hstmt, pStr, (SQLINTEGER) sql.length());
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
rc = SQLExecute(hstmt);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
// insert multiple rows
|
|
pStr = (SQLCHAR*) insert.c_str();
|
|
rc = SQLPrepare(hstmt, pStr, (SQLINTEGER) insert.length());
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
rc = SQLExecute(hstmt);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
do
|
|
{
|
|
SQLLEN rowCount = 0;
|
|
SQLRowCount(hstmt, &rowCount);
|
|
assertTrue (1 == rowCount);
|
|
} while (SQL_NO_DATA != SQLMoreResults(hstmt));
|
|
|
|
// make sure all five rows made it in
|
|
sql = "select count(*) from Test";
|
|
int count = 0;
|
|
SQLLEN length = 0;
|
|
pStr = (SQLCHAR*) sql.c_str();
|
|
rc = SQLPrepare(hstmt, pStr, (SQLINTEGER) sql.length());
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
if (SQLExecutor::DE_BOUND == extractMode)
|
|
{
|
|
rc = SQLBindCol(hstmt,
|
|
(SQLUSMALLINT) 1,
|
|
SQL_C_SLONG,
|
|
(SQLPOINTER) &count,
|
|
(SQLINTEGER) 0,
|
|
&length);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
}
|
|
|
|
rc = SQLExecute(hstmt);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
rc = SQLFetch(hstmt);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
if (SQLExecutor::DE_MANUAL == extractMode)
|
|
{
|
|
rc = SQLGetData(hstmt,
|
|
(SQLUSMALLINT) 1,
|
|
SQL_C_SLONG,
|
|
&count,
|
|
0,
|
|
&length);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
}
|
|
assertTrue (5 == count);
|
|
|
|
rc = SQLCloseCursor(hstmt);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
// select multiple rows
|
|
pStr = (SQLCHAR*) select.c_str();
|
|
rc = SQLPrepare(hstmt, pStr, (SQLINTEGER) select.length());
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
char chr[5] = { 0 };
|
|
SQLLEN lengths[3] = { 0 };
|
|
int second = 0;
|
|
float third = 0.0f;
|
|
|
|
if (SQLExecutor::DE_BOUND == extractMode)
|
|
{
|
|
rc = SQLBindCol(hstmt,
|
|
(SQLUSMALLINT) 1,
|
|
SQL_C_CHAR,
|
|
(SQLPOINTER) chr,
|
|
(SQLINTEGER) 4,
|
|
&lengths[0]);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
rc = SQLBindCol(hstmt,
|
|
(SQLUSMALLINT) 2,
|
|
SQL_C_SLONG,
|
|
(SQLPOINTER) &second,
|
|
(SQLINTEGER) 0,
|
|
&lengths[1]);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
rc = SQLBindCol(hstmt,
|
|
(SQLUSMALLINT) 3,
|
|
SQL_C_FLOAT,
|
|
(SQLPOINTER) &third,
|
|
(SQLINTEGER) 0,
|
|
&lengths[2]);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
}
|
|
|
|
rc = SQLExecute(hstmt);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
char one = 0x31;
|
|
int two = 2;
|
|
float three = 3.5;
|
|
count = 0;
|
|
|
|
do
|
|
{
|
|
rc = SQLFetch(hstmt);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
if (SQLExecutor::DE_MANUAL == extractMode)
|
|
{
|
|
rc = SQLGetData(hstmt,
|
|
(SQLUSMALLINT) 1,
|
|
SQL_C_CHAR,
|
|
chr,
|
|
4,
|
|
&lengths[0]);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
rc = SQLGetData(hstmt,
|
|
(SQLUSMALLINT) 2,
|
|
SQL_C_SLONG,
|
|
&second,
|
|
0,
|
|
&lengths[1]);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
rc = SQLGetData(hstmt,
|
|
(SQLUSMALLINT) 3,
|
|
SQL_C_FLOAT,
|
|
&third,
|
|
0,
|
|
&lengths[2]);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
}
|
|
|
|
assertTrue (one++ == chr[0]);
|
|
assertTrue (two++ == second);
|
|
assertTrue (three == third);
|
|
three += 1.0;
|
|
|
|
++count;
|
|
} while (SQL_NO_DATA != SQLMoreResults(hstmt));
|
|
|
|
assertTrue (5 == count);
|
|
|
|
sql = "DROP TABLE Test";
|
|
pStr = (SQLCHAR*) sql.c_str();
|
|
rc = SQLExecDirect(hstmt, pStr, (SQLINTEGER) sql.length());
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
// Connection end
|
|
rc = SQLDisconnect(hdbc);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
rc = SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
|
|
// Environment end
|
|
rc = SQLFreeHandle(SQL_HANDLE_ENV, henv);
|
|
poco_odbc_check_stmt (rc, hstmt);
|
|
}
|
|
|
|
|
|
void SQLExecutor::execute(const std::string& sql)
|
|
{
|
|
try { session() << sql, now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (sql); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (sql); }
|
|
}
|
|
|
|
|
|
void SQLExecutor::zeroRows()
|
|
{
|
|
Statement stmt = (session() << "SELECT * FROM Person WHERE 0 = 1");
|
|
assertTrue (0 == stmt.execute());
|
|
}
|
|
|
|
|
|
void SQLExecutor::simpleAccess()
|
|
{
|
|
std::string funct = "simpleAccess()";
|
|
std::string lastName = "lastName";
|
|
std::string firstName("firstName");
|
|
std::string address("Address");
|
|
int age = 133132;
|
|
int count = 0;
|
|
std::string result;
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(age), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 1);
|
|
|
|
try { session() << "SELECT LastName FROM Person", into(result), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (lastName == result);
|
|
|
|
try { session() << "SELECT Age FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == age);
|
|
}
|
|
|
|
|
|
void SQLExecutor::complexType()
|
|
{
|
|
std::string funct = "complexType()";
|
|
Person p1("LN1", "FN1", "ADDR1", 1);
|
|
Person p2("LN2", "FN2", "ADDR2", 2);
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(p1), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(p2), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 2);
|
|
|
|
Person c1;
|
|
try { session() << "SELECT * FROM Person WHERE LastName = 'LN1'", into(c1), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (c1 == p1);
|
|
}
|
|
|
|
|
|
void SQLExecutor::complexTypeTuple()
|
|
{
|
|
std::string funct = "complexTypeTuple()";
|
|
Person p1("LN1", "FN1", "ADDR1", 1);
|
|
Person p2("LN2", "FN2", "ADDR2", 2);
|
|
|
|
Tuple<Person,Person> t(p1,p2);
|
|
try { *_pSession << "INSERT INTO Person VALUES(?,?,?,?,?,?,?,?)", use(t), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
Tuple<Person,Person> ret;
|
|
assertTrue (ret != t);
|
|
try { *_pSession << "SELECT * FROM Person", into(ret), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (ret == t);
|
|
}
|
|
|
|
|
|
void SQLExecutor::simpleAccessVector()
|
|
{
|
|
std::string funct = "simpleAccessVector()";
|
|
std::vector<std::string> lastNames;
|
|
std::vector<std::string> firstNames;
|
|
std::vector<std::string> addresses;
|
|
std::vector<int> ages;
|
|
std::string tableName("Person");
|
|
lastNames.push_back("LN1");
|
|
lastNames.push_back("LN2");
|
|
firstNames.push_back("FN1");
|
|
firstNames.push_back("FN2");
|
|
addresses.push_back("ADDR1");
|
|
addresses.push_back("ADDR2");
|
|
ages.push_back(1);
|
|
ages.push_back(2);
|
|
int count = 0;
|
|
std::string result;
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 2);
|
|
|
|
std::vector<std::string> lastNamesR;
|
|
std::vector<std::string> firstNamesR;
|
|
std::vector<std::string> addressesR;
|
|
std::vector<int> agesR;
|
|
try { session() << "SELECT * FROM Person", into(lastNamesR), into(firstNamesR), into(addressesR), into(agesR), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (ages == agesR);
|
|
assertTrue (lastNames == lastNamesR);
|
|
assertTrue (firstNames == firstNamesR);
|
|
assertTrue (addresses == addressesR);
|
|
}
|
|
|
|
|
|
void SQLExecutor::complexTypeVector()
|
|
{
|
|
std::string funct = "complexTypeVector()";
|
|
std::vector<Person> people;
|
|
people.push_back(Person("LN1", "FN1", "ADDR1", 1));
|
|
people.push_back(Person("LN2", "FN2", "ADDR2", 2));
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 2);
|
|
|
|
std::vector<Person> result;
|
|
try { session() << "SELECT * FROM Person", into(result), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (result == people);
|
|
}
|
|
|
|
|
|
void SQLExecutor::sharedPtrComplexTypeVector()
|
|
{
|
|
std::string funct = "sharedPtrComplexTypeVector()";
|
|
std::vector<Poco::SharedPtr<Person> > people;
|
|
people.push_back(new Person("LN1", "FN1", "ADDR1", 1));
|
|
people.push_back(new Person("LN2", "FN2", "ADDR2", 2));
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 2);
|
|
|
|
std::vector<Person> result;
|
|
try { session() << "SELECT * FROM Person", into(result), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (2 == result.size());
|
|
assertTrue (result[0] == *people[0]);
|
|
assertTrue (result[1] == *people[1]);
|
|
}
|
|
|
|
|
|
void SQLExecutor::autoPtrComplexTypeVector()
|
|
{
|
|
std::string funct = "sharedPtrComplexTypeVector()";
|
|
std::vector<Poco::AutoPtr<RefCountedPerson> > people;
|
|
people.push_back(new RefCountedPerson("LN1", "FN1", "ADDR1", 1));
|
|
people.push_back(new RefCountedPerson("LN2", "FN2", "ADDR2", 2));
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 2);
|
|
|
|
std::vector<Person> result;
|
|
try { session() << "SELECT * FROM Person", into(result), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (2 == result.size());
|
|
assertTrue (result[0].address == people[0]->address);
|
|
assertTrue (result[0].age == people[0]->age);
|
|
assertTrue (result[0].firstName == people[0]->firstName);
|
|
assertTrue (result[0].lastName == people[0]->lastName);
|
|
assertTrue (result[1].address == people[1]->address);
|
|
assertTrue (result[1].age == people[1]->age);
|
|
assertTrue (result[1].firstName == people[1]->firstName);
|
|
assertTrue (result[1].lastName == people[1]->lastName);
|
|
}
|
|
|
|
|
|
void SQLExecutor::insertVector()
|
|
{
|
|
std::string funct = "insertVector()";
|
|
std::vector<std::string> str;
|
|
str.push_back("s1");
|
|
str.push_back("s2");
|
|
str.push_back("s3");
|
|
str.push_back("s3");
|
|
int count = 100;
|
|
|
|
{
|
|
Statement stmt((session() << "INSERT INTO Strings VALUES (?)", use(str)));
|
|
try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 0);
|
|
|
|
try { stmt.execute(); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 4);
|
|
}
|
|
count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 4);
|
|
}
|
|
|
|
|
|
void SQLExecutor::insertEmptyVector()
|
|
{
|
|
std::string funct = "insertEmptyVector()";
|
|
std::vector<std::string> str;
|
|
|
|
try
|
|
{
|
|
session() << "INSERT INTO Strings VALUES (?)", use(str), now;
|
|
fail("empty collections should not work");
|
|
}
|
|
catch (Poco::Exception&)
|
|
{
|
|
}
|
|
}
|
|
|
|
|
|
void SQLExecutor::simpleAccessList()
|
|
{
|
|
std::string funct = "simpleAccessList()";
|
|
std::list<std::string> lastNames;
|
|
std::list<std::string> firstNames;
|
|
std::list<std::string> addresses;
|
|
std::list<int> ages;
|
|
std::string tableName("Person");
|
|
lastNames.push_back("LN1");
|
|
lastNames.push_back("LN2");
|
|
firstNames.push_back("FN1");
|
|
firstNames.push_back("FN2");
|
|
addresses.push_back("ADDR1");
|
|
addresses.push_back("ADDR2");
|
|
ages.push_back(1);
|
|
ages.push_back(2);
|
|
int count = 0;
|
|
std::string result;
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 2);
|
|
|
|
std::list<std::string> lastNamesR;
|
|
std::list<std::string> firstNamesR;
|
|
std::list<std::string> addressesR;
|
|
std::list<int> agesR;
|
|
try { session() << "SELECT * FROM Person", into(lastNamesR), into(firstNamesR), into(addressesR), into(agesR), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (ages == agesR);
|
|
assertTrue (lastNames == lastNamesR);
|
|
assertTrue (firstNames == firstNamesR);
|
|
assertTrue (addresses == addressesR);
|
|
}
|
|
|
|
|
|
void SQLExecutor::complexTypeList()
|
|
{
|
|
std::string funct = "complexTypeList()";
|
|
std::list<Person> people;
|
|
people.push_back(Person("LN1", "FN1", "ADDR1", 1));
|
|
people.push_back(Person("LN2", "FN2", "ADDR2", 2));
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 2);
|
|
|
|
std::list<Person> result;
|
|
try { session() << "SELECT * FROM Person", into(result), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (result == people);
|
|
}
|
|
|
|
|
|
void SQLExecutor::insertList()
|
|
{
|
|
std::string funct = "insertList()";
|
|
std::list<std::string> str;
|
|
str.push_back("s1");
|
|
str.push_back("s2");
|
|
str.push_back("s3");
|
|
str.push_back("s3");
|
|
int count = 100;
|
|
|
|
{
|
|
Statement stmt((session() << "INSERT INTO Strings VALUES (?)", use(str)));
|
|
try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 0);
|
|
|
|
try { stmt.execute(); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 4);
|
|
}
|
|
count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 4);
|
|
}
|
|
|
|
|
|
void SQLExecutor::insertEmptyList()
|
|
{
|
|
std::string funct = "insertEmptyList()";
|
|
std::list<std::string> str;
|
|
|
|
try
|
|
{
|
|
session() << "INSERT INTO Strings VALUES (?)", use(str), now;
|
|
fail("empty collections should not work");
|
|
}
|
|
catch (Poco::Exception&)
|
|
{
|
|
}
|
|
}
|
|
|
|
|
|
void SQLExecutor::simpleAccessDeque()
|
|
{
|
|
std::string funct = "simpleAccessDeque()";
|
|
std::deque<std::string> lastNames;
|
|
std::deque<std::string> firstNames;
|
|
std::deque<std::string> addresses;
|
|
std::deque<int> ages;
|
|
std::string tableName("Person");
|
|
lastNames.push_back("LN1");
|
|
lastNames.push_back("LN2");
|
|
firstNames.push_back("FN1");
|
|
firstNames.push_back("FN2");
|
|
addresses.push_back("ADDR1");
|
|
addresses.push_back("ADDR2");
|
|
ages.push_back(1);
|
|
ages.push_back(2);
|
|
int count = 0;
|
|
std::string result;
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 2);
|
|
|
|
std::deque<std::string> lastNamesR;
|
|
std::deque<std::string> firstNamesR;
|
|
std::deque<std::string> addressesR;
|
|
std::deque<int> agesR;
|
|
try { session() << "SELECT * FROM Person", into(lastNamesR), into(firstNamesR), into(addressesR), into(agesR), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (ages == agesR);
|
|
assertTrue (lastNames == lastNamesR);
|
|
assertTrue (firstNames == firstNamesR);
|
|
assertTrue (addresses == addressesR);
|
|
}
|
|
|
|
|
|
void SQLExecutor::complexTypeDeque()
|
|
{
|
|
std::string funct = "complexTypeDeque()";
|
|
std::deque<Person> people;
|
|
people.push_back(Person("LN1", "FN1", "ADDR1", 1));
|
|
people.push_back(Person("LN2", "FN2", "ADDR2", 2));
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 2);
|
|
|
|
std::deque<Person> result;
|
|
try { session() << "SELECT * FROM Person", into(result), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (result == people);
|
|
}
|
|
|
|
|
|
void SQLExecutor::insertDeque()
|
|
{
|
|
std::string funct = "insertDeque()";
|
|
std::deque<std::string> str;
|
|
str.push_back("s1");
|
|
str.push_back("s2");
|
|
str.push_back("s3");
|
|
str.push_back("s3");
|
|
int count = 100;
|
|
|
|
{
|
|
Statement stmt((session() << "INSERT INTO Strings VALUES (?)", use(str)));
|
|
try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 0);
|
|
|
|
try { stmt.execute(); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 4);
|
|
}
|
|
count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 4);
|
|
}
|
|
|
|
|
|
void SQLExecutor::insertEmptyDeque()
|
|
{
|
|
std::string funct = "insertEmptyDeque()";
|
|
std::deque<std::string> str;
|
|
|
|
try
|
|
{
|
|
session() << "INSERT INTO Strings VALUES (?)", use(str), now;
|
|
fail("empty collections should not work");
|
|
}
|
|
catch (Poco::Exception&)
|
|
{
|
|
}
|
|
}
|
|
|
|
|
|
void SQLExecutor::affectedRows(const std::string& whereClause)
|
|
{
|
|
std::vector<std::string> str;
|
|
str.push_back("s1");
|
|
str.push_back("s2");
|
|
str.push_back("s3");
|
|
str.push_back("s3");
|
|
int count = 100;
|
|
|
|
Statement stmt1((session() << "INSERT INTO Strings VALUES(?)", use(str)));
|
|
session() << "SELECT COUNT(*) FROM Strings", into(count), now;
|
|
assertTrue (count == 0);
|
|
assertTrue (4 == stmt1.execute());
|
|
session() << "SELECT COUNT(*) FROM Strings", into(count), now;
|
|
assertTrue (count == 4);
|
|
|
|
Statement stmt2(session() << "UPDATE Strings SET str = 's4' WHERE str = 's3'");
|
|
assertTrue (2 == stmt2.execute());
|
|
|
|
Statement stmt3(session() << "DELETE FROM Strings WHERE str = 's1'");
|
|
assertTrue (1 == stmt3.execute());
|
|
|
|
std::string sql;
|
|
format(sql, "DELETE FROM Strings %s", whereClause);
|
|
Statement stmt4(session() << sql);
|
|
assertTrue (3 == stmt4.execute());
|
|
}
|
|
|
|
|
|
void SQLExecutor::insertSingleBulk()
|
|
{
|
|
std::string funct = "insertSingleBulk()";
|
|
int x = 0;
|
|
Statement stmt((session() << "INSERT INTO Strings VALUES (?)", use(x)));
|
|
|
|
for (x = 0; x < 100; ++x)
|
|
{
|
|
std::size_t i = stmt.execute();
|
|
assertTrue (1 == i);
|
|
}
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 100);
|
|
|
|
try { session() << "SELECT SUM(str) FROM Strings", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == ((0+99)*100/2));
|
|
}
|
|
|
|
|
|
void SQLExecutor::floats()
|
|
{
|
|
std::string funct = "floats()";
|
|
float data = 1.5f;
|
|
float ret = 0.0f;
|
|
|
|
try { session() << "INSERT INTO Strings VALUES (?)", use(data), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 1);
|
|
|
|
try { session() << "SELECT str FROM Strings", into(ret), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (ret == data);
|
|
}
|
|
|
|
|
|
void SQLExecutor::doubles()
|
|
{
|
|
std::string funct = "floats()";
|
|
double data = 1.5;
|
|
double ret = 0.0;
|
|
|
|
try { session() << "INSERT INTO Strings VALUES (?)", use(data), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 1);
|
|
|
|
try { session() << "SELECT str FROM Strings", into(ret), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (ret == data);
|
|
}
|
|
|
|
|
|
void SQLExecutor::insertSingleBulkVec()
|
|
{
|
|
std::string funct = "insertSingleBulkVec()";
|
|
std::vector<int> data;
|
|
|
|
for (int x = 0; x < 100; ++x)
|
|
data.push_back(x);
|
|
|
|
Statement stmt((session() << "INSERT INTO Strings VALUES (?)", use(data)));
|
|
stmt.execute();
|
|
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
assertTrue (count == 100);
|
|
try { session() << "SELECT SUM(str) FROM Strings", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == ((0+99)*100/2));
|
|
}
|
|
|
|
|
|
void SQLExecutor::limits()
|
|
{
|
|
std::string funct = "limit()";
|
|
std::vector<int> data;
|
|
for (int x = 0; x < 100; ++x)
|
|
{
|
|
data.push_back(x);
|
|
}
|
|
|
|
try { session() << "INSERT INTO Strings VALUES (?)", use(data), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
std::vector<int> retData;
|
|
try { session() << "SELECT * FROM Strings", into(retData), limit(50), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (retData.size() == 50);
|
|
for (int x = 0; x < 50; ++x)
|
|
{
|
|
assertTrue (data[x] == retData[x]);
|
|
}
|
|
}
|
|
|
|
|
|
void SQLExecutor::limitZero()
|
|
{
|
|
std::string funct = "limitZero()";
|
|
std::vector<int> data;
|
|
for (int x = 0; x < 100; ++x)
|
|
{
|
|
data.push_back(x);
|
|
}
|
|
|
|
try { session() << "INSERT INTO Strings VALUES (?)", use(data), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
std::vector<int> retData;
|
|
try { session() << "SELECT * FROM Strings", into(retData), limit(0), now; }// stupid test, but at least we shouldn't crash
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (retData.size() == 0);
|
|
}
|
|
|
|
|
|
void SQLExecutor::limitOnce()
|
|
{
|
|
std::string funct = "limitOnce()";
|
|
std::vector<int> data;
|
|
for (int x = 0; x < 101; ++x)
|
|
{
|
|
data.push_back(x);
|
|
}
|
|
|
|
try { session() << "INSERT INTO Strings VALUES (?)", use(data), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
std::vector<int> retData;
|
|
Statement stmt = (session() << "SELECT * FROM Strings", into(retData), limit(50), now);
|
|
assertTrue (!stmt.done());
|
|
assertTrue (retData.size() == 50);
|
|
stmt.execute();
|
|
assertTrue (!stmt.done());
|
|
assertTrue (retData.size() == 100);
|
|
stmt.execute();
|
|
assertTrue (stmt.done());
|
|
assertTrue (retData.size() == 101);
|
|
|
|
for (int x = 0; x < 101; ++x)
|
|
{
|
|
assertTrue (data[x] == retData[x]);
|
|
}
|
|
}
|
|
|
|
|
|
void SQLExecutor::limitPrepare()
|
|
{
|
|
std::string funct = "limitPrepare()";
|
|
std::vector<int> data;
|
|
for (int x = 0; x < 100; ++x)
|
|
{
|
|
data.push_back(x);
|
|
}
|
|
|
|
try
|
|
{
|
|
Statement stmt = (session() << "INSERT INTO Strings VALUES (?)", use(data));
|
|
assertTrue (100 == stmt.execute());
|
|
}
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
std::vector<int> retData;
|
|
Statement stmt = (session() << "SELECT * FROM Strings", into(retData), limit(50));
|
|
assertTrue (retData.size() == 0);
|
|
assertTrue (!stmt.done());
|
|
|
|
try { stmt.execute(); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (!stmt.done());
|
|
assertTrue (retData.size() == 50);
|
|
|
|
try { stmt.execute(); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (stmt.done());
|
|
assertTrue (retData.size() == 100);
|
|
|
|
try { stmt.execute(); }// will restart execution!
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
assertTrue (!stmt.done());
|
|
assertTrue (retData.size() == 150);
|
|
for (int x = 0; x < 150; ++x)
|
|
{
|
|
assertTrue (data[x%100] == retData[x]);
|
|
}
|
|
}
|
|
|
|
|
|
void SQLExecutor::prepare()
|
|
{
|
|
std::string funct = "prepare()";
|
|
std::vector<int> data;
|
|
for (int x = 0; x < 100; x += 2)
|
|
{
|
|
data.push_back(x);
|
|
}
|
|
|
|
{
|
|
Statement stmt((session() << "INSERT INTO Strings VALUES (?)", use(data)));
|
|
}
|
|
|
|
// stmt should not have been executed when destroyed
|
|
int count = 100;
|
|
try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 0);
|
|
}
|
|
|
|
|
|
void SQLExecutor::doBulkPerformance(Poco::UInt32 size)
|
|
{
|
|
std::string funct = "doBulk()";
|
|
std::vector<int> ints(size, 1);
|
|
std::vector<std::string> strings(size, "abc");
|
|
std::vector<double> floats(size, .5);
|
|
std::vector<DateTime> dateTimes(size);
|
|
|
|
Stopwatch sw;
|
|
try
|
|
{
|
|
sw.start();
|
|
session() << "INSERT INTO MiscTest (First, Third, Fourth, Fifth) VALUES (?,?,?,?)",
|
|
use(strings),
|
|
use(ints),
|
|
use(floats),
|
|
use(dateTimes), now;
|
|
sw.stop();
|
|
} catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
double time = sw.elapsed() / 1000.0;
|
|
|
|
try { session() << "DELETE FROM MiscTest", now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
try
|
|
{
|
|
sw.restart();
|
|
session() << "INSERT INTO MiscTest (First, Third, Fourth, Fifth) VALUES (?,?,?,?)",
|
|
use(strings, bulk),
|
|
use(ints, bulk),
|
|
use(floats, bulk),
|
|
use(dateTimes, bulk), now;
|
|
sw.stop();
|
|
} catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
double bulkTime = sw.elapsed() / 1000.0;
|
|
|
|
double speedup;
|
|
if (0.0 == bulkTime)
|
|
{
|
|
if (0.0 == time) speedup = 1.0;
|
|
else speedup = time;
|
|
}
|
|
else
|
|
speedup = time / bulkTime;
|
|
|
|
std::cout << "INSERT => Size:" << size
|
|
<< ", Time: " << time
|
|
<< ", Bulk Time: " << bulkTime
|
|
<< " [ms], Speedup: " << speedup
|
|
<< 'x' << std::endl;
|
|
|
|
ints.clear();
|
|
strings.clear();
|
|
floats.clear();
|
|
dateTimes.clear();
|
|
|
|
try
|
|
{
|
|
sw.restart();
|
|
session() << "SELECT First, Third, Fourth, Fifth FROM MiscTest",
|
|
into(strings),
|
|
into(ints),
|
|
into(floats),
|
|
into(dateTimes),
|
|
now;
|
|
sw.stop();
|
|
} catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
time = sw.elapsed() / 1000.0;
|
|
|
|
assertTrue (ints.size() == size);
|
|
|
|
ints.clear();
|
|
strings.clear();
|
|
floats.clear();
|
|
dateTimes.clear();
|
|
|
|
try
|
|
{
|
|
sw.restart();
|
|
session() << "SELECT First, Third, Fourth, Fifth FROM MiscTest",
|
|
into(strings, bulk(size)),
|
|
into(ints, bulk(size)),
|
|
into(floats, bulk(size)),
|
|
into(dateTimes, bulk(size)),
|
|
now;
|
|
sw.stop();
|
|
} catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
bulkTime = sw.elapsed() / 1000.0;
|
|
|
|
assertTrue (ints.size() == size);
|
|
|
|
if (0.0 == bulkTime)
|
|
{
|
|
if (0.0 == time) speedup = 1.0;
|
|
else speedup = time;
|
|
}
|
|
else
|
|
speedup = time / bulkTime;
|
|
|
|
std::cout << "SELECT => Size:" << size
|
|
<< ", Time: " << time
|
|
<< ", Bulk Time: " << bulkTime
|
|
<< " [ms], Speedup: " << speedup
|
|
<< 'x' << std::endl;
|
|
}
|
|
|
|
|
|
void SQLExecutor::setSimple()
|
|
{
|
|
std::string funct = "setSimple()";
|
|
std::set<std::string> lastNames;
|
|
std::set<std::string> firstNames;
|
|
std::set<std::string> addresses;
|
|
std::set<int> ages;
|
|
std::string tableName("Person");
|
|
lastNames.insert("LN1");
|
|
lastNames.insert("LN2");
|
|
firstNames.insert("FN1");
|
|
firstNames.insert("FN2");
|
|
addresses.insert("ADDR1");
|
|
addresses.insert("ADDR2");
|
|
ages.insert(1);
|
|
ages.insert(2);
|
|
int count = 0;
|
|
std::string result;
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 2);
|
|
|
|
std::set<std::string> lastNamesR;
|
|
std::set<std::string> firstNamesR;
|
|
std::set<std::string> addressesR;
|
|
std::set<int> agesR;
|
|
try { session() << "SELECT * FROM Person", into(lastNamesR), into(firstNamesR), into(addressesR), into(agesR), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (ages == agesR);
|
|
assertTrue (lastNames == lastNamesR);
|
|
assertTrue (firstNames == firstNamesR);
|
|
assertTrue (addresses == addressesR);
|
|
}
|
|
|
|
|
|
void SQLExecutor::setComplex()
|
|
{
|
|
std::string funct = "setComplex()";
|
|
std::set<Person> people;
|
|
people.insert(Person("LN1", "FN1", "ADDR1", 1));
|
|
people.insert(Person("LN2", "FN2", "ADDR2", 2));
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 2);
|
|
|
|
std::set<Person> result;
|
|
try { session() << "SELECT * FROM Person", into(result), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (result == people);
|
|
}
|
|
|
|
|
|
void SQLExecutor::setComplexUnique()
|
|
{
|
|
std::string funct = "setComplexUnique()";
|
|
std::vector<Person> people;
|
|
Person p1("LN1", "FN1", "ADDR1", 1);
|
|
people.push_back(p1);
|
|
people.push_back(p1);
|
|
people.push_back(p1);
|
|
people.push_back(p1);
|
|
Person p2("LN2", "FN2", "ADDR2", 2);
|
|
people.push_back(p2);
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 5);
|
|
|
|
std::set<Person> result;
|
|
try { session() << "SELECT * FROM Person", into(result), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (result.size() == 2);
|
|
assertTrue (*result.begin() == p1);
|
|
assertTrue (*++result.begin() == p2);
|
|
}
|
|
|
|
void SQLExecutor::multiSetSimple()
|
|
{
|
|
std::string funct = "multiSetSimple()";
|
|
std::multiset<std::string> lastNames;
|
|
std::multiset<std::string> firstNames;
|
|
std::multiset<std::string> addresses;
|
|
std::multiset<int> ages;
|
|
std::string tableName("Person");
|
|
lastNames.insert("LN1");
|
|
lastNames.insert("LN2");
|
|
firstNames.insert("FN1");
|
|
firstNames.insert("FN2");
|
|
addresses.insert("ADDR1");
|
|
addresses.insert("ADDR2");
|
|
ages.insert(1);
|
|
ages.insert(2);
|
|
int count = 0;
|
|
std::string result;
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 2);
|
|
|
|
std::multiset<std::string> lastNamesR;
|
|
std::multiset<std::string> firstNamesR;
|
|
std::multiset<std::string> addressesR;
|
|
std::multiset<int> agesR;
|
|
try { session() << "SELECT * FROM Person", into(lastNamesR), into(firstNamesR), into(addressesR), into(agesR), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (ages.size() == agesR.size());
|
|
assertTrue (lastNames.size() == lastNamesR.size());
|
|
assertTrue (firstNames.size() == firstNamesR.size());
|
|
assertTrue (addresses.size() == addressesR.size());
|
|
}
|
|
|
|
|
|
void SQLExecutor::multiSetComplex()
|
|
{
|
|
std::string funct = "multiSetComplex()";
|
|
std::multiset<Person> people;
|
|
Person p1("LN1", "FN1", "ADDR1", 1);
|
|
people.insert(p1);
|
|
people.insert(p1);
|
|
people.insert(p1);
|
|
people.insert(p1);
|
|
Person p2("LN2", "FN2", "ADDR2", 2);
|
|
people.insert(p2);
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 5);
|
|
|
|
std::multiset<Person> result;
|
|
try { session() << "SELECT * FROM Person", into(result), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (result.size() == people.size());
|
|
}
|
|
|
|
|
|
void SQLExecutor::mapComplex()
|
|
{
|
|
std::string funct = "mapComplex()";
|
|
std::map<std::string, Person> people;
|
|
Person p1("LN1", "FN1", "ADDR1", 1);
|
|
Person p2("LN2", "FN2", "ADDR2", 2);
|
|
people.insert(std::make_pair("LN1", p1));
|
|
people.insert(std::make_pair("LN2", p2));
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 2);
|
|
|
|
std::map<std::string, Person> result;
|
|
try { session() << "SELECT * FROM Person", into(result), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (result == people);
|
|
}
|
|
|
|
|
|
void SQLExecutor::mapComplexUnique()
|
|
{
|
|
std::string funct = "mapComplexUnique()";
|
|
std::multimap<std::string, Person> people;
|
|
Person p1("LN1", "FN1", "ADDR1", 1);
|
|
Person p2("LN2", "FN2", "ADDR2", 2);
|
|
people.insert(std::make_pair("LN1", p1));
|
|
people.insert(std::make_pair("LN1", p1));
|
|
people.insert(std::make_pair("LN1", p1));
|
|
people.insert(std::make_pair("LN1", p1));
|
|
people.insert(std::make_pair("LN2", p2));
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 5);
|
|
|
|
std::map<std::string, Person> result;
|
|
try { session() << "SELECT * FROM Person", into(result), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (result.size() == 2);
|
|
}
|
|
|
|
|
|
void SQLExecutor::multiMapComplex()
|
|
{
|
|
std::string funct = "multiMapComplex()";
|
|
std::multimap<std::string, Person> people;
|
|
Person p1("LN1", "FN1", "ADDR1", 1);
|
|
Person p2("LN2", "FN2", "ADDR2", 2);
|
|
people.insert(std::make_pair("LN1", p1));
|
|
people.insert(std::make_pair("LN1", p1));
|
|
people.insert(std::make_pair("LN1", p1));
|
|
people.insert(std::make_pair("LN1", p1));
|
|
people.insert(std::make_pair("LN2", p2));
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 5);
|
|
|
|
std::multimap<std::string, Person> result;
|
|
try { session() << "SELECT * FROM Person", into(result), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (result.size() == people.size());
|
|
}
|
|
|
|
|
|
void SQLExecutor::selectIntoSingle()
|
|
{
|
|
std::string funct = "selectIntoSingle()";
|
|
std::multimap<std::string, Person> people;
|
|
Person p1("LN1", "FN1", "ADDR1", 1);
|
|
Person p2("LN2", "FN2", "ADDR2", 2);
|
|
people.insert(std::make_pair("LN1", p1));
|
|
people.insert(std::make_pair("LN2", p2));
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 2);
|
|
Person result;
|
|
try { session() << "SELECT * FROM Person ORDER BY LastName", into(result), limit(1), now; }// will return 1 object into one single result
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (result == p1);
|
|
}
|
|
|
|
|
|
void SQLExecutor::selectIntoSingleStep()
|
|
{
|
|
std::string funct = "selectIntoSingleStep()";
|
|
std::multimap<std::string, Person> people;
|
|
Person p1("LN1", "FN1", "ADDR1", 1);
|
|
Person p2("LN2", "FN2", "ADDR2", 2);
|
|
people.insert(std::make_pair("LN1", p1));
|
|
people.insert(std::make_pair("LN2", p2));
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 2);
|
|
Person result;
|
|
Statement stmt = (session() << "SELECT * FROM Person", into(result), limit(1));
|
|
stmt.execute();
|
|
assertTrue (result == p1);
|
|
assertTrue (!stmt.done());
|
|
stmt.execute();
|
|
assertTrue (result == p2);
|
|
assertTrue (stmt.done());
|
|
}
|
|
|
|
|
|
void SQLExecutor::selectIntoSingleFail()
|
|
{
|
|
std::string funct = "selectIntoSingleFail()";
|
|
std::multimap<std::string, Person> people;
|
|
Person p1("LN1", "FN1", "ADDR1", 1);
|
|
Person p2("LN2", "FN2", "ADDR2", 2);
|
|
people.insert(std::make_pair("LN1", p1));
|
|
people.insert(std::make_pair("LN2", p2));
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), limit(2, true), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 2);
|
|
Person result;
|
|
try
|
|
{
|
|
session() << "SELECT * FROM Person", into(result), limit(1, true), now; // will fail now
|
|
fail("hardLimit is set: must fail");
|
|
}
|
|
catch(Poco::Data::LimitException&)
|
|
{
|
|
}
|
|
}
|
|
|
|
|
|
void SQLExecutor::lowerLimitOk()
|
|
{
|
|
std::string funct = "lowerLimitOk()";
|
|
std::multimap<std::string, Person> people;
|
|
Person p1("LN1", "FN1", "ADDR1", 1);
|
|
Person p2("LN2", "FN2", "ADDR2", 2);
|
|
people.insert(std::make_pair("LN1", p1));
|
|
people.insert(std::make_pair("LN1", p2));
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 2);
|
|
Person result;
|
|
try
|
|
{
|
|
session() << "SELECT * FROM Person", into(result), lowerLimit(2), now; // will return 2 objects into one single result but only room for one!
|
|
fail("Not enough space for results");
|
|
}
|
|
catch(Poco::Exception&)
|
|
{
|
|
}
|
|
}
|
|
|
|
|
|
void SQLExecutor::singleSelect()
|
|
{
|
|
std::string funct = "singleSelect()";
|
|
std::multimap<std::string, Person> people;
|
|
Person p1("LN1", "FN1", "ADDR1", 1);
|
|
Person p2("LN2", "FN2", "ADDR2", 2);
|
|
people.insert(std::make_pair("LN1", p1));
|
|
people.insert(std::make_pair("LN1", p2));
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 2);
|
|
Person result;
|
|
Statement stmt = (session() << "SELECT * FROM Person", into(result), limit(1));
|
|
stmt.execute();
|
|
assertTrue (result == p1);
|
|
assertTrue (!stmt.done());
|
|
stmt.execute();
|
|
assertTrue (result == p2);
|
|
assertTrue (stmt.done());
|
|
}
|
|
|
|
|
|
void SQLExecutor::lowerLimitFail()
|
|
{
|
|
std::string funct = "lowerLimitFail()";
|
|
std::multimap<std::string, Person> people;
|
|
Person p1("LN1", "FN1", "ADDR1", 1);
|
|
Person p2("LN2", "FN2", "ADDR2", 2);
|
|
people.insert(std::make_pair("LN1", p1));
|
|
people.insert(std::make_pair("LN1", p2));
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 2);
|
|
Person result;
|
|
try
|
|
{
|
|
session() << "SELECT * FROM Person", into(result), lowerLimit(3), now; // will fail
|
|
fail("should fail. not enough data");
|
|
}
|
|
catch(Poco::Exception&)
|
|
{
|
|
}
|
|
}
|
|
|
|
|
|
void SQLExecutor::combinedLimits()
|
|
{
|
|
std::string funct = "combinedLimits()";
|
|
std::multimap<std::string, Person> people;
|
|
Person p1("LN1", "FN1", "ADDR1", 1);
|
|
Person p2("LN2", "FN2", "ADDR2", 2);
|
|
people.insert(std::make_pair("LN1", p1));
|
|
people.insert(std::make_pair("LN1", p2));
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 2);
|
|
std::vector <Person> result;
|
|
try { session() << "SELECT * FROM Person", into(result), lowerLimit(2), upperLimit(2), now; }// will return 2 objects
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (result.size() == 2);
|
|
assertTrue (result[0] == p1);
|
|
assertTrue (result[1] == p2);
|
|
}
|
|
|
|
|
|
|
|
void SQLExecutor::ranges()
|
|
{
|
|
std::string funct = "range()";
|
|
std::multimap<std::string, Person> people;
|
|
Person p1("LN1", "FN1", "ADDR1", 1);
|
|
Person p2("LN2", "FN2", "ADDR2", 2);
|
|
people.insert(std::make_pair("LN1", p1));
|
|
people.insert(std::make_pair("LN1", p2));
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 2);
|
|
std::vector <Person> result;
|
|
try { session() << "SELECT * FROM Person", into(result), range(2, 2), now; }// will return 2 objects
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (result.size() == 2);
|
|
assertTrue (result[0] == p1);
|
|
assertTrue (result[1] == p2);
|
|
}
|
|
|
|
|
|
void SQLExecutor::combinedIllegalLimits()
|
|
{
|
|
std::string funct = "combinedIllegalLimits()";
|
|
std::multimap<std::string, Person> people;
|
|
Person p1("LN1", "FN1", "ADDR1", 1);
|
|
Person p2("LN2", "FN2", "ADDR2", 2);
|
|
people.insert(std::make_pair("LN1", p1));
|
|
people.insert(std::make_pair("LN1", p2));
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 2);
|
|
Person result;
|
|
try
|
|
{
|
|
session() << "SELECT * FROM Person", into(result), lowerLimit(3), upperLimit(2), now;
|
|
fail("lower > upper is not allowed");
|
|
}
|
|
catch(LimitException&)
|
|
{
|
|
}
|
|
}
|
|
|
|
|
|
void SQLExecutor::illegalRange()
|
|
{
|
|
std::string funct = "illegalRange()";
|
|
std::multimap<std::string, Person> people;
|
|
Person p1("LN1", "FN1", "ADDR1", 1);
|
|
Person p2("LN2", "FN2", "ADDR2", 2);
|
|
people.insert(std::make_pair("LN1", p1));
|
|
people.insert(std::make_pair("LN1", p2));
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(people), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 2);
|
|
Person result;
|
|
try
|
|
{
|
|
session() << "SELECT * FROM Person", into(result), range(3, 2), now;
|
|
fail("lower > upper is not allowed");
|
|
}
|
|
catch(LimitException&)
|
|
{
|
|
}
|
|
}
|
|
|
|
|
|
void SQLExecutor::emptyDB()
|
|
{
|
|
std::string funct = "emptyDB()";
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 0);
|
|
|
|
Person result;
|
|
Statement stmt = (session() << "SELECT * FROM Person", into(result), limit(1));
|
|
stmt.execute();
|
|
assertTrue (result.firstName.empty());
|
|
assertTrue (stmt.done());
|
|
}
|
|
|
|
|
|
void SQLExecutor::blob(int bigSize, const std::string& blobPlaceholder)
|
|
{
|
|
std::string funct = "blob()";
|
|
std::string lastName("lastname");
|
|
std::string firstName("firstname");
|
|
std::string address("Address");
|
|
|
|
CLOB img("0123456789", 10);
|
|
int count = 0;
|
|
try { session() << format("INSERT INTO Person VALUES (?,?,?,%s)", blobPlaceholder),
|
|
use(lastName), use(firstName), use(address), use(img), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 1);
|
|
|
|
CLOB res;
|
|
assertTrue (res.size() == 0);
|
|
try { session() << "SELECT Image FROM Person", into(res), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (res == img);
|
|
|
|
CLOB big;
|
|
std::vector<char> v(bigSize, 'x');
|
|
big.assignRaw(&v[0], v.size());
|
|
|
|
assertTrue (big.size() == bigSize);
|
|
|
|
try { session() << "DELETE FROM Person", now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
try { session() << format("INSERT INTO Person VALUES (?,?,?,%s)", blobPlaceholder),
|
|
use(lastName), use(firstName), use(address), use(big), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
try { session() << "SELECT Image FROM Person", into(res), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (res == big);
|
|
}
|
|
|
|
|
|
void SQLExecutor::blobStmt()
|
|
{
|
|
std::string funct = "blobStmt()";
|
|
std::string lastName("lastname");
|
|
std::string firstName("firstname");
|
|
std::string address("Address");
|
|
CLOB blob("0123456789", 10);
|
|
|
|
int count = 0;
|
|
Statement ins = (session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(blob));
|
|
ins.execute();
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 1);
|
|
|
|
CLOB res;
|
|
poco_assert (res.size() == 0);
|
|
Statement stmt = (session() << "SELECT Image FROM Person", into(res));
|
|
try { stmt.execute(); }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
poco_assert (res == blob);
|
|
}
|
|
|
|
|
|
void SQLExecutor::dateTime()
|
|
{
|
|
std::string funct = "dateTime()";
|
|
std::string lastName("lastname");
|
|
std::string firstName("firstname");
|
|
std::string address("Address");
|
|
|
|
DateTime born(1965, 6, 18, 5, 35, 1);
|
|
int count = 0;
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(born), now; }
|
|
catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail(funct); }
|
|
catch (StatementException& se){ std::cout << se.toString() << std::endl; fail(funct); }
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail(funct); }
|
|
catch (StatementException& se){ std::cout << se.toString() << std::endl; fail(funct); }
|
|
assertTrue (count == 1);
|
|
|
|
DateTime res;
|
|
try { session() << "SELECT Born FROM Person", into(res), now; }
|
|
catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail(funct); }
|
|
catch (StatementException& se){ std::cout << se.toString() << std::endl; fail(funct); }
|
|
assertTrue (res == born);
|
|
|
|
Statement stmt = (session() << "SELECT Born FROM Person", now);
|
|
RecordSet rset(stmt);
|
|
|
|
res = rset["Born"].convert<DateTime>();
|
|
assertTrue (res == born);
|
|
}
|
|
|
|
|
|
void SQLExecutor::date()
|
|
{
|
|
std::string funct = "date()";
|
|
std::string lastName("lastname");
|
|
std::string firstName("firstname");
|
|
std::string address("Address");
|
|
|
|
Date bornDate(1965, 6, 18);
|
|
int count = 0;
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)",
|
|
use(lastName),
|
|
use(firstName),
|
|
use(address),
|
|
use(bornDate),
|
|
now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 1);
|
|
|
|
Date d;
|
|
Time t;
|
|
try { session() << "SELECT BornDate FROM Person", into(d), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (d == bornDate);
|
|
|
|
Statement stmt = (session() << "SELECT BornDate FROM Person", now);
|
|
RecordSet rset(stmt);
|
|
|
|
DateTime dt1 = rset["BornDate"].convert<DateTime>();
|
|
|
|
Date d2(dt1);
|
|
assertTrue (d2 == bornDate);
|
|
}
|
|
|
|
|
|
void SQLExecutor::time()
|
|
{
|
|
std::string funct = "time()";
|
|
std::string lastName("lastname");
|
|
std::string firstName("firstname");
|
|
std::string address("Address");
|
|
|
|
Time bornTime (5, 35, 1);
|
|
int count = 0;
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)",
|
|
use(lastName),
|
|
use(firstName),
|
|
use(address),
|
|
use(bornTime),
|
|
now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 1);
|
|
|
|
Date d;
|
|
Time t;
|
|
try { session() << "SELECT BornTime FROM Person", into(t), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (t == bornTime);
|
|
|
|
Statement stmt = (session() << "SELECT BornTime FROM Person", now);
|
|
RecordSet rset(stmt);
|
|
|
|
DateTime dt2 = rset["BornTime"].convert<DateTime>();
|
|
Time t2(dt2);
|
|
assertTrue (t2 == bornTime);
|
|
}
|
|
|
|
|
|
void SQLExecutor::tuples()
|
|
{
|
|
typedef Tuple<int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int> TupleType;
|
|
std::string funct = "tuples()";
|
|
TupleType t(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19);
|
|
|
|
try { session() << "INSERT INTO Tuples VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", use(t), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
TupleType ret(-10,-11,-12,-13,-14,-15,-16,-17,-18,-19);
|
|
assertTrue (ret != t);
|
|
try { session() << "SELECT * FROM Tuples", into(ret), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (ret == t);
|
|
}
|
|
|
|
void SQLExecutor::tupleVector()
|
|
{
|
|
typedef Tuple<int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int> TupleType;
|
|
std::string funct = "tupleVector()";
|
|
TupleType t(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19);
|
|
Tuple<int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int>
|
|
t10(10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29);
|
|
TupleType t100(100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119);
|
|
std::vector<TupleType> v;
|
|
v.push_back(t);
|
|
v.push_back(t10);
|
|
v.push_back(t100);
|
|
|
|
try { session() << "INSERT INTO Tuples VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", use(v), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
int count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Tuples", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (v.size() == count);
|
|
|
|
std::vector<Tuple<int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int> > ret;
|
|
try { session() << "SELECT * FROM Tuples", into(ret), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (ret == v);
|
|
}
|
|
|
|
|
|
void SQLExecutor::internalExtraction()
|
|
{
|
|
std::string funct = "internalExtraction()";
|
|
std::vector<Tuple<int, double, std::string> > v;
|
|
v.push_back(Tuple<int, double, std::string>(1, 1.5f, "3"));
|
|
v.push_back(Tuple<int, double, std::string>(2, 2.5f, "4"));
|
|
v.push_back(Tuple<int, double, std::string>(3, 3.5f, "5"));
|
|
v.push_back(Tuple<int, double, std::string>(4, 4.5f, "6"));
|
|
|
|
try { session() << "INSERT INTO Vectors VALUES (?,?,?)", use(v), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
try
|
|
{
|
|
Statement stmt = (session() << "SELECT * FROM Vectors", now);
|
|
RecordSet rset(stmt);
|
|
|
|
assertTrue (3 == rset.columnCount());
|
|
assertTrue (4 == rset.rowCount());
|
|
|
|
int curVal = 3;
|
|
do
|
|
{
|
|
assertTrue (rset["str0"] == curVal);
|
|
++curVal;
|
|
} while (rset.moveNext());
|
|
|
|
rset.moveFirst();
|
|
assertTrue (rset["str0"] == "3");
|
|
rset.moveLast();
|
|
assertTrue (rset["str0"] == "6");
|
|
|
|
RecordSet rset2(rset);
|
|
assertTrue (3 == rset2.columnCount());
|
|
assertTrue (4 == rset2.rowCount());
|
|
|
|
int i = rset.value<int>(0,0);
|
|
assertTrue (1 == i);
|
|
|
|
std::string s = rset.value(0,0).convert<std::string>();
|
|
assertTrue ("1" == s);
|
|
|
|
int a = rset.value<int>(0,2);
|
|
assertTrue (3 == a);
|
|
|
|
try
|
|
{
|
|
double d = rset.value<double>(1,1);
|
|
assertTrue (2.5 == d);
|
|
}
|
|
catch (BadCastException&)
|
|
{
|
|
float f = rset.value<float>(1,1);
|
|
assertTrue (2.5 == f);
|
|
}
|
|
|
|
try
|
|
{
|
|
s = rset.value<std::string>(2, 2);
|
|
}
|
|
catch (BadCastException&)
|
|
{
|
|
UTF16String us = rset.value<Poco::UTF16String>(2, 2);
|
|
Poco::UnicodeConverter::convert(us, s);
|
|
}
|
|
assertTrue ("5" == s);
|
|
|
|
i = rset.value("str0", 2);
|
|
assertTrue (5 == i);
|
|
|
|
const Column<std::deque<int> >& col = rset.column<std::deque<int> >(0);
|
|
Column<std::deque<int> >::Iterator it = col.begin();
|
|
Column<std::deque<int> >::Iterator end = col.end();
|
|
for (int i = 1; it != end; ++it, ++i)
|
|
assertTrue (*it == i);
|
|
|
|
rset = (session() << "SELECT COUNT(*) AS cnt FROM Vectors", now);
|
|
|
|
//various results for COUNT(*) are received from different drivers
|
|
try
|
|
{
|
|
//this is what most drivers will return
|
|
int i = rset.value<int>(0,0);
|
|
assertTrue (4 == i);
|
|
}
|
|
catch(BadCastException&)
|
|
{
|
|
try
|
|
{
|
|
//this is for Oracle
|
|
double i = rset.value<double>(0,0);
|
|
assertTrue (4 == int(i));
|
|
}
|
|
catch(BadCastException&)
|
|
{
|
|
//this is for PostgreSQL
|
|
Poco::Int64 big = rset.value<Poco::Int64>(0,0);
|
|
assertTrue (4 == big);
|
|
}
|
|
}
|
|
|
|
s = rset.value("cnt", 0).convert<std::string>();
|
|
assertTrue ("4" == s);
|
|
|
|
try { rset.column<std::deque<int> >(100); fail ("must fail"); }
|
|
catch (RangeException&) { }
|
|
|
|
try { rset.value<std::string>(0,0); fail ("must fail"); }
|
|
catch (BadCastException&) { }
|
|
|
|
stmt = (session() << "DELETE FROM Vectors", now);
|
|
rset = stmt;
|
|
|
|
try { rset.column<std::deque<int> >(0); fail ("must fail"); }
|
|
catch (RangeException&) { }
|
|
}
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
}
|
|
|
|
|
|
void SQLExecutor::filter(const std::string& query, const std::string& intFldName)
|
|
{
|
|
std::string funct = "filter()";
|
|
std::vector<Tuple<int, double, std::string> > v;
|
|
v.push_back(Tuple<int, double, std::string>(1, 1.5f, "3"));
|
|
v.push_back(Tuple<int, double, std::string>(2, 2.5f, "4"));
|
|
v.push_back(Tuple<int, double, std::string>(3, 3.5f, "5"));
|
|
v.push_back(Tuple<int, double, std::string>(4, 4.5f, "6"));
|
|
|
|
try { session() << "INSERT INTO Vectors VALUES (?,?,?)", use(v), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
try
|
|
{
|
|
Statement stmt = (session() << query, now);
|
|
RecordSet rset(stmt);
|
|
assertTrue (rset.totalRowCount() == 4);
|
|
RowFilter::Ptr pRF = new RowFilter(&rset);
|
|
assertTrue (pRF->isEmpty());
|
|
pRF->add(intFldName, RowFilter::VALUE_EQUAL, 1);
|
|
assertTrue (!pRF->isEmpty());
|
|
|
|
Var da;
|
|
try
|
|
{
|
|
da = rset.value(0, 1);
|
|
fail ("must fail");
|
|
} catch (InvalidAccessException&)
|
|
{
|
|
da = rset.value(0, 1, false);
|
|
assertTrue (2 == da);
|
|
da = rset.value(0, 0);
|
|
assertTrue (1 == da);
|
|
}
|
|
|
|
assertTrue (rset.rowCount() == 1);
|
|
assertTrue (rset.moveFirst());
|
|
assertTrue (1 == rset[intFldName]);
|
|
assertTrue (!rset.moveNext());
|
|
pRF->add("flt0", RowFilter::VALUE_LESS_THAN_OR_EQUAL, 3.5f);
|
|
assertTrue (rset.rowCount() == 3);
|
|
assertTrue (rset.moveNext());
|
|
assertTrue (2.5 == rset["flt0"]);
|
|
assertTrue (rset.moveNext());
|
|
assertTrue (3.5 == rset["flt0"]);
|
|
assertTrue (!rset.moveNext());
|
|
pRF->add("str0", RowFilter::VALUE_EQUAL, 6);
|
|
assertTrue (rset.rowCount() == 4);
|
|
assertTrue (rset.moveLast());
|
|
assertTrue ("6" == rset["str0"]);
|
|
pRF->remove("flt0");
|
|
assertTrue (rset.rowCount() == 2);
|
|
assertTrue (rset.moveFirst());
|
|
assertTrue ("3" == rset["str0"]);
|
|
assertTrue (rset.moveNext());
|
|
assertTrue ("6" == rset["str0"]);
|
|
pRF->remove(intFldName);
|
|
pRF->remove("str0");
|
|
assertTrue (pRF->isEmpty());
|
|
pRF->add("str0", "!=", 3);
|
|
assertTrue (rset.rowCount() == 3);
|
|
|
|
RowFilter::Ptr pRF1 = new RowFilter(pRF, RowFilter::OP_AND);
|
|
pRF1->add(intFldName, "==", 2);
|
|
assertTrue (rset.rowCount() == 1);
|
|
pRF1->add(intFldName, "<", 2);
|
|
assertTrue (rset.rowCount() == 1);
|
|
pRF1->add(intFldName, ">", 3);
|
|
assertTrue (rset.rowCount() == 2);
|
|
pRF->removeFilter(pRF1);
|
|
pRF->remove("str0");
|
|
assertTrue (pRF->isEmpty());
|
|
assertTrue (rset.rowCount() == 4);
|
|
}
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
}
|
|
|
|
|
|
void SQLExecutor::internalBulkExtraction()
|
|
{
|
|
std::string funct = "internalBulkExtraction()";
|
|
int size = 100;
|
|
std::vector<std::string> lastName(size);
|
|
std::vector<std::string> firstName(size);
|
|
std::vector<std::string> address(size);
|
|
std::vector<int> age(size);
|
|
|
|
for (int i = 0; i < size; ++i)
|
|
{
|
|
lastName[i] = "LN" + NumberFormatter::format(i);
|
|
firstName[i] = "FN" + NumberFormatter::format(i);
|
|
address[i] = "Addr" + NumberFormatter::format(i);
|
|
age[i] = i;
|
|
}
|
|
|
|
try
|
|
{
|
|
session() << "INSERT INTO Person VALUES (?,?,?,?)",
|
|
use(lastName, bulk),
|
|
use(firstName, bulk),
|
|
use(address, bulk),
|
|
use(age, bulk),
|
|
now;
|
|
}
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
try
|
|
{
|
|
Statement stmt = (session() << "SELECT * FROM Person", bulk(size), now);
|
|
RecordSet rset(stmt);
|
|
assertTrue (size == rset.rowCount());
|
|
assertTrue ("LN0" == rset["LastName"]);
|
|
assertTrue (0 == rset["Age"]);
|
|
rset.moveNext();
|
|
assertTrue ("LN1" == rset["LastName"]);
|
|
assertTrue (1 == rset["Age"]);
|
|
rset.moveLast();
|
|
assertTrue (std::string("LN") + NumberFormatter::format(size - 1) == rset["LastName"]);
|
|
assertTrue (size - 1 == rset["Age"]);
|
|
}
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
try
|
|
{
|
|
Statement stmt = (session() << "SELECT * FROM Person", limit(size), bulk, now);
|
|
RecordSet rset(stmt);
|
|
assertTrue (size == rset.rowCount());
|
|
assertTrue ("LN0" == rset["LastName"]);
|
|
assertTrue (0 == rset["Age"]);
|
|
rset.moveLast();
|
|
assertTrue (std::string("LN") + NumberFormatter::format(size - 1) == rset["LastName"]);
|
|
assertTrue (size - 1 == rset["Age"]);
|
|
}
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
}
|
|
|
|
|
|
void SQLExecutor::internalBulkExtractionUTF16()
|
|
{
|
|
std::string funct = "internalBulkExtraction()";
|
|
int size = 100;
|
|
std::vector<UTF16String> lastName(size);
|
|
std::vector<UTF16String> firstName(size);
|
|
std::vector<UTF16String> address(size);
|
|
std::vector<int> age(size);
|
|
|
|
for (int i = 0; i < size; ++i)
|
|
{
|
|
lastName[i] = Poco::UnicodeConverter::to<UTF16String>("LN" + NumberFormatter::format(i));
|
|
firstName[i] = Poco::UnicodeConverter::to<UTF16String>("FN" + NumberFormatter::format(i));
|
|
address[i] = Poco::UnicodeConverter::to<UTF16String>("Addr" + NumberFormatter::format(i));
|
|
age[i] = i;
|
|
}
|
|
|
|
try
|
|
{
|
|
session() << "INSERT INTO Person VALUES (?,?,?,?)",
|
|
use(lastName, bulk),
|
|
use(firstName, bulk),
|
|
use(address, bulk),
|
|
use(age, bulk),
|
|
now;
|
|
}
|
|
catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail(funct); }
|
|
catch (StatementException& se){ std::cout << se.toString() << std::endl; fail(funct); }
|
|
|
|
try
|
|
{
|
|
Statement stmt = (session() << "SELECT * FROM Person", bulk(size), now);
|
|
RecordSet rset(stmt);
|
|
assertTrue (size == rset.rowCount());
|
|
assertTrue (Poco::UnicodeConverter::to<UTF16String>("LN0") == rset["LastName"]);
|
|
assertTrue (0 == rset["Age"]);
|
|
rset.moveNext();
|
|
assertTrue (Poco::UnicodeConverter::to<UTF16String>("LN1") == rset["LastName"]);
|
|
assertTrue (1 == rset["Age"]);
|
|
rset.moveLast();
|
|
assertTrue (std::string("LN") + NumberFormatter::format(size - 1) == rset["LastName"]);
|
|
assertTrue (size - 1 == rset["Age"]);
|
|
}
|
|
catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail(funct); }
|
|
catch (StatementException& se){ std::cout << se.toString() << std::endl; fail(funct); }
|
|
|
|
try
|
|
{
|
|
Statement stmt = (session() << "SELECT * FROM Person", limit(size), bulk, now);
|
|
RecordSet rset(stmt);
|
|
assertTrue (size == rset.rowCount());
|
|
assertTrue ("LN0" == rset["LastName"]);
|
|
assertTrue (0 == rset["Age"]);
|
|
rset.moveLast();
|
|
assertTrue (std::string("LN") + NumberFormatter::format(size - 1) == rset["LastName"]);
|
|
assertTrue (size - 1 == rset["Age"]);
|
|
}
|
|
catch (ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail(funct); }
|
|
catch (StatementException& se){ std::cout << se.toString() << std::endl; fail(funct); }
|
|
}
|
|
|
|
|
|
void SQLExecutor::internalStorageType()
|
|
{
|
|
std::string funct = "internalStorageType()";
|
|
std::vector<Statement::Manipulator> manips;
|
|
manips.push_back(list);
|
|
manips.push_back(deque);
|
|
manips.push_back(vector);
|
|
|
|
std::vector<Tuple<int, double, std::string> > v;
|
|
v.push_back(Tuple<int, double, std::string>(1, 1.5f, "3"));
|
|
v.push_back(Tuple<int, double, std::string>(2, 2.5f, "4"));
|
|
v.push_back(Tuple<int, double, std::string>(3, 3.5f, "5"));
|
|
v.push_back(Tuple<int, double, std::string>(4, 4.5f, "6"));
|
|
|
|
try { session() << "INSERT INTO Vectors VALUES (?,?,?)", use(v), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
try
|
|
{
|
|
std::vector<Statement::Manipulator>::iterator it = manips.begin();
|
|
std::vector<Statement::Manipulator>::iterator end = manips.end();
|
|
|
|
for (; it != end; ++it)
|
|
{
|
|
Statement stmt = (session() << "SELECT * FROM Vectors", *it, now);
|
|
RecordSet rset(stmt);
|
|
|
|
assertTrue (3 == rset.columnCount());
|
|
assertTrue (4 == rset.rowCount());
|
|
|
|
int curVal = 3;
|
|
do
|
|
{
|
|
assertTrue (rset["str0"] == curVal);
|
|
++curVal;
|
|
} while (rset.moveNext());
|
|
|
|
rset.moveFirst();
|
|
assertTrue (rset["str0"] == "3");
|
|
rset.moveLast();
|
|
assertTrue (rset["str0"] == "6");
|
|
|
|
try
|
|
{
|
|
stmt = (session() << "SELECT * FROM Vectors", now, *it);
|
|
fail ("must fail");
|
|
}
|
|
catch(InvalidAccessException&){}
|
|
|
|
try
|
|
{
|
|
stmt = (session() << "SELECT * FROM Vectors", into(v), now, *it);
|
|
fail ("must fail");
|
|
}
|
|
catch(InvalidAccessException&){}
|
|
|
|
try
|
|
{
|
|
stmt = (session() << "SELECT * FROM Vectors", into(v), *it, now);
|
|
fail ("must fail");
|
|
}
|
|
catch(InvalidAccessException&){}
|
|
}
|
|
}
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
}
|
|
|
|
|
|
void SQLExecutor::notNulls(const std::string& sqlState)
|
|
{
|
|
try
|
|
{
|
|
session() << "INSERT INTO NullTest (i,r,v) VALUES (?,?,?)", use(null), use(null), use(null), now;
|
|
fail ("must fail");
|
|
}catch (StatementException& se)
|
|
{
|
|
//double check if we're failing for the right reason
|
|
//default sqlState value is "23502"; some drivers report "HY???" codes
|
|
if (se.diagnostics().fields().size())
|
|
{
|
|
std::string st = se.diagnostics().sqlState(0);
|
|
if (sqlState != st)
|
|
std::cerr << '[' << name() << ']' << " Warning: expected SQL state [" << sqlState <<
|
|
"], received [" << se.diagnostics().sqlState(0) << "] instead." << std::endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void SQLExecutor::nulls()
|
|
{
|
|
std::string funct = "nulls()";
|
|
|
|
try { session() << "INSERT INTO NullTest (i,r,v) VALUES (?,?,?)", use(null), use(null), use(null), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
RecordSet rs(session(), "SELECT * FROM NullTest");
|
|
assertTrue (1 == rs.rowCount());
|
|
rs.moveFirst();
|
|
assertTrue (rs.isNull("i"));
|
|
assertTrue (rs["i"] != 0);
|
|
assertTrue (rs.isNull("r"));
|
|
assertTrue (rs.isNull("v"));
|
|
assertTrue (rs["v"] != "");
|
|
assertTrue (rs.nvl<int>("i") == 0);
|
|
assertTrue (rs.nvl("i", -1) == -1);
|
|
assertTrue (rs.nvl<double>("r") == double());
|
|
assertTrue (rs.nvl("r", -1.5) == -1.5);
|
|
assertTrue (rs.nvl<std::string>("v") == "");
|
|
assertTrue (rs.nvl("v", "123") == "123");
|
|
try { session() << "DELETE FROM NullTest", now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
int i = 1;
|
|
double f = 1.5;
|
|
std::string s = "123";
|
|
|
|
try { session() << "INSERT INTO NullTest (i, r, v) VALUES (?,?,?)", use(i), use(f), use(s), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
rs = (session() << "SELECT * FROM NullTest", now);
|
|
assertTrue (1 == rs.rowCount());
|
|
rs.moveFirst();
|
|
assertTrue (!rs.isNull("i"));
|
|
assertTrue (rs["i"] == 1);
|
|
assertTrue (!rs.isNull("v"));
|
|
assertTrue (!rs.isNull("r"));
|
|
assertTrue (rs["v"] == "123");
|
|
assertTrue (rs.nvl<int>("i") == 1);
|
|
assertTrue (rs.nvl("i", -1) == 1);
|
|
assertTrue (rs.nvl<double>("r") == 1.5);
|
|
assertTrue (rs.nvl("r", -1.5) == 1.5);
|
|
assertTrue (rs.nvl<std::string>("v") == "123");
|
|
assertTrue (rs.nvl("v", "456") == "123");
|
|
try { session() << "UPDATE NullTest SET v = ? WHERE i = ?", use(null), use(i), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
i = 2;
|
|
f = 3.4;
|
|
try { session() << "INSERT INTO NullTest (i, r, v) VALUES (?,?,?)", use(i), use(null), use(null), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
rs = (session() << "SELECT i, r, v FROM NullTest ORDER BY i ASC", now);
|
|
assertTrue (2 == rs.rowCount());
|
|
rs.moveFirst();
|
|
assertTrue (!rs.isNull("i"));
|
|
assertTrue (rs["i"] == 1);
|
|
assertTrue (!rs.isNull("r"));
|
|
assertTrue (rs.isNull("v"));
|
|
assertTrue (rs["v"] != "");
|
|
|
|
assertTrue (rs.moveNext());
|
|
assertTrue (!rs.isNull("i"));
|
|
assertTrue (rs["i"] == 2);
|
|
assertTrue (rs.isNull("r"));
|
|
assertTrue (rs.isNull("v"));
|
|
assertTrue (rs["v"] != "");
|
|
|
|
try { session() << "DELETE FROM NullTest", now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
try { session() << "INSERT INTO NullTest (v) VALUES (?)", bind(""), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
bool esin = session().getFeature("emptyStringIsNull");
|
|
session().setFeature("emptyStringIsNull", true);
|
|
|
|
try
|
|
{
|
|
session().setFeature("forceEmptyString", true);
|
|
fail ("must fail");
|
|
} catch (InvalidAccessException&) { }
|
|
|
|
bool fes = session().getFeature("forceEmptyString");
|
|
session().setFeature("forceEmptyString", false);
|
|
|
|
RecordSet rs1(session(), "SELECT v FROM NullTest");
|
|
assertTrue (1 == rs1.rowCount());
|
|
rs1.moveFirst();
|
|
assertTrue (rs1.isNull("v"));
|
|
assertTrue (!(rs["v"] == ""));
|
|
|
|
session().setFeature("emptyStringIsNull", false);
|
|
session().setFeature("forceEmptyString", true);
|
|
RecordSet rs2(session(), "SELECT v FROM NullTest");
|
|
assertTrue (1 == rs2.rowCount());
|
|
rs2.moveFirst();
|
|
assertTrue (!rs2.isNull("v"));
|
|
assertTrue ((rs2["v"] == ""));
|
|
|
|
try
|
|
{
|
|
session().setFeature("emptyStringIsNull", true);
|
|
fail ("must fail");
|
|
} catch (InvalidAccessException&) { }
|
|
|
|
session().setFeature("emptyStringIsNull", esin);
|
|
session().setFeature("forceEmptyString", fes);
|
|
}
|
|
|
|
|
|
void SQLExecutor::rowIterator()
|
|
{
|
|
std::string funct = "rowIterator()";
|
|
std::vector<Tuple<int, double, std::string> > v;
|
|
v.push_back(Tuple<int, double, std::string>(1, 1.5f, "3"));
|
|
v.push_back(Tuple<int, double, std::string>(2, 2.5f, "4"));
|
|
v.push_back(Tuple<int, double, std::string>(3, 3.5f, "5"));
|
|
v.push_back(Tuple<int, double, std::string>(4, 4.5f, "6"));
|
|
|
|
try { session() << "DELETE FROM Vectors", now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
RecordSet rset0(session(), "SELECT * FROM Vectors");
|
|
assertTrue (rset0.begin() == rset0.end());
|
|
|
|
try { session() << "INSERT INTO Vectors VALUES (?,?,?)", use(v), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
RecordSet rset(session(), "SELECT * FROM Vectors");
|
|
|
|
std::ostringstream osLoop;
|
|
RecordSet::Iterator it = rset.begin();
|
|
RecordSet::Iterator end = rset.end();
|
|
for (int i = 1; it != end; ++it, ++i)
|
|
{
|
|
assertTrue (it->get(0) == i);
|
|
osLoop << *it;
|
|
}
|
|
assertTrue (!osLoop.str().empty());
|
|
|
|
std::ostringstream osCopy;
|
|
std::copy(rset.begin(), rset.end(), std::ostream_iterator<Row>(osCopy));
|
|
assertTrue (osLoop.str() == osCopy.str());
|
|
|
|
RowFilter::Ptr pRF = new RowFilter(&rset);
|
|
assertTrue (pRF->isEmpty());
|
|
pRF->add("str0", RowFilter::VALUE_EQUAL, "3");
|
|
assertTrue (!pRF->isEmpty());
|
|
it = rset.begin();
|
|
end = rset.end();
|
|
for (int i = 1; it != end; ++it, ++i)
|
|
{
|
|
assertTrue (it->get(0) == i);
|
|
assertTrue (1 == i);
|
|
}
|
|
}
|
|
|
|
|
|
void SQLExecutor::stdVectorBool()
|
|
{
|
|
std::string funct = "stdVectorBool()";
|
|
|
|
bool b = false;
|
|
try { session() << "INSERT INTO BoolTest VALUES (?)", use(b), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
b = true;
|
|
session() << "SELECT * FROM BoolTest", into(b), now;
|
|
assertTrue (false == b);
|
|
session() << "DELETE FROM BoolTest", now;
|
|
|
|
b = true;
|
|
try { session() << "INSERT INTO BoolTest VALUES (?)", use(b), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
b = false;
|
|
session() << "SELECT * FROM BoolTest", into(b), now;
|
|
assertTrue (true == b);
|
|
session() << "DELETE FROM BoolTest", now;
|
|
|
|
std::vector<bool> v;
|
|
v.push_back(true);
|
|
v.push_back(false);
|
|
v.push_back(false);
|
|
v.push_back(true);
|
|
|
|
try { session() << "INSERT INTO BoolTest VALUES (?)", use(v), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
v.clear();
|
|
session() << "SELECT * FROM BoolTest", into(v), now;
|
|
|
|
assertTrue (4 == v.size());
|
|
std::vector<bool>::iterator it = v.begin();
|
|
std::vector<bool>::iterator end = v.end();
|
|
int t = 0;
|
|
for (; it != end; ++it)
|
|
t += *it ? 1 : 0;
|
|
assertTrue (2 == t);
|
|
|
|
try { session() << "SELECT * FROM BoolTest WHERE b = ?", out(v), now; fail("must fail"); }
|
|
catch (BindingException&) { }
|
|
|
|
try { session() << "SELECT * FROM BoolTest WHERE b = ?", io(v), now; fail("must fail"); }
|
|
catch (BindingException&) { }
|
|
|
|
RecordSet rset(session(), "SELECT * FROM BoolTest");
|
|
|
|
t = 0;
|
|
for (int i = 0; i < 4; ++i)
|
|
t += rset.value<bool>(0, i) ? 1 : 0;
|
|
assertTrue (2 == t);
|
|
}
|
|
|
|
|
|
void SQLExecutor::asynchronous(int rowCount)
|
|
{
|
|
Session tmp = session();
|
|
|
|
std::vector<int> data(rowCount);
|
|
Statement stmt = (tmp << "INSERT INTO Strings VALUES(?)", use(data));
|
|
Statement::Result result = stmt.executeAsync();
|
|
assertTrue (!stmt.isAsync());
|
|
result.wait();
|
|
|
|
Statement stmt1 = (tmp << "SELECT * FROM Strings", into(data), async, now);
|
|
assertTrue (stmt1.isAsync());
|
|
assertTrue (stmt1.wait() == rowCount);
|
|
|
|
// +++ if this part of the test case fails, increase the rowCount until achieved
|
|
// that first execute is still executing when the second one is called
|
|
stmt1.execute();
|
|
try {
|
|
stmt1.execute();
|
|
fail ("execute() must fail");
|
|
} catch (InvalidAccessException&)
|
|
{
|
|
stmt1.wait();
|
|
stmt1.execute();
|
|
stmt1.wait();
|
|
}
|
|
// ---
|
|
|
|
stmt = tmp << "SELECT * FROM Strings", into(data), async, now;
|
|
assertTrue (stmt.isAsync());
|
|
stmt.wait();
|
|
assertTrue (stmt.execute() == 0);
|
|
|
|
// +++ if this part of the test case fails, increase the rowCount until achieved
|
|
// that first execute is still executing when the second one is called
|
|
try {
|
|
result = stmt.executeAsync();
|
|
fail ("executeAsync() must fail");
|
|
} catch (InvalidAccessException&)
|
|
{
|
|
assertTrue (stmt.isAsync());
|
|
stmt.wait();
|
|
result = stmt.executeAsync();
|
|
}
|
|
// ---
|
|
|
|
assertTrue (stmt.wait() == rowCount);
|
|
assertTrue (result.data() == rowCount);
|
|
stmt.setAsync(false);
|
|
assertTrue (!stmt.isAsync());
|
|
assertTrue (stmt.execute() == rowCount);
|
|
|
|
stmt = tmp << "SELECT * FROM Strings", into(data), sync, now;
|
|
assertTrue (!stmt.isAsync());
|
|
assertTrue (stmt.wait() == 0);
|
|
assertTrue (stmt.execute() == rowCount);
|
|
result = stmt.executeAsync();
|
|
assertTrue (!stmt.isAsync());
|
|
result.wait();
|
|
assertTrue (result.data() == rowCount);
|
|
|
|
assertTrue (0 == rowCount % 10);
|
|
int step = (int) (rowCount/10);
|
|
data.clear();
|
|
Statement stmt2 = (tmp << "SELECT * FROM Strings", into(data), async, limit(step));
|
|
assertTrue (data.size() == 0);
|
|
assertTrue (!stmt2.done());
|
|
std::size_t rows = 0;
|
|
|
|
for (int i = 0; !stmt2.done(); i += step)
|
|
{
|
|
stmt2.execute();
|
|
rows = stmt2.wait();
|
|
assertTrue (step == rows);
|
|
assertTrue (step + i == data.size());
|
|
}
|
|
assertTrue (stmt2.done());
|
|
assertTrue (rowCount == data.size());
|
|
|
|
stmt2 = tmp << "SELECT * FROM Strings", reset;
|
|
assertTrue (!stmt2.isAsync());
|
|
assertTrue ("deque" == stmt2.getStorage());
|
|
assertTrue (stmt2.execute() == rowCount);
|
|
}
|
|
|
|
|
|
void SQLExecutor::any()
|
|
{
|
|
Any i = 42;
|
|
Any f = 42.5;
|
|
std::string ss("42");
|
|
Any s = ss;
|
|
#ifdef POCO_ODBC_UNICODE
|
|
UTF16String us;
|
|
Poco::UnicodeConverter::convert(ss, us);
|
|
s = us;
|
|
#endif
|
|
Session tmp = session();
|
|
|
|
tmp << "INSERT INTO Anys VALUES (?, ?, ?)", use(i), use(f), use(s), now;
|
|
|
|
int count = 0;
|
|
tmp << "SELECT COUNT(*) FROM Anys", into(count), now;
|
|
assertTrue (1 == count);
|
|
|
|
i = 0;
|
|
f = 0.0;
|
|
s = std::string("");
|
|
tmp << "SELECT * FROM Anys", into(i), into(f), into(s), now;
|
|
assertTrue (AnyCast<int>(i) == 42);
|
|
assertTrue (AnyCast<double>(f) == 42.5);
|
|
#ifdef POCO_ODBC_UNICODE
|
|
// drivers may behave differently here
|
|
try
|
|
{
|
|
assertTrue (AnyCast<UTF16String>(s) == us);
|
|
}
|
|
catch (BadCastException&)
|
|
{
|
|
assertTrue (AnyCast<std::string>(s) == "42");
|
|
}
|
|
#else
|
|
assertTrue (AnyCast<std::string>(s) == "42");
|
|
#endif
|
|
}
|
|
|
|
|
|
void SQLExecutor::dynamicAny()
|
|
{
|
|
Var i = 42;
|
|
Var f = 42.5;
|
|
Var s = "42";
|
|
|
|
Session tmp = session();
|
|
tmp << "INSERT INTO Anys VALUES (?, ?, ?)", use(i), use(f), use(s), now;
|
|
|
|
int count = 0;
|
|
tmp << "SELECT COUNT(*) FROM Anys", into(count), now;
|
|
assertTrue (1 == count);
|
|
|
|
i = 0;
|
|
f = 0.0;
|
|
s = std::string("");
|
|
tmp << "SELECT * FROM Anys", into(i), into(f), into(s), now;
|
|
assertTrue (42 == i);
|
|
assertTrue (42.5 == f);
|
|
assertTrue ("42" == s);
|
|
}
|
|
|
|
|
|
void SQLExecutor::multipleResults(const std::string& sql)
|
|
{
|
|
typedef Tuple<std::string, std::string, std::string, Poco::UInt32> Person;
|
|
std::vector<Person> people;
|
|
people.push_back(Person("Simpson", "Homer", "Springfield", 42));
|
|
people.push_back(Person("Simpson", "Marge", "Springfield", 38));
|
|
people.push_back(Person("Simpson", "Bart", "Springfield", 10));
|
|
people.push_back(Person("Simpson", "Lisa", "Springfield", 8));
|
|
people.push_back(Person("Simpson", "Maggie", "Springfield", 3));
|
|
session() << "INSERT INTO Person VALUES (?, ?, ?, ?)", use(people), now;
|
|
|
|
Person pHomer;
|
|
int aHomer = 42, aLisa = 8;
|
|
Poco::UInt32 aBart = 0;
|
|
|
|
Poco::UInt32 pos1 = 1;
|
|
int pos2 = 2;
|
|
std::vector<Person> people2;
|
|
Statement stmt(session());
|
|
stmt << sql, into(pHomer, from(0)), use(aHomer)
|
|
, into(aBart, pos1)
|
|
, into(people2, from(pos2)), use(aLisa), use(aHomer);
|
|
|
|
assertTrue (4 == stmt.execute());
|
|
assertTrue (Person("Simpson", "Homer", "Springfield", 42) == pHomer);
|
|
assertTrue (10 == aBart);
|
|
assertTrue (2 == people2.size());
|
|
assertTrue (Person("Simpson", "Lisa", "Springfield", 8) == people2[0]);
|
|
assertTrue (Person("Simpson", "Homer", "Springfield", 42) == people2[1]);
|
|
}
|
|
|
|
|
|
void SQLExecutor::sqlChannel(const std::string& connect)
|
|
{
|
|
try
|
|
{
|
|
AutoPtr<SQLChannel> pChannel = new SQLChannel(Poco::Data::ODBC::Connector::KEY, connect, "TestSQLChannel");
|
|
pChannel->setProperty("keep", "2 seconds");
|
|
|
|
Message msgInf("InformationSource", "a Informational async message", Message::PRIO_INFORMATION);
|
|
pChannel->log(msgInf);
|
|
Message msgWarn("WarningSource", "b Warning async message", Message::PRIO_WARNING);
|
|
pChannel->log(msgWarn);
|
|
pChannel->wait();
|
|
|
|
pChannel->setProperty("async", "false");
|
|
Message msgInfS("InformationSource", "c Informational sync message", Message::PRIO_INFORMATION);
|
|
pChannel->log(msgInfS);
|
|
Message msgWarnS("WarningSource", "d Warning sync message", Message::PRIO_WARNING);
|
|
pChannel->log(msgWarnS);
|
|
|
|
RecordSet rs(session(), "SELECT * FROM T_POCO_LOG ORDER by Text");
|
|
assertTrue (4 == rs.rowCount());
|
|
assertTrue ("InformationSource" == rs["Source"]);
|
|
assertTrue ("a Informational async message" == rs["Text"]);
|
|
rs.moveNext();
|
|
assertTrue ("WarningSource" == rs["Source"]);
|
|
assertTrue ("b Warning async message" == rs["Text"]);
|
|
rs.moveNext();
|
|
assertTrue ("InformationSource" == rs["Source"]);
|
|
assertTrue ("c Informational sync message" == rs["Text"]);
|
|
rs.moveNext();
|
|
assertTrue ("WarningSource" == rs["Source"]);
|
|
assertTrue ("d Warning sync message" == rs["Text"]);
|
|
|
|
Thread::sleep(3000);
|
|
|
|
Message msgInfA("InformationSource", "e Informational sync message", Message::PRIO_INFORMATION);
|
|
pChannel->log(msgInfA);
|
|
Message msgWarnA("WarningSource", "f Warning sync message", Message::PRIO_WARNING);
|
|
pChannel->log(msgWarnA);
|
|
|
|
RecordSet rs1(session(), "SELECT * FROM T_POCO_LOG_ARCHIVE");
|
|
assertTrue (4 == rs1.rowCount());
|
|
|
|
pChannel->setProperty("keep", "");
|
|
assertTrue ("forever" == pChannel->getProperty("keep"));
|
|
RecordSet rs2(session(), "SELECT * FROM T_POCO_LOG ORDER by Text");
|
|
assertTrue (2 == rs2.rowCount());
|
|
assertTrue ("InformationSource" == rs2["Source"]);
|
|
assertTrue ("e Informational sync message" == rs2["Text"]);
|
|
rs2.moveNext();
|
|
assertTrue ("WarningSource" == rs2["Source"]);
|
|
assertTrue ("f Warning sync message" == rs2["Text"]);
|
|
|
|
}
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("sqlChannel()"); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("sqlChannel()"); }
|
|
}
|
|
|
|
|
|
void SQLExecutor::sqlLogger(const std::string& connect)
|
|
{
|
|
try
|
|
{
|
|
Logger& root = Logger::root();
|
|
root.setChannel(new SQLChannel(Poco::Data::ODBC::Connector::KEY, connect, "TestSQLChannel"));
|
|
root.setLevel(Message::PRIO_INFORMATION);
|
|
|
|
root.information("a Informational message");
|
|
root.warning("b Warning message");
|
|
root.debug("Debug message");
|
|
|
|
Thread::sleep(100);
|
|
RecordSet rs(session(), "SELECT * FROM T_POCO_LOG ORDER by Text");
|
|
assertTrue (2 == rs.rowCount());
|
|
assertTrue ("TestSQLChannel" == rs["Source"]);
|
|
assertTrue ("a Informational message" == rs["Text"]);
|
|
rs.moveNext();
|
|
assertTrue ("TestSQLChannel" == rs["Source"]);
|
|
assertTrue ("b Warning message" == rs["Text"]);
|
|
}
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("sqlLogger()"); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("sqlLogger()"); }
|
|
}
|
|
|
|
|
|
void SQLExecutor::setTransactionIsolation(Session& session, Poco::UInt32 ti)
|
|
{
|
|
if (session.hasTransactionIsolation(ti))
|
|
{
|
|
std::string funct = "setTransactionIsolation()";
|
|
|
|
try
|
|
{
|
|
Transaction t(session, false);
|
|
t.setIsolation(ti);
|
|
|
|
assertTrue (ti == t.getIsolation());
|
|
assertTrue (t.isIsolation(ti));
|
|
|
|
assertTrue (ti == session.getTransactionIsolation());
|
|
assertTrue (session.isTransactionIsolation(ti));
|
|
}
|
|
catch(Poco::Exception& e){ std::cout << funct << ':' << e.displayText() << std::endl;}
|
|
}
|
|
else
|
|
{
|
|
std::cerr << '[' << name() << ']' << " Warning, transaction isolation not supported: ";
|
|
switch (ti)
|
|
{
|
|
case Session::TRANSACTION_READ_COMMITTED:
|
|
std::cerr << "READ COMMITTED"; break;
|
|
case Session::TRANSACTION_READ_UNCOMMITTED:
|
|
std::cerr << "READ UNCOMMITTED"; break;
|
|
case Session::TRANSACTION_REPEATABLE_READ:
|
|
std::cerr << "REPEATABLE READ"; break;
|
|
case Session::TRANSACTION_SERIALIZABLE:
|
|
std::cerr << "SERIALIZABLE"; break;
|
|
default:
|
|
std::cerr << "UNKNOWN"; break;
|
|
}
|
|
std::cerr << std::endl;
|
|
}
|
|
}
|
|
|
|
|
|
void SQLExecutor::sessionTransaction(const std::string& connect)
|
|
{
|
|
if (!session().canTransact())
|
|
{
|
|
std::cout << "Session not capable of transactions." << std::endl;
|
|
return;
|
|
}
|
|
|
|
Session local("odbc", connect);
|
|
local.setFeature("autoCommit", true);
|
|
|
|
std::string funct = "transaction()";
|
|
std::vector<std::string> lastNames;
|
|
std::vector<std::string> firstNames;
|
|
std::vector<std::string> addresses;
|
|
std::vector<int> ages;
|
|
std::string tableName("Person");
|
|
lastNames.push_back("LN1");
|
|
lastNames.push_back("LN2");
|
|
firstNames.push_back("FN1");
|
|
firstNames.push_back("FN2");
|
|
addresses.push_back("ADDR1");
|
|
addresses.push_back("ADDR2");
|
|
ages.push_back(1);
|
|
ages.push_back(2);
|
|
int count = 0, locCount = 0;
|
|
std::string result;
|
|
|
|
bool autoCommit = session().getFeature("autoCommit");
|
|
|
|
session().setFeature("autoCommit", true);
|
|
assertTrue (!session().isTransaction());
|
|
session().setFeature("autoCommit", false);
|
|
assertTrue (!session().isTransaction());
|
|
|
|
setTransactionIsolation(session(), Session::TRANSACTION_READ_UNCOMMITTED);
|
|
setTransactionIsolation(session(), Session::TRANSACTION_REPEATABLE_READ);
|
|
setTransactionIsolation(session(), Session::TRANSACTION_SERIALIZABLE);
|
|
|
|
setTransactionIsolation(session(), Session::TRANSACTION_READ_COMMITTED);
|
|
|
|
session().begin();
|
|
assertTrue (session().isTransaction());
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (session().isTransaction());
|
|
|
|
Statement stmt = (local << "SELECT COUNT(*) FROM Person", into(locCount), async, now);
|
|
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (2 == count);
|
|
assertTrue (session().isTransaction());
|
|
session().rollback();
|
|
assertTrue (!session().isTransaction());
|
|
|
|
stmt.wait();
|
|
assertTrue (0 == locCount);
|
|
|
|
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (0 == count);
|
|
assertTrue (!session().isTransaction());
|
|
|
|
session().begin();
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (session().isTransaction());
|
|
|
|
Statement stmt1 = (local << "SELECT COUNT(*) FROM Person", into(locCount), async, now);
|
|
|
|
session().commit();
|
|
assertTrue (!session().isTransaction());
|
|
|
|
stmt1.wait();
|
|
assertTrue (2 == locCount);
|
|
|
|
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (2 == count);
|
|
|
|
session().setFeature("autoCommit", autoCommit);
|
|
}
|
|
|
|
|
|
void SQLExecutor::transaction(const std::string& connect)
|
|
{
|
|
if (!session().canTransact())
|
|
{
|
|
std::cout << "Session not transaction-capable." << std::endl;
|
|
return;
|
|
}
|
|
|
|
Session local("odbc", connect);
|
|
local.setFeature("autoCommit", true);
|
|
|
|
setTransactionIsolation(session(), Session::TRANSACTION_READ_COMMITTED);
|
|
if (local.hasTransactionIsolation(Session::TRANSACTION_READ_UNCOMMITTED))
|
|
setTransactionIsolation(local, Session::TRANSACTION_READ_UNCOMMITTED);
|
|
else if (local.hasTransactionIsolation(Session::TRANSACTION_READ_COMMITTED))
|
|
setTransactionIsolation(local, Session::TRANSACTION_READ_COMMITTED);
|
|
|
|
std::string funct = "transaction()";
|
|
std::vector<std::string> lastNames;
|
|
std::vector<std::string> firstNames;
|
|
std::vector<std::string> addresses;
|
|
std::vector<int> ages;
|
|
std::string tableName("Person");
|
|
lastNames.push_back("LN1");
|
|
lastNames.push_back("LN2");
|
|
firstNames.push_back("FN1");
|
|
firstNames.push_back("FN2");
|
|
addresses.push_back("ADDR1");
|
|
addresses.push_back("ADDR2");
|
|
ages.push_back(1);
|
|
ages.push_back(2);
|
|
int count = 0, locCount = 0;
|
|
std::string result;
|
|
|
|
bool autoCommit = session().getFeature("autoCommit");
|
|
|
|
session().setFeature("autoCommit", true);
|
|
assertTrue (!session().isTransaction());
|
|
session().setFeature("autoCommit", false);
|
|
assertTrue (!session().isTransaction());
|
|
session().setTransactionIsolation(Session::TRANSACTION_READ_COMMITTED);
|
|
|
|
{
|
|
Transaction trans(session());
|
|
assertTrue (trans.isActive());
|
|
assertTrue (session().isTransaction());
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
assertTrue (session().isTransaction());
|
|
assertTrue (trans.isActive());
|
|
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (2 == count);
|
|
assertTrue (session().isTransaction());
|
|
assertTrue (trans.isActive());
|
|
}
|
|
assertTrue (!session().isTransaction());
|
|
|
|
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (0 == count);
|
|
assertTrue (!session().isTransaction());
|
|
|
|
{
|
|
Transaction trans(session());
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
Statement stmt1 = (local << "SELECT COUNT(*) FROM Person", into(locCount), async, now);
|
|
|
|
assertTrue (session().isTransaction());
|
|
assertTrue (trans.isActive());
|
|
trans.commit();
|
|
assertTrue (!session().isTransaction());
|
|
assertTrue (!trans.isActive());
|
|
|
|
stmt1.wait();
|
|
assertTrue (2 == locCount);
|
|
}
|
|
|
|
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (2 == count);
|
|
|
|
try { session() << "DELETE FROM Person", now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
Statement stmt1 = (local << "SELECT count(*) FROM Person", into(locCount), async, now);
|
|
|
|
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (0 == count);
|
|
try
|
|
{
|
|
stmt1.wait(5000);
|
|
if (local.getTransactionIsolation() == Session::TRANSACTION_READ_UNCOMMITTED)
|
|
assertTrue (0 == locCount);
|
|
} catch (TimeoutException&)
|
|
{ std::cerr << '[' << name() << ']' << " Warning: async query timed out." << std::endl; }
|
|
session().commit();
|
|
// repeat for those that don't support uncommitted read isolation
|
|
if (local.getTransactionIsolation() == Session::TRANSACTION_READ_COMMITTED)
|
|
{
|
|
stmt1.wait();
|
|
local << "SELECT count(*) FROM Person", into(locCount), now;
|
|
assertTrue (0 == locCount);
|
|
}
|
|
|
|
std::string sql1 = format("INSERT INTO Person VALUES ('%s','%s','%s',%d)", lastNames[0], firstNames[0], addresses[0], ages[0]);
|
|
std::string sql2 = format("INSERT INTO Person VALUES ('%s','%s','%s',%d)", lastNames[1], firstNames[1], addresses[1], ages[1]);
|
|
std::vector<std::string> sql;
|
|
sql.push_back(sql1);
|
|
sql.push_back(sql2);
|
|
|
|
Transaction trans(session());
|
|
|
|
trans.execute(sql1, false);
|
|
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (1 == count);
|
|
trans.execute(sql2, false);
|
|
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (2 == count);
|
|
|
|
Statement stmt2 = (local << "SELECT COUNT(*) FROM Person", into(locCount), async, now);
|
|
|
|
trans.rollback();
|
|
|
|
stmt2.wait();
|
|
assertTrue (0 == locCount);
|
|
|
|
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (0 == count);
|
|
|
|
trans.execute(sql);
|
|
|
|
Statement stmt3 = (local << "SELECT COUNT(*) FROM Person", into(locCount), now);
|
|
assertTrue (2 == locCount);
|
|
|
|
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (2 == count);
|
|
|
|
session().setFeature("autoCommit", autoCommit);
|
|
}
|
|
|
|
|
|
struct TestCommitTransactor
|
|
{
|
|
void operator () (Session& session) const
|
|
{
|
|
session << "INSERT INTO Person VALUES ('lastName','firstName','address',10)", now;
|
|
}
|
|
};
|
|
|
|
|
|
struct TestRollbackTransactor
|
|
{
|
|
void operator () (Session& session) const
|
|
{
|
|
session << "INSERT INTO Person VALUES ('lastName','firstName','address',10)", now;
|
|
throw Poco::Exception("test");
|
|
}
|
|
};
|
|
|
|
|
|
void SQLExecutor::transactor()
|
|
{
|
|
std::string funct = "transaction()";
|
|
int count = 0;
|
|
|
|
bool autoCommit = session().getFeature("autoCommit");
|
|
session().setFeature("autoCommit", false);
|
|
session().setTransactionIsolation(Session::TRANSACTION_READ_COMMITTED);
|
|
|
|
TestCommitTransactor ct;
|
|
Transaction t1(session(), ct);
|
|
|
|
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (1 == count);
|
|
|
|
try { session() << "DELETE FROM Person", now; session().commit();}
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (0 == count);
|
|
|
|
try
|
|
{
|
|
TestRollbackTransactor rt;
|
|
Transaction t(session(), rt);
|
|
fail ("must fail");
|
|
} catch (Poco::Exception&) { }
|
|
|
|
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (0 == count);
|
|
|
|
try
|
|
{
|
|
TestRollbackTransactor rt;
|
|
Transaction t(session());
|
|
t.transact(rt);
|
|
fail ("must fail");
|
|
} catch (Poco::Exception&) { }
|
|
|
|
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (0 == count);
|
|
|
|
try
|
|
{
|
|
TestRollbackTransactor rt;
|
|
Transaction t(session(), false);
|
|
t.transact(rt);
|
|
fail ("must fail");
|
|
} catch (Poco::Exception&) { }
|
|
|
|
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (0 == count);
|
|
|
|
try
|
|
{
|
|
TestRollbackTransactor rt;
|
|
Transaction t(session(), true);
|
|
t.transact(rt);
|
|
fail ("must fail");
|
|
} catch (Poco::Exception&) { }
|
|
|
|
try { session() << "SELECT count(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (0 == count);
|
|
|
|
session().setFeature("autoCommit", autoCommit);
|
|
}
|
|
|
|
|
|
void SQLExecutor::nullable()
|
|
{
|
|
try { session() << "INSERT INTO NullableTest VALUES(NULL, NULL, NULL, NULL)", now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("nullable()"); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("nullable()"); }
|
|
|
|
Nullable<int> i = 1;
|
|
Nullable<double> f = 1.5;
|
|
Nullable<std::string> s = std::string("abc");
|
|
Nullable<DateTime> d = DateTime();
|
|
|
|
assertTrue (!i.isNull());
|
|
assertTrue (!f.isNull());
|
|
assertTrue (!s.isNull());
|
|
assertTrue (!d.isNull());
|
|
|
|
session() << "SELECT EmptyString, EmptyInteger, EmptyFloat, EmptyDateTime FROM NullableTest", into(s), into(i), into(f), into(d), now;
|
|
|
|
assertTrue (i.isNull());
|
|
assertTrue (f.isNull());
|
|
assertTrue (s.isNull());
|
|
assertTrue (d.isNull());
|
|
|
|
RecordSet rs(session(), "SELECT * FROM NullableTest");
|
|
|
|
rs.moveFirst();
|
|
assertTrue (rs.isNull("EmptyString"));
|
|
assertTrue (rs.isNull("EmptyInteger"));
|
|
assertTrue (rs.isNull("EmptyFloat"));
|
|
assertTrue (rs.isNull("EmptyDateTime"));
|
|
|
|
Var di = 1;
|
|
Var df = 1.5;
|
|
Var ds = "abc";
|
|
Var dd = DateTime();
|
|
|
|
assertTrue (!di.isEmpty());
|
|
assertTrue (!df.isEmpty());
|
|
assertTrue (!ds.isEmpty());
|
|
assertTrue (!dd.isEmpty());
|
|
|
|
Statement stmt = (session() << "SELECT EmptyString, EmptyInteger, EmptyFloat, EmptyDateTime FROM NullableTest", into(ds), into(di), into(df), into(dd), now);
|
|
|
|
assertTrue (di.isEmpty());
|
|
assertTrue (df.isEmpty());
|
|
assertTrue (ds.isEmpty());
|
|
assertTrue (dd.isEmpty());
|
|
}
|
|
|
|
|
|
void SQLExecutor::reconnect()
|
|
{
|
|
std::string funct = "reconnect()";
|
|
std::string lastName = "lastName";
|
|
std::string firstName("firstName");
|
|
std::string address("Address");
|
|
int age = 133132;
|
|
int count = 0;
|
|
std::string result;
|
|
|
|
try { session() << "INSERT INTO Person VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(age), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
|
|
count = 0;
|
|
try { session() << "SELECT COUNT(*) FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == 1);
|
|
|
|
assertTrue (session().isConnected());
|
|
session().close();
|
|
assertTrue (!session().isConnected());
|
|
try
|
|
{
|
|
session() << "SELECT LastName FROM Person", into(result), now;
|
|
fail ("must fail");
|
|
}
|
|
catch(NotConnectedException&){ }
|
|
assertTrue (!session().isConnected());
|
|
|
|
session().open();
|
|
assertTrue (session().isConnected());
|
|
try { session() << "SELECT Age FROM Person", into(count), now; }
|
|
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail (funct); }
|
|
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail (funct); }
|
|
assertTrue (count == age);
|
|
assertTrue (session().isConnected());
|
|
}
|
|
|
|
|
|
void SQLExecutor::unicode(const std::string& dbConnString)
|
|
{
|
|
const unsigned char supp[] = { 0x41, 0x42, 0xf0, 0x90, 0x82, 0xa4, 0xf0, 0xaf, 0xa6, 0xa0, 0xf0, 0xaf, 0xa8, 0x9d, 0x00 };
|
|
std::string text((const char*) supp);
|
|
|
|
UTF16String wtext;
|
|
Poco::UnicodeConverter::convert(text, wtext);
|
|
session() << "INSERT INTO UnicodeTable VALUES (?)", use(wtext), now;
|
|
wtext.clear();
|
|
text.clear();
|
|
session() << "SELECT str FROM UnicodeTable", into(wtext), now;
|
|
Poco::UnicodeConverter::convert(wtext, text);
|
|
assertTrue (text == std::string((const char*)supp));
|
|
} |