Skip to content

Commit eaa7430

Browse files
committed
see CHANGELOG
- added Poco::istring (case-insensitive string) and Poco::isubstr (case-insensitive substring search) - improved SQLite execute() return (affected rows) value - added SQLite sys.dual (in-memory system table) - applied SF Patch pocoproject#120: The ExpireLRUCache does not compile with a tuple as key on Visual Studio 2010 - fixed SF Bug pocoproject#599: JSON::Array and JSON::Object size() member can implicitly lose precision - fixed SF Bug pocoproject#602: iterating database table rows not correct if no data in table - fixed SF Bug pocoproject#603: count() is missing in HashMap - fixed GH pocoproject#23: JSON::Object::stringify throw BadCastException - fixed GH pocoproject#16: NetworkInterface::firstAddress() should not throw on unconfigured interfaces - Android compile/build support (by Rangel Reale) - TypeHandler::prepare() now takes const-reference
1 parent 1138f43 commit eaa7430

19 files changed

Lines changed: 473 additions & 255 deletions

File tree

CHANGELOG

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,17 @@ This is the changelog file for the POCO C++ Libraries.
33
Release 1.5.0 (2012-12-17)
44
==========================
55
- using double-conversion library for floating-point numeric/string conversions
6+
- added Poco::istring (case-insensitive string) and Poco::isubstr
7+
- improved SQLite execute() return (affected rows) value
8+
- added SQLite sys.dual (in-memory system table)
9+
- applied SF Patch #120: The ExpireLRUCache does not compile with a tuple as key on Visual Studio 2010
10+
- fixed SF Bug #599: JSON::Array and JSON::Object size() member can implicitly lose precision
11+
- fixed SF Bug #602: iterating database table rows not correct if no data in table
12+
- fixed SF Bug #603: count() is missing in HashMap
13+
- fixed GH #23: JSON::Object::stringify throw BadCastException
14+
- fixed GH #16: NetworkInterface::firstAddress() should not throw on unconfigured interfaces
15+
- Android compile/build support (by Rangel Reale)
16+
- TypeHandler::prepare() now takes const-reference
617

718
Release 1.5.0 (2012-10-14)
819
==========================

CONTRIBUTORS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ Marian Krivos
2424
Franky Braem
2525
Philip Prindeville
2626
Anton Yabchinskiy
27+
Rangel Reale
28+
Fabrizio Duhem
29+
Patrick White
30+
Mike Naquin
2731

2832
--
2933
$Id$

Data/MySQL/testsuite/src/SQLExecutor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ class TypeHandler<Person>
119119
pBinder->bind(pos++, obj.age, dir);
120120
}
121121

122-
static void prepare(std::size_t pos, Person& obj, AbstractPreparator* pPrepare)
122+
static void prepare(std::size_t pos, const Person& obj, AbstractPreparator* pPrepare)
123123
{
124124
// the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))
125125
poco_assert_dbg (pPrepare != 0);

Data/ODBC/testsuite/src/SQLExecutor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ class TypeHandler<Person>
211211
pBinder->bind(pos++, obj.age, dir);
212212
}
213213

214-
static void prepare(std::size_t pos, Person& obj, AbstractPreparator* pPrepare)
214+
static void prepare(std::size_t pos, const Person& obj, AbstractPreparator* pPrepare)
215215
{
216216
// the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))
217217
poco_assert_dbg (pPrepare != 0);

Data/SQLite/include/Poco/Data/SQLite/SQLiteStatementImpl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ class SQLite_API SQLiteStatementImpl: public Poco::Data::StatementImpl
141141
bool _canBind;
142142
bool _isExtracted;
143143
bool _canCompile;
144+
145+
static const std::size_t POCO_SQLITE_INV_ROW_CNT;
144146
};
145147

146148

Data/SQLite/include/Poco/Data/SQLite/SessionImpl.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,17 @@ class SQLite_API SessionImpl: public Poco::Data::AbstractSessionImpl<SessionImpl
7171

7272
void open(const std::string& connect = "");
7373
/// Opens a connection to the Database.
74+
///
75+
/// An in-memory system database (sys), with a single table (dual)
76+
/// containing single field (dummy) is attached to the database.
77+
/// The in-memory system database is used to force change count
78+
/// to be reset to zero on every new query (or batch of queries)
79+
/// execution. Without this functionality, select statements
80+
/// executions that do not return any rows return the count of
81+
/// changes effected by the most recent insert, update or delete.
82+
/// In-memory system database can be queried and updated but can not
83+
/// be dropped. It may be used for other purposes
84+
/// in the future.
7485

