mirror of
https://github.com/pocoproject/poco.git
synced 2025-04-15 06:35:25 +02:00
see CHANGELOG
- upgraded SQLite to version 3.7.15.1 (2012-12-19) - fixed SQLite affectedRows reporting and added tests - added SQLite::Utility::isThreadSafe() function - added SQLite::Utility::setThreadMode(int mode) function - fixed GH #41: Buffer::resize crash
This commit is contained in:
parent
16533ef73b
commit
760fa4bbb0
@ -29,6 +29,11 @@ Release 1.5.0 (2012-12-17)
|
||||
- fixed GH #30: Poco::Path::home() throws when called from Windows Service
|
||||
- fixed GH #22: MySQL connection string lowercased
|
||||
- added MySQL support for Date/Time
|
||||
- upgraded SQLite to version 3.7.15.1 (2012-12-19)
|
||||
- fixed SQLite affectedRows reporting and added tests
|
||||
- added SQLite::Utility::isThreadSafe() function
|
||||
- added SQLite::Utility::setThreadMode(int mode) function
|
||||
- fixed GH #41: Buffer::resize crash
|
||||
|
||||
Release 1.5.0 (2012-10-14)
|
||||
==========================
|
||||
|
@ -80,4 +80,16 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// Thread safety mode defaults to "serialized".
|
||||
// See http://www.sqlite.org/threadsafe.html for details.
|
||||
// Threading mode significantly affects performance
|
||||
// (see TestSuite::benchmarkThreadModesTiming)
|
||||
//
|
||||
#ifndef SQLITE_THREADSAFE
|
||||
#define SQLITE_THREADSAFE 1
|
||||
#endif
|
||||
|
||||
|
||||
#endif // SQLite_SQLite_INCLUDED
|
||||
|
@ -63,6 +63,10 @@ public:
|
||||
static const std::string SQLITE_TIME_FORMAT;
|
||||
typedef std::map<std::string, MetaColumn::ColumnDataType> TypeMap;
|
||||
|
||||
static const int THREAD_MODE_SINGLE;
|
||||
static const int THREAD_MODE_MULTI;
|
||||
static const int THREAD_MODE_SERIAL;
|
||||
|
||||
Utility();
|
||||
/// Maps SQLite column declared types to Poco::Data types through
|
||||
/// static TypeMap member.
|
||||
@ -92,6 +96,14 @@ public:
|
||||
///
|
||||
/// Returns true if succesful
|
||||
|
||||
static bool isThreadSafe();
|
||||
/// Returns true if SQLite was compiled in thread or serialized mode.
|
||||
/// See http://www.sqlite.org/c3ref/threadsafe.html for details.
|
||||
|
||||
static bool setThreadMode(int mode);
|
||||
/// Sets the threading mode to single, multi or serialized.
|
||||
/// See http://www.sqlite.org/threadsafe.html for details.
|
||||
|
||||
private:
|
||||
static TypeMap _types;
|
||||
Poco::FastMutex _mutex;
|
||||
|
@ -215,14 +215,15 @@ void SQLiteStatementImpl::bindImpl()
|
||||
else if (bindCount > remainingBindCount)
|
||||
throw ParameterCountMismatchException();
|
||||
|
||||
std::size_t boundRowCount;
|
||||
if (_bindBegin != bindings().end())
|
||||
{
|
||||
_affectedRowCount = (*_bindBegin)->numOfRowsHandled();
|
||||
boundRowCount = (*_bindBegin)->numOfRowsHandled();
|
||||
|
||||
Bindings::iterator oldBegin = _bindBegin;
|
||||
for (std::size_t pos = 1; _bindBegin != bindEnd && (*_bindBegin)->canBind(); ++_bindBegin)
|
||||
{
|
||||
if (_affectedRowCount != (*_bindBegin)->numOfRowsHandled())
|
||||
if (boundRowCount != (*_bindBegin)->numOfRowsHandled())
|
||||
throw BindingException("Size mismatch in Bindings. All Bindings MUST have the same size");
|
||||
|
||||
(*_bindBegin)->bind(pos);
|
||||
@ -270,6 +271,9 @@ bool SQLiteStatementImpl::hasNext()
|
||||
_stepCalled = true;
|
||||
_nextResponse = sqlite3_step(_pStmt);
|
||||
|
||||
if (_affectedRowCount == POCO_SQLITE_INV_ROW_CNT) _affectedRowCount = 0;
|
||||
_affectedRowCount += sqlite3_changes(_pDB);
|
||||
|
||||
if (_nextResponse != SQLITE_ROW && _nextResponse != SQLITE_OK && _nextResponse != SQLITE_DONE)
|
||||
Utility::throwException(_nextResponse);
|
||||
|
||||
@ -296,6 +300,8 @@ std::size_t SQLiteStatementImpl::next()
|
||||
_isExtracted = true;
|
||||
}
|
||||
_stepCalled = false;
|
||||
if (_affectedRowCount == POCO_SQLITE_INV_ROW_CNT) _affectedRowCount = 0;
|
||||
_affectedRowCount += (*extracts.begin())->numOfRowsHandled();
|
||||
}
|
||||
else if (SQLITE_DONE == _nextResponse)
|
||||
{
|
||||
@ -303,8 +309,7 @@ std::size_t SQLiteStatementImpl::next()
|
||||
}
|
||||
else
|
||||
{
|
||||
int rc = _nextResponse;
|
||||
Utility::throwException(rc, std::string("Iterator Error: trying to access the next value"));
|
||||
Utility::throwException(_nextResponse, std::string("Iterator Error: trying to access the next value"));
|
||||
}
|
||||
|
||||
return 1u;
|
||||
|
@ -53,6 +53,10 @@ namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
const int Utility::THREAD_MODE_SINGLE = SQLITE_CONFIG_SINGLETHREAD;
|
||||
const int Utility::THREAD_MODE_MULTI = SQLITE_CONFIG_MULTITHREAD;
|
||||
const int Utility::THREAD_MODE_SERIAL = SQLITE_CONFIG_SERIALIZED;
|
||||
|
||||
const std::string Utility::SQLITE_DATE_FORMAT = "%Y-%m-%d";
|
||||
const std::string Utility::SQLITE_TIME_FORMAT = "%H:%M:%S";
|
||||
Utility::TypeMap Utility::_types;
|
||||
@ -255,4 +259,16 @@ bool Utility::memoryToFile(const std::string& fileName, sqlite3* pInMemory)
|
||||
}
|
||||
|
||||
|
||||
bool Utility::isThreadSafe()
|
||||
{
|
||||
return 0 != sqlite3_threadsafe;
|
||||
}
|
||||
|
||||
|
||||
bool Utility::setThreadMode(int mode)
|
||||
{
|
||||
return SQLITE_OK == sqlite3_config((int) mode);
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -107,9 +107,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.7.14.1"
|
||||
#define SQLITE_VERSION_NUMBER 3007014
|
||||
#define SQLITE_SOURCE_ID "2012-10-04 19:37:12 091570e46d04e84b67228e0bdbcd6e1fb60c6bdb"
|
||||
#define SQLITE_VERSION "3.7.15.1"
|
||||
#define SQLITE_VERSION_NUMBER 3007015
|
||||
#define SQLITE_SOURCE_ID "2012-12-19 20:39:10 6b85b767d0ff7975146156a99ad673f2c1a23318"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@ -474,10 +474,12 @@ SQLITE_API int sqlite3_exec(
|
||||
#define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8))
|
||||
#define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8))
|
||||
#define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8))
|
||||
#define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8))
|
||||
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
|
||||
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
|
||||
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
|
||||
#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
|
||||
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
|
||||
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
|
||||
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
|
||||
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
|
||||
@ -855,6 +857,26 @@ struct sqlite3_io_methods {
|
||||
** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
|
||||
** file control occurs at the beginning of pragma statement analysis and so
|
||||
** it is able to override built-in [PRAGMA] statements.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_BUSYHANDLER]]
|
||||
** ^This file-control may be invoked by SQLite on the database file handle
|
||||
** shortly after it is opened in order to provide a custom VFS with access
|
||||
** to the connections busy-handler callback. The argument is of type (void **)
|
||||
** - an array of two (void *) values. The first (void *) actually points
|
||||
** to a function of type (int (*)(void *)). In order to invoke the connections
|
||||
** busy-handler, this function should be invoked with the second (void *) in
|
||||
** the array as the only argument. If it returns non-zero, then the operation
|
||||
** should be retried. If it returns zero, the custom VFS should abandon the
|
||||
** current operation.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_TEMPFILENAME]]
|
||||
** ^Application can invoke this file-control to have SQLite generate a
|
||||
** temporary filename using the same algorithm that is followed to generate
|
||||
** temporary filenames for TEMP tables and other internal uses. The
|
||||
** argument should be a char** which will be filled with the filename
|
||||
** written into memory obtained from [sqlite3_malloc()]. The caller should
|
||||
** invoke [sqlite3_free()] on the result to avoid a memory leak.
|
||||
**
|
||||
** </ul>
|
||||
*/
|
||||
#define SQLITE_FCNTL_LOCKSTATE 1
|
||||
@ -871,6 +893,8 @@ struct sqlite3_io_methods {
|
||||
#define SQLITE_FCNTL_VFSNAME 12
|
||||
#define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13
|
||||
#define SQLITE_FCNTL_PRAGMA 14
|
||||
#define SQLITE_FCNTL_BUSYHANDLER 15
|
||||
#define SQLITE_FCNTL_TEMPFILENAME 16
|
||||
|
||||
/*
|
||||
** CAPI3REF: Mutex Handle
|
||||
@ -1567,11 +1591,39 @@ struct sqlite3_mem_methods {
|
||||
** disabled. The default value may be changed by compiling with the
|
||||
** [SQLITE_USE_URI] symbol defined.
|
||||
**
|
||||
** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
|
||||
** <dd> This option takes a single integer argument which is interpreted as
|
||||
** a boolean in order to enable or disable the use of covering indices for
|
||||
** full table scans in the query optimizer. The default setting is determined
|
||||
** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
|
||||
** if that compile-time option is omitted.
|
||||
** The ability to disable the use of covering indices for full table scans
|
||||
** is because some incorrectly coded legacy applications might malfunction
|
||||
** malfunction when the optimization is enabled. Providing the ability to
|
||||
** disable the optimization allows the older, buggy application code to work
|
||||
** without change even with newer versions of SQLite.
|
||||
**
|
||||
** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]]
|
||||
** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE
|
||||
** <dd> These options are obsolete and should not be used by new code.
|
||||
** They are retained for backwards compatibility but are now no-ops.
|
||||
** </dl>
|
||||
**
|
||||
** [[SQLITE_CONFIG_SQLLOG]]
|
||||
** <dt>SQLITE_CONFIG_SQLLOG
|
||||
** <dd>This option is only available if sqlite is compiled with the
|
||||
** SQLITE_ENABLE_SQLLOG pre-processor macro defined. The first argument should
|
||||
** be a pointer to a function of type void(*)(void*,sqlite3*,const char*, int).
|
||||
** The second should be of type (void*). The callback is invoked by the library
|
||||
** in three separate circumstances, identified by the value passed as the
|
||||
** fourth parameter. If the fourth parameter is 0, then the database connection
|
||||
** passed as the second argument has just been opened. The third argument
|
||||
** points to a buffer containing the name of the main database file. If the
|
||||
** fourth parameter is 1, then the SQL statement that the third parameter
|
||||
** points to has just been executed. Or, if the fourth parameter is 2, then
|
||||
** the connection being passed as the second parameter is being closed. The
|
||||
** third parameter is passed NULL In this case.
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
|
||||
#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
|
||||
@ -1592,6 +1644,8 @@ struct sqlite3_mem_methods {
|
||||
#define SQLITE_CONFIG_URI 17 /* int */
|
||||
#define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */
|
||||
#define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */
|
||||
#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */
|
||||
#define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Database Connection Configuration Options
|
||||
@ -2600,7 +2654,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
||||
** an error)^.
|
||||
** ^If "ro" is specified, then the database is opened for read-only
|
||||
** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the
|
||||
** third argument to sqlite3_prepare_v2(). ^If the mode option is set to
|
||||
** third argument to sqlite3_open_v2(). ^If the mode option is set to
|
||||
** "rw", then the database is opened for read-write (but not create)
|
||||
** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had
|
||||
** been set. ^Value "rwc" is equivalent to setting both
|
||||
@ -2752,6 +2806,11 @@ SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int
|
||||
** However, the error string might be overwritten or deallocated by
|
||||
** subsequent calls to other SQLite interface functions.)^
|
||||
**
|
||||
** ^The sqlite3_errstr() interface returns the English-language text
|
||||
** that describes the [result code], as UTF-8.
|
||||
** ^(Memory to hold the error message string is managed internally
|
||||
** and must not be freed by the application)^.
|
||||
**
|
||||
** When the serialized [threading mode] is in use, it might be the
|
||||
** case that a second error occurs on a separate thread in between
|
||||
** the time of the first error and the call to these interfaces.
|
||||
@ -2770,6 +2829,7 @@ SQLITE_API int sqlite3_errcode(sqlite3 *db);
|
||||
SQLITE_API int sqlite3_extended_errcode(sqlite3 *db);
|
||||
SQLITE_API const char *sqlite3_errmsg(sqlite3*);
|
||||
SQLITE_API const void *sqlite3_errmsg16(sqlite3*);
|
||||
SQLITE_API const char *sqlite3_errstr(int);
|
||||
|
||||
/*
|
||||
** CAPI3REF: SQL Statement Object
|
||||
@ -4732,6 +4792,9 @@ SQLITE_API void *sqlite3_update_hook(
|
||||
** future releases of SQLite. Applications that care about shared
|
||||
** cache setting should set it explicitly.
|
||||
**
|
||||
** This interface is threadsafe on processors where writing a
|
||||
** 32-bit integer is atomic.
|
||||
**
|
||||
** See Also: [SQLite Shared-Cache Mode]
|
||||
*/
|
||||
SQLITE_API int sqlite3_enable_shared_cache(int);
|
||||
|
@ -58,6 +58,7 @@
|
||||
#include "Poco/AutoPtr.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/RefCountedObject.h"
|
||||
#include "Poco/Stopwatch.h"
|
||||
#include <iostream>
|
||||
|
||||
|
||||
@ -618,7 +619,6 @@ void SQLiteTest::testSharedPtrComplexTypeVector()
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SQLiteTest::testInsertVector()
|
||||
{
|
||||
Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
|
||||
@ -680,6 +680,7 @@ void SQLiteTest::testAffectedRows()
|
||||
assert (0 == stmt.execute());
|
||||
|
||||
Statement stmt1((tmp << "INSERT INTO Strings VALUES(:str)", use(str)));
|
||||
count = -1;
|
||||
tmp << "SELECT COUNT(*) FROM Strings", into(count), now;
|
||||
assert (count == 0);
|
||||
assert (4 == stmt1.execute());
|
||||
@ -692,10 +693,13 @@ void SQLiteTest::testAffectedRows()
|
||||
Statement stmt3(tmp << "DELETE FROM Strings WHERE str = 's1'");
|
||||
assert (1 == stmt3.execute());
|
||||
|
||||
Statement stmt4(tmp << "DELETE FROM Strings WHERE str = 'bad value'");
|
||||
assert (0 == stmt4.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());
|
||||
Statement stmt5(tmp << "DELETE FROM Strings WHERE 1");
|
||||
assert (3 == stmt5.execute());
|
||||
}
|
||||
|
||||
|
||||
@ -2263,8 +2267,6 @@ void SQLiteTest::testDynamicAny()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SQLiteTest::testPair()
|
||||
{
|
||||
Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
|
||||
@ -2299,6 +2301,7 @@ void SQLiteTest::testPair()
|
||||
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::testSQLChannel()
|
||||
{
|
||||
Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
|
||||
@ -2580,6 +2583,51 @@ void SQLiteTest::testSystemTable()
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::benchmarkThreadModesTiming()
|
||||
{
|
||||
using namespace Poco::Data::SQLite;
|
||||
typedef std::vector<int> ModeVec;
|
||||
|
||||
const int datasize = 1000;
|
||||
ModeVec mode;
|
||||
mode.push_back(Utility::THREAD_MODE_SINGLE);
|
||||
mode.push_back(Utility::THREAD_MODE_MULTI);
|
||||
mode.push_back(Utility::THREAD_MODE_SERIAL);
|
||||
|
||||
Poco::Stopwatch sw;
|
||||
ModeVec::iterator it = mode.begin();
|
||||
ModeVec::iterator end = mode.end();
|
||||
for (; it != end; ++it)
|
||||
{
|
||||
sw.start();
|
||||
Utility::setThreadMode(*it);
|
||||
Session tmp (Connector::KEY, "dummy.db");
|
||||
std::vector<int> iv;
|
||||
int count = 0;
|
||||
for (int i =0; i < datasize; ++i) iv.push_back(i);
|
||||
|
||||
tmp << "DROP TABLE IF EXISTS Ints", now;
|
||||
tmp << "CREATE TABLE IF NOT EXISTS Ints (theInt INTEGER)", now;
|
||||
{
|
||||
Statement stmt((tmp << "INSERT INTO Ints VALUES(?)", use(iv)));
|
||||
tmp << "SELECT COUNT(*) FROM Ints", into(count), now;
|
||||
assert (count == 0);
|
||||
stmt.execute();
|
||||
tmp << "SELECT COUNT(*) FROM Ints", into(count), now;
|
||||
assert (count == datasize);
|
||||
}
|
||||
count = 0;
|
||||
tmp << "SELECT COUNT(*) FROM Ints", into(count), now;
|
||||
assert (count == datasize);
|
||||
sw.stop();
|
||||
std::cout << "Mode: " << ((*it == Utility::THREAD_MODE_SINGLE) ? "single,"
|
||||
:(*it == Utility::THREAD_MODE_MULTI) ? "multi,"
|
||||
:(*it == Utility::THREAD_MODE_SERIAL) ? "serial,"
|
||||
: "unknown,") << " Time: " << sw.elapsed() / 1000.0 << " [ms]" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::setUp()
|
||||
{
|
||||
}
|
||||
@ -2671,6 +2719,7 @@ CppUnit::Test* SQLiteTest::suite()
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testPair);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testReconnect);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testSystemTable);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, benchmarkThreadModesTiming);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@ -134,6 +134,8 @@ public:
|
||||
void testReconnect();
|
||||
void testSystemTable();
|
||||
|
||||
void benchmarkThreadModesTiming();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
||||
|
@ -96,7 +96,7 @@ public:
|
||||
|
||||
std::size_t numOfRowsHandled() const
|
||||
{
|
||||
return 1;
|
||||
return 1u;
|
||||
}
|
||||
|
||||
bool canBind() const
|
||||
@ -120,8 +120,8 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
const T& _val;
|
||||
bool _bound;
|
||||
const T& _val;
|
||||
bool _bound;
|
||||
};
|
||||
|
||||
|
||||
|
@ -96,7 +96,7 @@ public:
|
||||
|
||||
std::size_t numOfRowsHandled() const
|
||||
{
|
||||
return 0;
|
||||
return _extracted ? 1u : 0;
|
||||
}
|
||||
|
||||
std::size_t numOfRowsAllowed() const
|
||||
|
@ -142,10 +142,10 @@ public:
|
||||
{
|
||||
T* ptr = new T[newCapacity];
|
||||
if (preserveContent)
|
||||
std::memcpy(ptr, _ptr, newCapacity);
|
||||
std::memcpy(ptr, _ptr, _capacity);
|
||||
|
||||
delete [] _ptr;
|
||||
_ptr = ptr;
|
||||
_ptr = ptr;
|
||||
_capacity = newCapacity;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user