using lf instead crlf to decrease errors

This commit is contained in:
TinyAtoms 2019-06-27 00:32:09 -03:00
parent 77919e4ce0
commit 6be7af0933
6 changed files with 172 additions and 282 deletions

View File

@ -10,95 +10,78 @@
* or copy at http://opensource.org/licenses/MIT) * or copy at http://opensource.org/licenses/MIT)
*/ */
#include <SQLiteCpp/Backup.h> #include <SQLiteCpp/Backup.h>
#include <SQLiteCpp/Exception.h> #include <SQLiteCpp/Exception.h>
#include <sqlite3.h> #include <sqlite3.h>
namespace SQLite {
namespace SQLite
{
// Initialize resource for SQLite database backup // Initialize resource for SQLite database backup
Backup::Backup(Database& aDestDatabase, Backup::Backup(Database& aDestDatabase,
const char* apDestDatabaseName, const char* apDestDatabaseName,
Database& aSrcDatabase, Database& aSrcDatabase,
const char* apSrcDatabaseName) : const char* apSrcDatabaseName)
mpSQLiteBackup(NULL) : mpSQLiteBackup(NULL)
{ {
mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(), mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(),
apDestDatabaseName, apDestDatabaseName,
aSrcDatabase.getHandle(), aSrcDatabase.getHandle(),
apSrcDatabaseName); apSrcDatabaseName);
if (NULL == mpSQLiteBackup) if (NULL == mpSQLiteBackup) {
{
// If an error occurs, the error code and message are attached to the destination database connection. // If an error occurs, the error code and message are attached to the destination database connection.
throw SQLite::Exception(aDestDatabase.getHandle()); throw SQLite::Exception(aDestDatabase.getHandle());
} }
} }
// Initialize resource for SQLite database backup // Initialize resource for SQLite database backup
Backup::Backup(Database& aDestDatabase, Backup::Backup(Database& aDestDatabase,
const std::string& aDestDatabaseName, const std::string& aDestDatabaseName,
Database& aSrcDatabase, Database& aSrcDatabase,
const std::string& aSrcDatabaseName) : const std::string& aSrcDatabaseName)
mpSQLiteBackup(NULL) : mpSQLiteBackup(NULL)
{ {
mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(), mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(),
aDestDatabaseName.c_str(), aDestDatabaseName.c_str(),
aSrcDatabase.getHandle(), aSrcDatabase.getHandle(),
aSrcDatabaseName.c_str()); aSrcDatabaseName.c_str());
if (NULL == mpSQLiteBackup) if (NULL == mpSQLiteBackup) {
{
// If an error occurs, the error code and message are attached to the destination database connection. // If an error occurs, the error code and message are attached to the destination database connection.
throw SQLite::Exception(aDestDatabase.getHandle()); throw SQLite::Exception(aDestDatabase.getHandle());
} }
} }
// Initialize resource for SQLite database backup // Initialize resource for SQLite database backup
Backup::Backup(Database &aDestDatabase, Database &aSrcDatabase) : Backup::Backup(Database& aDestDatabase, Database& aSrcDatabase)
mpSQLiteBackup(NULL) : mpSQLiteBackup(NULL)
{ {
mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(), mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(),
"main", "main",
aSrcDatabase.getHandle(), aSrcDatabase.getHandle(),
"main"); "main");
if (NULL == mpSQLiteBackup) if (NULL == mpSQLiteBackup) {
{
// If an error occurs, the error code and message are attached to the destination database connection. // If an error occurs, the error code and message are attached to the destination database connection.
throw SQLite::Exception(aDestDatabase.getHandle()); throw SQLite::Exception(aDestDatabase.getHandle());
} }
} }
// Release resource for SQLite database backup // Release resource for SQLite database backup
Backup::~Backup() Backup::~Backup()
{ {
if (NULL != mpSQLiteBackup) if (NULL != mpSQLiteBackup) {
{
sqlite3_backup_finish(mpSQLiteBackup); sqlite3_backup_finish(mpSQLiteBackup);
} }
} }
// Execute backup step with a given number of source pages to be copied // Execute backup step with a given number of source pages to be copied
int Backup::executeStep(const int aNumPage /* = -1 */) int Backup::executeStep(const int aNumPage /* = -1 */)
{ {
const int res = sqlite3_backup_step(mpSQLiteBackup, aNumPage); const int res = sqlite3_backup_step(mpSQLiteBackup, aNumPage);
if (SQLITE_OK != res && SQLITE_DONE != res && SQLITE_BUSY != res && SQLITE_LOCKED != res) if (SQLITE_OK != res && SQLITE_DONE != res && SQLITE_BUSY != res && SQLITE_LOCKED != res) {
{
throw SQLite::Exception(sqlite3_errstr(res), res); throw SQLite::Exception(sqlite3_errstr(res), res);
} }
return res; return res;
} }
// Get the number of remaining source pages to be copied in this backup process // Get the number of remaining source pages to be copied in this backup process
int Backup::getRemainingPageCount() int Backup::getRemainingPageCount()
{ {
return sqlite3_backup_remaining(mpSQLiteBackup); return sqlite3_backup_remaining(mpSQLiteBackup);
} }
// Get the number of total source pages to be copied in this backup process // Get the number of total source pages to be copied in this backup process
int Backup::getTotalPageCount() int Backup::getTotalPageCount()
{ {
return sqlite3_backup_pagecount(mpSQLiteBackup); return sqlite3_backup_pagecount(mpSQLiteBackup);
} }
} // namespace SQLite
} // namespace SQLite

View File