7586
void close();
7687
/// Closes the session.

Data/SQLite/src/SQLiteStatementImpl.cpp

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,16 @@ namespace Data {
5252
namespace SQLite {
5353

5454

55+
const std::size_t SQLiteStatementImpl::POCO_SQLITE_INV_ROW_CNT = std::numeric_limits<std::size_t>::max();
56+
57+
5558
SQLiteStatementImpl::SQLiteStatementImpl(Poco::Data::SessionImpl& rSession, sqlite3* pDB):
5659
StatementImpl(rSession),
5760
_pDB(pDB),
5861
_pStmt(0),
5962
_stepCalled(false),
6063
_nextResponse(0),
61-
_affectedRowCount(0),
64+
_affectedRowCount(POCO_SQLITE_INV_ROW_CNT),
6265
_canBind(false),
6366
_isExtracted(false),
6467
_canCompile(true)
@@ -75,9 +78,29 @@ SQLiteStatementImpl::~SQLiteStatementImpl()
7578

7679
void SQLiteStatementImpl::compileImpl()
7780
{
78-
if (!_pLeftover) _bindBegin = bindings().begin();
81+
if (!_pLeftover)
82+
{
83+
// Executed to force reset of previous changes count to zero.
84+
// Without this, execute() will not return accurate (zero) count if select
85+
// statement returns no results previous [insert|update|delete] affected rows.
86+
if (sqlite3_changes(_pDB))
87+
{
88+
if (SQLITE_OK != sqlite3_exec(_pDB, "delete from sys.dual where 1 <> 1;", 0, 0, 0))
89+
throw ExecutionException("Error updating system database.");
90+
}
91+
92+
_bindBegin = bindings().begin();
93+
}
7994

8095
std::string statement(toString());
96+
97+
if (isubstr(statement, std::string("drop")) != istring::npos &&
98+
isubstr(statement, std::string("table")) != istring::npos &&
99+
isubstr(statement, std::string("dual")) != istring::npos)
100+
{
101+
throw InvalidAccessException("Cannot drop system table!");
102+
}
103+
81104
sqlite3_stmt* pStmt = 0;
82105
const char* pSql = _pLeftover ? _pLeftover->c_str() : statement.c_str();
83106

@@ -194,12 +217,12 @@ void SQLiteStatementImpl::bindImpl()
194217

195218
if (_bindBegin != bindings().end())
196219
{
197-
std::size_t boundRowCount = (*_bindBegin)->numOfRowsHandled();
220+
_affectedRowCount = (*_bindBegin)->numOfRowsHandled();
198221

199222
Bindings::iterator oldBegin = _bindBegin;
200223
for (std::size_t pos = 1; _bindBegin != bindEnd && (*_bindBegin)->canBind(); ++_bindBegin)
201224
{
202-
if (boundRowCount != (*_bindBegin)->numOfRowsHandled())
225+
if (_affectedRowCount != (*_bindBegin)->numOfRowsHandled())
203226
throw BindingException("Size mismatch in Bindings. All Bindings MUST have the same size");
204227

205228
(*_bindBegin)->bind(pos);
@@ -220,7 +243,7 @@ void SQLiteStatementImpl::bindImpl()
220243
void SQLiteStatementImpl::clear()
221244
{
222245
_columns[currentDataSet()].clear();
223-
_affectedRowCount = 0;
246+
_affectedRowCount = POCO_SQLITE_INV_ROW_CNT;
224247

225248
if (_pStmt)
226249
{
@@ -304,7 +327,7 @@ const MetaColumn& SQLiteStatementImpl::metaColumn(std::size_t pos) const
304327

305328
std::size_t SQLiteStatementImpl::affectedRowCount() const
306329
{
307-
return _affectedRowCount ? _affectedRowCount : sqlite3_changes(_pDB);
330+
return _affectedRowCount != POCO_SQLITE_INV_ROW_CNT ? _affectedRowCount : sqlite3_changes(_pDB);
308331
}
309332

310333

Data/SQLite/src/SessionImpl.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
#include "Poco/ActiveMethod.h"
4444
#include "Poco/ActiveResult.h"
4545
#include "Poco/String.h"
46-
#include "Poco/Exception.h"
46+
#include "Poco/Data/DataException.h"
4747
#include "sqlite3.h"
4848
#include <cstdlib>
4949

@@ -195,6 +195,14 @@ void SessionImpl::open(const std::string& connect)
195195
throw ConnectionFailedException(ex.displayText());
196196
}
197197

198+
if (SQLITE_OK != sqlite3_exec(_pDB,
199+
"attach database ':memory:' as sys;"
200+
"create table sys.dual (dummy);",
201+
0, 0, 0))
202+
{
203+
throw ExecutionException("Cannot create system database.");
204+
}
205+
198206
_connected = true;
199207
}
200208

Data/SQLite/testsuite/src/SQLiteTest.cpp

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ class TypeHandler<Person>
193193
pBinder->bind(pos++, obj.getAge(), dir);
194194
}
195195

196-
static void prepare(std::size_t pos, Person& obj, AbstractPreparator* pPrepare)
196+
static void prepare(std::size_t pos, const Person& obj, AbstractPreparator* pPrepare)
197197
{
198198
// the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))
199199
poco_assert_dbg (pPrepare != 0);
@@ -674,6 +674,11 @@ void SQLiteTest::testAffectedRows()
674674
tmp << "DROP TABLE IF EXISTS Strings", now;
675675
tmp << "CREATE TABLE IF NOT EXISTS Strings (str VARCHAR(30))", now;
676676

677+
Statement stmt((tmp << "SELECT * FROM Strings"));
678+
tmp << "SELECT COUNT(*) FROM Strings", into(count), now;
679+
assert (count == 0);
680+
assert (0 == stmt.execute());
681+
677682
Statement stmt1((tmp << "INSERT INTO Strings VALUES(:str)", use(str)));
678683
tmp << "SELECT COUNT(*) FROM Strings", into(count), now;
679684
assert (count == 0);
@@ -1242,6 +1247,12 @@ void SQLiteTest::testCombinedLimits()
12421247
tmp << "DROP TABLE IF EXISTS Person", now;
12431248
tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
12441249
tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :age)", use(people), now;
1250+
1251+
std::string a, b, c;
1252+
Statement stmt = (tmp << "SELECT LastName, FirstName, Address FROM Person WHERE Address = 'invalid value'",
1253+
into(a), into(b), into(c), limit(1));
1254+
assert (!stmt.done() && stmt.execute() == 0);
1255+
12451256
int count = 0;
12461257
tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
12471258
assert (count == 2);
@@ -2543,6 +2554,32 @@ void SQLiteTest::testReconnect()
25432554
}
25442555

25452556

2557+
void SQLiteTest::testSystemTable()
2558+
{
2559+
Session session (Poco::Data::SQLite::Connector::KEY, "dummy.db");
2560+
2561+
int cnt = -1;
2562+
session << "SELECT count(*) FROM sys.dual", into(cnt), now;
2563+
assert (0 == cnt);
2564+
2565+
session << "INSERT INTO sys.dual VALUES ('test')", now;
2566+
session << "SELECT count(*) FROM sys.dual", into(cnt), now;
2567+
assert (1 == cnt);
2568+
2569+
session << "DELETE FROM sys.dual", now;
2570+
session << "SELECT count(*) FROM sys.dual", into(cnt), now;
2571+
assert (0 == cnt);
2572+
2573+
try
2574+
{
2575+
session << "DROP TABLE sys.dual", now;
2576+
fail ("must throw");
2577+
}
2578+
catch (InvalidAccessException&) { }
2579+
2580+
}
2581+
2582+
25462583
void SQLiteTest::setUp()
25472584
{
25482585
}
@@ -2633,6 +2670,7 @@ CppUnit::Test* SQLiteTest::suite()
26332670
CppUnit_addTest(pSuite, SQLiteTest, testMultipleResults);
26342671
CppUnit_addTest(pSuite, SQLiteTest, testPair);
26352672
CppUnit_addTest(pSuite, SQLiteTest, testReconnect);
2673+
CppUnit_addTest(pSuite, SQLiteTest, testSystemTable);
26362674

26372675
return pSuite;
26382676
}

Data/SQLite/testsuite/src/SQLiteTest.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ class SQLiteTest: public CppUnit::TestCase
132132
void testMultipleResults();
133133

134134
void testReconnect();
135+
void testSystemTable();
135136

136137
void setUp();
137138
void tearDown();

0 commit comments

Comments
 (0)