1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624
|
/**
* @file Database.h
* @ingroup SQLiteCpp
* @brief Management of a SQLite Database Connection.
*
* Copyright (c) 2012-2025 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#pragma once
#include <SQLiteCpp/SQLiteCppExport.h>
#include <SQLiteCpp/Column.h>
// c++17: MinGW GCC version > 8
// c++17: Visual Studio 2017 version 15.7
// c++17: macOS unless targetting compatibility with macOS < 10.15
#ifndef SQLITECPP_HAVE_STD_EXPERIMENTAL_FILESYSTEM
#if __cplusplus >= 201703L
#if defined(__MINGW32__) || defined(__MINGW64__)
#if __GNUC__ > 8 // MinGW requires GCC version > 8 for std::filesystem
#define SQLITECPP_HAVE_STD_FILESYSTEM
#endif
#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
// macOS clang won't let us touch std::filesystem if we're targetting earlier than 10.15
#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && defined(__IPHONE_13_0) && \
__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_13_0
// build for iOS clang won't let us touch std::filesystem if we're targetting earlier than iOS 13
#else
#define SQLITECPP_HAVE_STD_FILESYSTEM
#endif
#elif defined(_MSVC_LANG) && _MSVC_LANG >= 201703L
#define SQLITECPP_HAVE_STD_FILESYSTEM
#endif
// disable the support if the required header is not available
#ifdef __has_include
#if !__has_include(<filesystem>)
#undef SQLITECPP_HAVE_STD_FILESYSTEM
#endif
#if !__has_include(<experimental/filesystem>)
#undef SQLITECPP_HAVE_EXPERIMENTAL_FILESYSTEM
#endif
#endif
// C++17 allow to disable std::filesystem support
#ifdef SQLITECPP_DISABLE_STD_FILESYSTEM
#undef SQLITECPP_HAVE_STD_FILESYSTEM
#undef SQLITECPP_HAVE_STD_EXPERIMENTAL_FILESYSTEM
#endif
#ifdef SQLITECPP_HAVE_STD_FILESYSTEM
#include <filesystem>
#endif // c++17 and a suitable compiler
#else // SQLITECPP_HAVE_STD_EXPERIMENTAL_FILESYSTEM
#define SQLITECPP_HAVE_STD_FILESYSTEM
#include <experimental/filesystem>
namespace std {
namespace filesystem = experimental::filesystem;
}
#endif // SQLITECPP_HAVE_STD_EXPERIMENTAL_FILESYSTEM
#include <memory>
#include <string.h>
// Forward declarations to avoid inclusion of <sqlite3.h> in a header
struct sqlite3;
struct sqlite3_context;
#ifndef SQLITE_USE_LEGACY_STRUCT // Since SQLITE 3.19 (used by default since SQLiteCpp 2.1.0)
typedef struct sqlite3_value sqlite3_value;
#else // Before SQLite 3.19 (legacy struct forward declaration can be activated with CMake SQLITECPP_LEGACY_STRUCT var)
struct Mem;
typedef struct Mem sqlite3_value;
#endif
namespace SQLite
{
// Those public constants enable most usages of SQLiteCpp without including <sqlite3.h> in the client application.
/// The database is opened in read-only mode. If the database does not already exist, an error is returned.
SQLITECPP_API extern const int OPEN_READONLY; // SQLITE_OPEN_READONLY
/// The database is opened for reading and writing if possible, or reading only if the file is write protected
/// by the operating system. In either case the database must already exist, otherwise an error is returned.
SQLITECPP_API extern const int OPEN_READWRITE; // SQLITE_OPEN_READWRITE
/// With OPEN_READWRITE: The database is opened for reading and writing, and is created if it does not already exist.
SQLITECPP_API extern const int OPEN_CREATE; // SQLITE_OPEN_CREATE
/// Enable URI filename interpretation, parsed according to RFC 3986 (ex. "file:data.db?mode=ro&cache=private")
SQLITECPP_API extern const int OPEN_URI; // SQLITE_OPEN_URI
/// Open in memory database
SQLITECPP_API extern const int OPEN_MEMORY; // SQLITE_OPEN_MEMORY
/// Open database in multi-thread threading mode
SQLITECPP_API extern const int OPEN_NOMUTEX; // SQLITE_OPEN_NOMUTEX
/// Open database with thread-safety in serialized threading mode
SQLITECPP_API extern const int OPEN_FULLMUTEX; // SQLITE_OPEN_FULLMUTEX
/// Open database with shared cache enabled
SQLITECPP_API extern const int OPEN_SHAREDCACHE; // SQLITE_OPEN_SHAREDCACHE
/// Open database with shared cache disabled
SQLITECPP_API extern const int OPEN_PRIVATECACHE; // SQLITE_OPEN_PRIVATECACHE
/// Database filename is not allowed to be a symbolic link (Note: only since SQlite 3.31.0 from 2020-01-22)
SQLITECPP_API extern const int OPEN_NOFOLLOW; // SQLITE_OPEN_NOFOLLOW
SQLITECPP_API extern const int OK; ///< SQLITE_OK (used by check() bellow)
SQLITECPP_API extern const char* const VERSION; ///< SQLITE_VERSION string from sqlite3.h used at compile time
SQLITECPP_API extern const int VERSION_NUMBER; ///< SQLITE_VERSION_NUMBER from sqlite3.h used at compile time
/// Return SQLite version string using runtime call to the compiled library
SQLITECPP_API const char* getLibVersion() noexcept;
/// Return SQLite version number using runtime call to the compiled library
SQLITECPP_API int getLibVersionNumber() noexcept;
// Public structure for representing all fields contained within the SQLite header.
// Official documentation for fields: https://www.sqlite.org/fileformat.html#the_database_header
struct Header {
unsigned char headerStr[16];
unsigned int pageSizeBytes;
unsigned char fileFormatWriteVersion;
unsigned char fileFormatReadVersion;
unsigned char reservedSpaceBytes;
unsigned char maxEmbeddedPayloadFrac;
unsigned char minEmbeddedPayloadFrac;
unsigned char leafPayloadFrac;
unsigned long fileChangeCounter;
unsigned long databaseSizePages;
unsigned long firstFreelistTrunkPage;
unsigned long totalFreelistPages;
unsigned long schemaCookie;
unsigned long schemaFormatNumber;
unsigned long defaultPageCacheSizeBytes;
unsigned long largestBTreePageNumber;
unsigned long databaseTextEncoding;
unsigned long userVersion;
unsigned long incrementalVaccumMode;
unsigned long applicationId;
unsigned long versionValidFor;
unsigned long sqliteVersion;
};
/**
* @brief RAII management of a SQLite Database Connection.
*
* A Database object manage a list of all SQLite Statements associated with the
* underlying SQLite 3 database connection.
*
* Resource Acquisition Is Initialization (RAII) means that the Database Connection
* is opened in the constructor and closed in the destructor, so that there is
* no need to worry about memory management or the validity of the underlying SQLite Connection.
*
* Thread-safety: a Database object shall not be shared by multiple threads, because :
* 1) in the SQLite "Thread Safe" mode, "SQLite can be safely used by multiple threads
* provided that no single database connection is used simultaneously in two or more threads."
* 2) the SQLite "Serialized" mode is not supported by SQLiteC++,
* because of the way it shares the underling SQLite precompiled statement
* in a custom shared pointer (See the inner class "Statement::Ptr").
*/
class SQLITECPP_API Database
{
friend class Statement; // Give Statement constructor access to the mSQLitePtr Connection Handle
public:
/**
* @brief Open the provided database UTF-8 filename.
*
* Uses sqlite3_open_v2() with readonly default flag, which is the opposite behavior
* of the old sqlite3_open() function (READWRITE+CREATE).
* This makes sense if you want to use it on a readonly filesystem
* or to prevent creation of a void file when a required file is missing.
*
* Exception is thrown in case of error, then the Database object is NOT constructed.
*
* @param[in] apFilename UTF-8 path/uri to the database file ("filename" sqlite3 parameter)
* @param[in] aFlags SQLite::OPEN_READONLY/SQLite::OPEN_READWRITE/SQLite::OPEN_CREATE...
* @param[in] aBusyTimeoutMs Amount of milliseconds to wait before returning SQLITE_BUSY (see setBusyTimeout())
* @param[in] apVfs UTF-8 name of custom VFS to use, or nullptr for sqlite3 default
*
* @throw SQLite::Exception in case of error
*/
Database(const char* apFilename,
const int aFlags = SQLite::OPEN_READONLY,
const int aBusyTimeoutMs = 0,
const char* apVfs = nullptr);
/**
* @brief Open the provided database UTF-8 filename.
*
* Uses sqlite3_open_v2() with readonly default flag, which is the opposite behavior
* of the old sqlite3_open() function (READWRITE+CREATE).
* This makes sense if you want to use it on a readonly filesystem
* or to prevent creation of a void file when a required file is missing.
*
* Exception is thrown in case of error, then the Database object is NOT constructed.
*
* @param[in] aFilename UTF-8 path/uri to the database file ("filename" sqlite3 parameter)
* @param[in] aFlags SQLite::OPEN_READONLY/SQLite::OPEN_READWRITE/SQLite::OPEN_CREATE...
* @param[in] aBusyTimeoutMs Amount of milliseconds to wait before returning SQLITE_BUSY (see setBusyTimeout())
* @param[in] aVfs UTF-8 name of custom VFS to use, or empty string for sqlite3 default
*
* @throw SQLite::Exception in case of error
*/
Database(const std::string& aFilename,
const int aFlags = SQLite::OPEN_READONLY,
const int aBusyTimeoutMs = 0,
const std::string& aVfs = "") :
Database(aFilename.c_str(), aFlags, aBusyTimeoutMs, aVfs.empty() ? nullptr : aVfs.c_str())
{
}
#ifdef SQLITECPP_HAVE_STD_FILESYSTEM
/**
* @brief Open the provided database std::filesystem::path.
*
* @note This feature requires std=C++17
*
* Uses sqlite3_open_v2() with readonly default flag, which is the opposite behavior
* of the old sqlite3_open() function (READWRITE+CREATE).
* This makes sense if you want to use it on a readonly filesystem
* or to prevent creation of a void file when a required file is missing.
*
* Exception is thrown in case of error, then the Database object is NOT constructed.
*
* @param[in] apFilename Path/uri to the database file ("filename" sqlite3 parameter)
* @param[in] aFlags SQLite::OPEN_READONLY/SQLite::OPEN_READWRITE/SQLite::OPEN_CREATE...
* @param[in] aBusyTimeoutMs Amount of milliseconds to wait before returning SQLITE_BUSY (see setBusyTimeout())
* @param[in] apVfs UTF-8 name of custom VFS to use, or nullptr for sqlite3 default
*
* @throw SQLite::Exception in case of error
*/
Database(const std::filesystem::path& apFilename,
const int aFlags = SQLite::OPEN_READONLY,
const int aBusyTimeoutMs = 0,
const std::string& aVfs = "") :
Database(reinterpret_cast<const char*>(apFilename.u8string().c_str()),
aFlags, aBusyTimeoutMs, aVfs.empty() ? nullptr : aVfs.c_str())
{
}
#endif // have std::filesystem
// Database is non-copyable
Database(const Database&) = delete;
Database& operator=(const Database&) = delete;
// Database is movable
Database(Database&& aDatabase) = default;
Database& operator=(Database&& aDatabase) = default;
/**
* @brief Close the SQLite database connection.
*
* All SQLite statements must have been finalized before,
* so all Statement objects must have been unregistered.
*
* @warning assert in case of error
*/
~Database() = default;
// Deleter functor to use with smart pointers to close the SQLite database connection in an RAII fashion.
struct Deleter
{
SQLITECPP_API void operator()(sqlite3* apSQLite);
};
/**
* @brief Set a busy handler that sleeps for a specified amount of time when a table is locked.
*
* This is useful in multithreaded program to handle case where a table is locked for writing by a thread.
* Any other thread cannot access the table and will receive a SQLITE_BUSY error:
* setting a timeout will wait and retry up to the time specified before returning this SQLITE_BUSY error.
* Reading the value of timeout for current connection can be done with SQL query "PRAGMA busy_timeout;".
* Default busy timeout is 0ms.
*
* @param[in] aBusyTimeoutMs Amount of milliseconds to wait before returning SQLITE_BUSY
*
* @throw SQLite::Exception in case of error
*/
void setBusyTimeout(const int aBusyTimeoutMs);
/**
* @brief Shortcut to execute one or multiple statements without results. Return the number of changes.
*
* This is useful for any kind of statements other than the Data Query Language (DQL) "SELECT" :
* - Data Manipulation Language (DML) statements "INSERT", "UPDATE" and "DELETE"
* - Data Definition Language (DDL) statements "CREATE", "ALTER" and "DROP"
* - Data Control Language (DCL) statements "GRANT", "REVOKE", "COMMIT" and "ROLLBACK"
*
* @see Database::tryExec() to execute, returning the sqlite result code
* @see Statement::exec() to handle precompiled statements (for better performances) without results
* @see Statement::executeStep() to handle "SELECT" queries with results
*
* @param[in] apQueries one or multiple UTF-8 encoded, semicolon-separate SQL statements
*
* @return number of rows modified by the *last* INSERT, UPDATE or DELETE statement (beware of multiple statements)
* @warning undefined for CREATE or DROP table: returns the value of a previous INSERT, UPDATE or DELETE statement.
*
* @throw SQLite::Exception in case of error
*/
int exec(const char* apQueries);
/**
* @brief Shortcut to execute one or multiple statements without results.
*
* This is useful for any kind of statements other than the Data Query Language (DQL) "SELECT" :
* - Data Manipulation Language (DML) statements "INSERT", "UPDATE" and "DELETE"
* - Data Definition Language (DDL) statements "CREATE", "ALTER" and "DROP"
* - Data Control Language (DCL) statements "GRANT", "REVOKE", "COMMIT" and "ROLLBACK"
*
* @see Database::tryExec() to execute, returning the sqlite result code
* @see Statement::exec() to handle precompiled statements (for better performances) without results
* @see Statement::executeStep() to handle "SELECT" queries with results
*
* @param[in] aQueries one or multiple UTF-8 encoded, semicolon-separate SQL statements
*
* @return number of rows modified by the *last* INSERT, UPDATE or DELETE statement (beware of multiple statements)
* @warning undefined for CREATE or DROP table: returns the value of a previous INSERT, UPDATE or DELETE statement.
*
* @throw SQLite::Exception in case of error
*/
int exec(const std::string& aQueries)
{
return exec(aQueries.c_str());
}
/**
* @brief Try to execute one or multiple statements, returning the sqlite result code.
*
* This is useful for any kind of statements other than the Data Query Language (DQL) "SELECT" :
* - Data Manipulation Language (DML) statements "INSERT", "UPDATE" and "DELETE"
* - Data Definition Language (DDL) statements "CREATE", "ALTER" and "DROP"
* - Data Control Language (DCL) statements "GRANT", "REVOKE", "COMMIT" and "ROLLBACK"
*
* @see exec() to execute, returning number of rows modified
*
* @param[in] apQueries one or multiple UTF-8 encoded, semicolon-separate SQL statements
*
* @return the sqlite result code.
*/
int tryExec(const char* apQueries) noexcept;
/**
* @brief Try to execute one or multiple statements, returning the sqlite result code.
*
* This is useful for any kind of statements other than the Data Query Language (DQL) "SELECT" :
* - Data Manipulation Language (DML) statements "INSERT", "UPDATE" and "DELETE"
* - Data Definition Language (DDL) statements "CREATE", "ALTER" and "DROP"
* - Data Control Language (DCL) statements "GRANT", "REVOKE", "COMMIT" and "ROLLBACK"
*
* @see exec() to execute, returning number of rows modified
*
* @param[in] aQueries one or multiple UTF-8 encoded, semicolon-separate SQL statements
*
* @return the sqlite result code.
*/
int tryExec(const std::string& aQueries) noexcept
{
return tryExec(aQueries.c_str());
}
/**
* @brief Shortcut to execute a one step query and fetch the first column of the result.
*
* This is a shortcut to execute a simple statement with a single result.
* This should be used only for non reusable queries (else you should use a Statement with bind()).
* This should be used only for queries with expected results (else an exception is fired).
*
* @warning 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
* (when the underlying temporary Statement and Column objects are destroyed)
*
* @see also Statement class for handling queries with multiple results
*
* @param[in] apQuery an UTF-8 encoded SQL query
*
* @return a temporary Column object with the first column of result.
*
* @throw SQLite::Exception in case of error
*/
Column execAndGet(const char* apQuery);
/**
* @brief Shortcut to execute a one step query and fetch the first column of the result.
*
* This is a shortcut to execute a simple statement with a single result.
* This should be used only for non reusable queries (else you should use a Statement with bind()).
* This should be used only for queries with expected results (else an exception is fired).
*
* @warning 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
* (when the underlying temporary Statement and Column objects are destroyed)
*
* @see also Statement class for handling queries with multiple results
*
* @param[in] aQuery an UTF-8 encoded SQL query
*
* @return a temporary Column object with the first column of result.
*
* @throw SQLite::Exception in case of error
*/
Column execAndGet(const std::string& aQuery)
{
return execAndGet(aQuery.c_str());
}
/**
* @brief Shortcut to test if a table exists.
*
* Table names are case sensitive.
*
* @param[in] apTableName an UTF-8 encoded case sensitive Table name
*
* @return true if the table exists.
*
* @throw SQLite::Exception in case of error
*/
bool tableExists(const char* apTableName) const;
/**
* @brief Shortcut to test if a table exists.
*
* Table names are case sensitive.
*
* @param[in] aTableName an UTF-8 encoded case sensitive Table name
*
* @return true if the table exists.
*
* @throw SQLite::Exception in case of error
*/
bool tableExists(const std::string& aTableName) const
{
return tableExists(aTableName.c_str());
}
/**
* @brief Get the rowid of the most recent successful INSERT into the database from the current connection.
*
* Each entry in an SQLite table always has a unique 64-bit signed integer key called the rowid.
* If the table has a column of type INTEGER PRIMARY KEY, then it is an alias for the rowid.
*
* @return Rowid of the most recent successful INSERT into the database, or 0 if there was none.
*/
int64_t getLastInsertRowid() const noexcept;
/// Get number of rows modified by last INSERT, UPDATE or DELETE statement (not DROP table).
int getChanges() const noexcept;
/// Get total number of rows modified by all INSERT, UPDATE or DELETE statement since connection (not DROP table).
int getTotalChanges() const noexcept;
/// Return the numeric result code for the most recent failed API call (if any).
int getErrorCode() const noexcept;
/// Return the extended numeric result code for the most recent failed API call (if any).
int getExtendedErrorCode() const noexcept;
/// Return UTF-8 encoded English language explanation of the most recent failed API call (if any).
const char* getErrorMsg() const noexcept;
/// Return the filename used to open the database.
const std::string& getFilename() const noexcept
{
return mFilename;
}
/**
* @brief Return raw pointer to SQLite Database Connection Handle.
*
* This is often needed to mix this wrapper with other libraries or for advance usage not supported by SQLiteCpp.
*/
sqlite3* getHandle() const noexcept
{
return mSQLitePtr.get();
}
/**
* @brief Create or redefine a SQL function or aggregate in the sqlite database.
*
* This is the equivalent of the sqlite3_create_function_v2 command.
* @see http://www.sqlite.org/c3ref/create_function.html
*
* @note UTF-8 text encoding assumed.
*
* @param[in] apFuncName Name of the SQL function to be created or redefined
* @param[in] aNbArg Number of arguments in the function
* @param[in] abDeterministic Optimize for deterministic functions (most are). A random number generator is not.
* @param[in] apApp Arbitrary pointer of user data, accessible with sqlite3_user_data().
* @param[in] apFunc Pointer to a C-function to implement a scalar SQL function (apStep & apFinal nullptr)
* @param[in] apStep Pointer to a C-function to implement an aggregate SQL function (apFunc nullptr)
* @param[in] apFinal Pointer to a C-function to implement an aggregate SQL function (apFunc nullptr)
* @param[in] apDestroy If not nullptr, then it is the destructor for the application data pointer.
*
* @throw SQLite::Exception in case of error
*/
void createFunction(const char* apFuncName,
int aNbArg,
bool abDeterministic,
void* apApp,
void (*apFunc)(sqlite3_context *, int, sqlite3_value **),
void (*apStep)(sqlite3_context *, int, sqlite3_value **) = nullptr,
void (*apFinal)(sqlite3_context *) = nullptr, // NOLINT(readability/casting)
void (*apDestroy)(void *) = nullptr);
/**
* @brief Load a module into the current sqlite database instance.
*
* This is the equivalent of the sqlite3_load_extension call, but additionally enables
* module loading support prior to loading the requested module.
*
* @see http://www.sqlite.org/c3ref/load_extension.html
*
* @note UTF-8 text encoding assumed.
*
* @param[in] apExtensionName Name of the shared library containing extension
* @param[in] apEntryPointName Name of the entry point (nullptr to let sqlite work it out)
*
* @throw SQLite::Exception in case of error
*/
void loadExtension(const char* apExtensionName, const char* apEntryPointName);
/**
* @brief Set the key for the current sqlite database instance.
*
* This is the equivalent of the sqlite3_key call and should thus be called
* directly after opening the database.
* Open encrypted database -> call db.key("secret") -> database ready
*
* @param[in] aKey Key to decode/encode the database
*
* @throw SQLite::Exception in case of error
*/
void key(const std::string& aKey) const;
/**
* @brief Reset the key for the current sqlite database instance.
*
* This is the equivalent of the sqlite3_rekey call and should thus be called
* after the database has been opened with a valid key. To decrypt a
* database, call this method with an empty string.
* Open normal database -> call db.rekey("secret") -> encrypted database, database ready
* Open encrypted database -> call db.key("secret") -> call db.rekey("newsecret") -> change key, database ready
* Open encrypted database -> call db.key("secret") -> call db.rekey("") -> decrypted database, database ready
*
* @param[in] aNewKey New key to encode the database
*
* @throw SQLite::Exception in case of error
*/
void rekey(const std::string& aNewKey) const;
/**
* @brief Test if a file contains an unencrypted database.
*
* This is a simple test that reads the first bytes of a database file and
* compares them to the standard header for unencrypted databases. If the
* header does not match the standard string, we assume that we have an
* encrypted file.
*
* @param[in] aFilename path/uri to a file
*
* @return true if the database has the standard header.
*
* @throw SQLite::Exception in case of error
*/
static bool isUnencrypted(const std::string& aFilename);
/**
* @brief Parse SQLite header data from a database file.
*
* This function reads the first 100 bytes of a SQLite database file
* and reconstructs groups of individual bytes into the associated fields
* in a Header object.
*
* @param[in] aFilename path/uri to a file
*
* @return Header object containing file data
*
* @throw SQLite::Exception in case of error
*/
static Header getHeaderInfo(const std::string& aFilename);
// Parse SQLite header data from a database file.
Header getHeaderInfo() const
{
return getHeaderInfo(mFilename);
}
/**
* @brief BackupType for the backup() method
*/
enum BackupType { Save, Load };
/**
* @brief Load or save the database content.
*
* This function is used to load the contents of a database file on disk
* into the "main" database of open database connection, or to save the current
* contents of the database into a database file on disk.
*
* @throw SQLite::Exception in case of error
*/
void backup(const char* apFilename, BackupType aType);
/**
* @brief Check if aRet equal SQLITE_OK, else throw a SQLite::Exception with the SQLite error message
*/
void check(const int aRet) const
{
if (SQLite::OK != aRet)
{
throw SQLite::Exception(getHandle(), aRet);
}
}
private:
// TODO: perhaps switch to having Statement sharing a pointer to the Connexion
std::unique_ptr<sqlite3, Deleter> mSQLitePtr; ///< Pointer to SQLite Database Connection Handle
std::string mFilename; ///< UTF-8 filename used to open the database
};
} // namespace SQLite
|