@ -9,41 +9,33 @@
* or copy at http://opensource.org/licenses/MIT) * or copy at http://opensource.org/licenses/MIT)
*/ */
#include <SQLiteCpp/Column.h> #include <SQLiteCpp/Column.h>
#include <sqlite3.h> #include <sqlite3.h>
#include <iostream> #include <iostream>
namespace SQLite namespace SQLite
{ {
const int INTEGER = SQLITE_INTEGER;
const int INTEGER = SQLITE_INTEGER; const int FLOAT = SQLITE_FLOAT;
const int FLOAT = SQLITE_FLOAT; const int TEXT = SQLITE_TEXT;
const int TEXT = SQLITE_TEXT; const int BLOB = SQLITE_BLOB;
const int BLOB = SQLITE_BLOB; const int Null = SQLITE_NULL;
const int Null = SQLITE_NULL;
// Encapsulation of a Column in a row of the result pointed by the prepared Statement. // Encapsulation of a Column in a row of the result pointed by the prepared Statement.
Column::Column(Statement::Ptr& aStmtPtr, int aIndex) noexcept : // nothrow Column::Column(Statement::Ptr& aStmtPtr, int aIndex) noexcept
mStmtPtr(aStmtPtr), : // nothrow
mStmtPtr(aStmtPtr)
,
mIndex(aIndex) mIndex(aIndex)
{ {
} }
// Finalize and unregister the SQL query from the SQLite Database Connection. // Finalize and unregister the SQL query from the SQLite Database Connection.
Column::~Column() Column::~Column()
{ {
// the finalization will be done by the destructor of the last shared pointer // the finalization will be done by the destructor of the last shared pointer
} }
// Return the named assigned to this result column (potentially aliased) // Return the named assigned to this result column (potentially aliased)
const char* Column::getName() const noexcept // nothrow const char* Column::getName() const noexcept // nothrow
{ {
return sqlite3_column_name(mStmtPtr, mIndex); return sqlite3_column_name(mStmtPtr, mIndex);
} }
#ifdef SQLITE_ENABLE_COLUMN_METADATA #ifdef SQLITE_ENABLE_COLUMN_METADATA
// Return the name of the table column that is the origin of this result column // Return the name of the table column that is the origin of this result column
const char* Column::getOriginName() const noexcept // nothrow const char* Column::getOriginName() const noexcept // nothrow
@ -51,74 +43,61 @@ const char* Column::getOriginName() const noexcept // nothrow
return sqlite3_column_origin_name(mStmtPtr, mIndex); return sqlite3_column_origin_name(mStmtPtr, mIndex);
} }
#endif #endif
// Return the integer value of the column specified by its index starting at 0 // Return the integer value of the column specified by its index starting at 0
int Column::getInt() const noexcept // nothrow int Column::getInt() const noexcept // nothrow
{ {
return sqlite3_column_int(mStmtPtr, mIndex); return sqlite3_column_int(mStmtPtr, mIndex);
} }
// Return the unsigned integer value of the column specified by its index starting at 0 // Return the unsigned integer value of the column specified by its index starting at 0
unsigned Column::getUInt() const noexcept // nothrow unsigned Column::getUInt() const noexcept // nothrow
{ {
return static_cast<unsigned>(getInt64()); return static_cast<unsigned>(getInt64());
} }
// Return the 64bits integer value of the column specified by its index starting at 0 // Return the 64bits integer value of the column specified by its index starting at 0
long long Column::getInt64() const noexcept // nothrow long long Column::getInt64() const noexcept // nothrow
{ {
return sqlite3_column_int64(mStmtPtr, mIndex); return sqlite3_column_int64(mStmtPtr, mIndex);
} }
// Return the double value of the column specified by its index starting at 0 // Return the double value of the column specified by its index starting at 0
double Column::getDouble() const noexcept // nothrow double Column::getDouble() const noexcept // nothrow
{ {
return sqlite3_column_double(mStmtPtr, mIndex); return sqlite3_column_double(mStmtPtr, mIndex);
} }
// Return a pointer to the text value (NULL terminated string) of the column specified by its index starting at 0 // Return a pointer to the text value (NULL terminated string) of the column specified by its index starting at 0
const char* Column::getText(const char* apDefaultValue /* = "" */) const noexcept // nothrow const char* Column::getText(const char* apDefaultValue /* = "" */) const noexcept // nothrow
{ {
const char* pText = reinterpret_cast<const char*>(sqlite3_column_text(mStmtPtr, mIndex)); const char* pText = reinterpret_cast<const char*>(sqlite3_column_text(mStmtPtr, mIndex));
return (pText?pText:apDefaultValue); return (pText ? pText : apDefaultValue);
} }
// Return a pointer to the blob value (*not* NULL terminated) of the column specified by its index starting at 0 // Return a pointer to the blob value (*not* NULL terminated) of the column specified by its index starting at 0
const void* Column::getBlob() const noexcept // nothrow const void* Column::getBlob() const noexcept // nothrow
{ {
return sqlite3_column_blob(mStmtPtr, mIndex); return sqlite3_column_blob(mStmtPtr, mIndex);
} }
// Return a std::string to a TEXT or BLOB column // Return a std::string to a TEXT or BLOB column
std::string Column::getString() const std::string Column::getString() const
{ {
// Note: using sqlite3_column_blob and not sqlite3_column_text // Note: using sqlite3_column_blob and not sqlite3_column_text
// - no need for sqlite3_column_text to add a \0 on the end, as we're getting the bytes length directly // - no need for sqlite3_column_text to add a \0 on the end, as we're getting the bytes length directly
const char *data = static_cast<const char *>(sqlite3_column_blob(mStmtPtr, mIndex)); const char* data = static_cast<const char*>(sqlite3_column_blob(mStmtPtr, mIndex));
// SQLite docs: "The safest policy is to invoke… sqlite3_column_blob() followed by sqlite3_column_bytes()" // SQLite docs: "The safest policy is to invoke… sqlite3_column_blob() followed by sqlite3_column_bytes()"
// Note: std::string is ok to pass nullptr as first arg, if length is 0 // Note: std::string is ok to pass nullptr as first arg, if length is 0
return std::string(data, sqlite3_column_bytes(mStmtPtr, mIndex)); return std::string(data, sqlite3_column_bytes(mStmtPtr, mIndex));
} }
// Return the type of the value of the column // Return the type of the value of the column
int Column::getType() const noexcept // nothrow int Column::getType() const noexcept // nothrow
{ {
return sqlite3_column_type(mStmtPtr, mIndex); return sqlite3_column_type(mStmtPtr, mIndex);
} }
// Return the number of bytes used by the text value of the column // Return the number of bytes used by the text value of the column
int Column::getBytes() const noexcept // nothrow int Column::getBytes() const noexcept // nothrow
{ {
return sqlite3_column_bytes(mStmtPtr, mIndex); return sqlite3_column_bytes(mStmtPtr, mIndex);
} }
// Standard std::ostream inserter // Standard std::ostream inserter
std::ostream& operator<<(std::ostream& aStream, const Column& aColumn) std::ostream& operator<<(std::ostream& aStream, const Column& aColumn)
{ {
aStream.write(aColumn.getText(), aColumn.getBytes()); aStream.write(aColumn.getText(), aColumn.getBytes());
return aStream; return aStream;
} }
} // namespace SQLite
} // namespace SQLite

View File

