mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-16 18:56:52 +02:00
- SQL logging channel and archiving strategy
- row formatting refactored - affected row count for insert, delete and update returned from Statement::execute() - internal SQL string formatting capability using Poco::format()
This commit is contained in:
@@ -247,6 +247,9 @@
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\SessionImpl.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\SimpleRowFormatter.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\Statement.h">
|
||||
</File>
|
||||
@@ -335,6 +338,9 @@
|
||||
<File
|
||||
RelativePath=".\src\SessionImpl.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\SimpleRowFormatter.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\Statement.cpp">
|
||||
</File>
|
||||
@@ -379,6 +385,30 @@
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Logging"
|
||||
Filter="">
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\ArchiveStrategy.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\SQLChannel.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\src\ArchiveStrategy.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\SQLChannel.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
|
@@ -333,6 +333,10 @@
|
||||
RelativePath=".\include\Poco\Data\SessionImpl.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\SimpleRowFormatter.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\Statement.h"
|
||||
>
|
||||
@@ -449,6 +453,10 @@
|
||||
RelativePath=".\src\SessionImpl.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\SimpleRowFormatter.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\Statement.cpp"
|
||||
>
|
||||
@@ -503,6 +511,34 @@
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Logging"
|
||||
>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\ArchiveStrategy.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\Poco\Data\SQLChannel.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\ArchiveStrategy.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\SQLChannel.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
|
@@ -9,12 +9,12 @@
|
||||
include $(POCO_BASE)/build/rules/global
|
||||
|
||||
objects = AbstractBinder AbstractBinding AbstractExtraction \
|
||||
AbstractExtractor AbstractPreparation AbstractPrepare Bulk \
|
||||
Connector BLOB BLOBStream DataException Date Limit MetaColumn \
|
||||
AbstractExtractor AbstractPreparation AbstractPrepare ArchiveStrategy \
|
||||
Bulk Connector BLOB BLOBStream DataException Date Limit MetaColumn \
|
||||
PooledSessionHolder PooledSessionImpl Position \
|
||||
Range RecordSet Row RowFormatter RowIterator \
|
||||
Session SessionFactory SessionImpl \
|
||||
SessionPool Statement StatementCreator StatementImpl Time
|
||||
SimpleRowFormatter Session SessionFactory SessionImpl \
|
||||
SessionPool SQLChannel Statement StatementCreator StatementImpl Time
|
||||
|
||||
target = PocoData
|
||||
target_version = $(LIBVERSION)
|
||||
|
@@ -62,6 +62,9 @@ public:
|
||||
~Connector();
|
||||
/// Destroys the Connector.
|
||||
|
||||
const std::string& name() const;
|
||||
/// Returns the name associated with this connector.
|
||||
|
||||
Poco::AutoPtr<Poco::Data::SessionImpl> createSession(const std::string& connectionString);
|
||||
/// Creates a ODBC SessionImpl object and initializes it with the given connectionString.
|
||||
|
||||
@@ -73,6 +76,15 @@ public:
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// inlines
|
||||
///
|
||||
inline const std::string& Connector::name() const
|
||||
{
|
||||
return KEY;
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::ODBC
|
||||
|
||||
|
||||
|
@@ -92,7 +92,7 @@ public:
|
||||
return str;
|
||||
|
||||
std::string s;
|
||||
format(s,
|
||||
Poco::format(s,
|
||||
"===========================\n"
|
||||
"ODBC Diagnostic record #%d:\n"
|
||||
"===========================\n"
|
||||
@@ -112,7 +112,7 @@ public:
|
||||
{
|
||||
std::string str;
|
||||
|
||||
format(str,
|
||||
Poco::format(str,
|
||||
"Connection:%s\nServer:%s\n",
|
||||
_diagnostics.connectionName(),
|
||||
_diagnostics.serverName());
|
||||
|
@@ -78,6 +78,10 @@ protected:
|
||||
Poco::UInt32 columnsReturned() const;
|
||||
/// Returns number of columns returned by query.
|
||||
|
||||
Poco::UInt32 affectedRowCount() const;
|
||||
/// Returns the number of affected rows.
|
||||
/// Used to find out the number of rows affected by insert or update.
|
||||
|
||||
const MetaColumn& metaColumn(Poco::UInt32 pos) const;
|
||||
/// Returns column meta data.
|
||||
|
||||
@@ -165,6 +169,7 @@ private:
|
||||
int _nextResponse;
|
||||
ColumnPtrVec _columnPtrs;
|
||||
bool _prepared;
|
||||
mutable Poco::UInt32 _affectedRowCount;
|
||||
};
|
||||
|
||||
|
||||
|
@@ -134,14 +134,22 @@ void Binder::bind(std::size_t pos, const std::string& val, Direction dir)
|
||||
}
|
||||
else if (isInBound(dir))
|
||||
{
|
||||
pVal = (SQLPOINTER) val.c_str();
|
||||
if (size) pVal = (SQLPOINTER) val.c_str();
|
||||
_inParams.insert(ParamMap::value_type(pVal, size));
|
||||
}
|
||||
else
|
||||
throw InvalidArgumentException("Parameter must be [in] OR [out] bound.");
|
||||
|
||||
SQLLEN* pLenIn = new SQLLEN;
|
||||
*pLenIn = SQL_NTS;
|
||||
if (0 != size) *pLenIn = SQL_NTS;
|
||||
else
|
||||
{
|
||||
*pLenIn = SQL_NULL_DATA;
|
||||
SQLINTEGER colSize = 0;
|
||||
SQLSMALLINT decDigits = 0;
|
||||
getColSizeAndPrecision(pos, SQL_C_CHAR, colSize, decDigits);
|
||||
size = colSize;
|
||||
}
|
||||
|
||||
if (PB_AT_EXEC == _paramBinding)
|
||||
*pLenIn = SQL_LEN_DATA_AT_EXEC(size);
|
||||
@@ -175,7 +183,16 @@ void Binder::bind(std::size_t pos, const BLOB& val, Direction dir)
|
||||
_inParams.insert(ParamMap::value_type(pVal, size));
|
||||
|
||||
SQLLEN* pLenIn = new SQLLEN;
|
||||
*pLenIn = size;
|
||||
|
||||
if (0 != size) *pLenIn = size;
|
||||
else
|
||||
{
|
||||
*pLenIn = SQL_NULL_DATA;
|
||||
SQLINTEGER colSize = 0;
|
||||
SQLSMALLINT decDigits = 0;
|
||||
getColSizeAndPrecision(pos, SQL_C_CHAR, colSize, decDigits);
|
||||
size = colSize;
|
||||
}
|
||||
|
||||
if (PB_AT_EXEC == _paramBinding)
|
||||
*pLenIn = SQL_LEN_DATA_AT_EXEC(size);
|
||||
|
@@ -65,7 +65,7 @@ Poco::AutoPtr<Poco::Data::SessionImpl> Connector::createSession(const std::strin
|
||||
|
||||
void Connector::registerConnector()
|
||||
{
|
||||
Poco::Data::SessionFactory::instance().add(KEY, new Connector());
|
||||
Poco::Data::SessionFactory::instance().add(new Connector());
|
||||
}
|
||||
|
||||
|
||||
|
@@ -107,6 +107,7 @@ void ODBCMetaColumn::init()
|
||||
case SQL_VARCHAR:
|
||||
case SQL_LONGVARCHAR:
|
||||
case -9:// SQL Server NVARCHAR
|
||||
case -10:// PostgreSQL VARCHAR (without size specified)
|
||||
setType(MetaColumn::FDT_STRING); break;
|
||||
case SQL_TINYINT:
|
||||
setType(MetaColumn::FDT_INT8); break;
|
||||
|
@@ -64,7 +64,8 @@ ODBCStatementImpl::ODBCStatementImpl(SessionImpl& rSession):
|
||||
_stmt(rSession.dbc()),
|
||||
_stepCalled(false),
|
||||
_nextResponse(0),
|
||||
_prepared(false)
|
||||
_prepared(false),
|
||||
_affectedRowCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -205,6 +206,9 @@ void ODBCStatementImpl::doBind(bool clear, bool reset)
|
||||
Bindings::iterator it = binds.begin();
|
||||
Bindings::iterator itEnd = binds.end();
|
||||
|
||||
if (it != itEnd && 0 == _affectedRowCount)
|
||||
_affectedRowCount = static_cast<Poco::UInt32>((*it)->numOfRowsHandled());
|
||||
|
||||
if (reset)
|
||||
{
|
||||
it = binds.begin();
|
||||
@@ -257,6 +261,8 @@ void ODBCStatementImpl::clear()
|
||||
{
|
||||
SQLRETURN rc = SQLCloseCursor(_stmt);
|
||||
_stepCalled = false;
|
||||
_affectedRowCount = 0;
|
||||
|
||||
if (Utility::isError(rc))
|
||||
{
|
||||
StatementError err(_stmt);
|
||||
@@ -438,4 +444,17 @@ const MetaColumn& ODBCStatementImpl::metaColumn(Poco::UInt32 pos) const
|
||||
}
|
||||
|
||||
|
||||
Poco::UInt32 ODBCStatementImpl::affectedRowCount() const
|
||||
{
|
||||
if (0 == _affectedRowCount)
|
||||
{
|
||||
SQLLEN rows;
|
||||
if (!Utility::isError(SQLRowCount(_stmt, &rows)))
|
||||
_affectedRowCount = static_cast<Poco::UInt32>(rows);
|
||||
}
|
||||
|
||||
return _affectedRowCount;
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::ODBC
|
||||
|
@@ -555,6 +555,31 @@ void ODBCDB2Test::recreateMiscTable()
|
||||
}
|
||||
|
||||
|
||||
void ODBCDB2Test::recreateLogTable()
|
||||
{
|
||||
dropObject("TABLE", "T_POCO_LOG");
|
||||
dropObject("TABLE", "T_POCO_LOG_ARCHIVE");
|
||||
|
||||
try
|
||||
{
|
||||
std::string sql = "CREATE TABLE %s "
|
||||
"(Source VARCHAR(100),"
|
||||
"Name VARCHAR(100),"
|
||||
"ProcessId INTEGER,"
|
||||
"Thread VARCHAR(100), "
|
||||
"ThreadId INTEGER,"
|
||||
"Priority INTEGER,"
|
||||
"Text VARCHAR(100),"
|
||||
"DateTime TIMESTAMP)";
|
||||
|
||||
session() << sql, "T_POCO_LOG", now;
|
||||
session() << sql, "T_POCO_LOG_ARCHIVE", now;
|
||||
|
||||
} catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateLogTable()"); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateLogTable()"); }
|
||||
}
|
||||
|
||||
|
||||
CppUnit::Test* ODBCDB2Test::suite()
|
||||
{
|
||||
if (_pSession = init(_driver, _dsn, _uid, _pwd, _connectString))
|
||||
@@ -580,6 +605,7 @@ CppUnit::Test* ODBCDB2Test::suite()
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testComplexTypeDeque);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testInsertDeque);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testInsertEmptyDeque);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testAffectedRows);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testInsertSingleBulk);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testInsertSingleBulkVec);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testLimit);
|
||||
@@ -631,6 +657,8 @@ CppUnit::Test* ODBCDB2Test::suite()
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testAny);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testDynamicAny);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testMultipleResults);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testSQLChannel);
|
||||
CppUnit_addTest(pSuite, ODBCDB2Test, testSQLLogger);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@@ -78,6 +78,7 @@ private:
|
||||
void recreateAnysTable();
|
||||
void recreateNullsTable(const std::string& notNull = "");
|
||||
void recreateMiscTable();
|
||||
void recreateLogTable();
|
||||
|
||||
static ODBCTest::SessionPtr _pSession;
|
||||
static ODBCTest::ExecPtr _pExecutor;
|
||||
|
@@ -373,6 +373,31 @@ void ODBCMySQLTest::recreateMiscTable()
|
||||
}
|
||||
|
||||
|
||||
void ODBCMySQLTest::recreateLogTable()
|
||||
{
|
||||
dropObject("TABLE", "T_POCO_LOG");
|
||||
dropObject("TABLE", "T_POCO_LOG_ARCHIVE");
|
||||
|
||||
try
|
||||
{
|
||||
std::string sql = "CREATE TABLE %s "
|
||||
"(Source VARCHAR(100),"
|
||||
"Name VARCHAR(100),"
|
||||
"ProcessId INTEGER,"
|
||||
"Thread VARCHAR(100), "
|
||||
"ThreadId INTEGER,"
|
||||
"Priority INTEGER,"
|
||||
"Text VARCHAR(100),"
|
||||
"DateTime DATETIME)";
|
||||
|
||||
session() << sql, "T_POCO_LOG", now;
|
||||
session() << sql, "T_POCO_LOG_ARCHIVE", now;
|
||||
|
||||
} catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateLogTable()"); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateLogTable()"); }
|
||||
}
|
||||
|
||||
|
||||
CppUnit::Test* ODBCMySQLTest::suite()
|
||||
{
|
||||
if (_pSession = init(_driver, _dsn, _uid, _pwd, _connectString))
|
||||
@@ -398,6 +423,7 @@ CppUnit::Test* ODBCMySQLTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testComplexTypeDeque);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testInsertDeque);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testInsertEmptyDeque);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testAffectedRows);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testInsertSingleBulk);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testInsertSingleBulkVec);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testLimit);
|
||||
@@ -447,6 +473,8 @@ CppUnit::Test* ODBCMySQLTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testAny);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testDynamicAny);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testMultipleResults);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testSQLChannel);
|
||||
CppUnit_addTest(pSuite, ODBCMySQLTest, testSQLLogger);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@@ -83,6 +83,7 @@ private:
|
||||
void recreateAnysTable();
|
||||
void recreateNullsTable(const std::string& notNull = "");
|
||||
void recreateMiscTable();
|
||||
void recreateLogTable();
|
||||
|
||||
static ODBCTest::SessionPtr _pSession;
|
||||
static ODBCTest::ExecPtr _pExecutor;
|
||||
|
@@ -755,6 +755,31 @@ void ODBCOracleTest::recreateMiscTable()
|
||||
}
|
||||
|
||||
|
||||
void ODBCOracleTest::recreateLogTable()
|
||||
{
|
||||
dropObject("TABLE", "T_POCO_LOG");
|
||||
dropObject("TABLE", "T_POCO_LOG_ARCHIVE");
|
||||
|
||||
try
|
||||
{
|
||||
std::string sql = "CREATE TABLE %s "
|
||||
"(Source VARCHAR(100),"
|
||||
"Name VARCHAR(100),"
|
||||
"ProcessId INTEGER,"
|
||||
"Thread VARCHAR(100), "
|
||||
"ThreadId INTEGER,"
|
||||
"Priority INTEGER,"
|
||||
"Text VARCHAR(100),"
|
||||
"DateTime TIMESTAMP)";
|
||||
|
||||
session() << sql, "T_POCO_LOG", now;
|
||||
session() << sql, "T_POCO_LOG_ARCHIVE", now;
|
||||
|
||||
} catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateLogTable()"); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateLogTable()"); }
|
||||
}
|
||||
|
||||
|
||||
CppUnit::Test* ODBCOracleTest::suite()
|
||||
{
|
||||
if (_pSession = init(_driver, _dsn, _uid, _pwd, _connectString))
|
||||
@@ -780,6 +805,7 @@ CppUnit::Test* ODBCOracleTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testComplexTypeDeque);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testInsertDeque);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testInsertEmptyDeque);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testAffectedRows);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testInsertSingleBulk);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testInsertSingleBulkVec);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testLimit);
|
||||
@@ -832,6 +858,8 @@ CppUnit::Test* ODBCOracleTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testAny);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testDynamicAny);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testMultipleResults);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testSQLChannel);
|
||||
CppUnit_addTest(pSuite, ODBCOracleTest, testSQLLogger);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@@ -85,9 +85,11 @@ private:
|
||||
void recreateAnysTable();
|
||||
void recreateNullsTable(const std::string& notNull = "");
|
||||
void recreateMiscTable();
|
||||
void recreateLogTable();
|
||||
|
||||
static ODBCTest::SessionPtr _pSession;
|
||||
static ODBCTest::ExecPtr _pExecutor;
|
||||
|
||||
static std::string _driver;
|
||||
static std::string _dsn;
|
||||
static std::string _uid;
|
||||
|
@@ -534,6 +534,31 @@ void ODBCPostgreSQLTest::recreateMiscTable()
|
||||
}
|
||||
|
||||
|
||||
void ODBCPostgreSQLTest::recreateLogTable()
|
||||
{
|
||||
dropObject("TABLE", "T_POCO_LOG");
|
||||
dropObject("TABLE", "T_POCO_LOG_ARCHIVE");
|
||||
|
||||
try
|
||||
{
|
||||
std::string sql = "CREATE TABLE %s "
|
||||
"(Source VARCHAR,"
|
||||
"Name VARCHAR,"
|
||||
"ProcessId INTEGER,"
|
||||
"Thread VARCHAR, "
|
||||
"ThreadId INTEGER,"
|
||||
"Priority INTEGER,"
|
||||
"Text VARCHAR,"
|
||||
"DateTime TIMESTAMP)";
|
||||
|
||||
session() << sql, "T_POCO_LOG", now;
|
||||
session() << sql, "T_POCO_LOG_ARCHIVE", now;
|
||||
|
||||
} catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateLogTable()"); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateLogTable()"); }
|
||||
}
|
||||
|
||||
|
||||
CppUnit::Test* ODBCPostgreSQLTest::suite()
|
||||
{
|
||||
if (_pSession = init(_driver, _dsn, _uid, _pwd, _connectString))
|
||||
@@ -559,6 +584,7 @@ CppUnit::Test* ODBCPostgreSQLTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testComplexTypeDeque);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testInsertDeque);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testInsertEmptyDeque);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testAffectedRows);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testInsertSingleBulk);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testInsertSingleBulkVec);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testLimit);
|
||||
@@ -624,6 +650,8 @@ CppUnit::Test* ODBCPostgreSQLTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testDynamicAny);
|
||||
//neither pSQL ODBC nor Mammoth drivers support multiple results properly
|
||||
//CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testMultipleResults);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSQLChannel);
|
||||
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSQLLogger);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@@ -87,6 +87,7 @@ private:
|
||||
void recreateNullsTable(const std::string& notNull="");
|
||||
void recreateBoolTable();
|
||||
void recreateMiscTable();
|
||||
void recreateLogTable();
|
||||
|
||||
void configurePLPgSQL();
|
||||
/// Configures PL/pgSQL in the database. A reasonable defaults
|
||||
|
@@ -660,6 +660,31 @@ void ODBCSQLServerTest::recreateMiscTable()
|
||||
}
|
||||
|
||||
|
||||
void ODBCSQLServerTest::recreateLogTable()
|
||||
{
|
||||
dropObject("TABLE", "T_POCO_LOG");
|
||||
dropObject("TABLE", "T_POCO_LOG_ARCHIVE");
|
||||
|
||||
try
|
||||
{
|
||||
std::string sql = "CREATE TABLE %s "
|
||||
"(Source VARCHAR(max),"
|
||||
"Name VARCHAR(max),"
|
||||
"ProcessId INTEGER,"
|
||||
"Thread VARCHAR(max), "
|
||||
"ThreadId INTEGER,"
|
||||
"Priority INTEGER,"
|
||||
"Text VARCHAR(max),"
|
||||
"DateTime DATETIME)";
|
||||
|
||||
session() << sql, "T_POCO_LOG", now;
|
||||
session() << sql, "T_POCO_LOG_ARCHIVE", now;
|
||||
|
||||
} catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateLogTable()"); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateLogTable()"); }
|
||||
}
|
||||
|
||||
|
||||
CppUnit::Test* ODBCSQLServerTest::suite()
|
||||
{
|
||||
if (_pSession = init(_driver, _dsn, _uid, _pwd, _connectString, _db))
|
||||
@@ -685,6 +710,7 @@ CppUnit::Test* ODBCSQLServerTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testComplexTypeDeque);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testInsertDeque);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testInsertEmptyDeque);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testAffectedRows);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testInsertSingleBulk);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testInsertSingleBulkVec);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testLimit);
|
||||
@@ -736,6 +762,8 @@ CppUnit::Test* ODBCSQLServerTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testAny);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testDynamicAny);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testMultipleResults);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSQLChannel);
|
||||
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSQLLogger);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@@ -91,6 +91,7 @@ private:
|
||||
void recreateNullsTable(const std::string& notNull = "");
|
||||
void recreateBoolTable();
|
||||
void recreateMiscTable();
|
||||
void recreateLogTable();
|
||||
|
||||
static SessionPtr _pSession;
|
||||
static ExecPtr _pExecutor;
|
||||
|
@@ -125,6 +125,23 @@ void ODBCSQLiteTest::testBareboneODBC()
|
||||
}
|
||||
|
||||
|
||||
void ODBCSQLiteTest::testAffectedRows()
|
||||
{
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
|
||||
for (int i = 0; i < 8;)
|
||||
{
|
||||
recreateStringsTable();
|
||||
_pSession->setFeature("autoBind", bindValue(i));
|
||||
_pSession->setFeature("autoExtract", bindValue(i+1));
|
||||
// see SQLiteStatementImpl::affectedRows() documentation for explanation
|
||||
// why "WHERE 1" is necessary here
|
||||
_pExecutor->affectedRows("WHERE 1");
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODBCSQLiteTest::testNull()
|
||||
{
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
@@ -279,6 +296,31 @@ void ODBCSQLiteTest::recreateMiscTable()
|
||||
}
|
||||
|
||||
|
||||
void ODBCSQLiteTest::recreateLogTable()
|
||||
{
|
||||
dropObject("TABLE", "T_POCO_LOG");
|
||||
dropObject("TABLE", "T_POCO_LOG_ARCHIVE");
|
||||
|
||||
try
|
||||
{
|
||||
std::string sql = "CREATE TABLE %s "
|
||||
"(Source VARCHAR,"
|
||||
"Name VARCHAR,"
|
||||
"ProcessId INTEGER,"
|
||||
"Thread VARCHAR, "
|
||||
"ThreadId INTEGER,"
|
||||
"Priority INTEGER,"
|
||||
"Text VARCHAR,"
|
||||
"DateTime DATETIME)";
|
||||
|
||||
session() << sql, "T_POCO_LOG", now;
|
||||
session() << sql, "T_POCO_LOG_ARCHIVE", now;
|
||||
|
||||
} catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateLogTable()"); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateLogTable()"); }
|
||||
}
|
||||
|
||||
|
||||
CppUnit::Test* ODBCSQLiteTest::suite()
|
||||
{
|
||||
if (_pSession = init(_driver, _dsn, _uid, _pwd, _connectString))
|
||||
@@ -304,6 +346,7 @@ CppUnit::Test* ODBCSQLiteTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testComplexTypeDeque);
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testInsertDeque);
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testInsertEmptyDeque);
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testAffectedRows);
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testInsertSingleBulk);
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testInsertSingleBulkVec);
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testLimit);
|
||||
@@ -345,6 +388,8 @@ CppUnit::Test* ODBCSQLiteTest::suite()
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testAsync);
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testAny);
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testDynamicAny);
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testSQLChannel);
|
||||
CppUnit_addTest(pSuite, ODBCSQLiteTest, testSQLLogger);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@@ -53,6 +53,7 @@ public:
|
||||
~ODBCSQLiteTest();
|
||||
|
||||
void testBareboneODBC();
|
||||
void testAffectedRows();
|
||||
void testNull();
|
||||
|
||||
static CppUnit::Test* suite();
|
||||
@@ -70,6 +71,7 @@ private:
|
||||
void recreateAnysTable();
|
||||
void recreateNullsTable(const std::string& notNull = "");
|
||||
void recreateMiscTable();
|
||||
void recreateLogTable();
|
||||
|
||||
static ODBCTest::SessionPtr _pSession;
|
||||
static ODBCTest::ExecPtr _pExecutor;
|
||||
|
@@ -306,6 +306,21 @@ void ODBCTest::testInsertEmptyDeque()
|
||||
}
|
||||
|
||||
|
||||
void ODBCTest::testAffectedRows()
|
||||
{
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
|
||||
for (int i = 0; i < 8;)
|
||||
{
|
||||
recreateStringsTable();
|
||||
_pSession->setFeature("autoBind", bindValue(i));
|
||||
_pSession->setFeature("autoExtract", bindValue(i+1));
|
||||
_pExecutor->affectedRows();
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODBCTest::testInsertSingleBulk()
|
||||
{
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
@@ -1048,6 +1063,38 @@ void ODBCTest::testMultipleResults()
|
||||
}
|
||||
|
||||
|
||||
void ODBCTest::testSQLChannel()
|
||||
{
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
|
||||
for (int i = 0; i < 8;)
|
||||
{
|
||||
recreateLogTable();
|
||||
_pSession->setFeature("autoBind", bindValue(i));
|
||||
_pSession->setFeature("autoExtract", bindValue(i+1));
|
||||
_pExecutor->sqlChannel(_rConnectString);
|
||||
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ODBCTest::testSQLLogger()
|
||||
{
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
|
||||
for (int i = 0; i < 8;)
|
||||
{
|
||||
recreateLogTable();
|
||||
_pSession->setFeature("autoBind", bindValue(i));
|
||||
_pSession->setFeature("autoExtract", bindValue(i+1));
|
||||
_pExecutor->sqlLogger(_rConnectString);
|
||||
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ODBCTest::canConnect(const std::string& driver,
|
||||
std::string& dsn,
|
||||
std::string& uid,
|
||||
|
@@ -37,10 +37,11 @@
|
||||
|
||||
|
||||
#include "Poco/Data/ODBC/ODBC.h"
|
||||
#include "CppUnit/TestCase.h"
|
||||
#include "Poco/Data/Session.h"
|
||||
#include "Poco/Data/ODBC/Utility.h"
|
||||
#include "Poco/SharedPtr.h"
|
||||
#include "CppUnit/TestCase.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "SQLExecutor.h"
|
||||
|
||||
|
||||
@@ -86,6 +87,8 @@ public:
|
||||
virtual void testInsertDeque();
|
||||
virtual void testInsertEmptyDeque();
|
||||
|
||||
virtual void testAffectedRows();
|
||||
|
||||
virtual void testInsertSingleBulk();
|
||||
virtual void testInsertSingleBulkVec();
|
||||
|
||||
@@ -135,13 +138,13 @@ public:
|
||||
virtual void testInternalBulkExtraction();
|
||||
virtual void testInternalStorageType();
|
||||
|
||||
virtual void testStoredProcedure() { /* no-op */ };
|
||||
virtual void testStoredProcedureAny() { /* no-op */ };
|
||||
virtual void testStoredProcedureDynamicAny() { /* no-op */ };
|
||||
virtual void testStoredProcedure();
|
||||
virtual void testStoredProcedureAny();
|
||||
virtual void testStoredProcedureDynamicAny();
|
||||
|
||||
virtual void testStoredFunction() { /* no-op */ };
|
||||
virtual void testStoredFunctionAny() { /* no-op */ };
|
||||
virtual void testStoredFunctionDynamicAny() { /* no-op */ };
|
||||
virtual void testStoredFunction();
|
||||
virtual void testStoredFunctionAny();
|
||||
virtual void testStoredFunctionDynamicAny();
|
||||
|
||||
virtual void testNull();
|
||||
virtual void testRowIterator();
|
||||
@@ -154,24 +157,29 @@ public:
|
||||
|
||||
virtual void testMultipleResults();
|
||||
|
||||
virtual void testSQLChannel();
|
||||
|
||||
virtual void testSQLLogger();
|
||||
|
||||
protected:
|
||||
typedef Poco::Data::ODBC::Utility::DriverMap Drivers;
|
||||
|
||||
virtual void dropObject(const std::string& type, const std::string& name) { /* no-op */ };
|
||||
virtual void recreatePersonTable() { /* no-op */ };
|
||||
virtual void recreatePersonBLOBTable() { /* no-op */ };
|
||||
virtual void recreatePersonDateTimeTable() { /* no-op */ };
|
||||
virtual void recreatePersonDateTable() { /* no-op */ };
|
||||
virtual void recreatePersonTimeTable() { /* no-op */ };
|
||||
virtual void recreateStringsTable() { /* no-op */ };
|
||||
virtual void recreateIntsTable() { /* no-op */ };
|
||||
virtual void recreateFloatsTable() { /* no-op */ };
|
||||
virtual void recreateTuplesTable() { /* no-op */ };
|
||||
virtual void recreateVectorsTable() { /* no-op */ };
|
||||
virtual void recreateAnysTable() { /* no-op */ };
|
||||
virtual void recreateNullsTable(const std::string& notNull="") { /* no-op */ };
|
||||
virtual void recreateBoolTable() { /* no-op */ };
|
||||
virtual void recreateMiscTable() { /* no-op */ };
|
||||
virtual void dropObject(const std::string& type, const std::string& name);
|
||||
virtual void recreatePersonTable();
|
||||
virtual void recreatePersonBLOBTable();
|
||||
virtual void recreatePersonDateTimeTable();
|
||||
virtual void recreatePersonDateTable();
|
||||
virtual void recreatePersonTimeTable();
|
||||
virtual void recreateStringsTable();
|
||||
virtual void recreateIntsTable();
|
||||
virtual void recreateFloatsTable();
|
||||
virtual void recreateTuplesTable();
|
||||
virtual void recreateVectorsTable();
|
||||
virtual void recreateAnysTable();
|
||||
virtual void recreateNullsTable(const std::string& notNull="");
|
||||
virtual void recreateBoolTable();
|
||||
virtual void recreateMiscTable();
|
||||
virtual void recreateLogTable();
|
||||
|
||||
static SessionPtr init(const std::string& driver,
|
||||
std::string& dsn,
|
||||
@@ -209,9 +217,142 @@ private:
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// inlines
|
||||
///
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
|
||||
inline void ODBCTest::testStoredProcedure()
|
||||
{
|
||||
throw Poco::NotImplementedException("ODBCTest::testStoredProcedure()");
|
||||
}
|
||||
|
||||
|
||||
inline void ODBCTest::testStoredProcedureAny()
|
||||
{
|
||||
throw Poco::NotImplementedException("ODBCTest::testStoredProcedureAny()");
|
||||
}
|
||||
|
||||
|
||||
inline void ODBCTest::testStoredProcedureDynamicAny()
|
||||
{
|
||||
throw Poco::NotImplementedException("ODBCTest::testStoredProcedureDynamicAny()");
|
||||
}
|
||||
|
||||
|
||||
inline void ODBCTest::testStoredFunction()
|
||||
{
|
||||
throw Poco::NotImplementedException("ODBCTest::testStoredFunction()");
|
||||
}
|
||||
|
||||
|
||||
inline void ODBCTest::testStoredFunctionAny()
|
||||
{
|
||||
throw Poco::NotImplementedException("ODBCTest::testStoredFunctionAny()");
|
||||
}
|
||||
|
||||
|
||||
inline void ODBCTest::testStoredFunctionDynamicAny()
|
||||
{
|
||||
throw Poco::NotImplementedException("ODBCTest::testStoredFunctionDynamicAny()");
|
||||
}
|
||||
|
||||
|
||||
inline void ODBCTest::dropObject(const std::string& type, const std::string& name)
|
||||
{
|
||||
throw Poco::NotImplementedException("ODBCTest::dropObject()");
|
||||
}
|
||||
|
||||
|
||||
inline void ODBCTest::recreatePersonTable()
|
||||
{
|
||||
throw Poco::NotImplementedException("ODBCTest::testStoredFunctionDynamicAny()");
|
||||
}
|
||||
|
||||
|
||||
inline void ODBCTest::recreatePersonBLOBTable()
|
||||
{
|
||||
throw Poco::NotImplementedException("ODBCTest::testStoredFunctionDynamicAny()");
|
||||
}
|
||||
|
||||
|
||||
inline void ODBCTest::recreatePersonDateTimeTable()
|
||||
{
|
||||
throw Poco::NotImplementedException("ODBCTest::testStoredFunctionDynamicAny()");
|
||||
}
|
||||
|
||||
|
||||
inline void ODBCTest::recreatePersonDateTable()
|
||||
{
|
||||
throw Poco::NotImplementedException("ODBCTest::testStoredFunctionDynamicAny()");
|
||||
}
|
||||
|
||||
|
||||
inline void ODBCTest::recreatePersonTimeTable()
|
||||
{
|
||||
throw Poco::NotImplementedException("ODBCTest::testStoredFunctionDynamicAny()");
|
||||
}
|
||||
|
||||
|
||||
inline void ODBCTest::recreateStringsTable()
|
||||
{
|
||||
throw Poco::NotImplementedException("ODBCTest::recreateStringsTable()");
|
||||
}
|
||||
|
||||
|
||||
inline void ODBCTest::recreateIntsTable()
|
||||
{
|
||||
throw Poco::NotImplementedException("ODBCTest::recreateIntsTable()");
|
||||
}
|
||||
|
||||
|
||||
inline void ODBCTest::recreateFloatsTable()
|
||||
{
|
||||
throw Poco::NotImplementedException("ODBCTest::recreateFloatsTable()");
|
||||
}
|
||||
|
||||
|
||||
inline void ODBCTest::recreateTuplesTable()
|
||||
{
|
||||
throw Poco::NotImplementedException("ODBCTest::recreateTuplesTable()");
|
||||
}
|
||||
|
||||
|
||||
inline void ODBCTest::recreateVectorsTable()
|
||||
{
|
||||
throw Poco::NotImplementedException("ODBCTest::recreateVectorsTable()");
|
||||
}
|
||||
|
||||
|
||||
inline void ODBCTest::recreateAnysTable()
|
||||
{
|
||||
throw Poco::NotImplementedException("ODBCTest::recreateAnysTable()");
|
||||
}
|
||||
|
||||
|
||||
inline void ODBCTest::recreateNullsTable(const std::string&)
|
||||
{
|
||||
throw Poco::NotImplementedException("ODBCTest::recreateNullsTable()");
|
||||
}
|
||||
|
||||
|
||||
inline void ODBCTest::recreateBoolTable()
|
||||
{
|
||||
throw Poco::NotImplementedException("ODBCTest::recreateBoolTable()");
|
||||
}
|
||||
|
||||
|
||||
inline void ODBCTest::recreateMiscTable()
|
||||
{
|
||||
throw Poco::NotImplementedException("ODBCTest::recreateMiscTable()");
|
||||
}
|
||||
|
||||
|
||||
inline void ODBCTest::recreateLogTable()
|
||||
{
|
||||
throw Poco::NotImplementedException("ODBCTest::recreateLogTable()");
|
||||
}
|
||||
|
||||
|
||||
inline bool ODBCTest::bindValue(int i)
|
||||
{
|
||||
poco_assert (i < 8);
|
||||
|
@@ -40,6 +40,10 @@
|
||||
#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/AutoPtr.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/Data/Date.h"
|
||||
#include "Poco/Data/Time.h"
|
||||
@@ -49,6 +53,7 @@
|
||||
#include "Poco/Data/RowIterator.h"
|
||||
#include "Poco/Data/BulkExtraction.h"
|
||||
#include "Poco/Data/BulkBinding.h"
|
||||
#include "Poco/Data/SQLChannel.h"
|
||||
#include "Poco/Data/ODBC/Connector.h"
|
||||
#include "Poco/Data/ODBC/Utility.h"
|
||||
#include "Poco/Data/ODBC/Diagnostics.h"
|
||||
@@ -76,6 +81,10 @@ using Poco::DynamicAny;
|
||||
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;
|
||||
@@ -1234,6 +1243,35 @@ void SQLExecutor::insertEmptyDeque()
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
assert (count == 0);
|
||||
assert (4 == stmt1.execute());
|
||||
session() << "SELECT COUNT(*) FROM Strings", into(count), now;
|
||||
assert (count == 4);
|
||||
|
||||
Statement stmt2(session() << "UPDATE Strings SET str = 's4' WHERE str = 's3'");
|
||||
assert (2 == stmt2.execute());
|
||||
|
||||
Statement stmt3(session() << "DELETE FROM Strings WHERE str = 's1'");
|
||||
assert (1 == stmt3.execute());
|
||||
|
||||
std::string sql;
|
||||
format(sql, "DELETE FROM Strings %s", whereClause);
|
||||
Statement stmt4(session() << sql);
|
||||
assert (3 == stmt4.execute());
|
||||
}
|
||||
|
||||
|
||||
void SQLExecutor::insertSingleBulk()
|
||||
{
|
||||
std::string funct = "insertSingleBulk()";
|
||||
@@ -1243,7 +1281,7 @@ void SQLExecutor::insertSingleBulk()
|
||||
for (x = 0; x < 100; ++x)
|
||||
{
|
||||
int i = stmt.execute();
|
||||
assert (i == 0);
|
||||
assert (1 == i);
|
||||
}
|
||||
int count = 0;
|
||||
try { session() << "SELECT COUNT(*) FROM Strings", into(count), now; }
|
||||
@@ -1414,7 +1452,11 @@ void SQLExecutor::limitPrepare()
|
||||
data.push_back(x);
|
||||
}
|
||||
|
||||
try { session() << "INSERT INTO Strings VALUES (?)", use(data), now; }
|
||||
try
|
||||
{
|
||||
Statement stmt = (session() << "INSERT INTO Strings VALUES (?)", use(data));
|
||||
assert (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); }
|
||||
|
||||
@@ -2932,3 +2974,87 @@ void SQLExecutor::multipleResults(const std::string& sql)
|
||||
assert (12 == aBart);
|
||||
assert (Person("Simpson", "Lisa", "Springfield", 10) == pLisa);
|
||||
}
|
||||
|
||||
|
||||
void SQLExecutor::sqlChannel(const std::string& connect)
|
||||
{
|
||||
try
|
||||
{
|
||||
AutoPtr<SQLChannel> pChannel = new SQLChannel(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");
|
||||
assert (4 == rs.rowCount());
|
||||
assert ("InformationSource" == rs["Source"]);
|
||||
assert ("a Informational async message" == rs["Text"]);
|
||||
rs.moveNext();
|
||||
assert ("WarningSource" == rs["Source"]);
|
||||
assert ("b Warning async message" == rs["Text"]);
|
||||
rs.moveNext();
|
||||
assert ("InformationSource" == rs["Source"]);
|
||||
assert ("c Informational sync message" == rs["Text"]);
|
||||
rs.moveNext();
|
||||
assert ("WarningSource" == rs["Source"]);
|
||||
assert ("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");
|
||||
assert (4 == rs1.rowCount());
|
||||
|
||||
pChannel->setProperty("keep", "");
|
||||
assert ("forever" == pChannel->getProperty("keep"));
|
||||
RecordSet rs2(session(), "SELECT * FROM T_POCO_LOG ORDER by Text");
|
||||
assert (2 == rs2.rowCount());
|
||||
assert ("InformationSource" == rs2["Source"]);
|
||||
assert ("e Informational sync message" == rs2["Text"]);
|
||||
rs2.moveNext();
|
||||
assert ("WarningSource" == rs2["Source"]);
|
||||
assert ("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(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");
|
||||
assert (2 == rs.rowCount());
|
||||
assert ("TestSQLChannel" == rs["Source"]);
|
||||
assert ("a Informational message" == rs["Text"]);
|
||||
rs.moveNext();
|
||||
assert ("TestSQLChannel" == rs["Source"]);
|
||||
assert ("b Warning message" == rs["Text"]);
|
||||
}
|
||||
catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("sqlChannel()"); }
|
||||
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("sqlChannel()"); }
|
||||
}
|
||||
|
@@ -148,6 +148,8 @@ public:
|
||||
void insertDeque();
|
||||
void insertEmptyDeque();
|
||||
|
||||
void affectedRows(const std::string& whereClause = "");
|
||||
|
||||
void insertSingleBulk();
|
||||
void insertSingleBulkVec();
|
||||
|
||||
@@ -499,6 +501,9 @@ public:
|
||||
"SELECT Age FROM Person WHERE FirstName = 'Bart'; "
|
||||
"SELECT * FROM Person WHERE Age = ?; ");
|
||||
|
||||
void sqlChannel(const std::string& connect);
|
||||
void sqlLogger(const std::string& connect);
|
||||
|
||||
private:
|
||||
static const std::string MULTI_INSERT;
|
||||
static const std::string MULTI_SELECT;
|
||||
|
@@ -36,8 +36,8 @@
|
||||
//
|
||||
|
||||
|
||||
#ifndef DataConnectors_SQLite_Binder_INCLUDED
|
||||
#define DataConnectors_SQLite_Binder_INCLUDED
|
||||
#ifndef Data_SQLite_Binder_INCLUDED
|
||||
#define Data_SQLite_Binder_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/SQLite.h"
|
||||
@@ -180,15 +180,6 @@ inline void Binder::bind(std::size_t pos, const Poco::UInt64 &val, Direction dir
|
||||
}
|
||||
|
||||
|
||||
#ifndef POCO_LONG_IS_64_BIT
|
||||
inline void Binder::bind(std::size_t pos, const long &val, Direction dir)
|
||||
{
|
||||
long tmp = static_cast<long>(val);
|
||||
bind(pos, tmp, dir);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
inline void Binder::bind(std::size_t pos, const bool &val, Direction dir)
|
||||
{
|
||||
Poco::Int32 tmp = (val ? 1 : 0);
|
||||
@@ -220,4 +211,4 @@ inline void Binder::bind(std::size_t pos, const char* const &pVal, Direction dir
|
||||
} } } // namespace Poco::Data::SQLite
|
||||
|
||||
|
||||
#endif // DataConnectors_SQLite_Binder_INCLUDED
|
||||
#endif // Data_SQLite_Binder_INCLUDED
|
||||
|
@@ -36,8 +36,8 @@
|
||||
//
|
||||
|
||||
|
||||
#ifndef DataConnectors_SQLite_Connector_INCLUDED
|
||||
#define DataConnectors_SQLite_Connector_INCLUDED
|
||||
#ifndef Data_SQLite_Connector_INCLUDED
|
||||
#define Data_SQLite_Connector_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/SQLite.h"
|
||||
@@ -62,6 +62,9 @@ public:
|
||||
~Connector();
|
||||
/// Destroys the Connector.
|
||||
|
||||
const std::string& name() const;
|
||||
/// Returns the name associated with this connector.
|
||||
|
||||
Poco::AutoPtr<Poco::Data::SessionImpl> createSession(const std::string& connectionString);
|
||||
/// Creates a SQLite SessionImpl object and initializes it with the given connectionString.
|
||||
|
||||
@@ -73,7 +76,16 @@ public:
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// inlines
|
||||
///
|
||||
inline const std::string& Connector::name() const
|
||||
{
|
||||
return KEY;
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
||||
|
||||
|
||||
#endif // DataConnectors_SQLite_Connector_INCLUDED
|
||||
#endif // Data_SQLite_Connector_INCLUDED
|
||||
|
@@ -36,8 +36,8 @@
|
||||
//
|
||||
|
||||
|
||||
#ifndef DataConnectors_SQLite_Extractor_INCLUDED
|
||||
#define DataConnectors_SQLite_Extractor_INCLUDED
|
||||
#ifndef Data_SQLite_Extractor_INCLUDED
|
||||
#define Data_SQLite_Extractor_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/SQLite.h"
|
||||
@@ -301,4 +301,4 @@ inline void Extractor::reset()
|
||||
} } } // namespace Poco::Data::SQLite
|
||||
|
||||
|
||||
#endif // DataConnectors_SQLite_Extractor_INCLUDED
|
||||
#endif // Data_SQLite_Extractor_INCLUDED
|
||||
|
@@ -36,8 +36,8 @@
|
||||
//
|
||||
|
||||
|
||||
#ifndef DataConnectors_SQLite_SQLiteStatementImpl_INCLUDED
|
||||
#define DataConnectors_SQLite_SQLiteStatementImpl_INCLUDED
|
||||
#ifndef Data_SQLite_SQLiteStatementImpl_INCLUDED
|
||||
#define Data_SQLite_SQLiteStatementImpl_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/SQLite.h"
|
||||
@@ -71,6 +71,17 @@ protected:
|
||||
Poco::UInt32 columnsReturned() const;
|
||||
/// Returns number of columns returned by query.
|
||||
|
||||
Poco::UInt32 affectedRowCount() const;
|
||||
/// Returns the number of affected rows.
|
||||
/// Used to find out the number of rows affected by insert, delete or update.
|
||||
/// All changes are counted, even if they are later undone by a ROLLBACK or ABORT.
|
||||
/// Changes associated with creating and dropping tables are not counted.
|
||||
/// SQLite implements the command "DELETE FROM table" without a WHERE clause by
|
||||
/// dropping and recreating the table. Because of this optimization, the change count
|
||||
/// for "DELETE FROM table" will be zero regardless of the number of elements that
|
||||
/// were originally in the table. To get an accurate count of the number of rows deleted,
|
||||
/// use "DELETE FROM table WHERE 1".
|
||||
|
||||
const MetaColumn& metaColumn(Poco::UInt32 pos) const;
|
||||
/// Returns column meta data.
|
||||
|
||||
@@ -100,16 +111,20 @@ private:
|
||||
void clear();
|
||||
/// Removes the _pStmt
|
||||
|
||||
typedef Poco::SharedPtr<Binder> BinderPtr;
|
||||
typedef Poco::SharedPtr<Extractor> ExtractorPtr;
|
||||
typedef Poco::Data::AbstractBindingVec Bindings;
|
||||
typedef Poco::Data::AbstractExtractionVec Extractions;
|
||||
typedef std::vector<Poco::Data::MetaColumn> MetaColumnVec;
|
||||
|
||||
sqlite3* _pDB;
|
||||
sqlite3_stmt* _pStmt;
|
||||
bool _stepCalled;
|
||||
int _nextResponse;
|
||||
Poco::SharedPtr<Binder> _pBinder;
|
||||
Poco::SharedPtr<Extractor> _pExtractor;
|
||||
std::vector<Poco::Data::MetaColumn> _columns;
|
||||
BinderPtr _pBinder;
|
||||
ExtractorPtr _pExtractor;
|
||||
MetaColumnVec _columns;
|
||||
Poco::UInt32 _affectedRowCount;
|
||||
};
|
||||
|
||||
|
||||
@@ -131,4 +146,4 @@ inline AbstractBinder& SQLiteStatementImpl::binder()
|
||||
} } } // namespace Poco::Data::SQLite
|
||||
|
||||
|
||||
#endif // DataConnectors_SQLite_SQLiteStatementImpl_INCLUDED
|
||||
#endif // Data_SQLite_SQLiteStatementImpl_INCLUDED
|
||||
|
@@ -36,8 +36,8 @@
|
||||
//
|
||||
|
||||
|
||||
#ifndef DataConnectors_SQLite_SessionImpl_INCLUDED
|
||||
#define DataConnectors_SQLite_SessionImpl_INCLUDED
|
||||
#ifndef Data_SQLite_SessionImpl_INCLUDED
|
||||
#define Data_SQLite_SessionImpl_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/SQLite.h"
|
||||
@@ -113,4 +113,4 @@ inline bool SessionImpl::isTransaction()
|
||||
} } } // namespace Poco::Data::SQLite
|
||||
|
||||
|
||||
#endif // DataConnectors_SQLite_SessionImpl_INCLUDED
|
||||
#endif // Data_SQLite_SessionImpl_INCLUDED
|
||||
|
@@ -80,6 +80,16 @@ void Binder::bind(std::size_t pos, const Poco::Int64 &val, Direction dir)
|
||||
}
|
||||
|
||||
|
||||
#ifndef POCO_LONG_IS_64_BIT
|
||||
void Binder::bind(std::size_t pos, const long &val, Direction dir)
|
||||
{
|
||||
long tmp = static_cast<long>(val);
|
||||
int rc = sqlite3_bind_int(_pStmt, (int) pos, val);
|
||||
checkReturn(rc);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const double &val, Direction dir)
|
||||
{
|
||||
int rc = sqlite3_bind_double(_pStmt, (int) pos, val);
|
||||
|
@@ -65,7 +65,7 @@ Poco::AutoPtr<Poco::Data::SessionImpl> Connector::createSession(const std::strin
|
||||
|
||||
void Connector::registerConnector()
|
||||
{
|
||||
Poco::Data::SessionFactory::instance().add(KEY, new Connector());
|
||||
Poco::Data::SessionFactory::instance().add(new Connector());
|
||||
}
|
||||
|
||||
|
||||
|
@@ -53,7 +53,8 @@ SQLiteStatementImpl::SQLiteStatementImpl(Poco::Data::SessionImpl& rSession, sqli
|
||||
_pDB(pDB),
|
||||
_pStmt(0),
|
||||
_stepCalled(false),
|
||||
_nextResponse(0)
|
||||
_nextResponse(0),
|
||||
_affectedRowCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -150,6 +151,8 @@ void SQLiteStatementImpl::bindImpl()
|
||||
|
||||
Bindings::iterator it = binds.begin();
|
||||
Bindings::iterator itEnd = binds.end();
|
||||
if (it != itEnd)
|
||||
_affectedRowCount = (*it)->numOfRowsHandled();
|
||||
for (; it != itEnd && (*it)->canBind(); ++it)
|
||||
{
|
||||
(*it)->bind(pos);
|
||||
@@ -161,6 +164,7 @@ void SQLiteStatementImpl::bindImpl()
|
||||
void SQLiteStatementImpl::clear()
|
||||
{
|
||||
_columns.clear();
|
||||
_affectedRowCount = 0;
|
||||
|
||||
if (_pStmt)
|
||||
{
|
||||
@@ -240,4 +244,10 @@ const MetaColumn& SQLiteStatementImpl::metaColumn(Poco::UInt32 pos) const
|
||||
}
|
||||
|
||||
|
||||
Poco::UInt32 SQLiteStatementImpl::affectedRowCount() const
|
||||
{
|
||||
return _affectedRowCount ? _affectedRowCount : sqlite3_changes(_pDB);
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
||||
|
@@ -38,6 +38,7 @@
|
||||
#include "Poco/Data/BLOB.h"
|
||||
#include "Poco/Data/Statement.h"
|
||||
#include "Poco/Data/RecordSet.h"
|
||||
#include "Poco/Data/SQLChannel.h"
|
||||
#include "Poco/Data/SessionFactory.h"
|
||||
#include "Poco/Data/SQLite/Connector.h"
|
||||
#include "Poco/Data/SQLite/SQLiteException.h"
|
||||
@@ -46,6 +47,10 @@
|
||||
#include "Poco/Any.h"
|
||||
#include "Poco/DynamicAny.h"
|
||||
#include "Poco/DateTime.h"
|
||||
#include "Poco/Logger.h"
|
||||
#include "Poco/Message.h"
|
||||
#include "Poco/Thread.h"
|
||||
#include "Poco/AutoPtr.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include <iostream>
|
||||
|
||||
@@ -56,6 +61,10 @@ using Poco::Any;
|
||||
using Poco::AnyCast;
|
||||
using Poco::DynamicAny;
|
||||
using Poco::DateTime;
|
||||
using Poco::Logger;
|
||||
using Poco::Message;
|
||||
using Poco::AutoPtr;
|
||||
using Poco::Thread;
|
||||
using Poco::InvalidAccessException;
|
||||
using Poco::RangeException;
|
||||
using Poco::BadCastException;
|
||||
@@ -174,7 +183,7 @@ SQLiteTest::~SQLiteTest()
|
||||
|
||||
void SQLiteTest::testSimpleAccess()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
assert (tmp.isConnected());
|
||||
std::string tableName("Person");
|
||||
std::string lastName("lastname");
|
||||
@@ -205,7 +214,7 @@ void SQLiteTest::testSimpleAccess()
|
||||
|
||||
void SQLiteTest::testInsertCharPointer()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::string tableName("Person");
|
||||
std::string lastName("lastname");
|
||||
std::string firstName("firstname");
|
||||
@@ -229,7 +238,7 @@ void SQLiteTest::testInsertCharPointer()
|
||||
|
||||
void SQLiteTest::testInsertCharPointer2()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::string tableName("Person");
|
||||
std::string lastName("lastname");
|
||||
std::string firstName("firstname");
|
||||
@@ -255,7 +264,7 @@ void SQLiteTest::testInsertCharPointer2()
|
||||
|
||||
void SQLiteTest::testComplexType()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
Person p1("LN1", "FN1", "ADDR1", 1);
|
||||
Person p2("LN2", "FN2", "ADDR2", 2);
|
||||
tmp << "DROP TABLE IF EXISTS Person", now;
|
||||
@@ -276,7 +285,7 @@ void SQLiteTest::testComplexType()
|
||||
|
||||
void SQLiteTest::testSimpleAccessVector()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::vector<std::string> lastNames;
|
||||
std::vector<std::string> firstNames;
|
||||
std::vector<std::string> addresses;
|
||||
@@ -313,7 +322,7 @@ void SQLiteTest::testSimpleAccessVector()
|
||||
|
||||
void SQLiteTest::testComplexTypeVector()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::vector<Person> people;
|
||||
people.push_back(Person("LN1", "FN1", "ADDR1", 1));
|
||||
people.push_back(Person("LN2", "FN2", "ADDR2", 2));
|
||||
@@ -332,7 +341,7 @@ void SQLiteTest::testComplexTypeVector()
|
||||
|
||||
void SQLiteTest::testInsertVector()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::vector<std::string> str;
|
||||
str.push_back("s1");
|
||||
str.push_back("s2");
|
||||
@@ -357,7 +366,7 @@ void SQLiteTest::testInsertVector()
|
||||
|
||||
void SQLiteTest::testInsertEmptyVector()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::vector<std::string> str;
|
||||
|
||||
tmp << "DROP TABLE IF EXISTS Strings", now;
|
||||
@@ -373,9 +382,41 @@ void SQLiteTest::testInsertEmptyVector()
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::testAffectedRows()
|
||||
{
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::vector<std::string> str;
|
||||
str.push_back("s1");
|
||||
str.push_back("s2");
|
||||
str.push_back("s3");
|
||||
str.push_back("s3");
|
||||
int count = 100;
|
||||
tmp << "DROP TABLE IF EXISTS Strings", now;
|
||||
tmp << "CREATE TABLE IF NOT EXISTS Strings (str VARCHAR(30))", now;
|
||||
|
||||
Statement stmt1((tmp << "INSERT INTO Strings VALUES(:str)", use(str)));
|
||||
tmp << "SELECT COUNT(*) FROM Strings", into(count), now;
|
||||
assert (count == 0);
|
||||
assert (4 == stmt1.execute());
|
||||
tmp << "SELECT COUNT(*) FROM Strings", into(count), now;
|
||||
assert (count == 4);
|
||||
|
||||
Statement stmt2(tmp << "UPDATE Strings SET str = 's4' WHERE str = 's3'");
|
||||
assert (2 == stmt2.execute());
|
||||
|
||||
Statement stmt3(tmp << "DELETE FROM Strings WHERE str = 's1'");
|
||||
assert (1 == stmt3.execute());
|
||||
|
||||
// see SQLiteStatementImpl::affectedRows() documentation for explanation
|
||||
// why "WHERE 1" is necessary here
|
||||
Statement stmt4(tmp << "DELETE FROM Strings WHERE 1");
|
||||
assert (3 == stmt4.execute());
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::testInsertSingleBulk()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Strings", now;
|
||||
tmp << "CREATE TABLE IF NOT EXISTS Strings (str INTEGER(10))", now;
|
||||
int x = 0;
|
||||
@@ -384,7 +425,7 @@ void SQLiteTest::testInsertSingleBulk()
|
||||
for (x = 0; x < 100; ++x)
|
||||
{
|
||||
int i = stmt.execute();
|
||||
assert (i == 0);
|
||||
assert (1 == i);
|
||||
}
|
||||
int count = 0;
|
||||
tmp << "SELECT COUNT(*) FROM Strings", into(count), now;
|
||||
@@ -396,7 +437,7 @@ void SQLiteTest::testInsertSingleBulk()
|
||||
|
||||
void SQLiteTest::testInsertSingleBulkVec()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Strings", now;
|
||||
tmp << "CREATE TABLE IF NOT EXISTS Strings (str INTEGER(10))", now;
|
||||
std::vector<int> data;
|
||||
@@ -421,7 +462,7 @@ void SQLiteTest::testInsertSingleBulkVec()
|
||||
|
||||
void SQLiteTest::testLimit()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Strings", now;
|
||||
tmp << "CREATE TABLE IF NOT EXISTS Strings (str INTEGER(10))", now;
|
||||
std::vector<int> data;
|
||||
@@ -443,7 +484,7 @@ void SQLiteTest::testLimit()
|
||||
|
||||
void SQLiteTest::testLimitZero()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Strings", now;
|
||||
tmp << "CREATE TABLE IF NOT EXISTS Strings (str INTEGER(10))", now;
|
||||
std::vector<int> data;
|
||||
@@ -461,7 +502,7 @@ void SQLiteTest::testLimitZero()
|
||||
|
||||
void SQLiteTest::testLimitOnce()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Strings", now;
|
||||
tmp << "CREATE TABLE IF NOT EXISTS Strings (str INTEGER(10))", now;
|
||||
std::vector<int> data;
|
||||
@@ -491,7 +532,7 @@ void SQLiteTest::testLimitOnce()
|
||||
|
||||
void SQLiteTest::testLimitPrepare()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Strings", now;
|
||||
tmp << "CREATE TABLE IF NOT EXISTS Strings (str INTEGER(10))", now;
|
||||
std::vector<int> data;
|
||||
@@ -500,7 +541,9 @@ void SQLiteTest::testLimitPrepare()
|
||||
data.push_back(x);
|
||||
}
|
||||
|
||||
tmp << "INSERT INTO Strings VALUES(:str)", use(data), now;
|
||||
Statement stmtIns = (tmp << "INSERT INTO Strings VALUES(:str)", use(data));
|
||||
assert (100 == stmtIns.execute());
|
||||
|
||||
std::vector<int> retData;
|
||||
Statement stmt = (tmp << "SELECT * FROM Strings", into(retData), limit(50));
|
||||
assert (retData.size() == 0);
|
||||
@@ -527,7 +570,7 @@ void SQLiteTest::testLimitPrepare()
|
||||
|
||||
void SQLiteTest::testPrepare()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Strings", now;
|
||||
tmp << "CREATE TABLE IF NOT EXISTS Strings (str INTEGER(10))", now;
|
||||
std::vector<int> data;
|
||||
@@ -548,7 +591,7 @@ void SQLiteTest::testPrepare()
|
||||
|
||||
void SQLiteTest::testSetSimple()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::set<std::string> lastNames;
|
||||
std::set<std::string> firstNames;
|
||||
std::set<std::string> addresses;
|
||||
@@ -585,7 +628,7 @@ void SQLiteTest::testSetSimple()
|
||||
|
||||
void SQLiteTest::testSetComplex()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::set<Person> people;
|
||||
people.insert(Person("LN1", "FN1", "ADDR1", 1));
|
||||
people.insert(Person("LN2", "FN2", "ADDR2", 2));
|
||||
@@ -604,7 +647,7 @@ void SQLiteTest::testSetComplex()
|
||||
|
||||
void SQLiteTest::testSetComplexUnique()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::vector<Person> people;
|
||||
Person p1("LN1", "FN1", "ADDR1", 1);
|
||||
people.push_back(p1);
|
||||
@@ -630,7 +673,7 @@ void SQLiteTest::testSetComplexUnique()
|
||||
|
||||
void SQLiteTest::testMultiSetSimple()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::multiset<std::string> lastNames;
|
||||
std::multiset<std::string> firstNames;
|
||||
std::multiset<std::string> addresses;
|
||||
@@ -667,7 +710,7 @@ void SQLiteTest::testMultiSetSimple()
|
||||
|
||||
void SQLiteTest::testMultiSetComplex()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::multiset<Person> people;
|
||||
Person p1("LN1", "FN1", "ADDR1", 1);
|
||||
people.insert(p1);
|
||||
@@ -692,7 +735,7 @@ void SQLiteTest::testMultiSetComplex()
|
||||
|
||||
void SQLiteTest::testMapComplex()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::map<std::string, Person> people;
|
||||
Person p1("LN1", "FN1", "ADDR1", 1);
|
||||
Person p2("LN2", "FN2", "ADDR2", 2);
|
||||
@@ -713,7 +756,7 @@ void SQLiteTest::testMapComplex()
|
||||
|
||||
void SQLiteTest::testMapComplexUnique()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::multimap<std::string, Person> people;
|
||||
Person p1("LN1", "FN1", "ADDR1", 1);
|
||||
Person p2("LN2", "FN2", "ADDR2", 2);
|
||||
@@ -737,7 +780,7 @@ void SQLiteTest::testMapComplexUnique()
|
||||
|
||||
void SQLiteTest::testMultiMapComplex()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::multimap<std::string, Person> people;
|
||||
Person p1("LN1", "FN1", "ADDR1", 1);
|
||||
Person p2("LN2", "FN2", "ADDR2", 2);
|
||||
@@ -761,7 +804,7 @@ void SQLiteTest::testMultiMapComplex()
|
||||
|
||||
void SQLiteTest::testSelectIntoSingle()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::multimap<std::string, Person> people;
|
||||
Person p1("LN1", "FN1", "ADDR1", 1);
|
||||
Person p2("LN2", "FN2", "ADDR2", 2);
|
||||
@@ -781,7 +824,7 @@ void SQLiteTest::testSelectIntoSingle()
|
||||
|
||||
void SQLiteTest::testSelectIntoSingleStep()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::multimap<std::string, Person> people;
|
||||
Person p1("LN1", "FN1", "ADDR1", 1);
|
||||
Person p2("LN2", "FN2", "ADDR2", 2);
|
||||
@@ -806,7 +849,7 @@ void SQLiteTest::testSelectIntoSingleStep()
|
||||
|
||||
void SQLiteTest::testSelectIntoSingleFail()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::multimap<std::string, Person> people;
|
||||
Person p1("LN1", "FN1", "ADDR1", 1);
|
||||
Person p2("LN2", "FN2", "ADDR2", 2);
|
||||
@@ -832,7 +875,7 @@ void SQLiteTest::testSelectIntoSingleFail()
|
||||
|
||||
void SQLiteTest::testLowerLimitOk()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::multimap<std::string, Person> people;
|
||||
Person p1("LN1", "FN1", "ADDR1", 1);
|
||||
Person p2("LN2", "FN2", "ADDR2", 2);
|
||||
@@ -858,7 +901,7 @@ void SQLiteTest::testLowerLimitOk()
|
||||
|
||||
void SQLiteTest::testSingleSelect()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::multimap<std::string, Person> people;
|
||||
Person p1("LN1", "FN1", "ADDR1", 1);
|
||||
Person p2("LN2", "FN2", "ADDR2", 2);
|
||||
@@ -883,7 +926,7 @@ void SQLiteTest::testSingleSelect()
|
||||
|
||||
void SQLiteTest::testLowerLimitFail()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::multimap<std::string, Person> people;
|
||||
Person p1("LN1", "FN1", "ADDR1", 1);
|
||||
Person p2("LN2", "FN2", "ADDR2", 2);
|
||||
@@ -909,7 +952,7 @@ void SQLiteTest::testLowerLimitFail()
|
||||
|
||||
void SQLiteTest::testCombinedLimits()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::multimap<std::string, Person> people;
|
||||
Person p1("LN1", "FN1", "ADDR1", 1);
|
||||
Person p2("LN2", "FN2", "ADDR2", 2);
|
||||
@@ -932,7 +975,7 @@ void SQLiteTest::testCombinedLimits()
|
||||
|
||||
void SQLiteTest::testRange()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::multimap<std::string, Person> people;
|
||||
Person p1("LN1", "FN1", "ADDR1", 1);
|
||||
Person p2("LN2", "FN2", "ADDR2", 2);
|
||||
@@ -954,7 +997,7 @@ void SQLiteTest::testRange()
|
||||
|
||||
void SQLiteTest::testCombinedIllegalLimits()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::multimap<std::string, Person> people;
|
||||
Person p1("LN1", "FN1", "ADDR1", 1);
|
||||
Person p2("LN2", "FN2", "ADDR2", 2);
|
||||
@@ -981,7 +1024,7 @@ void SQLiteTest::testCombinedIllegalLimits()
|
||||
|
||||
void SQLiteTest::testIllegalRange()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
std::multimap<std::string, Person> people;
|
||||
Person p1("LN1", "FN1", "ADDR1", 1);
|
||||
Person p2("LN2", "FN2", "ADDR2", 2);
|
||||
@@ -1007,7 +1050,7 @@ void SQLiteTest::testIllegalRange()
|
||||
|
||||
void SQLiteTest::testEmptyDB()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
|
||||
tmp << "DROP TABLE IF EXISTS Person", now;
|
||||
tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
|
||||
@@ -1027,7 +1070,7 @@ void SQLiteTest::testBLOB()
|
||||
std::string lastName("lastname");
|
||||
std::string firstName("firstname");
|
||||
std::string address("Address");
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Person", now;
|
||||
tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Image BLOB)", now;
|
||||
BLOB img("0123456789", 10);
|
||||
@@ -1044,7 +1087,7 @@ void SQLiteTest::testBLOB()
|
||||
|
||||
void SQLiteTest::testTuple10()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Tuples", now;
|
||||
tmp << "CREATE TABLE Tuples "
|
||||
"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, "
|
||||
@@ -1063,7 +1106,7 @@ void SQLiteTest::testTuple10()
|
||||
|
||||
void SQLiteTest::testTupleVector10()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Tuples", now;
|
||||
tmp << "CREATE TABLE Tuples "
|
||||
"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, "
|
||||
@@ -1092,7 +1135,7 @@ void SQLiteTest::testTupleVector10()
|
||||
|
||||
void SQLiteTest::testTuple9()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Tuples", now;
|
||||
tmp << "CREATE TABLE Tuples "
|
||||
"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, "
|
||||
@@ -1111,7 +1154,7 @@ void SQLiteTest::testTuple9()
|
||||
|
||||
void SQLiteTest::testTupleVector9()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Tuples", now;
|
||||
tmp << "CREATE TABLE Tuples "
|
||||
"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, "
|
||||
@@ -1140,7 +1183,7 @@ void SQLiteTest::testTupleVector9()
|
||||
|
||||
void SQLiteTest::testTuple8()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Tuples", now;
|
||||
tmp << "CREATE TABLE Tuples "
|
||||
"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, "
|
||||
@@ -1159,7 +1202,7 @@ void SQLiteTest::testTuple8()
|
||||
|
||||
void SQLiteTest::testTupleVector8()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Tuples", now;
|
||||
tmp << "CREATE TABLE Tuples "
|
||||
"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, "
|
||||
@@ -1188,7 +1231,7 @@ void SQLiteTest::testTupleVector8()
|
||||
|
||||
void SQLiteTest::testTuple7()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Tuples", now;
|
||||
tmp << "CREATE TABLE Tuples "
|
||||
"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER)", now;
|
||||
@@ -1206,7 +1249,7 @@ void SQLiteTest::testTuple7()
|
||||
|
||||
void SQLiteTest::testTupleVector7()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Tuples", now;
|
||||
tmp << "CREATE TABLE Tuples "
|
||||
"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER)", now;
|
||||
@@ -1234,7 +1277,7 @@ void SQLiteTest::testTupleVector7()
|
||||
|
||||
void SQLiteTest::testTuple6()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Tuples", now;
|
||||
tmp << "CREATE TABLE Tuples "
|
||||
"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER)", now;
|
||||
@@ -1252,7 +1295,7 @@ void SQLiteTest::testTuple6()
|
||||
|
||||
void SQLiteTest::testTupleVector6()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Tuples", now;
|
||||
tmp << "CREATE TABLE Tuples "
|
||||
"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER)", now;
|
||||
@@ -1280,7 +1323,7 @@ void SQLiteTest::testTupleVector6()
|
||||
|
||||
void SQLiteTest::testTuple5()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Tuples", now;
|
||||
tmp << "CREATE TABLE Tuples "
|
||||
"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER)", now;
|
||||
@@ -1298,7 +1341,7 @@ void SQLiteTest::testTuple5()
|
||||
|
||||
void SQLiteTest::testTupleVector5()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Tuples", now;
|
||||
tmp << "CREATE TABLE Tuples "
|
||||
"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER)", now;
|
||||
@@ -1326,7 +1369,7 @@ void SQLiteTest::testTupleVector5()
|
||||
|
||||
void SQLiteTest::testTuple4()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Tuples", now;
|
||||
tmp << "CREATE TABLE Tuples "
|
||||
"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER)", now;
|
||||
@@ -1344,7 +1387,7 @@ void SQLiteTest::testTuple4()
|
||||
|
||||
void SQLiteTest::testTupleVector4()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Tuples", now;
|
||||
tmp << "CREATE TABLE Tuples "
|
||||
"(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER)", now;
|
||||
@@ -1372,7 +1415,7 @@ void SQLiteTest::testTupleVector4()
|
||||
|
||||
void SQLiteTest::testTuple3()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Tuples", now;
|
||||
tmp << "CREATE TABLE Tuples "
|
||||
"(int0 INTEGER, int1 INTEGER, int2 INTEGER)", now;
|
||||
@@ -1390,7 +1433,7 @@ void SQLiteTest::testTuple3()
|
||||
|
||||
void SQLiteTest::testTupleVector3()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Tuples", now;
|
||||
tmp << "CREATE TABLE Tuples "
|
||||
"(int0 INTEGER, int1 INTEGER, int2 INTEGER)", now;
|
||||
@@ -1418,7 +1461,7 @@ void SQLiteTest::testTupleVector3()
|
||||
|
||||
void SQLiteTest::testTuple2()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Tuples", now;
|
||||
tmp << "CREATE TABLE Tuples (int0 INTEGER, int1 INTEGER)", now;
|
||||
|
||||
@@ -1435,7 +1478,7 @@ void SQLiteTest::testTuple2()
|
||||
|
||||
void SQLiteTest::testTupleVector2()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Tuples", now;
|
||||
tmp << "CREATE TABLE Tuples (int0 INTEGER, int1 INTEGER)", now;
|
||||
|
||||
@@ -1462,7 +1505,7 @@ void SQLiteTest::testTupleVector2()
|
||||
|
||||
void SQLiteTest::testTuple1()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Tuples", now;
|
||||
tmp << "CREATE TABLE Tuples (int0 INTEGER)", now;
|
||||
|
||||
@@ -1479,7 +1522,7 @@ void SQLiteTest::testTuple1()
|
||||
|
||||
void SQLiteTest::testTupleVector1()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Tuples", now;
|
||||
tmp << "CREATE TABLE Tuples (int0 INTEGER)", now;
|
||||
|
||||
@@ -1506,7 +1549,7 @@ void SQLiteTest::testTupleVector1()
|
||||
|
||||
void SQLiteTest::testDateTime()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS DateTimes", now;
|
||||
tmp << "CREATE TABLE DateTimes (dt0 DATE)", now;
|
||||
|
||||
@@ -1542,7 +1585,7 @@ void SQLiteTest::testDateTime()
|
||||
|
||||
void SQLiteTest::testInternalExtraction()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Vectors", now;
|
||||
tmp << "CREATE TABLE Vectors (int0 INTEGER, flt0 REAL, str0 VARCHAR)", now;
|
||||
|
||||
@@ -1608,7 +1651,7 @@ void SQLiteTest::testInternalExtraction()
|
||||
|
||||
void SQLiteTest::testPrimaryKeyConstraint()
|
||||
{
|
||||
Session ses (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session ses (SQLite::Connector::KEY, "dummy.db");
|
||||
ses << "DROP TABLE IF EXISTS LogTest", now;
|
||||
ses << "CREATE TABLE LogTest (Id INTEGER PRIMARY KEY, Time INTEGER, Value INTEGER)", now;
|
||||
const double value = -200000000000.0;
|
||||
@@ -1638,7 +1681,7 @@ void SQLiteTest::testPrimaryKeyConstraint()
|
||||
|
||||
void SQLiteTest::testNull()
|
||||
{
|
||||
Session ses (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session ses (SQLite::Connector::KEY, "dummy.db");
|
||||
ses << "DROP TABLE IF EXISTS NullTest", now;
|
||||
|
||||
ses << "CREATE TABLE NullTest (i INTEGER NOT NULL)", now;
|
||||
@@ -1708,7 +1751,7 @@ void SQLiteTest::testNull()
|
||||
|
||||
void SQLiteTest::testRowIterator()
|
||||
{
|
||||
Session ses (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session ses (SQLite::Connector::KEY, "dummy.db");
|
||||
ses << "DROP TABLE IF EXISTS Vectors", now;
|
||||
ses << "CREATE TABLE Vectors (int0 INTEGER, flt0 REAL, str0 VARCHAR)", now;
|
||||
|
||||
@@ -1740,7 +1783,7 @@ void SQLiteTest::testRowIterator()
|
||||
|
||||
void SQLiteTest::testAsync()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Strings", now;
|
||||
tmp << "CREATE TABLE IF NOT EXISTS Strings (str INTEGER(10))", now;
|
||||
|
||||
@@ -1750,6 +1793,7 @@ void SQLiteTest::testAsync()
|
||||
Statement::Result result = stmt.executeAsync();
|
||||
assert (!stmt.isAsync());
|
||||
result.wait();
|
||||
assert (500 == result.data());
|
||||
|
||||
Statement stmt1 = (tmp << "SELECT * FROM Strings", into(data), async, now);
|
||||
assert (stmt1.isAsync());
|
||||
@@ -1823,7 +1867,7 @@ void SQLiteTest::testAsync()
|
||||
|
||||
void SQLiteTest::testAny()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Anys", now;
|
||||
tmp << "CREATE TABLE Anys (int0 INTEGER, flt0 REAL, str0 VARCHAR)", now;
|
||||
|
||||
@@ -1849,7 +1893,7 @@ void SQLiteTest::testAny()
|
||||
|
||||
void SQLiteTest::testDynamicAny()
|
||||
{
|
||||
Session tmp (SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Anys", now;
|
||||
tmp << "CREATE TABLE Anys (int0 INTEGER, flt0 REAL, str0 VARCHAR)", now;
|
||||
|
||||
@@ -1873,6 +1917,115 @@ void SQLiteTest::testDynamicAny()
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::testSQLChannel()
|
||||
{
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS T_POCO_LOG", now;
|
||||
tmp << "CREATE TABLE T_POCO_LOG (Source VARCHAR,"
|
||||
"Name VARCHAR,"
|
||||
"ProcessId INTEGER,"
|
||||
"Thread VARCHAR, "
|
||||
"ThreadId INTEGER,"
|
||||
"Priority INTEGER,"
|
||||
"Text VARCHAR,"
|
||||
"DateTime DATE)", now;
|
||||
|
||||
tmp << "DROP TABLE IF EXISTS T_POCO_LOG_ARCHIVE", now;
|
||||
tmp << "CREATE TABLE T_POCO_LOG_ARCHIVE (Source VARCHAR,"
|
||||
"Name VARCHAR,"
|
||||
"ProcessId INTEGER,"
|
||||
"Thread VARCHAR, "
|
||||
"ThreadId INTEGER,"
|
||||
"Priority INTEGER,"
|
||||
"Text VARCHAR,"
|
||||
"DateTime DATE)", now;
|
||||
|
||||
AutoPtr<SQLChannel> pChannel = new SQLChannel(SQLite::Connector::KEY, "dummy.db", "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(tmp, "SELECT * FROM T_POCO_LOG ORDER by Text");
|
||||
assert (4 == rs.rowCount());
|
||||
assert ("InformationSource" == rs["Source"]);
|
||||
assert ("a Informational async message" == rs["Text"]);
|
||||
rs.moveNext();
|
||||
assert ("WarningSource" == rs["Source"]);
|
||||
assert ("b Warning async message" == rs["Text"]);
|
||||
rs.moveNext();
|
||||
assert ("InformationSource" == rs["Source"]);
|
||||
assert ("c Informational sync message" == rs["Text"]);
|
||||
rs.moveNext();
|
||||
assert ("WarningSource" == rs["Source"]);
|
||||
assert ("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(tmp, "SELECT * FROM T_POCO_LOG_ARCHIVE");
|
||||
assert (4 == rs1.rowCount());
|
||||
|
||||
pChannel->setProperty("keep", "");
|
||||
assert ("forever" == pChannel->getProperty("keep"));
|
||||
RecordSet rs2(tmp, "SELECT * FROM T_POCO_LOG ORDER by Text");
|
||||
assert (2 == rs2.rowCount());
|
||||
assert ("InformationSource" == rs2["Source"]);
|
||||
assert ("e Informational sync message" == rs2["Text"]);
|
||||
rs2.moveNext();
|
||||
assert ("WarningSource" == rs2["Source"]);
|
||||
assert ("f Warning sync message" == rs2["Text"]);
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::testSQLLogger()
|
||||
{
|
||||
Session tmp (SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS T_POCO_LOG", now;
|
||||
tmp << "CREATE TABLE T_POCO_LOG (Source VARCHAR,"
|
||||
"Name VARCHAR,"
|
||||
"ProcessId INTEGER,"
|
||||
"Thread VARCHAR, "
|
||||
"ThreadId INTEGER,"
|
||||
"Priority INTEGER,"
|
||||
"Text VARCHAR,"
|
||||
"DateTime DATE)", now;
|
||||
|
||||
{
|
||||
AutoPtr<SQLChannel> pChannel = new SQLChannel(SQLite::Connector::KEY, "dummy.db", "TestSQLChannel");
|
||||
Logger& root = Logger::root();
|
||||
root.setChannel(pChannel.get());
|
||||
root.setLevel(Message::PRIO_INFORMATION);
|
||||
|
||||
root.information("Informational message");
|
||||
root.warning("Warning message");
|
||||
root.debug("Debug message");
|
||||
}
|
||||
|
||||
Thread::sleep(100);
|
||||
RecordSet rs(tmp, "SELECT * FROM T_POCO_LOG ORDER by DateTime");
|
||||
assert (2 == rs.rowCount());
|
||||
assert ("TestSQLChannel" == rs["Source"]);
|
||||
assert ("Informational message" == rs["Text"]);
|
||||
rs.moveNext();
|
||||
assert ("TestSQLChannel" == rs["Source"]);
|
||||
assert ("Warning message" == rs["Text"]);
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::setUp()
|
||||
{
|
||||
}
|
||||
@@ -1895,6 +2048,7 @@ CppUnit::Test* SQLiteTest::suite()
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testComplexTypeVector);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testInsertVector);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testInsertEmptyVector);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testAffectedRows);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testInsertSingleBulk);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testInsertSingleBulkVec);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testLimit);
|
||||
@@ -1950,6 +2104,8 @@ CppUnit::Test* SQLiteTest::suite()
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testAsync);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testAny);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testDynamicAny);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testSQLChannel);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testSQLLogger);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@@ -54,7 +54,7 @@ public:
|
||||
void testComplexTypeVector();
|
||||
void testInsertVector();
|
||||
void testInsertEmptyVector();
|
||||
|
||||
void testAffectedRows();
|
||||
void testInsertSingleBulk();
|
||||
void testInsertSingleBulkVec();
|
||||
|
||||
@@ -118,6 +118,9 @@ public:
|
||||
void testAny();
|
||||
void testDynamicAny();
|
||||
|
||||
void testSQLChannel();
|
||||
void testSQLLogger();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
||||
|
244
Data/include/Poco/Data/ArchiveStrategy.h
Normal file
244
Data/include/Poco/Data/ArchiveStrategy.h
Normal file
@@ -0,0 +1,244 @@
|
||||
//
|
||||
// ArchiveStrategy.h
|
||||
//
|
||||
// $Id: //poco/Main/Data/include/Poco/ArchiveStrategy.h#1 $
|
||||
//
|
||||
// Library: Data
|
||||
// Package: Logging
|
||||
// Module: ArchiveStrategy
|
||||
//
|
||||
// Definition of the ArchiveStrategy class and subclasses.
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#ifndef Data_ArchiveStrategy_INCLUDED
|
||||
#define Data_ArchiveStrategy_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Data/Data.h"
|
||||
#include "Poco/Data/Session.h"
|
||||
#include "Poco/DateTime.h"
|
||||
#include "Poco/Timespan.h"
|
||||
#include "Poco/DynamicAny.h"
|
||||
#include "Poco/SharedPtr.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
|
||||
|
||||
class Data_API ArchiveStrategy
|
||||
/// The ArchiveStrategy is used by SQLChannel to archive log rows.
|
||||
{
|
||||
public:
|
||||
static const std::string DEFAULT_ARCHIVE_DESTINATION;
|
||||
|
||||
ArchiveStrategy(const std::string& connector,
|
||||
const std::string& connect,
|
||||
const std::string& source,
|
||||
const std::string& destination = DEFAULT_ARCHIVE_DESTINATION);
|
||||
/// Creates archive strategy.
|
||||
|
||||
virtual ~ArchiveStrategy();
|
||||
/// Destroys archive strategy.
|
||||
|
||||
void open();
|
||||
/// Opens the session.
|
||||
|
||||
virtual void archive() = 0;
|
||||
/// Archives the rows.
|
||||
|
||||
const std::string& getSource() const;
|
||||
/// Returns the name of the source table containing rows to be archived.
|
||||
|
||||
void setSource(const std::string& source);
|
||||
/// Sets the name of the source table.
|
||||
|
||||
const std::string& getDestination() const;
|
||||
/// Returns the name of the destination table for rows to be archived.
|
||||
|
||||
void setDestination(const std::string& destination);
|
||||
/// Sets the name of the destination table.
|
||||
|
||||
virtual const std::string& getThreshold() const = 0;
|
||||
/// Returns the archive threshold.
|
||||
|
||||
virtual void setThreshold(const std::string& threshold) = 0;
|
||||
/// Sets the archive threshold.
|
||||
|
||||
protected:
|
||||
typedef Poco::SharedPtr<Session> SessionPtr;
|
||||
typedef Poco::SharedPtr<Statement> StatementPtr;
|
||||
|
||||
Session& session();
|
||||
|
||||
void setCopyStatement();
|
||||
void setDeleteStatement();
|
||||
void setCountStatement();
|
||||
|
||||
Statement& getCopyStatement();
|
||||
Statement& getDeleteStatement();
|
||||
Statement& getCountStatement();
|
||||
private:
|
||||
|
||||
ArchiveStrategy();
|
||||
ArchiveStrategy(const ArchiveStrategy&);
|
||||
ArchiveStrategy& operator = (const ArchiveStrategy&);
|
||||
|
||||
std::string _connector;
|
||||
std::string _connect;
|
||||
SessionPtr _pSession;
|
||||
StatementPtr _pCopyStatement;
|
||||
StatementPtr _pDeleteStatement;
|
||||
StatementPtr _pCountStatement;
|
||||
std::string _source;
|
||||
std::string _destination;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
|
||||
inline const std::string& ArchiveStrategy::getSource() const
|
||||
{
|
||||
return _source;
|
||||
}
|
||||
|
||||
|
||||
inline void ArchiveStrategy::setSource(const std::string& source)
|
||||
{
|
||||
_source = source;
|
||||
}
|
||||
|
||||
|
||||
inline void ArchiveStrategy::setDestination(const std::string& destination)
|
||||
{
|
||||
_destination = destination;
|
||||
}
|
||||
|
||||
|
||||
inline const std::string& ArchiveStrategy::getDestination() const
|
||||
{
|
||||
return _destination;
|
||||
}
|
||||
|
||||
|
||||
inline Session& ArchiveStrategy::session()
|
||||
{
|
||||
return *_pSession;
|
||||
}
|
||||
|
||||
|
||||
inline void ArchiveStrategy::setCopyStatement()
|
||||
{
|
||||
_pCopyStatement = new Statement(*_pSession);
|
||||
}
|
||||
|
||||
|
||||
inline void ArchiveStrategy::setDeleteStatement()
|
||||
{
|
||||
_pDeleteStatement = new Statement(*_pSession);
|
||||
}
|
||||
|
||||
|
||||
inline void ArchiveStrategy::setCountStatement()
|
||||
{
|
||||
_pCountStatement = new Statement(*_pSession);
|
||||
}
|
||||
|
||||
|
||||
inline Statement& ArchiveStrategy::getCopyStatement()
|
||||
{
|
||||
return *_pCopyStatement;
|
||||
}
|
||||
|
||||
|
||||
inline Statement& ArchiveStrategy::getDeleteStatement()
|
||||
{
|
||||
return *_pDeleteStatement;
|
||||
}
|
||||
|
||||
|
||||
inline Statement& ArchiveStrategy::getCountStatement()
|
||||
{
|
||||
return *_pCountStatement;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// ArchiveByAgeStrategy
|
||||
//
|
||||
class Data_API ArchiveByAgeStrategy: public ArchiveStrategy
|
||||
/// Archives rows scheduled for archiving.
|
||||
{
|
||||
public:
|
||||
ArchiveByAgeStrategy(const std::string& connector,
|
||||
const std::string& connect,
|
||||
const std::string& sourceTable,
|
||||
const std::string& destinationTable = DEFAULT_ARCHIVE_DESTINATION);
|
||||
|
||||
~ArchiveByAgeStrategy();
|
||||
|
||||
void archive();
|
||||
|
||||
const std::string& getThreshold() const;
|
||||
/// Returns the archive threshold.
|
||||
|
||||
void setThreshold(const std::string& threshold);
|
||||
/// Sets the archive threshold.
|
||||
|
||||
private:
|
||||
ArchiveByAgeStrategy();
|
||||
ArchiveByAgeStrategy(const ArchiveByAgeStrategy&);
|
||||
ArchiveByAgeStrategy& operator = (const ArchiveByAgeStrategy&);
|
||||
|
||||
void initStatements();
|
||||
|
||||
Timespan _maxAge;
|
||||
std::string _ageString;
|
||||
DateTime _archiveDateTime;
|
||||
DynamicAny _archiveCount;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
|
||||
inline const std::string& ArchiveByAgeStrategy::getThreshold() const
|
||||
{
|
||||
return _ageString;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Data
|
||||
|
||||
|
||||
#endif // Data_ArchiveStrategy_INCLUDED
|
@@ -99,7 +99,9 @@ public:
|
||||
void reset ()
|
||||
{
|
||||
_bound = false;
|
||||
getBinder()->reset();
|
||||
AbstractBinder* pBinder = getBinder();
|
||||
poco_check_ptr (pBinder);
|
||||
pBinder->reset();
|
||||
}
|
||||
|
||||
private:
|
||||
|
@@ -63,6 +63,9 @@ public:
|
||||
virtual ~Connector();
|
||||
/// Destroys the Connector.
|
||||
|
||||
virtual const std::string& name() const = 0;
|
||||
/// Returns the name associated with this connector.
|
||||
|
||||
virtual Poco::AutoPtr<SessionImpl> createSession(const std::string& connectionString) = 0;
|
||||
/// Create a SessionImpl object and initialize it with the given connectionString.
|
||||
};
|
||||
|
@@ -45,7 +45,6 @@
|
||||
#include "Poco/Data/BulkExtraction.h"
|
||||
#include "Poco/Data/Statement.h"
|
||||
#include "Poco/Data/RowIterator.h"
|
||||
#include "Poco/Data/RowFormatter.h"
|
||||
#include "Poco/Data/BLOB.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/DynamicAny.h"
|
||||
@@ -85,6 +84,7 @@ public:
|
||||
typedef RowIterator Iterator;
|
||||
|
||||
using Statement::isNull;
|
||||
using Statement::setRowFormatter;
|
||||
|
||||
explicit RecordSet(const Statement& rStatement);
|
||||
/// Creates the RecordSet.
|
||||
@@ -288,15 +288,6 @@ public:
|
||||
bool isNull(const std::string& name) const;
|
||||
/// Returns true if column value of the current row is null.
|
||||
|
||||
void setFormatter(Row::FormatterPtr pRowFormatter);
|
||||
/// Sets the row formatter for this recordset.
|
||||
/// Row formatter is null pointer by default, indicating
|
||||
/// use of default formatter for output formatting.
|
||||
/// This function allows for custom formatters to be
|
||||
/// supplied by users. After setting a user supplied formatter,
|
||||
/// to revert back to the default one, call this function with
|
||||
/// zero argument.
|
||||
|
||||
std::ostream& copyNames(std::ostream& os) const;
|
||||
/// Copies the column names to the target output stream.
|
||||
/// Copied string is formatted by the current RowFormatter.
|
||||
@@ -346,9 +337,9 @@ private:
|
||||
}
|
||||
|
||||
if (typeFound)
|
||||
throw NotFoundException(format("Column name: %s", name));
|
||||
throw NotFoundException(Poco::format("Column name: %s", name));
|
||||
else
|
||||
throw NotFoundException(format("Column type: %s, name: %s", std::string(typeid(T).name()), name));
|
||||
throw NotFoundException(Poco::format("Column type: %s, name: %s", std::string(typeid(T).name()), name));
|
||||
}
|
||||
|
||||
template <class C, class E>
|
||||
@@ -369,7 +360,7 @@ private:
|
||||
|
||||
std::size_t s = rExtractions.size();
|
||||
if (0 == s || pos >= s)
|
||||
throw RangeException(format("Invalid column index: %z", pos));
|
||||
throw RangeException(Poco::format("Invalid column index: %z", pos));
|
||||
|
||||
ExtractionVecPtr pExtraction = dynamic_cast<ExtractionVecPtr>(rExtractions[pos].get());
|
||||
|
||||
@@ -379,7 +370,7 @@ private:
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Poco::BadCastException(format("Type cast failed!\nColumn: %z\nTarget type:\t%s",
|
||||
throw Poco::BadCastException(Poco::format("Type cast failed!\nColumn: %z\nTarget type:\t%s",
|
||||
pos,
|
||||
std::string(typeid(T).name())));
|
||||
}
|
||||
@@ -389,7 +380,6 @@ private:
|
||||
RowIterator* _pBegin;
|
||||
RowIterator* _pEnd;
|
||||
RowMap _rowMap;
|
||||
Row::FormatterPtr _pRowFormatter;
|
||||
};
|
||||
|
||||
|
||||
@@ -519,12 +509,6 @@ inline RecordSet::Iterator RecordSet::end()
|
||||
}
|
||||
|
||||
|
||||
inline void RecordSet::setFormatter(Row::FormatterPtr pRowFormatter)
|
||||
{
|
||||
_pRowFormatter = pRowFormatter;
|
||||
}
|
||||
|
||||
|
||||
inline std::ostream& RecordSet::copyNames(std::ostream& os) const
|
||||
{
|
||||
os << (*_pBegin)->namesToString();
|
||||
|
@@ -82,7 +82,6 @@ public:
|
||||
typedef RowFormatter::NameVec NameVec;
|
||||
typedef RowFormatter::NameVecPtr NameVecPtr;
|
||||
typedef RowFormatter::ValueVec ValueVec;
|
||||
typedef SharedPtr<RowFormatter> FormatterPtr;
|
||||
|
||||
enum ComparisonType
|
||||
{
|
||||
@@ -94,7 +93,7 @@ public:
|
||||
Row();
|
||||
/// Creates the Row.
|
||||
|
||||
explicit Row(NameVecPtr pNames, FormatterPtr* pFormatter = 0);
|
||||
Row(NameVecPtr pNames, const RowFormatterPtr& pFormatter = 0);
|
||||
/// Creates the Row.
|
||||
|
||||
~Row();
|
||||
@@ -201,7 +200,7 @@ public:
|
||||
const ValueVec& values() const;
|
||||
/// Returns the const reference to values vector.
|
||||
|
||||
void setFormatter(FormatterPtr* pFormatter);
|
||||
void setFormatter(const RowFormatterPtr& pFormatter);
|
||||
/// Sets the formatter for this row and takes the
|
||||
/// shared ownership of it.
|
||||
|
||||
@@ -226,7 +225,7 @@ private:
|
||||
NameVecPtr _pNames;
|
||||
ValueVec _values;
|
||||
SortMap _sortFields;
|
||||
FormatterPtr _pFormatter;
|
||||
RowFormatterPtr _pFormatter;
|
||||
mutable std::string _nameStr;
|
||||
mutable std::string _valueStr;
|
||||
};
|
||||
|
@@ -42,6 +42,7 @@
|
||||
|
||||
#include "Poco/Data/Data.h"
|
||||
#include "Poco/SharedPtr.h"
|
||||
#include "Poco/RefCountedObject.h"
|
||||
#include "Poco/DynamicAny.h"
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
@@ -52,51 +53,53 @@ namespace Data {
|
||||
|
||||
|
||||
class Data_API RowFormatter
|
||||
/// Row formatter is a rudimentary formatting class providing
|
||||
/// basic row formatting. For custom formatting
|
||||
/// strategies, inherit from this class and override formatNames()
|
||||
/// Row formatter is an abstract class providing definition for row formatting functionality.
|
||||
/// For custom formatting strategies, inherit from this class and override formatNames()
|
||||
/// and formatValues() member functions.
|
||||
///
|
||||
/// Row formatter can be either passed to the RecordSet at construction time,
|
||||
/// like in the following example:
|
||||
///
|
||||
/// RecordSet rs(session. "SELECT * FROM Table", new MyRowFormater);
|
||||
///
|
||||
/// or it can be supplied to the statement as in the following example:
|
||||
///
|
||||
/// MyRowFormatter rf
|
||||
/// session << "SELECT * FROM Table", format(rf);
|
||||
///
|
||||
/// If no formatter is externally supplied to the statement, the SimpleRowFormatter is used.
|
||||
/// Statement always has the ownership of the row formatter and shares
|
||||
/// it with rows through RecordSet.
|
||||
///
|
||||
{
|
||||
public:
|
||||
typedef std::vector<std::string> NameVec;
|
||||
typedef SharedPtr<std::vector<std::string> > NameVecPtr;
|
||||
typedef std::vector<DynamicAny> ValueVec;
|
||||
|
||||
static const int DEFAULT_COLUMN_WIDTH = 16;
|
||||
|
||||
RowFormatter(std::streamsize width);
|
||||
/// Creates the RowFormatter and sets the column width to specified value.
|
||||
|
||||
RowFormatter(const std::string& prefix = "", const std::string& postfix = "");
|
||||
/// Creates the RowFormatter and sets the prefix and postfix to specified values.
|
||||
|
||||
virtual ~RowFormatter();
|
||||
/// Destroys the RowFormatter.
|
||||
|
||||
virtual std::string& formatNames(const NameVecPtr pNames, std::string& formattedNames) const = 0;
|
||||
/// Formats the row field names.
|
||||
|
||||
virtual std::string& formatValues(const ValueVec& vals, std::string& formattedValues) const = 0;
|
||||
/// Formats the row values.
|
||||
|
||||
const std::string& prefix() const;
|
||||
/// Returns prefix string;
|
||||
|
||||
virtual std::string& formatNames(const NameVecPtr pNames, std::string& formattedNames) const;
|
||||
/// Formats the row field names.
|
||||
|
||||
virtual std::string& formatValues(const ValueVec& vals, std::string& formattedValues) const;
|
||||
/// Formats the row values.
|
||||
|
||||
const std::string& postfix() const;
|
||||
/// Returns postfix string;
|
||||
|
||||
void setWidth(std::streamsize width);
|
||||
/// Sets the column width.
|
||||
|
||||
std::streamsize getWidth() const;
|
||||
/// Returns the column width.
|
||||
|
||||
protected:
|
||||
void setPrefix(const std::string& prefix);
|
||||
void setPostfix(const std::string& postfix);
|
||||
|
||||
private:
|
||||
std::streamsize _width;
|
||||
std::string _prefix;
|
||||
std::string _postfix;
|
||||
};
|
||||
@@ -106,17 +109,6 @@ private:
|
||||
/// inlines
|
||||
///
|
||||
|
||||
inline void RowFormatter::setWidth(std::streamsize width)
|
||||
{
|
||||
_width = width;
|
||||
}
|
||||
|
||||
|
||||
inline std::streamsize RowFormatter::getWidth() const
|
||||
{
|
||||
return _width;
|
||||
}
|
||||
|
||||
|
||||
inline void RowFormatter::setPrefix(const std::string& prefix)
|
||||
{
|
||||
@@ -142,6 +134,18 @@ inline const std::string& RowFormatter::postfix() const
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
inline T* format(const T& formatter)
|
||||
/// Utility function used to pass formatter to the statement.
|
||||
/// Statement takes the ownership of the formatter.
|
||||
{
|
||||
return new T(formatter);
|
||||
}
|
||||
|
||||
|
||||
typedef SharedPtr<RowFormatter> RowFormatterPtr;
|
||||
|
||||
|
||||
} } // namespace Poco::Data
|
||||
|
||||
|
||||
|
242
Data/include/Poco/Data/SQLChannel.h
Normal file
242
Data/include/Poco/Data/SQLChannel.h
Normal file
@@ -0,0 +1,242 @@
|
||||
//
|
||||
// SQLChannel.h
|
||||
//
|
||||
// $Id: //poco/Main/Data/include/Poco/Data/SQLChannel.h#4 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: Logging
|
||||
// Module: SQLChannel
|
||||
//
|
||||
// Definition of the SQLChannel class.
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#ifndef Data_SQLChannel_INCLUDED
|
||||
#define Data_SQLChannel_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Data/Data.h"
|
||||
#include "Poco/Data/Connector.h"
|
||||
#include "Poco/Data/Session.h"
|
||||
#include "Poco/Data/Statement.h"
|
||||
#include "Poco/Data/ArchiveStrategy.h"
|
||||
#include "Poco/Channel.h"
|
||||
#include "Poco/Message.h"
|
||||
#include "Poco/AutoPtr.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/DynamicAny.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
|
||||
|
||||
class Data_API SQLChannel: public Poco::Channel
|
||||
/// This Channel implements logging to a SQL database.
|
||||
/// The channel is dependent on the schema. The DDL for
|
||||
/// table creation (subject to target DDL dialect dependent
|
||||
/// modifications) is:
|
||||
///
|
||||
/// "CREATE TABLE T_POCO_LOG (Source VARCHAR,
|
||||
/// Name VARCHAR,
|
||||
/// ProcessId INTEGER,
|
||||
/// Thread VARCHAR,
|
||||
/// ThreadId INTEGER,
|
||||
/// Priority INTEGER,
|
||||
/// Text VARCHAR,
|
||||
/// DateTime DATE)"
|
||||
///
|
||||
/// The table name is configurable through "table" property.
|
||||
/// Other than DateTime filed name used for optiona time-based archiving purposes, currently the
|
||||
/// field names are not mandated. However, it is recomended to use names as specified above.
|
||||
///
|
||||
/// To provide as non-intrusive operation as possbile, the log entries are cached and
|
||||
/// inserted into the target database asynchronously by default . The blocking, however, will occur
|
||||
/// before the next entry insertion with default timeout of 1 second. The default settings can be
|
||||
/// overriden (see async, timeout and throw properties for details).
|
||||
/// If throw property is false, insertion timeouts are ignored, otherwise a TimeoutException is thrown.
|
||||
/// To force insertion of every entry, set timeout to 0. This setting, however, introduces
|
||||
/// a risk of long blocking periods in case of remote server communication delays.
|
||||
{
|
||||
public:
|
||||
typedef Statement::ResultType ResultType;
|
||||
|
||||
SQLChannel();
|
||||
/// Creates SQLChannel.
|
||||
|
||||
SQLChannel(const std::string& connector,
|
||||
const std::string& connect,
|
||||
const std::string& name = "-");
|
||||
/// Creates a SQLChannel with the given connector, connect string, timeout, table and name.
|
||||
/// The connector must be already registered.
|
||||
|
||||
void open();
|
||||
/// Opens the SQLChannel.
|
||||
|
||||
void close();
|
||||
/// Closes the SQLChannel.
|
||||
|
||||
void log(const Message& msg);
|
||||
/// Sends the message's text to the syslog service.
|
||||
|
||||
void setProperty(const std::string& name, const std::string& value);
|
||||
/// Sets the property with the given value.
|
||||
///
|
||||
/// The following properties are supported:
|
||||
/// * name: The name used to identify the source of log messages.
|
||||
/// Defaults to "-".
|
||||
///
|
||||
/// * target: The target data storage type ("SQLite", "ODBC", ...).
|
||||
///
|
||||
/// * connector: The target data storage connector name.
|
||||
///
|
||||
/// * connect: The target data storage connection string.
|
||||
///
|
||||
/// * table: Destination log table name. Defaults to "T_POCO_LOG".
|
||||
/// Table must exist in the target database.
|
||||
///
|
||||
/// * keep: Max row age for the log table. To disable archiving,
|
||||
/// set this property to empty string or "forever".
|
||||
///
|
||||
/// * archive: Archive table name. Defaults to "T_POCO_LOG_ARCHIVE".
|
||||
/// Table must exist in the target database. To disable archiving,
|
||||
/// set this property to empty string.
|
||||
///
|
||||
/// * async: Indicates asynchronous execution. When excuting asynchronously,
|
||||
/// messages are sent to the target using asyncronous execution.
|
||||
/// However, prior to the next message being processed and sent to
|
||||
/// the target, the previous operation must have been either completed
|
||||
/// or timed out (see timeout and throw properties for details on
|
||||
/// how abnormal conditos are handled).
|
||||
///
|
||||
/// * timeout: Timeout (ms) to wait for previous log operation completion.
|
||||
/// Values "0" and "" mean no timeout. Only valid when logging
|
||||
/// is asynchronous, otherwise ignored.
|
||||
///
|
||||
/// * throw: Boolean value indicating whether to throw in case of timeout.
|
||||
/// Setting this property to false may result in log entries being lost.
|
||||
/// True values are (case insensitive) "true", "t", "yes", "y".
|
||||
/// Anything else yields false.
|
||||
|
||||
std::string getProperty(const std::string& name) const;
|
||||
/// Returns the value of the property with the given name.
|
||||
|
||||
ResultType wait();
|
||||
/// Waits for the completion of the previous operation and returns
|
||||
/// the result. If chanel is in synchronous mode, returns 0 immediately.
|
||||
|
||||
static void registerChannel();
|
||||
/// Registers the channel with the global LoggingFactory.
|
||||
|
||||
static const std::string PROP_CONNECT;
|
||||
static const std::string PROP_CONNECTOR;
|
||||
static const std::string PROP_NAME;
|
||||
static const std::string PROP_TABLE;
|
||||
static const std::string PROP_ARCHIVE_TABLE;
|
||||
static const std::string PROP_MAX_AGE;
|
||||
static const std::string PROP_ASYNC;
|
||||
static const std::string PROP_TIMEOUT;
|
||||
static const std::string PROP_THROW;
|
||||
|
||||
protected:
|
||||
~SQLChannel();
|
||||
|
||||
private:
|
||||
typedef Poco::SharedPtr<Session> SessionPtr;
|
||||
typedef Poco::SharedPtr<Statement> StatementPtr;
|
||||
typedef Poco::Message::Priority Priority;
|
||||
typedef Poco::SharedPtr<ArchiveStrategy> StrategyPtr;
|
||||
|
||||
void initLogStatement();
|
||||
/// Initiallizes the log statement.
|
||||
|
||||
void initArchiveStatements();
|
||||
/// Initiallizes the archive statement.
|
||||
|
||||
void logAsync(const Message& msg);
|
||||
/// Waits for previous operation completion and
|
||||
/// calls logSync(). If the previous operation times out,
|
||||
/// and _throw is true, TimeoutException is thrown, oterwise
|
||||
/// the timeout is ignored and log entry is lost.
|
||||
|
||||
void logSync(const Message& msg);
|
||||
/// Inserts the message in the target database.
|
||||
|
||||
bool isTrue(const std::string& value) const;
|
||||
/// Returns true is value is "true", "t", "yes" or "y".
|
||||
/// Case insensitive.
|
||||
|
||||
std::string _connector;
|
||||
std::string _connect;
|
||||
SessionPtr _pSession;
|
||||
StatementPtr _pLogStatement;
|
||||
std::string _name;
|
||||
std::string _table;
|
||||
int _timeout;
|
||||
bool _throw;
|
||||
bool _async;
|
||||
|
||||
// members for log entry cache (needed for async mode)
|
||||
std::string _source;
|
||||
long _pid;
|
||||
std::string _thread;
|
||||
long _tid;
|
||||
int _priority;
|
||||
std::string _text;
|
||||
DateTime _dateTime;
|
||||
|
||||
StrategyPtr _pArchiveStrategy;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
|
||||
inline SQLChannel::ResultType SQLChannel::wait()
|
||||
{
|
||||
if (_async && _pLogStatement)
|
||||
return _pLogStatement->wait(_timeout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
inline bool SQLChannel::isTrue(const std::string& value) const
|
||||
{
|
||||
return ((0 == icompare(value, "true")) ||
|
||||
(0 == icompare(value, "t")) ||
|
||||
(0 == icompare(value, "yes")) ||
|
||||
(0 == icompare(value, "y")));
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Data
|
||||
|
||||
|
||||
#endif // Data_SQLChannel_INCLUDED
|
@@ -143,9 +143,10 @@ class Data_API Session
|
||||
/// ses << "INSERT INTO Person (LastName, Age) VALUES(:ln, :age)", use(nameVec), use(ageVec);
|
||||
///
|
||||
/// The size of all use parameters MUST be the same, otherwise an exception is thrown. Furthermore,
|
||||
/// the amount of use clauses must match the number of wildcards in the query (to be more precisely:
|
||||
/// each binding has a numberOfColumnsHandled() value which is per default 1. The sum of all these values must match the wildcard count in the query.
|
||||
/// But this is only important if you have written your own TypeHandler specializations).
|
||||
/// the amount of use clauses must match the number of wildcards in the query (to be more precise:
|
||||
/// each binding has a numberOfColumnsHandled() value which defaults to 1. The sum of all these values
|
||||
/// must match the wildcard count in the query.
|
||||
/// However, this is only important if you have written your own TypeHandler specializations.
|
||||
/// If you plan to map complex object types to tables see the TypeHandler documentation.
|
||||
/// For now, we simply assume we have written one TypeHandler for Person objects. Instead of having n different vectors,
|
||||
/// we have one collection:
|
||||
@@ -159,6 +160,17 @@ class Data_API Session
|
||||
///
|
||||
/// std::vector<Person> people;
|
||||
/// ses << "SELECT * FROM PERSON", into(people);
|
||||
///
|
||||
/// Mixing constants or variables with manipulators is allowed provided there are corresponding placeholders for the constants provided in
|
||||
/// the SQL string, such as in following example:
|
||||
///
|
||||
/// std::vector<Person> people;
|
||||
/// ses << "SELECT * FROM %s", into(people), "PERSON";
|
||||
///
|
||||
/// Formatting only kicks in if there are values to be injected into the SQL string, otherwise it is skipped.
|
||||
/// If the formatting will occur and the percent sign is part of the query itself, it can be passed to the query by entering it twice (%%).
|
||||
/// However, if no formatting is used, one percent sign is sufficient as the string will be passed unaltered.
|
||||
/// For complete list of supported data types with their respective specifications, see the documentation for format in Foundation.
|
||||
{
|
||||
public:
|
||||
Session(Poco::AutoPtr<SessionImpl> ptrImpl);
|
||||
@@ -172,7 +184,7 @@ public:
|
||||
/// Creates a session by copying another one.
|
||||
|
||||
Session& operator = (const Session&);
|
||||
/// Assignement operator.
|
||||
/// Assignment operator.
|
||||
|
||||
~Session();
|
||||
/// Destroys the Session.
|
||||
|
@@ -74,8 +74,8 @@ public:
|
||||
static SessionFactory& instance();
|
||||
/// returns the static instance of the singleton.
|
||||
|
||||
void add(const std::string& key, Connector* pIn);
|
||||
/// Registers a Connector under the given key at the factory. If a registration for that
|
||||
void add(Connector* pIn);
|
||||
/// Registers a Connector under its key at the factory. If a registration for that
|
||||
/// key is already active, the first registration will be kept, only its reference count will be increased.
|
||||
/// Always takes ownership of parameter pIn.
|
||||
|
||||
|
125
Data/include/Poco/Data/SimpleRowFormatter.h
Normal file
125
Data/include/Poco/Data/SimpleRowFormatter.h
Normal file
@@ -0,0 +1,125 @@
|
||||
//
|
||||
// RowFormatter.h
|
||||
//
|
||||
// $Id: //poco/Main/Data/include/Poco/Data/SimpleRowFormatter.h#1 $
|
||||
//
|
||||
// Library: Data
|
||||
// Package: DataCore
|
||||
// Module: SimpleRowFormatter
|
||||
//
|
||||
// Definition of the RowFormatter class.
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#ifndef Data_SimpleRowFormatter_INCLUDED
|
||||
#define Data_SimpleRowFormatter_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Data/Data.h"
|
||||
#include "Poco/Data/RowFormatter.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
|
||||
|
||||
class Data_API SimpleRowFormatter: public RowFormatter
|
||||
/// A simple row formatting class.
|
||||
{
|
||||
public:
|
||||
//typedef RowFormatter::NameVec NameVec;
|
||||
//typedef RowFormatter::NameVecPtr NameVecPtr;
|
||||
//typedef RowFormatter::ValueVec ValueVec;
|
||||
|
||||
static const int DEFAULT_COLUMN_WIDTH = 16;
|
||||
|
||||
SimpleRowFormatter(std::streamsize columnWidth = DEFAULT_COLUMN_WIDTH);
|
||||
/// Creates the SimpleRowFormatter and sets the column width to specified value.
|
||||
|
||||
SimpleRowFormatter(const SimpleRowFormatter& other);
|
||||
/// Creates the copy of the supplied SimpleRowFormatter.
|
||||
|
||||
SimpleRowFormatter& operator = (const SimpleRowFormatter& row);
|
||||
/// Assignment operator.
|
||||
|
||||
~SimpleRowFormatter();
|
||||
/// Destroys the SimpleRowFormatter.
|
||||
|
||||
void swap(SimpleRowFormatter& other);
|
||||
/// Swaps the row formatter with another one.
|
||||
|
||||
std::string& formatNames(const NameVecPtr pNames, std::string& formattedNames) const;
|
||||
/// Formats the row field names.
|
||||
|
||||
std::string& formatValues(const ValueVec& vals, std::string& formattedValues) const;
|
||||
/// Formats the row values.
|
||||
|
||||
void setColumnWidth(std::streamsize width);
|
||||
/// Sets the column width.
|
||||
|
||||
std::streamsize getColumnWidth() const;
|
||||
/// Returns the column width.
|
||||
|
||||
private:
|
||||
std::streamsize _colWidth;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// inlines
|
||||
///
|
||||
|
||||
|
||||
inline void SimpleRowFormatter::setColumnWidth(std::streamsize columnWidth)
|
||||
{
|
||||
_colWidth = columnWidth;
|
||||
}
|
||||
|
||||
|
||||
inline std::streamsize SimpleRowFormatter::getColumnWidth() const
|
||||
{
|
||||
return _colWidth;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Data
|
||||
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<>
|
||||
inline void swap<Poco::Data::SimpleRowFormatter>(Poco::Data::SimpleRowFormatter& s1,
|
||||
Poco::Data::SimpleRowFormatter& s2)
|
||||
/// Full template specalization of std:::swap for SimpleRowFormatter
|
||||
{
|
||||
s1.swap(s2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // Data_SimpleRowFormatter_INCLUDED
|
@@ -44,10 +44,13 @@
|
||||
#include "Poco/Data/StatementImpl.h"
|
||||
#include "Poco/Data/Range.h"
|
||||
#include "Poco/Data/Bulk.h"
|
||||
#include "Poco/Data/Row.h"
|
||||
#include "Poco/Data/SimpleRowFormatter.h"
|
||||
#include "Poco/SharedPtr.h"
|
||||
#include "Poco/Mutex.h"
|
||||
#include "Poco/ActiveMethod.h"
|
||||
#include "Poco/ActiveResult.h"
|
||||
#include "Poco/Format.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -68,35 +71,6 @@ class Data_API Statement
|
||||
/// Synchronous ececution is achieved through execute() call, while asynchronous is
|
||||
/// achieved through executeAsync() method call.
|
||||
/// An asynchronously executing statement should not be copied during the execution.
|
||||
/// Copying is not prohibited, however the benefits of the asynchronous call shall
|
||||
/// be lost for that particular call since the synchronizing call shall internally be
|
||||
/// called in the copy constructor.
|
||||
///
|
||||
/// For example, in the following case, although the execution is asyncronous, the
|
||||
/// synchronization part happens in the copy constructor, so the asynchronous nature
|
||||
/// of the statement is lost for the end user:
|
||||
///
|
||||
/// Statement stmt = (session << "SELECT * FROM Table", async, now);
|
||||
///
|
||||
/// while in this case it is preserved:
|
||||
///
|
||||
/// Statement stmt = session << "SELECT * FROM Table", async, now;
|
||||
///
|
||||
/// There are two ways to preserve the asynchronous nature of a statement:
|
||||
///
|
||||
/// 1) Call executeAsync() method directly:
|
||||
///
|
||||
/// Statement stmt = session << "SELECT * FROM Table"; // no execution yet
|
||||
/// stmt.executeAsync(); // asynchronous execution
|
||||
/// // do something else ...
|
||||
/// stmt.wait(); // synchronize
|
||||
///
|
||||
/// 2) Ensure asynchronous execution through careful syntax constructs:
|
||||
///
|
||||
/// Statement stmt(session);
|
||||
/// stmt = session << "SELECT * FROM Table", async, now;
|
||||
/// // do something else ...
|
||||
/// stmt.wait(); // synchronize
|
||||
///
|
||||
/// Note:
|
||||
///
|
||||
@@ -112,6 +86,10 @@ class Data_API Statement
|
||||
///
|
||||
/// See individual functions documentation for more details.
|
||||
///
|
||||
/// Statement owns the RowFormatter, which can be provided externaly through setFormatter()
|
||||
/// member function.
|
||||
/// If no formatter is externally supplied to the statement, the SimpleRowFormatter is lazy
|
||||
/// created and used.
|
||||
{
|
||||
public:
|
||||
typedef void (*Manipulator)(Statement&);
|
||||
@@ -122,6 +100,8 @@ public:
|
||||
typedef ActiveMethod<ResultType, void, StatementImpl> AsyncExecMethod;
|
||||
typedef SharedPtr<AsyncExecMethod> AsyncExecMethodPtr;
|
||||
|
||||
static const int WAIT_FOREVER = -1;
|
||||
|
||||
enum Storage
|
||||
{
|
||||
STORAGE_DEQUE = StatementImpl::STORAGE_DEQUE_IMPL,
|
||||
@@ -200,28 +180,83 @@ public:
|
||||
///
|
||||
/// Set per default to zero to Limit::LIMIT_UNLIMITED, which disables the limit.
|
||||
|
||||
Statement& operator , (RowFormatter* pRowFformatter);
|
||||
/// Sets the row formatter for the statement.
|
||||
|
||||
Statement& operator , (const Range& extrRange);
|
||||
/// Sets a an extraction range for the maximum number of rows a select is allowed to return.
|
||||
///
|
||||
/// Set per default to Limit::LIMIT_UNLIMITED which disables the range.
|
||||
|
||||
std::string toString() const;
|
||||
Statement& operator , (char value);
|
||||
/// Adds the value to the list of values to be supplied to the SQL string formatting function.
|
||||
|
||||
Statement& operator , (Poco::UInt8 value);
|
||||
/// Adds the value to the list of values to be supplied to the SQL string formatting function.
|
||||
|
||||
Statement& operator , (Poco::Int8 value);
|
||||
/// Adds the value to the list of values to be supplied to the SQL string formatting function.
|
||||
|
||||
Statement& operator , (Poco::UInt16 value);
|
||||
/// Adds the value to the list of values to be supplied to the SQL string formatting function.
|
||||
|
||||
Statement& operator , (Poco::Int16 value);
|
||||
/// Adds the value to the list of values to be supplied to the SQL string formatting function.
|
||||
|
||||
Statement& operator , (Poco::UInt32 value);
|
||||
/// Adds the value to the list of values to be supplied to the SQL string formatting function.
|
||||
|
||||
Statement& operator , (Poco::Int32 value);
|
||||
/// Adds the value to the list of values to be supplied to the SQL string formatting function.
|
||||
|
||||
#ifndef POCO_LONG_IS_64_BIT
|
||||
Statement& operator , (long value);
|
||||
/// Adds the value to the list of values to be supplied to the SQL string formatting function.
|
||||
|
||||
Statement& operator , (unsigned long value);
|
||||
/// Adds the value to the list of values to be supplied to the SQL string formatting function.
|
||||
|
||||
#endif
|
||||
Statement& operator , (Poco::UInt64 value);
|
||||
/// Adds the value to the list of values to be supplied to the SQL string formatting function.
|
||||
|
||||
Statement& operator , (Poco::Int64 value);
|
||||
/// Adds the value to the list of values to be supplied to the SQL string formatting function.
|
||||
|
||||
Statement& operator , (double value);
|
||||
/// Adds the value to the list of values to be supplied to the SQL string formatting function.
|
||||
|
||||
Statement& operator , (float value);
|
||||
/// Adds the value to the list of values to be supplied to the SQL string formatting function.
|
||||
|
||||
Statement& operator , (bool value);
|
||||
/// Adds the value to the list of values to be supplied to the SQL string formatting function.
|
||||
|
||||
Statement& operator , (const std::string& value);
|
||||
/// Adds the value to the list of values to be supplied to the SQL string formatting function.
|
||||
|
||||
Statement& operator , (const char* value);
|
||||
/// Adds the value to the list of values to be supplied to the SQL string formatting function.
|
||||
|
||||
const std::string& toString() const;
|
||||
/// Creates a string from the accumulated SQL statement.
|
||||
|
||||
ResultType execute();
|
||||
/// Executes the statement synchronously or asynchronously.
|
||||
/// Stops when either a limit is hit or the whole statement was executed.
|
||||
/// Returns the number of rows extracted from the database.
|
||||
/// Returns the number of rows extracted from the database (for statements
|
||||
/// returning data) or number of rows affected (for all other statements).
|
||||
/// If isAsync() returns true, the statement is executed asynchronously
|
||||
/// and the return value from this function is zero.
|
||||
/// The number of extracted rows from the query can be obtained by calling
|
||||
/// wait().
|
||||
/// The result of execution (i.e. number of returned or affected rows) can be
|
||||
/// obtained by calling wait() on the statement at a later point in time.
|
||||
|
||||
const Result& executeAsync();
|
||||
/// Executes the statement asynchronously.
|
||||
/// Stops when either a limit is hit or the whole statement was executed.
|
||||
/// Returns immediately. For statements returning data, the number of rows extracted is
|
||||
/// available by calling wait() method on either the returned value or the statement itself.
|
||||
/// Returns immediately. Calling wait() (on either the result returned from this
|
||||
/// call or the statement itself) returns the number of rows extracted or number
|
||||
/// of rows affected by the statement execution.
|
||||
/// When executed on a synchronous statement, this method does not alter the
|
||||
/// statement's synchronous nature.
|
||||
|
||||
@@ -269,6 +304,10 @@ public:
|
||||
/// Returns the number of extraction storage buffers associated
|
||||
/// with the statement.
|
||||
|
||||
void setRowFormatter(RowFormatter* pRowFormatter);
|
||||
/// Sets the row formatter for this statement.
|
||||
/// Statement takes the ownership of the formatter.
|
||||
|
||||
protected:
|
||||
typedef Poco::AutoPtr<StatementImpl> StatementImplPtr;
|
||||
|
||||
@@ -290,12 +329,20 @@ protected:
|
||||
StatementImplPtr impl() const;
|
||||
/// Returns pointer to statement implementation.
|
||||
|
||||
private:
|
||||
static const int WAIT_FOREVER = -1;
|
||||
const RowFormatterPtr& getRowFormatter();
|
||||
/// Returns the row formatter for this statement.
|
||||
|
||||
private:
|
||||
const Result& doAsyncExec();
|
||||
/// Asynchronously executes the statement.
|
||||
|
||||
template <typename T>
|
||||
Statement& commaImpl (const T& val)
|
||||
{
|
||||
_arguments.push_back(val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
StatementImplPtr _pImpl;
|
||||
|
||||
// asynchronous execution related members
|
||||
@@ -303,6 +350,9 @@ private:
|
||||
mutable ResultPtr _pResult;
|
||||
Mutex _mutex;
|
||||
AsyncExecMethodPtr _pAsyncExec;
|
||||
std::vector<Any> _arguments;
|
||||
RowFormatterPtr _pRowFormatter;
|
||||
mutable std::string _stmtString;
|
||||
};
|
||||
|
||||
|
||||
@@ -381,6 +431,110 @@ inline void Data_API reset(Statement& statement)
|
||||
// inlines
|
||||
//
|
||||
|
||||
inline Statement& Statement::operator , (RowFormatter* pRowFformatter)
|
||||
{
|
||||
_pRowFormatter = pRowFformatter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
inline Statement& Statement::operator , (char value)
|
||||
{
|
||||
return commaImpl(value);
|
||||
}
|
||||
|
||||
|
||||
inline Statement& Statement::operator , (Poco::UInt8 value)
|
||||
{
|
||||
return commaImpl(value);
|
||||
}
|
||||
|
||||
|
||||
inline Statement& Statement::operator , (Poco::Int8 value)
|
||||
{
|
||||
return commaImpl(value);
|
||||
}
|
||||
|
||||
|
||||
inline Statement& Statement::operator , (Poco::UInt16 value)
|
||||
{
|
||||
return commaImpl(value);
|
||||
}
|
||||
|
||||
|
||||
inline Statement& Statement::operator , (Poco::Int16 value)
|
||||
{
|
||||
return commaImpl(value);
|
||||
}
|
||||
|
||||
|
||||
inline Statement& Statement::operator , (Poco::UInt32 value)
|
||||
{
|
||||
return commaImpl(value);
|
||||
}
|
||||
|
||||
|
||||
inline Statement& Statement::operator , (Poco::Int32 value)
|
||||
{
|
||||
return commaImpl(value);
|
||||
}
|
||||
|
||||
|
||||
#ifndef POCO_LONG_IS_64_BIT
|
||||
inline Statement& Statement::operator , (long value)
|
||||
{
|
||||
return commaImpl(value);
|
||||
}
|
||||
|
||||
|
||||
inline Statement& Statement::operator , (unsigned long value)
|
||||
{
|
||||
return commaImpl(value);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
inline Statement& Statement::operator , (Poco::UInt64 value)
|
||||
{
|
||||
return commaImpl(value);
|
||||
}
|
||||
|
||||
|
||||
inline Statement& Statement::operator , (Poco::Int64 value)
|
||||
{
|
||||
return commaImpl(value);
|
||||
}
|
||||
|
||||
|
||||
inline Statement& Statement::operator , (double value)
|
||||
{
|
||||
return commaImpl(value);
|
||||
}
|
||||
|
||||
|
||||
inline Statement& Statement::operator , (float value)
|
||||
{
|
||||
return commaImpl(value);
|
||||
}
|
||||
|
||||
|
||||
inline Statement& Statement::operator , (bool value)
|
||||
{
|
||||
return commaImpl(value);
|
||||
}
|
||||
|
||||
|
||||
inline Statement& Statement::operator , (const std::string& value)
|
||||
{
|
||||
return commaImpl(value);
|
||||
}
|
||||
|
||||
|
||||
inline Statement& Statement::operator , (const char* value)
|
||||
{
|
||||
return commaImpl(std::string(value));
|
||||
}
|
||||
|
||||
|
||||
inline Statement::StatementImplPtr Statement::impl() const
|
||||
{
|
||||
@@ -388,12 +542,11 @@ inline Statement::StatementImplPtr Statement::impl() const
|
||||
}
|
||||
|
||||
|
||||
inline std::string Statement::toString() const
|
||||
inline const std::string& Statement::toString() const
|
||||
{
|
||||
return _pImpl->toString();
|
||||
return _stmtString = _pImpl->toString();
|
||||
}
|
||||
|
||||
|
||||
inline const AbstractExtractionVec& Statement::extractions() const
|
||||
{
|
||||
return _pImpl->extractions();
|
||||
@@ -472,6 +625,19 @@ inline bool Statement::isAsync() const
|
||||
}
|
||||
|
||||
|
||||
inline void Statement::setRowFormatter(RowFormatter* pRowFormatter)
|
||||
{
|
||||
_pRowFormatter = pRowFormatter;
|
||||
}
|
||||
|
||||
|
||||
inline const RowFormatterPtr& Statement::getRowFormatter()
|
||||
{
|
||||
if (!_pRowFormatter) _pRowFormatter = new SimpleRowFormatter;
|
||||
return _pRowFormatter;
|
||||
}
|
||||
|
||||
|
||||
inline void swap(Statement& s1, Statement& s2)
|
||||
{
|
||||
s1.swap(s2);
|
||||
|
@@ -138,7 +138,8 @@ public:
|
||||
/// Create a string version of the SQL statement.
|
||||
|
||||
Poco::UInt32 execute();
|
||||
/// Executes a statement. Returns the number of rows extracted.
|
||||
/// Executes a statement. Returns the number of rows extracted for statements
|
||||
/// returning data or number of rows affected for all other statements (insert, update, delete).
|
||||
|
||||
void reset();
|
||||
/// Resets the statement, so that we can reuse all bindings and re-execute again.
|
||||
@@ -166,6 +167,10 @@ protected:
|
||||
virtual Poco::UInt32 columnsReturned() const = 0;
|
||||
/// Returns number of columns returned by query.
|
||||
|
||||
virtual Poco::UInt32 affectedRowCount() const = 0;
|
||||
/// Returns the number of affected rows.
|
||||
/// Used to find out the number of rows affected by insert, delete or update.
|
||||
|
||||
virtual const MetaColumn& metaColumn(Poco::UInt32 pos) const = 0;
|
||||
/// Returns column meta data.
|
||||
|
||||
@@ -395,6 +400,9 @@ private:
|
||||
bool isBulkSupported() const;
|
||||
/// Returns true if connector and session support bulk operation.
|
||||
|
||||
void formatSQL(std::vector<Any>& arguments);
|
||||
/// Formats the SQL string by filling in placeholders with values from supplied vector.
|
||||
|
||||
StatementImpl(const StatementImpl& stmt);
|
||||
StatementImpl& operator = (const StatementImpl& stmt);
|
||||
|
||||
@@ -421,7 +429,6 @@ private:
|
||||
inline void StatementImpl::addBinding(AbstractBinding* pBinding)
|
||||
{
|
||||
poco_check_ptr (pBinding);
|
||||
|
||||
_bindings.push_back(pBinding);
|
||||
}
|
||||
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include "Poco/SharedPtr.h"
|
||||
#include "Poco/Data/SessionFactory.h"
|
||||
#include "Poco/Data/Session.h"
|
||||
#include "Poco/Data/Statement.h"
|
||||
#include "Poco/Data/RecordSet.h"
|
||||
#include "Poco/Data/RowFormatter.h"
|
||||
#include "Poco/Data/SQLite/Connector.h"
|
||||
@@ -88,19 +89,30 @@ int main(int argc, char** argv)
|
||||
Session session("SQLite", "sample.db");
|
||||
|
||||
// drop sample table, if it exists
|
||||
session << "DROP TABLE IF EXISTS Person", now;
|
||||
session << "DROP TABLE IF EXISTS Simpsons", now;
|
||||
|
||||
// (re)create table
|
||||
session << "CREATE TABLE Person (Name VARCHAR(30), Address VARCHAR, Age INTEGER(3))", now;
|
||||
session << "CREATE TABLE Simpsons (Name VARCHAR(30), Address VARCHAR, Age INTEGER(3))", now;
|
||||
|
||||
// insert some rows
|
||||
session << "INSERT INTO Person VALUES('Homer Simpson', 'Springfield', 42)", now;
|
||||
session << "INSERT INTO Person VALUES('Marge Simpson', 'Springfield', 38)", now;
|
||||
session << "INSERT INTO Person VALUES('Bart Simpson', 'Springfield', 12)", now;
|
||||
session << "INSERT INTO Person VALUES('Lisa Simpson', 'Springfield', 10)", now;
|
||||
session << "INSERT INTO Simpsons VALUES('Homer Simpson', 'Springfield', 42)", now;
|
||||
session << "INSERT INTO Simpsons VALUES('Marge Simpson', 'Springfield', 38)", now;
|
||||
session << "INSERT INTO Simpsons VALUES('Bart Simpson', 'Springfield', 12)", now;
|
||||
session << "INSERT INTO Simpsons VALUES('Lisa Simpson', 'Springfield', 10)", now;
|
||||
|
||||
// create a recordset and print the column names and data as HTML table
|
||||
std::cout << RecordSet(session, "SELECT * FROM Person", new HTMLTableFormatter);
|
||||
// create a statement and print the column names and data as HTML table
|
||||
HTMLTableFormatter tf;
|
||||
Statement stmt = (session << "SELECT * FROM Simpsons", format(tf), now);
|
||||
RecordSet rs(stmt);
|
||||
std::cout << rs << std::endl;
|
||||
|
||||
// Note: The code above is divided into individual steps for clarity purpose.
|
||||
// The four lines can be reduced to the following single line of code:
|
||||
std::cout << RecordSet(session, "SELECT * FROM Simpsons", new HTMLTableFormatter);
|
||||
|
||||
// simple formatting example (uses the default SimpleRowFormatter provided by framework)
|
||||
std::cout << std::endl << "Simple formatting:" << std::endl << std::endl;
|
||||
std::cout << RecordSet(session, "SELECT * FROM Simpsons");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
166
Data/src/ArchiveStrategy.cpp
Normal file
166
Data/src/ArchiveStrategy.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
//
|
||||
// ArchiveStrategy.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Data/src/ArchiveStrategy.cpp#8 $
|
||||
//
|
||||
// Library: Data
|
||||
// Package: Logging
|
||||
// Module: ArchiveStrategy
|
||||
//
|
||||
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Data/ArchiveStrategy.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
|
||||
|
||||
//
|
||||
// ArchiveStrategy
|
||||
//
|
||||
|
||||
|
||||
const std::string ArchiveStrategy::DEFAULT_ARCHIVE_DESTINATION = "T_POCO_LOG_ARCHIVE";
|
||||
|
||||
|
||||
ArchiveStrategy::ArchiveStrategy(const std::string& connector,
|
||||
const std::string& connect,
|
||||
const std::string& source,
|
||||
const std::string& destination):
|
||||
_connector(connector),
|
||||
_connect(connect),
|
||||
_source(source),
|
||||
_destination(destination)
|
||||
{
|
||||
open();
|
||||
}
|
||||
|
||||
|
||||
ArchiveStrategy::~ArchiveStrategy()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ArchiveStrategy::open()
|
||||
{
|
||||
if (_connector.empty() || _connect.empty())
|
||||
throw IllegalStateException("Connector and connect string must be non-empty.");
|
||||
|
||||
_pSession = new Session(_connector, _connect);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// ArchiveByAgeStrategy
|
||||
//
|
||||
|
||||
|
||||
ArchiveByAgeStrategy::ArchiveByAgeStrategy(const std::string& connector,
|
||||
const std::string& connect,
|
||||
const std::string& sourceTable,
|
||||
const std::string& destinationTable):
|
||||
ArchiveStrategy(connector, connect, sourceTable, destinationTable)
|
||||
{
|
||||
initStatements();
|
||||
}
|
||||
|
||||
|
||||
ArchiveByAgeStrategy::~ArchiveByAgeStrategy()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ArchiveByAgeStrategy::archive()
|
||||
{
|
||||
if (!session().isConnected()) open();
|
||||
|
||||
DateTime now;
|
||||
_archiveDateTime = now - _maxAge;
|
||||
getCountStatement().execute();
|
||||
if (_archiveCount > 0)
|
||||
{
|
||||
getCopyStatement().execute();
|
||||
getDeleteStatement().execute();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ArchiveByAgeStrategy::initStatements()
|
||||
{
|
||||
std::string src = getSource();
|
||||
std::string dest = getDestination();
|
||||
|
||||
setCountStatement();
|
||||
_archiveCount = 0;
|
||||
std::string sql;
|
||||
Poco::format(sql, "SELECT COUNT(*) FROM %s WHERE DateTime < ?", src);
|
||||
getCountStatement() << sql, into(_archiveCount), use(_archiveDateTime);
|
||||
|
||||
setCopyStatement();
|
||||
sql.clear();
|
||||
Poco::format(sql, "INSERT INTO %s SELECT * FROM %s WHERE DateTime < ?", dest, src);
|
||||
getCopyStatement() << sql, use(_archiveDateTime);
|
||||
|
||||
setDeleteStatement();
|
||||
sql.clear();
|
||||
Poco::format(sql, "DELETE FROM %s WHERE DateTime < ?", src);
|
||||
getDeleteStatement() << sql, use(_archiveDateTime);
|
||||
}
|
||||
|
||||
|
||||
void ArchiveByAgeStrategy::setThreshold(const std::string& age)
|
||||
{
|
||||
std::string::const_iterator it = age.begin();
|
||||
std::string::const_iterator end = age.end();
|
||||
int n = 0;
|
||||
while (it != end && std::isspace(*it)) ++it;
|
||||
while (it != end && std::isdigit(*it)) { n *= 10; n += *it++ - '0'; }
|
||||
while (it != end && std::isspace(*it)) ++it;
|
||||
std::string unit;
|
||||
while (it != end && std::isalpha(*it)) unit += *it++;
|
||||
|
||||
Timespan::TimeDiff factor = Timespan::SECONDS;
|
||||
if (unit == "minutes")
|
||||
factor = Timespan::MINUTES;
|
||||
else if (unit == "hours")
|
||||
factor = Timespan::HOURS;
|
||||
else if (unit == "days")
|
||||
factor = Timespan::DAYS;
|
||||
else if (unit == "weeks")
|
||||
factor = 7*Timespan::DAYS;
|
||||
else if (unit == "months")
|
||||
factor = 30*Timespan::DAYS;
|
||||
else if (unit != "seconds")
|
||||
throw InvalidArgumentException("setMaxAge", age);
|
||||
|
||||
_maxAge = factor * n;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Data
|
@@ -64,9 +64,9 @@ RecordSet::RecordSet(Session& rSession,
|
||||
Statement((rSession << query, now)),
|
||||
_currentRow(0),
|
||||
_pBegin(new RowIterator(this)),
|
||||
_pEnd(new RowIterator(this, true)),
|
||||
_pRowFormatter(pRowFormatter)
|
||||
_pEnd(new RowIterator(this, true))
|
||||
{
|
||||
if (pRowFormatter) setRowFormatter(pRowFormatter);
|
||||
}
|
||||
|
||||
|
||||
@@ -74,8 +74,7 @@ RecordSet::RecordSet(const RecordSet& other):
|
||||
Statement(other.impl().duplicate()),
|
||||
_currentRow(other._currentRow),
|
||||
_pBegin(new RowIterator(this)),
|
||||
_pEnd(new RowIterator(this, true)),
|
||||
_pRowFormatter(other._pRowFormatter)
|
||||
_pEnd(new RowIterator(this, true))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -155,14 +154,14 @@ Row& RecordSet::row(std::size_t pos)
|
||||
{
|
||||
if (_rowMap.size())//reuse first row column names to save some memory
|
||||
{
|
||||
pRow = new Row(_rowMap.begin()->second->names(), &_pRowFormatter);
|
||||
pRow = new Row(_rowMap.begin()->second->names(), getRowFormatter());
|
||||
for (std::size_t col = 0; col < columns; ++col)
|
||||
pRow->set(col, value(col, pos));
|
||||
}
|
||||
else
|
||||
{
|
||||
pRow = new Row;
|
||||
if (_pRowFormatter) pRow->setFormatter(&_pRowFormatter);
|
||||
pRow->setFormatter(getRowFormatter());
|
||||
for (std::size_t col = 0; col < columns; ++col)
|
||||
pRow->append(metaColumn(static_cast<UInt32>(col)).name(), value(col, pos));
|
||||
}
|
||||
|
@@ -35,7 +35,7 @@
|
||||
|
||||
|
||||
#include "Poco/Data/Row.h"
|
||||
#include "Poco/Data/RowFormatter.h"
|
||||
#include "Poco/Data/SimpleRowFormatter.h"
|
||||
#include "Poco/Exception.h"
|
||||
|
||||
|
||||
@@ -52,18 +52,17 @@ std::ostream& operator << (std::ostream &os, const Row& row)
|
||||
|
||||
Row::Row():
|
||||
_pNames(0),
|
||||
_pFormatter(new RowFormatter)
|
||||
_pFormatter(new SimpleRowFormatter)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Row::Row(NameVecPtr pNames, FormatterPtr* pFormatter):
|
||||
Row::Row(NameVecPtr pNames, const RowFormatterPtr& pFormatter):
|
||||
_pNames(pNames)
|
||||
{
|
||||
if (!_pNames) throw NullPointerException();
|
||||
|
||||
if (pFormatter && *pFormatter) _pFormatter = *pFormatter;
|
||||
else _pFormatter = new RowFormatter;
|
||||
setFormatter(pFormatter);
|
||||
|
||||
_values.resize(_pNames->size());
|
||||
addSortField(0);
|
||||
@@ -315,12 +314,12 @@ bool Row::operator < (const Row& other) const
|
||||
}
|
||||
|
||||
|
||||
void Row::setFormatter(FormatterPtr* pFormatter)
|
||||
void Row::setFormatter(const RowFormatterPtr& pFormatter)
|
||||
{
|
||||
if (pFormatter && *pFormatter)
|
||||
_pFormatter = *pFormatter;
|
||||
if (pFormatter)
|
||||
_pFormatter = pFormatter;
|
||||
else
|
||||
_pFormatter = new RowFormatter;
|
||||
_pFormatter = new SimpleRowFormatter;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -43,14 +43,7 @@ namespace Poco {
|
||||
namespace Data {
|
||||
|
||||
|
||||
RowFormatter::RowFormatter(std::streamsize width):
|
||||
_width(width)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
RowFormatter::RowFormatter(const std::string& prefix, const std::string& postfix):
|
||||
_width(DEFAULT_COLUMN_WIDTH),
|
||||
_prefix(prefix),
|
||||
_postfix(postfix)
|
||||
{
|
||||
@@ -62,44 +55,4 @@ RowFormatter::~RowFormatter()
|
||||
}
|
||||
|
||||
|
||||
std::string& RowFormatter::formatNames(const NameVecPtr pNames, std::string& formattedNames) const
|
||||
{
|
||||
std::ostringstream str;
|
||||
std::string line(_width * pNames->size(), '-');
|
||||
|
||||
NameVec::const_iterator it = pNames->begin();
|
||||
NameVec::const_iterator end = pNames->end();
|
||||
for (; it != end; ++it)
|
||||
{
|
||||
str << std::left << std::setw(_width) << *it;
|
||||
}
|
||||
str << std::endl << line << std::endl;
|
||||
|
||||
return formattedNames = str.str();
|
||||
}
|
||||
|
||||
|
||||
std::string& RowFormatter::formatValues(const ValueVec& vals, std::string& formattedValues) const
|
||||
{
|
||||
std::ostringstream str;
|
||||
|
||||
ValueVec::const_iterator it = vals.begin();
|
||||
ValueVec::const_iterator end = vals.end();
|
||||
for (; it != end; ++it)
|
||||
{
|
||||
if (it->isNumeric())
|
||||
{
|
||||
str << std::right
|
||||
<< std::fixed
|
||||
<< std::setprecision(2);
|
||||
}
|
||||
else str << std::left;
|
||||
|
||||
str << std::setw(_width) << it->convert<std::string>();
|
||||
}
|
||||
str << std::endl;
|
||||
|
||||
return formattedValues = str.str();
|
||||
}
|
||||
|
||||
} } // namespace Poco::Data
|
||||
|
296
Data/src/SQLChannel.cpp
Normal file
296
Data/src/SQLChannel.cpp
Normal file
@@ -0,0 +1,296 @@
|
||||
//
|
||||
// SQLChannel.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Data/src/SQLChannel.cpp#3 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: Logging
|
||||
// Module: SQLChannel
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Data/SQLChannel.h"
|
||||
#include "Poco/Data/SessionFactory.h"
|
||||
#include "Poco/DateTime.h"
|
||||
#include "Poco/LoggingFactory.h"
|
||||
#include "Poco/Instantiator.h"
|
||||
#include "Poco/NumberParser.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include "Poco/Format.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
|
||||
|
||||
const std::string SQLChannel::PROP_CONNECTOR("connector");
|
||||
const std::string SQLChannel::PROP_CONNECT("connect");
|
||||
const std::string SQLChannel::PROP_NAME("name");
|
||||
const std::string SQLChannel::PROP_TABLE("table");
|
||||
const std::string SQLChannel::PROP_ARCHIVE_TABLE("archive");
|
||||
const std::string SQLChannel::PROP_MAX_AGE("keep");
|
||||
const std::string SQLChannel::PROP_ASYNC("async");
|
||||
const std::string SQLChannel::PROP_TIMEOUT("timeout");
|
||||
const std::string SQLChannel::PROP_THROW("throw");
|
||||
|
||||
|
||||
SQLChannel::SQLChannel():
|
||||
_name("-"),
|
||||
_table("T_POCO_LOG"),
|
||||
_timeout(1000),
|
||||
_throw(true),
|
||||
_async(true)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
SQLChannel::SQLChannel(const std::string& connector,
|
||||
const std::string& connect,
|
||||
const std::string& name):
|
||||
_connector(connector),
|
||||
_connect(connect),
|
||||
_name(name),
|
||||
_table("T_POCO_LOG"),
|
||||
_timeout(1000),
|
||||
_throw(true),
|
||||
_async(true)
|
||||
{
|
||||
open();
|
||||
}
|
||||
|
||||
|
||||
SQLChannel::~SQLChannel()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
void SQLChannel::open()
|
||||
{
|
||||
if (_connector.empty() || _connect.empty())
|
||||
throw IllegalStateException("Connector and connect string must be non-empty.");
|
||||
|
||||
_pSession = new Session(_connector, _connect);
|
||||
initLogStatement();
|
||||
}
|
||||
|
||||
|
||||
void SQLChannel::close()
|
||||
{
|
||||
wait();
|
||||
}
|
||||
|
||||
|
||||
void SQLChannel::log(const Message& msg)
|
||||
{
|
||||
if (_async) logAsync(msg);
|
||||
else logSync(msg);
|
||||
}
|
||||
|
||||
|
||||
void SQLChannel::logAsync(const Message& msg)
|
||||
{
|
||||
if (!_pSession || !_pSession->isConnected()) open();
|
||||
|
||||
Statement::ResultType ret = wait();
|
||||
if (0 == ret && !_pLogStatement->done() && !_pLogStatement->initialized())
|
||||
{
|
||||
if (_throw)
|
||||
throw TimeoutException("Timed out waiting for previous statement completion");
|
||||
else return;
|
||||
}
|
||||
|
||||
logSync(msg);
|
||||
}
|
||||
|
||||
|
||||
void SQLChannel::logSync(const Message& msg)
|
||||
{
|
||||
//if (isArchiving()) archive();
|
||||
if (_pArchiveStrategy) _pArchiveStrategy->archive();
|
||||
|
||||
_source = msg.getSource();
|
||||
_pid = msg.getPid();
|
||||
_thread = msg.getThread();
|
||||
_tid = msg.getTid();
|
||||
_priority = msg.getPriority();
|
||||
_text = msg.getText();
|
||||
_dateTime = msg.getTime();
|
||||
if (_source.empty()) _source = _name;
|
||||
|
||||
_pLogStatement->execute();
|
||||
}
|
||||
|
||||
|
||||
void SQLChannel::setProperty(const std::string& name, const std::string& value)
|
||||
{
|
||||
if (name == PROP_NAME)
|
||||
{
|
||||
_name = value;
|
||||
if (_name.empty()) _name = "-";
|
||||
}
|
||||
else if (name == PROP_CONNECTOR)
|
||||
{
|
||||
_connector = value;
|
||||
close(); open();
|
||||
}
|
||||
else if (name == PROP_CONNECT)
|
||||
{
|
||||
_connect = value;
|
||||
close(); open();
|
||||
}
|
||||
else if (name == PROP_TABLE)
|
||||
{
|
||||
_table = value;
|
||||
initLogStatement();
|
||||
}
|
||||
else if (name == PROP_ARCHIVE_TABLE)
|
||||
{
|
||||
if (value.empty())
|
||||
{
|
||||
_pArchiveStrategy = 0;
|
||||
}
|
||||
else if (_pArchiveStrategy)
|
||||
{
|
||||
_pArchiveStrategy->setDestination(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
_pArchiveStrategy = new ArchiveByAgeStrategy(_connector, _connect, _table, value);
|
||||
}
|
||||
}
|
||||
else if (name == PROP_MAX_AGE)
|
||||
{
|
||||
if (value.empty() || "forever" == value)
|
||||
{
|
||||
_pArchiveStrategy = 0;
|
||||
}
|
||||
else if (_pArchiveStrategy)
|
||||
{
|
||||
_pArchiveStrategy->setThreshold(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
ArchiveByAgeStrategy* p = new ArchiveByAgeStrategy(_connector, _connect, _table);
|
||||
p->setThreshold(value);
|
||||
_pArchiveStrategy = p;
|
||||
}
|
||||
}
|
||||
else if (name == PROP_ASYNC)
|
||||
{
|
||||
_async = isTrue(value);
|
||||
initLogStatement();
|
||||
}
|
||||
else if (name == PROP_TIMEOUT)
|
||||
{
|
||||
if (value.empty() || '0' == value[0])
|
||||
_timeout = Statement::WAIT_FOREVER;
|
||||
else
|
||||
_timeout = NumberParser::parse(value);
|
||||
}
|
||||
else if (name == PROP_THROW)
|
||||
{
|
||||
_throw = isTrue(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Channel::setProperty(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string SQLChannel::getProperty(const std::string& name) const
|
||||
{
|
||||
if (name == PROP_NAME)
|
||||
{
|
||||
if (_name != "-") return _name;
|
||||
else return "";
|
||||
}
|
||||
else if (name == PROP_CONNECTOR)
|
||||
{
|
||||
return _connector;
|
||||
}
|
||||
else if (name == PROP_CONNECT)
|
||||
{
|
||||
return _connect;
|
||||
}
|
||||
else if (name == PROP_TABLE)
|
||||
{
|
||||
return _table;
|
||||
}
|
||||
else if (name == PROP_ARCHIVE_TABLE)
|
||||
{
|
||||
return _pArchiveStrategy ? _pArchiveStrategy->getDestination() : "" ;
|
||||
}
|
||||
else if (name == PROP_MAX_AGE)
|
||||
{
|
||||
return _pArchiveStrategy ? _pArchiveStrategy->getThreshold() : "forever";
|
||||
}
|
||||
else if (name == PROP_TIMEOUT)
|
||||
{
|
||||
return NumberFormatter::format(_timeout);
|
||||
}
|
||||
else if (name == PROP_THROW)
|
||||
{
|
||||
if (_throw) return "true";
|
||||
else return "false";
|
||||
}
|
||||
else
|
||||
{
|
||||
return Channel::getProperty(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SQLChannel::initLogStatement()
|
||||
{
|
||||
_pLogStatement = new Statement(*_pSession);
|
||||
|
||||
std::string sql;
|
||||
Poco::format(sql, "INSERT INTO %s VALUES (?,?,?,?,?,?,?,?)", _table);
|
||||
*_pLogStatement << sql,
|
||||
use(_source),
|
||||
use(_name),
|
||||
use(_pid),
|
||||
use(_thread),
|
||||
use(_tid),
|
||||
use(_priority),
|
||||
use(_text),
|
||||
use(_dateTime);
|
||||
|
||||
if (_async) _pLogStatement->setAsync();
|
||||
}
|
||||
|
||||
|
||||
void SQLChannel::registerChannel()
|
||||
{
|
||||
Poco::LoggingFactory::defaultFactory().registerChannelClass("SQLChannel", new Poco::Instantiator<SQLChannel, Poco::Channel>);
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Data
|
@@ -58,11 +58,11 @@ SessionFactory& SessionFactory::instance()
|
||||
}
|
||||
|
||||
|
||||
void SessionFactory::add(const std::string& key, Connector* pIn)
|
||||
void SessionFactory::add(Connector* pIn)
|
||||
{
|
||||
Poco::FastMutex::ScopedLock lock(_mutex);
|
||||
SessionInfo info(pIn);
|
||||
std::pair<Connectors::iterator, bool> res = _connectors.insert(std::make_pair(key, info));
|
||||
std::pair<Connectors::iterator, bool> res = _connectors.insert(std::make_pair(pIn->name(), info));
|
||||
if (!res.second)
|
||||
{
|
||||
res.first->second.cnt++;
|
||||
|
123
Data/src/SimpleRowFormatter.cpp
Normal file
123
Data/src/SimpleRowFormatter.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
//
|
||||
// RowFormatter.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Data/src/RowFormatter.cpp#1 $
|
||||
//
|
||||
// Library: Data
|
||||
// Package: DataCore
|
||||
// Module: RowFormatter
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
//
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Data/SimpleRowFormatter.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include <iomanip>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
|
||||
|
||||
SimpleRowFormatter::SimpleRowFormatter(std::streamsize columnWidth):
|
||||
_colWidth(columnWidth)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
SimpleRowFormatter::SimpleRowFormatter(const SimpleRowFormatter& other):
|
||||
RowFormatter(other.prefix(), other.postfix()),
|
||||
_colWidth(other._colWidth)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
SimpleRowFormatter::~SimpleRowFormatter()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
SimpleRowFormatter& SimpleRowFormatter::operator = (const SimpleRowFormatter& row)
|
||||
{
|
||||
SimpleRowFormatter tmp(row);
|
||||
swap(tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void SimpleRowFormatter::swap(SimpleRowFormatter& other)
|
||||
{
|
||||
using std::swap;
|
||||
|
||||
setPrefix(other.prefix());
|
||||
setPostfix(other.postfix());
|
||||
swap(_colWidth, other._colWidth);
|
||||
}
|
||||
|
||||
|
||||
std::string& SimpleRowFormatter::formatNames(const NameVecPtr pNames, std::string& formattedNames) const
|
||||
{
|
||||
std::ostringstream str;
|
||||
std::string line(_colWidth * pNames->size(), '-');
|
||||
|
||||
NameVec::const_iterator it = pNames->begin();
|
||||
NameVec::const_iterator end = pNames->end();
|
||||
for (; it != end; ++it)
|
||||
{
|
||||
str << std::left << std::setw(_colWidth) << *it;
|
||||
}
|
||||
str << std::endl << line << std::endl;
|
||||
|
||||
return formattedNames = str.str();
|
||||
}
|
||||
|
||||
|
||||
std::string& SimpleRowFormatter::formatValues(const ValueVec& vals, std::string& formattedValues) const
|
||||
{
|
||||
std::ostringstream str;
|
||||
|
||||
ValueVec::const_iterator it = vals.begin();
|
||||
ValueVec::const_iterator end = vals.end();
|
||||
for (; it != end; ++it)
|
||||
{
|
||||
if (it->isNumeric())
|
||||
{
|
||||
str << std::right
|
||||
<< std::fixed
|
||||
<< std::setprecision(2);
|
||||
}
|
||||
else str << std::left;
|
||||
|
||||
str << std::setw(_colWidth) << it->convert<std::string>();
|
||||
}
|
||||
str << std::endl;
|
||||
|
||||
return formattedValues = str.str();
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Data
|
@@ -68,7 +68,9 @@ Statement::Statement(const Statement& stmt):
|
||||
_pImpl(stmt._pImpl),
|
||||
_async(stmt._async),
|
||||
_pResult(stmt._pResult),
|
||||
_pAsyncExec(stmt._pAsyncExec)
|
||||
_pAsyncExec(stmt._pAsyncExec),
|
||||
_arguments(stmt._arguments),
|
||||
_pRowFormatter(stmt._pRowFormatter)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -94,6 +96,8 @@ void Statement::swap(Statement& other)
|
||||
swap(_async, other._async);
|
||||
swap(_pAsyncExec, other._pAsyncExec);
|
||||
swap(_pResult, other._pResult);
|
||||
_arguments.swap(other._arguments);
|
||||
swap(_pRowFormatter, other._pRowFormatter);
|
||||
}
|
||||
|
||||
|
||||
@@ -111,6 +115,12 @@ Statement::ResultType Statement::execute()
|
||||
bool isDone = done();
|
||||
if (initialized() || paused() || isDone)
|
||||
{
|
||||
if (_arguments.size())
|
||||
{
|
||||
_pImpl->formatSQL(_arguments);
|
||||
_arguments.clear();
|
||||
}
|
||||
|
||||
if (!isAsync())
|
||||
{
|
||||
if (isDone) _pImpl->reset();
|
||||
@@ -141,9 +151,7 @@ const Statement::Result& Statement::doAsyncExec()
|
||||
if (done()) _pImpl->reset();
|
||||
if (!_pAsyncExec)
|
||||
_pAsyncExec = new AsyncExecMethod(_pImpl, &StatementImpl::execute);
|
||||
poco_check_ptr (_pAsyncExec);
|
||||
_pResult = new Result((*_pAsyncExec)());
|
||||
poco_check_ptr (_pResult);
|
||||
return *_pResult;
|
||||
}
|
||||
|
||||
|
@@ -96,6 +96,8 @@ Poco::UInt32 StatementImpl::execute()
|
||||
if (lim < _lowerLimit)
|
||||
throw LimitException("Did not receive enough data.");
|
||||
|
||||
if (0 == lim) lim = affectedRowCount();
|
||||
|
||||
return lim;
|
||||
}
|
||||
|
||||
@@ -361,4 +363,12 @@ void StatementImpl::addExtract(AbstractExtraction* pExtraction)
|
||||
}
|
||||
|
||||
|
||||
void StatementImpl::formatSQL(std::vector<Any>& arguments)
|
||||
{
|
||||
std::string sql;
|
||||
Poco::format(sql, _ostr.str(), arguments);
|
||||
_ostr.str(""); _ostr << sql;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Data
|
||||
|
@@ -61,7 +61,7 @@ Poco::AutoPtr<Poco::Data::SessionImpl> Connector::createSession(const std::strin
|
||||
|
||||
void Connector::addToFactory()
|
||||
{
|
||||
Poco::Data::SessionFactory::instance().add(KEY, new Connector());
|
||||
Poco::Data::SessionFactory::instance().add(new Connector());
|
||||
}
|
||||
|
||||
|
||||
|
@@ -57,6 +57,9 @@ public:
|
||||
~Connector();
|
||||
/// Destroys the Connector.
|
||||
|
||||
const std::string& name() const;
|
||||
/// Returns the name associated with this connector.
|
||||
|
||||
Poco::AutoPtr<Poco::Data::SessionImpl> createSession(const std::string& connectionString);
|
||||
/// Creates a test SessionImpl object and initializes it with the given connectionString.
|
||||
|
||||
@@ -68,6 +71,15 @@ public:
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// inlines
|
||||
///
|
||||
inline const std::string& Connector::name() const
|
||||
{
|
||||
return KEY;
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::Test
|
||||
|
||||
|
||||
|
@@ -41,6 +41,7 @@
|
||||
#include "Poco/Data/Column.h"
|
||||
#include "Poco/Data/Date.h"
|
||||
#include "Poco/Data/Time.h"
|
||||
#include "Poco/Data/SimpleRowFormatter.h"
|
||||
#include "Connector.h"
|
||||
#include "Poco/BinaryReader.h"
|
||||
#include "Poco/BinaryWriter.h"
|
||||
@@ -94,6 +95,17 @@ void DataTest::testSession()
|
||||
}
|
||||
|
||||
|
||||
void DataTest::testStatementFormatting()
|
||||
{
|
||||
Session sess(SessionFactory::instance().create("test", "cs"));
|
||||
|
||||
Statement stmt = (sess << "SELECT %s%c%s,%d,%u,%f,%s FROM Person WHERE Name LIKE 'Simp%%'",
|
||||
"'",'a',"'",-1, 1u, 1.5, "42", now);
|
||||
|
||||
assert ("SELECT 'a',-1,1,1.500000,42 FROM Person WHERE Name LIKE 'Simp%'" == stmt.toString());
|
||||
}
|
||||
|
||||
|
||||
void DataTest::testFeatures()
|
||||
{
|
||||
Session sess(SessionFactory::instance().create("test", "cs"));
|
||||
@@ -1001,8 +1013,8 @@ void DataTest::testRowFormat()
|
||||
row1.append("field3", 3);
|
||||
row1.append("field4", 4);
|
||||
|
||||
RowFormatter rf;
|
||||
std::streamsize sz = rf.getWidth();
|
||||
SimpleRowFormatter rf;
|
||||
std::streamsize sz = rf.getColumnWidth();
|
||||
|
||||
std::string line(sz * 5, '-');
|
||||
std::ostringstream os;
|
||||
@@ -1125,6 +1137,7 @@ CppUnit::Test* DataTest::suite()
|
||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("DataTest");
|
||||
|
||||
CppUnit_addTest(pSuite, DataTest, testSession);
|
||||
CppUnit_addTest(pSuite, DataTest, testStatementFormatting);
|
||||
CppUnit_addTest(pSuite, DataTest, testFeatures);
|
||||
CppUnit_addTest(pSuite, DataTest, testProperties);
|
||||
CppUnit_addTest(pSuite, DataTest, testBLOB);
|
||||
|
@@ -50,6 +50,7 @@ public:
|
||||
~DataTest();
|
||||
|
||||
void testSession();
|
||||
void testStatementFormatting();
|
||||
void testFeatures();
|
||||
void testProperties();
|
||||
void testBLOB();
|
||||
|
@@ -66,6 +66,10 @@ protected:
|
||||
Poco::UInt32 columnsReturned() const;
|
||||
/// Returns number of columns returned by query.
|
||||
|
||||
Poco::UInt32 affectedRowCount() const;
|
||||
/// Returns the number of affected rows.
|
||||
/// Used to find out the number of rows affected by insert or update.
|
||||
|
||||
const MetaColumn& metaColumn(Poco::UInt32 pos) const;
|
||||
/// Returns column meta data.
|
||||
|
||||
@@ -113,6 +117,12 @@ inline AbstractBinder& TestStatementImpl::binder()
|
||||
}
|
||||
|
||||
|
||||
inline Poco::UInt32 TestStatementImpl::affectedRowCount() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::Test
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user