@ -9,52 +9,42 @@
* or copy at http://opensource.org/licenses/MIT) * or copy at http://opensource.org/licenses/MIT)
*/ */
#include <SQLiteCpp/Database.h> #include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Statement.h> #include <SQLiteCpp/Statement.h>
#include <SQLiteCpp/Assertion.h> #include <SQLiteCpp/Assertion.h>
#include <SQLiteCpp/Exception.h> #include <SQLiteCpp/Exception.h>
#include <sqlite3.h> #include <sqlite3.h>
#include <fstream> #include <fstream>
#include <string.h> #include <string.h>
#ifndef SQLITE_DETERMINISTIC #ifndef SQLITE_DETERMINISTIC
#define SQLITE_DETERMINISTIC 0x800 #define SQLITE_DETERMINISTIC 0x800
#endif // SQLITE_DETERMINISTIC #endif // SQLITE_DETERMINISTIC
namespace SQLite namespace SQLite
{ {
const int OPEN_READONLY = SQLITE_OPEN_READONLY;
const int OPEN_READONLY = SQLITE_OPEN_READONLY; const int OPEN_READWRITE = SQLITE_OPEN_READWRITE;
const int OPEN_READWRITE = SQLITE_OPEN_READWRITE; const int OPEN_CREATE = SQLITE_OPEN_CREATE;
const int OPEN_CREATE = SQLITE_OPEN_CREATE; const int OPEN_URI = SQLITE_OPEN_URI;
const int OPEN_URI = SQLITE_OPEN_URI; const int OK = SQLITE_OK;
const char* VERSION = SQLITE_VERSION;
const int OK = SQLITE_OK; const int VERSION_NUMBER = SQLITE_VERSION_NUMBER;
const char* VERSION = SQLITE_VERSION;
const int VERSION_NUMBER = SQLITE_VERSION_NUMBER;
// Return SQLite version string using runtime call to the compiled library // Return SQLite version string using runtime call to the compiled library
const char* getLibVersion() noexcept // nothrow const char* getLibVersion() noexcept // nothrow
{ {
return sqlite3_libversion(); return sqlite3_libversion();
} }
// Return SQLite version number using runtime call to the compiled library // Return SQLite version number using runtime call to the compiled library
int getLibVersionNumber() noexcept // nothrow int getLibVersionNumber() noexcept // nothrow
{ {
return sqlite3_libversion_number(); return sqlite3_libversion_number();
} }
// Open the provided database UTF-8 filename with SQLite::OPEN_xxx provided flags. // Open the provided database UTF-8 filename with SQLite::OPEN_xxx provided flags.
Database::Database(const char* apFilename, Database::Database(const char* apFilename,
const int aFlags /* = SQLite::OPEN_READONLY*/, const int aFlags /* = SQLite::OPEN_READONLY*/,
const int aBusyTimeoutMs /* = 0 */, const int aBusyTimeoutMs /* = 0 */,
const char* apVfs /* = nullptr*/) : const char* apVfs /* = nullptr*/)
mpSQLite(nullptr), :
mpSQLite(nullptr)
,
mFilename(apFilename) mFilename(apFilename)
{ {
const int ret = sqlite3_open_v2(apFilename, &mpSQLite, aFlags, apVfs); const int ret = sqlite3_open_v2(apFilename, &mpSQLite, aFlags, apVfs);
@ -69,13 +59,14 @@ Database::Database(const char* apFilename,
setBusyTimeout(aBusyTimeoutMs); setBusyTimeout(aBusyTimeoutMs);
} }
} }
// Open the provided database UTF-8 filename with SQLite::OPEN_xxx provided flags. // Open the provided database UTF-8 filename with SQLite::OPEN_xxx provided flags.
Database::Database(const std::string& aFilename, Database::Database(const std::string& aFilename,
const int aFlags /* = SQLite::OPEN_READONLY*/, const int aFlags /* = SQLite::OPEN_READONLY*/,
const int aBusyTimeoutMs /* = 0 */, const int aBusyTimeoutMs /* = 0 */,
const std::string& aVfs /* = "" */) : const std::string& aVfs /* = "" */)
mpSQLite(nullptr), :
mpSQLite(nullptr)
,
mFilename(aFilename) mFilename(aFilename)
{ {
const int ret = sqlite3_open_v2(aFilename.c_str(), &mpSQLite, aFlags, aVfs.empty() ? nullptr : aVfs.c_str()); const int ret = sqlite3_open_v2(aFilename.c_str(), &mpSQLite, aFlags, aVfs.empty() ? nullptr : aVfs.c_str());
@ -90,20 +81,16 @@ Database::Database(const std::string& aFilename,
setBusyTimeout(aBusyTimeoutMs); setBusyTimeout(aBusyTimeoutMs);
} }
} }
// Close the SQLite database connection. // Close the SQLite database connection.
Database::~Database() Database::~Database()
{ {
const int ret = sqlite3_close(mpSQLite); const int ret = sqlite3_close(mpSQLite);
// Avoid unreferenced variable warning when build in release mode // Avoid unreferenced variable warning when build in release mode
(void) ret; (void)ret;
// Only case of error is SQLITE_BUSY: "database is locked" (some statements are not finalized) // Only case of error is SQLITE_BUSY: "database is locked" (some statements are not finalized)
// Never throw an exception in a destructor : // Never throw an exception in a destructor :
SQLITECPP_ASSERT(SQLITE_OK == ret, "database is locked"); // See SQLITECPP_ENABLE_ASSERT_HANDLER SQLITECPP_ASSERT(SQLITE_OK == ret, "database is locked"); // See SQLITECPP_ENABLE_ASSERT_HANDLER
} }
/** /**
* @brief Set a busy handler that sleeps for a specified amount of time when a table is locked. * @brief Set a busy handler that sleeps for a specified amount of time when a table is locked.
* *
@ -122,17 +109,14 @@ void Database::setBusyTimeout(const int aBusyTimeoutMs)
const int ret = sqlite3_busy_timeout(mpSQLite, aBusyTimeoutMs); const int ret = sqlite3_busy_timeout(mpSQLite, aBusyTimeoutMs);
check(ret); check(ret);
} }
// Shortcut to execute one or multiple SQL statements without results (UPDATE, INSERT, ALTER, COMMIT, CREATE...). // Shortcut to execute one or multiple SQL statements without results (UPDATE, INSERT, ALTER, COMMIT, CREATE...).
int Database::exec(const char* apQueries) int Database::exec(const char* apQueries)
{ {
const int ret = sqlite3_exec(mpSQLite, apQueries, nullptr, nullptr, nullptr); const int ret = sqlite3_exec(mpSQLite, apQueries, nullptr, nullptr, nullptr);
check(ret); check(ret);
// Return the number of rows modified by those SQL statements (INSERT, UPDATE or DELETE only) // Return the number of rows modified by those SQL statements (INSERT, UPDATE or DELETE only)
return sqlite3_changes(mpSQLite); return sqlite3_changes(mpSQLite);
} }
// Shortcut to execute a one step query and fetch the first column of the result. // Shortcut to execute a one step query and fetch the first column of the result.
// WARNING: Be very careful with this dangerous method: you have to // WARNING: Be very careful with this dangerous method: you have to
// make a COPY OF THE result, else it will be destroy before the next line // make a COPY OF THE result, else it will be destroy before the next line
@ -145,7 +129,6 @@ Column Database::execAndGet(const char* apQuery)
(void)query.executeStep(); // Can return false if no result, which will throw next line in getColumn() (void)query.executeStep(); // Can return false if no result, which will throw next line in getColumn()
return query.getColumn(0); return query.getColumn(0);
} }
// Shortcut to test if a table exists. // Shortcut to test if a table exists.
bool Database::tableExists(const char* apTableName) bool Database::tableExists(const char* apTableName)
{ {
@ -154,68 +137,60 @@ bool Database::tableExists(const char* apTableName)
(void)query.executeStep(); // Cannot return false, as the above query always return a result (void)query.executeStep(); // Cannot return false, as the above query always return a result
return (1 == query.getColumn(0).getInt()); return (1 == query.getColumn(0).getInt());
} }
// Get the rowid of the most recent successful INSERT into the database from the current connection. // Get the rowid of the most recent successful INSERT into the database from the current connection.
long long Database::getLastInsertRowid() const noexcept // nothrow long long Database::getLastInsertRowid() const noexcept // nothrow
{ {
return sqlite3_last_insert_rowid(mpSQLite); return sqlite3_last_insert_rowid(mpSQLite);
} }
// Get total number of rows modified by all INSERT, UPDATE or DELETE statement since connection. // Get total number of rows modified by all INSERT, UPDATE or DELETE statement since connection.
int Database::getTotalChanges() const noexcept // nothrow int Database::getTotalChanges() const noexcept // nothrow
{ {
return sqlite3_total_changes(mpSQLite); return sqlite3_total_changes(mpSQLite);
} }
// Return the numeric result code for the most recent failed API call (if any). // Return the numeric result code for the most recent failed API call (if any).
int Database::getErrorCode() const noexcept // nothrow int Database::getErrorCode() const noexcept // nothrow
{ {
return sqlite3_errcode(mpSQLite); return sqlite3_errcode(mpSQLite);
} }
// Return the extended numeric result code for the most recent failed API call (if any). // Return the extended numeric result code for the most recent failed API call (if any).
int Database::getExtendedErrorCode() const noexcept // nothrow int Database::getExtendedErrorCode() const noexcept // nothrow
{ {
return sqlite3_extended_errcode(mpSQLite); return sqlite3_extended_errcode(mpSQLite);
} }
// Return UTF-8 encoded English language explanation of the most recent failed API call (if any). // Return UTF-8 encoded English language explanation of the most recent failed API call (if any).
const char* Database::getErrorMsg() const noexcept // nothrow const char* Database::getErrorMsg() const noexcept // nothrow
{ {
return sqlite3_errmsg(mpSQLite); return sqlite3_errmsg(mpSQLite);
} }
// Attach a custom function to your sqlite database. Assumes UTF8 text representation. // Attach a custom function to your sqlite database. Assumes UTF8 text representation.
// Parameter details can be found here: http://www.sqlite.org/c3ref/create_function.html // Parameter details can be found here: http://www.sqlite.org/c3ref/create_function.html
void Database::createFunction(const char* apFuncName, void Database::createFunction(const char* apFuncName,
int aNbArg, int aNbArg,
bool abDeterministic, bool abDeterministic,
void* apApp, void* apApp,
void (*apFunc)(sqlite3_context *, int, sqlite3_value **), void (*apFunc)(sqlite3_context*, int, sqlite3_value**),
void (*apStep)(sqlite3_context *, int, sqlite3_value **), void (*apStep)(sqlite3_context*, int, sqlite3_value**),
void (*apFinal)(sqlite3_context *), // NOLINT(readability/casting) void (*apFinal)(sqlite3_context*), // NOLINT(readability/casting)
void (*apDestroy)(void *)) void (*apDestroy)(void*))
{ {
int TextRep = SQLITE_UTF8; int TextRep = SQLITE_UTF8;
// optimization if deterministic function (e.g. of nondeterministic function random()) // optimization if deterministic function (e.g. of nondeterministic function random())
if (abDeterministic) if (abDeterministic)
{ {
TextRep = TextRep|SQLITE_DETERMINISTIC; TextRep = TextRep | SQLITE_DETERMINISTIC;
} }
const int ret = sqlite3_create_function_v2(mpSQLite, apFuncName, aNbArg, TextRep, const int ret = sqlite3_create_function_v2(mpSQLite, apFuncName, aNbArg, TextRep,
apApp, apFunc, apStep, apFinal, apDestroy); apApp, apFunc, apStep, apFinal, apDestroy);
check(ret); check(ret);
} }
// Load an extension into the sqlite database. Only affects the current connection. // Load an extension into the sqlite database. Only affects the current connection.
// Parameter details can be found here: http://www.sqlite.org/c3ref/load_extension.html // Parameter details can be found here: http://www.sqlite.org/c3ref/load_extension.html
void Database::loadExtension(const char* apExtensionName, const char *apEntryPointName) void Database::loadExtension(const char* apExtensionName, const char* apEntryPointName)
{ {
#ifdef SQLITE_OMIT_LOAD_EXTENSION #ifdef SQLITE_OMIT_LOAD_EXTENSION
// Unused // Unused
(void)apExtensionName; (void)apExtensionName;
(void)apEntryPointName; (void)apEntryPointName;
throw std::runtime_error("sqlite extensions are disabled"); throw std::runtime_error("sqlite extensions are disabled");
#else #else
#ifdef SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION // Since SQLite 3.13 (2016-05-18): #ifdef SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION // Since SQLite 3.13 (2016-05-18):
@ -229,12 +204,10 @@ void Database::loadExtension(const char* apExtensionName, const char *apEntryPoi
int ret = sqlite3_enable_load_extension(mpSQLite, 1); int ret = sqlite3_enable_load_extension(mpSQLite, 1);
#endif #endif
check(ret); check(ret);
ret = sqlite3_load_extension(mpSQLite, apExtensionName, apEntryPointName, 0); ret = sqlite3_load_extension(mpSQLite, apExtensionName, apEntryPointName, 0);
check(ret); check(ret);
#endif #endif
} }
// Set the key for the current sqlite database instance. // Set the key for the current sqlite database instance.
void Database::key(const std::string& aKey) const void Database::key(const std::string& aKey) const
{ {
@ -253,7 +226,6 @@ void Database::key(const std::string& aKey) const
} }
#endif // SQLITE_HAS_CODEC #endif // SQLITE_HAS_CODEC
} }
// Reset the key for the current sqlite database instance. // Reset the key for the current sqlite database instance.
void Database::rekey(const std::string& aNewKey) const void Database::rekey(const std::string& aNewKey) const
{ {
@ -275,7 +247,6 @@ void Database::rekey(const std::string& aNewKey) const
throw exception; throw exception;
#endif // SQLITE_HAS_CODEC #endif // SQLITE_HAS_CODEC
} }
// Test if a file contains an unencrypted database. // Test if a file contains an unencrypted database.
bool Database::isUnencrypted(const std::string& aFilename) bool Database::isUnencrypted(const std::string& aFilename)
{ {
@ -299,5 +270,4 @@ bool Database::isUnencrypted(const std::string& aFilename)
const SQLite::Exception exception("Could not open database, the aFilename parameter was empty."); const SQLite::Exception exception("Could not open database, the aFilename parameter was empty.");
throw exception; throw exception;
} }
} // namespace SQLite
} // namespace SQLite

View File

@ -9,59 +9,66 @@
* or copy at http://opensource.org/licenses/MIT) * or copy at http://opensource.org/licenses/MIT)
*/ */
#include <SQLiteCpp/Exception.h> #include <SQLiteCpp/Exception.h>
#include <sqlite3.h> #include <sqlite3.h>
namespace SQLite namespace SQLite
{ {
Exception::Exception(const char* aErrorMessage)
Exception::Exception(const char* aErrorMessage) : :
std::runtime_error(aErrorMessage), std::runtime_error(aErrorMessage)
mErrcode(-1), // 0 would be SQLITE_OK, which doesn't make sense ,
mErrcode(-1)
, // 0 would be SQLITE_OK, which doesn't make sense
mExtendedErrcode(-1) mExtendedErrcode(-1)
{ {
} }
Exception::Exception(const std::string& aErrorMessage) : Exception::Exception(const std::string& aErrorMessage)
std::runtime_error(aErrorMessage), :
mErrcode(-1), // 0 would be SQLITE_OK, which doesn't make sense std::runtime_error(aErrorMessage)
,
mErrcode(-1)
, // 0 would be SQLITE_OK, which doesn't make sense
mExtendedErrcode(-1) mExtendedErrcode(-1)
{ {
} }
Exception::Exception(const char* aErrorMessage, int ret)
Exception::Exception(const char* aErrorMessage, int ret) : :
std::runtime_error(aErrorMessage), std::runtime_error(aErrorMessage)
mErrcode(ret), ,
mErrcode(ret)
,
mExtendedErrcode(-1) mExtendedErrcode(-1)
{ {
} }
Exception::Exception(const std::string& aErrorMessage, int ret)
Exception::Exception(const std::string& aErrorMessage, int ret) : :
std::runtime_error(aErrorMessage), std::runtime_error(aErrorMessage)
mErrcode(ret), ,
mErrcode(ret)
,
mExtendedErrcode(-1) mExtendedErrcode(-1)
{ {
} }
Exception::Exception(sqlite3* apSQLite)
Exception::Exception(sqlite3* apSQLite) : :
std::runtime_error(sqlite3_errmsg(apSQLite)), std::runtime_error(sqlite3_errmsg(apSQLite))
mErrcode(sqlite3_errcode(apSQLite)), ,
mErrcode(sqlite3_errcode(apSQLite))
,
mExtendedErrcode(sqlite3_extended_errcode(apSQLite)) mExtendedErrcode(sqlite3_extended_errcode(apSQLite))
{ {
} }
Exception::Exception(sqlite3* apSQLite, int ret)
Exception::Exception(sqlite3* apSQLite, int ret) : :
std::runtime_error(sqlite3_errmsg(apSQLite)), std::runtime_error(sqlite3_errmsg(apSQLite))
mErrcode(ret), ,
mErrcode(ret)
,
mExtendedErrcode(sqlite3_extended_errcode(apSQLite)) mExtendedErrcode(sqlite3_extended_errcode(apSQLite))
{ {
} }
// Return a string, solely based on the error code // Return a string, solely based on the error code
const char* Exception::getErrorStr() const noexcept // nothrow const char* Exception::getErrorStr() const noexcept // nothrow
{ {
return sqlite3_errstr(mErrcode); return sqlite3_errstr(mErrcode);
} }
} // namespace SQLite
} // namespace SQLite

View File

@ -9,45 +9,54 @@
* or copy at http://opensource.org/licenses/MIT) * or copy at http://opensource.org/licenses/MIT)
*/ */
#include <SQLiteCpp/Statement.h> #include <SQLiteCpp/Statement.h>
#include <SQLiteCpp/Database.h> #include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Column.h> #include <SQLiteCpp/Column.h>
#include <SQLiteCpp/Assertion.h> #include <SQLiteCpp/Assertion.h>
#include <SQLiteCpp/Exception.h> #include <SQLiteCpp/Exception.h>
#include <sqlite3.h> #include <sqlite3.h>
namespace SQLite namespace SQLite
{ {
// Compile and register the SQL query for the provided SQLite Database Connection // Compile and register the SQL query for the provided SQLite Database Connection
Statement::Statement(Database &aDatabase, const char* apQuery) : Statement::Statement(Database& aDatabase, const char* apQuery)
mQuery(apQuery), :
mStmtPtr(aDatabase.mpSQLite, mQuery), // prepare the SQL query, and ref count (needs Database friendship) mQuery(apQuery)
mColumnCount(0), ,
mbHasRow(false), mStmtPtr(aDatabase.mpSQLite, mQuery)
, // prepare the SQL query, and ref count (needs Database friendship)
mColumnCount(0)
,
mbHasRow(false)
,
mbDone(false) mbDone(false)
{ {
mColumnCount = sqlite3_column_count(mStmtPtr); mColumnCount = sqlite3_column_count(mStmtPtr);
} }
// Compile and register the SQL query for the provided SQLite Database Connection // Compile and register the SQL query for the provided SQLite Database Connection
Statement::Statement(Database &aDatabase, const std::string& aQuery) : Statement::Statement(Database& aDatabase, const std::string& aQuery)
mQuery(aQuery), :
mStmtPtr(aDatabase.mpSQLite, mQuery), // prepare the SQL query, and ref count (needs Database friendship) mQuery(aQuery)
mColumnCount(0), ,
mbHasRow(false), mStmtPtr(aDatabase.mpSQLite, mQuery)
, // prepare the SQL query, and ref count (needs Database friendship)
mColumnCount(0)
,
mbHasRow(false)
,
mbDone(false) mbDone(false)
{ {
mColumnCount = sqlite3_column_count(mStmtPtr); mColumnCount = sqlite3_column_count(mStmtPtr);
} }
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600) #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600)
Statement::Statement(Statement&& aStatement) noexcept : Statement::Statement(Statement&& aStatement) noexcept
mQuery(std::move(aStatement.mQuery)), :
mStmtPtr(std::move(aStatement.mStmtPtr)), mQuery(std::move(aStatement.mQuery))
mColumnCount(aStatement.mColumnCount), ,
mbHasRow(aStatement.mbHasRow), mStmtPtr(std::move(aStatement.mStmtPtr))
,
mColumnCount(aStatement.mColumnCount)
,
mbHasRow(aStatement.mbHasRow)
,
mbDone(aStatement.mbDone) mbDone(aStatement.mbDone)
{ {
aStatement.mColumnCount = 0; aStatement.mColumnCount = 0;
@ -55,114 +64,97 @@ Statement::Statement(Statement&& aStatement) noexcept :
aStatement.mbDone = false; aStatement.mbDone = false;
} }
#endif #endif
// Finalize and unregister the SQL query from the SQLite Database Connection. // Finalize and unregister the SQL query from the SQLite Database Connection.
Statement::~Statement() Statement::~Statement()
{ {
// the finalization will be done by the destructor of the last shared pointer // the finalization will be done by the destructor of the last shared pointer
} }
// Reset the statement to make it ready for a new execution (see also #clearBindings() bellow) // Reset the statement to make it ready for a new execution (see also #clearBindings() bellow)
void Statement::reset() void Statement::reset()
{ {
const int ret = tryReset(); const int ret = tryReset();
check(ret); check(ret);
} }
int Statement::tryReset() noexcept int Statement::tryReset() noexcept
{ {
mbHasRow = false; mbHasRow = false;
mbDone = false; mbDone = false;
return sqlite3_reset(mStmtPtr); return sqlite3_reset(mStmtPtr);
} }
// Clears away all the bindings of a prepared statement (can be associated with #reset() above). // Clears away all the bindings of a prepared statement (can be associated with #reset() above).
void Statement::clearBindings() void Statement::clearBindings()
{ {
const int ret = sqlite3_clear_bindings(mStmtPtr); const int ret = sqlite3_clear_bindings(mStmtPtr);
check(ret); check(ret);
} }
// Bind an int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind an int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const int aValue) void Statement::bind(const int aIndex, const int aValue)
{ {
const int ret = sqlite3_bind_int(mStmtPtr, aIndex, aValue); const int ret = sqlite3_bind_int(mStmtPtr, aIndex, aValue);
check(ret); check(ret);
} }
// Bind a 32bits unsigned int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a 32bits unsigned int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const unsigned aValue) void Statement::bind(const int aIndex, const unsigned aValue)
{ {
const int ret = sqlite3_bind_int64(mStmtPtr, aIndex, aValue); const int ret = sqlite3_bind_int64(mStmtPtr, aIndex, aValue);
check(ret); check(ret);
} }
// Bind a 64bits int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a 64bits int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const long long aValue) void Statement::bind(const int aIndex, const long long aValue)
{ {
const int ret = sqlite3_bind_int64(mStmtPtr, aIndex, aValue); const int ret = sqlite3_bind_int64(mStmtPtr, aIndex, aValue);
check(ret); check(ret);
} }
// Bind a double (64bits float) value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a double (64bits float) value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const double aValue) void Statement::bind(const int aIndex, const double aValue)
{ {
const int ret = sqlite3_bind_double(mStmtPtr, aIndex, aValue); const int ret = sqlite3_bind_double(mStmtPtr, aIndex, aValue);
check(ret); check(ret);
} }
// Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const std::string& aValue) void Statement::bind(const int aIndex, const std::string& aValue)
{ {
const int ret = sqlite3_bind_text(mStmtPtr, aIndex, aValue.c_str(), const int ret = sqlite3_bind_text(mStmtPtr, aIndex, aValue.c_str(),
static_cast<int>(aValue.size()), SQLITE_TRANSIENT); static_cast<int>(aValue.size()), SQLITE_TRANSIENT);
check(ret); check(ret);
} }
// Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const char* apValue) void Statement::bind(const int aIndex, const char* apValue)
{ {
const int ret = sqlite3_bind_text(mStmtPtr, aIndex, apValue, -1, SQLITE_TRANSIENT); const int ret = sqlite3_bind_text(mStmtPtr, aIndex, apValue, -1, SQLITE_TRANSIENT);
check(ret); check(ret);
} }
// Bind a binary blob value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a binary blob value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const void* apValue, const int aSize) void Statement::bind(const int aIndex, const void* apValue, const int aSize)
{ {
const int ret = sqlite3_bind_blob(mStmtPtr, aIndex, apValue, aSize, SQLITE_TRANSIENT); const int ret = sqlite3_bind_blob(mStmtPtr, aIndex, apValue, aSize, SQLITE_TRANSIENT);
check(ret); check(ret);
} }
// Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bindNoCopy(const int aIndex, const std::string& aValue) void Statement::bindNoCopy(const int aIndex, const std::string& aValue)
{ {
const int ret = sqlite3_bind_text(mStmtPtr, aIndex, aValue.c_str(), const int ret = sqlite3_bind_text(mStmtPtr, aIndex, aValue.c_str(),
static_cast<int>(aValue.size()), SQLITE_STATIC); static_cast<int>(aValue.size()), SQLITE_STATIC);
check(ret); check(ret);
} }
// Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bindNoCopy(const int aIndex, const char* apValue) void Statement::bindNoCopy(const int aIndex, const char* apValue)
{ {
const int ret = sqlite3_bind_text(mStmtPtr, aIndex, apValue, -1, SQLITE_STATIC); const int ret = sqlite3_bind_text(mStmtPtr, aIndex, apValue, -1, SQLITE_STATIC);
check(ret); check(ret);
} }
// Bind a binary blob value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a binary blob value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bindNoCopy(const int aIndex, const void* apValue, const int aSize) void Statement::bindNoCopy(const int aIndex, const void* apValue, const int aSize)
{ {
const int ret = sqlite3_bind_blob(mStmtPtr, aIndex, apValue, aSize, SQLITE_STATIC); const int ret = sqlite3_bind_blob(mStmtPtr, aIndex, apValue, aSize, SQLITE_STATIC);
check(ret); check(ret);
} }
// Bind a NULL value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a NULL value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex) void Statement::bind(const int aIndex)
{ {
const int ret = sqlite3_bind_null(mStmtPtr, aIndex); const int ret = sqlite3_bind_null(mStmtPtr, aIndex);
check(ret); check(ret);
} }
// Bind an int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind an int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName, const int aValue) void Statement::bind(const char* apName, const int aValue)
{ {
@ -170,7 +162,6 @@ void Statement::bind(const char* apName, const int aValue)
const int ret = sqlite3_bind_int(mStmtPtr, index, aValue); const int ret = sqlite3_bind_int(mStmtPtr, index, aValue);
check(ret); check(ret);
} }
// Bind a 32bits unsigned int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a 32bits unsigned int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName, const unsigned aValue) void Statement::bind(const char* apName, const unsigned aValue)
{ {
@ -178,7 +169,6 @@ void Statement::bind(const char* apName, const unsigned aValue)
const int ret = sqlite3_bind_int64(mStmtPtr, index, aValue); const int ret = sqlite3_bind_int64(mStmtPtr, index, aValue);
check(ret); check(ret);
} }
// Bind a 64bits int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a 64bits int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName, const long long aValue) void Statement::bind(const char* apName, const long long aValue)
{ {
@ -186,7 +176,6 @@ void Statement::bind(const char* apName, const long long aValue)
const int ret = sqlite3_bind_int64(mStmtPtr, index, aValue); const int ret = sqlite3_bind_int64(mStmtPtr, index, aValue);
check(ret); check(ret);
} }
// Bind a double (64bits float) value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a double (64bits float) value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName, const double aValue) void Statement::bind(const char* apName, const double aValue)
{ {
@ -194,16 +183,14 @@ void Statement::bind(const char* apName, const double aValue)
const int ret = sqlite3_bind_double(mStmtPtr, index, aValue); const int ret = sqlite3_bind_double(mStmtPtr, index, aValue);
check(ret); check(ret);
} }
// Bind a string value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a string value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName, const std::string& aValue) void Statement::bind(const char* apName, const std::string& aValue)
{ {
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName); const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
const int ret = sqlite3_bind_text(mStmtPtr, index, aValue.c_str(), const int ret = sqlite3_bind_text(mStmtPtr, index, aValue.c_str(),
static_cast<int>(aValue.size()), SQLITE_TRANSIENT); static_cast<int>(aValue.size()), SQLITE_TRANSIENT);
check(ret); check(ret);
} }
// Bind a text value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a text value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName, const char* apValue) void Statement::bind(const char* apName, const char* apValue)
{ {
@ -211,7 +198,6 @@ void Statement::bind(const char* apName, const char* apValue)
const int ret = sqlite3_bind_text(mStmtPtr, index, apValue, -1, SQLITE_TRANSIENT); const int ret = sqlite3_bind_text(mStmtPtr, index, apValue, -1, SQLITE_TRANSIENT);
check(ret); check(ret);
} }
// Bind a binary blob value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a binary blob value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName, const void* apValue, const int aSize) void Statement::bind(const char* apName, const void* apValue, const int aSize)
{ {
@ -219,16 +205,14 @@ void Statement::bind(const char* apName, const void* apValue, const int aSize)
const int ret = sqlite3_bind_blob(mStmtPtr, index, apValue, aSize, SQLITE_TRANSIENT); const int ret = sqlite3_bind_blob(mStmtPtr, index, apValue, aSize, SQLITE_TRANSIENT);
check(ret); check(ret);
} }
// Bind a string value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a string value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bindNoCopy(const char* apName, const std::string& aValue) void Statement::bindNoCopy(const char* apName, const std::string& aValue)
{ {
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName); const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
const int ret = sqlite3_bind_text(mStmtPtr, index, aValue.c_str(), const int ret = sqlite3_bind_text(mStmtPtr, index, aValue.c_str(),
static_cast<int>(aValue.size()), SQLITE_STATIC); static_cast<int>(aValue.size()), SQLITE_STATIC);
check(ret); check(ret);
} }
// Bind a text value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a text value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bindNoCopy(const char* apName, const char* apValue) void Statement::bindNoCopy(const char* apName, const char* apValue)
{ {
@ -236,7 +220,6 @@ void Statement::bindNoCopy(const char* apName, const char* apValue)
const int ret = sqlite3_bind_text(mStmtPtr, index, apValue, -1, SQLITE_STATIC); const int ret = sqlite3_bind_text(mStmtPtr, index, apValue, -1, SQLITE_STATIC);
check(ret); check(ret);
} }
// Bind a binary blob value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a binary blob value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bindNoCopy(const char* apName, const void* apValue, const int aSize) void Statement::bindNoCopy(const char* apName, const void* apValue, const int aSize)
{ {
@ -244,7 +227,6 @@ void Statement::bindNoCopy(const char* apName, const void* apValue, const int aS
const int ret = sqlite3_bind_blob(mStmtPtr, index, apValue, aSize, SQLITE_STATIC); const int ret = sqlite3_bind_blob(mStmtPtr, index, apValue, aSize, SQLITE_STATIC);
check(ret); check(ret);
} }
// Bind a NULL value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement // Bind a NULL value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName) void Statement::bind(const char* apName)
{ {
@ -252,8 +234,6 @@ void Statement::bind(const char* apName)
const int ret = sqlite3_bind_null(mStmtPtr, index); const int ret = sqlite3_bind_null(mStmtPtr, index);
check(ret); check(ret);
} }
// Execute a step of the query to fetch one row of results // Execute a step of the query to fetch one row of results
bool Statement::executeStep() bool Statement::executeStep()
{ {
@ -269,10 +249,8 @@ bool Statement::executeStep()
throw SQLite::Exception("Statement needs to be reseted", ret); throw SQLite::Exception("Statement needs to be reseted", ret);
} }
} }
return mbHasRow; // true only if one row is accessible by getColumn(N) return mbHasRow; // true only if one row is accessible by getColumn(N)
} }
// Execute a one-step query with no expected result // Execute a one-step query with no expected result
int Statement::exec() int Statement::exec()
{ {
@ -292,11 +270,9 @@ int Statement::exec()
throw SQLite::Exception("Statement needs to be reseted", ret); throw SQLite::Exception("Statement needs to be reseted", ret);
} }
} }
// Return the number of rows modified by those SQL statements (INSERT, UPDATE or DELETE) // Return the number of rows modified by those SQL statements (INSERT, UPDATE or DELETE)
return sqlite3_changes(mStmtPtr); return sqlite3_changes(mStmtPtr);
} }
int Statement::tryExecuteStep() noexcept int Statement::tryExecuteStep() noexcept
{ {
if (false == mbDone) if (false == mbDone)
@ -316,7 +292,6 @@ int Statement::tryExecuteStep() noexcept
mbHasRow = false; mbHasRow = false;
mbDone = false; mbDone = false;
} }
return ret; return ret;
} }
else else
@ -325,30 +300,24 @@ int Statement::tryExecuteStep() noexcept
return SQLITE_MISUSE; return SQLITE_MISUSE;
} }
} }
// Return a copy of the column data specified by its index starting at 0 // Return a copy of the column data specified by its index starting at 0
// (use the Column copy-constructor) // (use the Column copy-constructor)
Column Statement::getColumn(const int aIndex) Column Statement::getColumn(const int aIndex)
{ {
checkRow(); checkRow();
checkIndex(aIndex); checkIndex(aIndex);
// Share the Statement Object handle with the new Column created // Share the Statement Object handle with the new Column created
return Column(mStmtPtr, aIndex); return Column(mStmtPtr, aIndex);
} }
// Return a copy of the column data specified by its column name starting at 0 // Return a copy of the column data specified by its column name starting at 0
// (use the Column copy-constructor) // (use the Column copy-constructor)
Column Statement::getColumn(const char* apName) Column Statement::getColumn(const char* apName)
{ {
checkRow(); checkRow();
const int index = getColumnIndex(apName); const int index = getColumnIndex(apName);
// Share the Statement Object handle with the new Column created // Share the Statement Object handle with the new Column created
return Column(mStmtPtr, index); return Column(mStmtPtr, index);
} }
// Test if the column is NULL // Test if the column is NULL
bool Statement::isColumnNull(const int aIndex) const bool Statement::isColumnNull(const int aIndex) const
{ {
@ -356,21 +325,18 @@ bool Statement::isColumnNull(const int aIndex) const
checkIndex(aIndex); checkIndex(aIndex);
return (SQLITE_NULL == sqlite3_column_type(mStmtPtr, aIndex)); return (SQLITE_NULL == sqlite3_column_type(mStmtPtr, aIndex));
} }
bool Statement::isColumnNull(const char* apName) const bool Statement::isColumnNull(const char* apName) const
{ {
checkRow(); checkRow();
const int index = getColumnIndex(apName); const int index = getColumnIndex(apName);
return (SQLITE_NULL == sqlite3_column_type(mStmtPtr, index)); return (SQLITE_NULL == sqlite3_column_type(mStmtPtr, index));
} }
// Return the named assigned to the specified result column (potentially aliased) // Return the named assigned to the specified result column (potentially aliased)
const char* Statement::getColumnName(const int aIndex) const const char* Statement::getColumnName(const int aIndex) const
{ {
checkIndex(aIndex); checkIndex(aIndex);
return sqlite3_column_name(mStmtPtr, aIndex); return sqlite3_column_name(mStmtPtr, aIndex);
} }
#ifdef SQLITE_ENABLE_COLUMN_METADATA #ifdef SQLITE_ENABLE_COLUMN_METADATA
// Return the named assigned to the specified result column (potentially aliased) // Return the named assigned to the specified result column (potentially aliased)
const char* Statement::getColumnOriginName(const int aIndex) const const char* Statement::getColumnOriginName(const int aIndex) const
@ -379,7 +345,6 @@ const char* Statement::getColumnOriginName(const int aIndex) const
return sqlite3_column_origin_name(mStmtPtr, aIndex); return sqlite3_column_origin_name(mStmtPtr, aIndex);
} }
#endif #endif
// Return the index of the specified (potentially aliased) column name // Return the index of the specified (potentially aliased) column name
int Statement::getColumnIndex(const char* apName) const int Statement::getColumnIndex(const char* apName) const
{ {
@ -392,60 +357,55 @@ int Statement::getColumnIndex(const char* apName) const
mColumnNames[pName] = i; mColumnNames[pName] = i;
} }
} }
const TColumnNames::const_iterator iIndex = mColumnNames.find(apName); const TColumnNames::const_iterator iIndex = mColumnNames.find(apName);
if (iIndex == mColumnNames.end()) if (iIndex == mColumnNames.end())
{ {
throw SQLite::Exception("Unknown column name."); throw SQLite::Exception("Unknown column name.");
} }
return (*iIndex).second; return (*iIndex).second;
} }
int Statement::getBindParameterCount() const noexcept int Statement::getBindParameterCount() const noexcept
{ {
return sqlite3_bind_parameter_count(mStmtPtr); return sqlite3_bind_parameter_count(mStmtPtr);
} }
// Return the numeric result code for the most recent failed API call (if any). // Return the numeric result code for the most recent failed API call (if any).
int Statement::getErrorCode() const noexcept // nothrow int Statement::getErrorCode() const noexcept // nothrow
{ {
return sqlite3_errcode(mStmtPtr); return sqlite3_errcode(mStmtPtr);
} }
// Return the extended numeric result code for the most recent failed API call (if any). // Return the extended numeric result code for the most recent failed API call (if any).
int Statement::getExtendedErrorCode() const noexcept // nothrow int Statement::getExtendedErrorCode() const noexcept // nothrow
{ {
return sqlite3_extended_errcode(mStmtPtr); return sqlite3_extended_errcode(mStmtPtr);
} }
// Return UTF-8 encoded English language explanation of the most recent failed API call (if any). // Return UTF-8 encoded English language explanation of the most recent failed API call (if any).
const char* Statement::getErrorMsg() const noexcept // nothrow const char* Statement::getErrorMsg() const noexcept // nothrow
{ {
return sqlite3_errmsg(mStmtPtr); return sqlite3_errmsg(mStmtPtr);
} }
// Return a UTF-8 string containing the SQL text of prepared statement with bound parameters expanded. // Return a UTF-8 string containing the SQL text of prepared statement with bound parameters expanded.
std::string Statement::getExpandedSQL() { std::string Statement::getExpandedSQL()
{
char* expanded = sqlite3_expanded_sql(mStmtPtr); char* expanded = sqlite3_expanded_sql(mStmtPtr);
std::string expandedString(expanded); std::string expandedString(expanded);
sqlite3_free(expanded); sqlite3_free(expanded);
return expandedString; return expandedString;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Internal class : shared pointer to the sqlite3_stmt SQLite Statement Object // Internal class : shared pointer to the sqlite3_stmt SQLite Statement Object
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/** /**
* @brief Prepare the statement and initialize its reference counter * @brief Prepare the statement and initialize its reference counter
* *
* @param[in] apSQLite The sqlite3 database connexion * @param[in] apSQLite The sqlite3 database connexion
* @param[in] aQuery The SQL query string to prepare * @param[in] aQuery The SQL query string to prepare
*/ */
Statement::Ptr::Ptr(sqlite3* apSQLite, std::string& aQuery) : Statement::Ptr::Ptr(sqlite3* apSQLite, std::string& aQuery)
mpSQLite(apSQLite), :
mpStmt(NULL), mpSQLite(apSQLite)
,
mpStmt(NULL)
,
mpRefCount(NULL) mpRefCount(NULL)
{ {
const int ret = sqlite3_prepare_v2(apSQLite, aQuery.c_str(), static_cast<int>(aQuery.size()), &mpStmt, NULL); const int ret = sqlite3_prepare_v2(apSQLite, aQuery.c_str(), static_cast<int>(aQuery.size()), &mpStmt, NULL);
@ -456,31 +416,34 @@ Statement::Ptr::Ptr(sqlite3* apSQLite, std::string& aQuery) :
// Initialize the reference counter of the sqlite3_stmt : // Initialize the reference counter of the sqlite3_stmt :
// used to share the mStmtPtr between Statement and Column objects; // used to share the mStmtPtr between Statement and Column objects;
// This is needed to enable Column objects to live longer than the Statement objet it refers to. // This is needed to enable Column objects to live longer than the Statement objet it refers to.
mpRefCount = new unsigned int(1); // NOLINT(readability/casting) mpRefCount = new unsigned int(1); // NOLINT(readability/casting)
} }
/** /**
* @brief Copy constructor increments the ref counter * @brief Copy constructor increments the ref counter
* *
* @param[in] aPtr Pointer to copy * @param[in] aPtr Pointer to copy
*/ */
Statement::Ptr::Ptr(const Statement::Ptr& aPtr) : Statement::Ptr::Ptr(const Statement::Ptr& aPtr)
mpSQLite(aPtr.mpSQLite), :
mpStmt(aPtr.mpStmt), mpSQLite(aPtr.mpSQLite)
,
mpStmt(aPtr.mpStmt)
,
mpRefCount(aPtr.mpRefCount) mpRefCount(aPtr.mpRefCount)
{ {
assert(NULL != mpRefCount); assert(NULL != mpRefCount);
assert(0 != *mpRefCount); assert(0 != *mpRefCount);
// Increment the reference counter of the sqlite3_stmt, // Increment the reference counter of the sqlite3_stmt,
// asking not to finalize the sqlite3_stmt during the lifetime of the new objet // asking not to finalize the sqlite3_stmt during the lifetime of the new objet
++(*mpRefCount); ++(*mpRefCount);
} }
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600) #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600)
Statement::Ptr::Ptr(Ptr&& aPtr) : Statement::Ptr::Ptr(Ptr&& aPtr)
mpSQLite(aPtr.mpSQLite), :
mpStmt(aPtr.mpStmt), mpSQLite(aPtr.mpSQLite)
,
mpStmt(aPtr.mpStmt)
,
mpRefCount(aPtr.mpRefCount) mpRefCount(aPtr.mpRefCount)
{ {
aPtr.mpSQLite = NULL; aPtr.mpSQLite = NULL;
@ -488,7 +451,6 @@ Statement::Ptr::Ptr(Ptr&& aPtr) :
aPtr.mpRefCount = NULL; aPtr.mpRefCount = NULL;
} }
#endif #endif
/** /**
* @brief Decrement the ref counter and finalize the sqlite3_stmt when it reaches 0 * @brief Decrement the ref counter and finalize the sqlite3_stmt when it reaches 0
*/ */
@ -497,7 +459,6 @@ Statement::Ptr::~Ptr()
if (NULL != mpRefCount) if (NULL != mpRefCount)
{ {
assert(0 != *mpRefCount); assert(0 != *mpRefCount);
// Decrement and check the reference counter of the sqlite3_stmt // Decrement and check the reference counter of the sqlite3_stmt
--(*mpRefCount); --(*mpRefCount);
if (0 == *mpRefCount) if (0 == *mpRefCount)
@ -505,7 +466,6 @@ Statement::Ptr::~Ptr()
// If count reaches zero, finalize the sqlite3_stmt, as no Statement nor Column objet use it anymore. // If count reaches zero, finalize the sqlite3_stmt, as no Statement nor Column objet use it anymore.
// No need to check the return code, as it is the same as the last statement evaluation. // No need to check the return code, as it is the same as the last statement evaluation.
sqlite3_finalize(mpStmt); sqlite3_finalize(mpStmt);
// and delete the reference counter // and delete the reference counter
delete mpRefCount; delete mpRefCount;
mpRefCount = NULL; mpRefCount = NULL;
@ -514,6 +474,4 @@ Statement::Ptr::~Ptr()
// else, the finalization will be done later, by the last object // else, the finalization will be done later, by the last object
} }
} }
} // namespace SQLite
} // namespace SQLite

View File

@ -9,23 +9,19 @@
* or copy at http://opensource.org/licenses/MIT) * or copy at http://opensource.org/licenses/MIT)
*/ */
#include <SQLiteCpp/Transaction.h> #include <SQLiteCpp/Transaction.h>
#include <SQLiteCpp/Database.h> #include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Assertion.h> #include <SQLiteCpp/Assertion.h>
namespace SQLite namespace SQLite
{ {
// Begins the SQLite transaction // Begins the SQLite transaction
Transaction::Transaction(Database& aDatabase) : Transaction::Transaction(Database& aDatabase)
mDatabase(aDatabase), :
mDatabase(aDatabase)
,
mbCommited(false) mbCommited(false)
{ {
mDatabase.exec("BEGIN"); mDatabase.exec("BEGIN");
} }
// Safely rollback the transaction if it has not been committed. // Safely rollback the transaction if it has not been committed.
Transaction::~Transaction() Transaction::~Transaction()
{ {
@ -41,7 +37,6 @@ Transaction::~Transaction()
} }
} }
} }
// Commit the transaction. // Commit the transaction.
void Transaction::commit() void Transaction::commit()
{ {
@ -55,6 +50,4 @@ void Transaction::commit()
throw SQLite::Exception("Transaction already commited."); throw SQLite::Exception("Transaction already commited.");
} }
} }
} // namespace SQLite
} // namespace SQLite