summaryrefslogtreecommitdiff
path: root/3rdparty/sqlitecpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/sqlitecpp')
-rw-r--r--3rdparty/sqlitecpp/CMakeLists.txt10
-rw-r--r--3rdparty/sqlitecpp/source/SQLiteCpp/Assertion.h46
-rw-r--r--3rdparty/sqlitecpp/source/SQLiteCpp/Backup.cpp83
-rw-r--r--3rdparty/sqlitecpp/source/SQLiteCpp/Backup.h127
-rw-r--r--3rdparty/sqlitecpp/source/SQLiteCpp/Column.cpp122
-rw-r--r--3rdparty/sqlitecpp/source/SQLiteCpp/Column.h291
-rw-r--r--3rdparty/sqlitecpp/source/SQLiteCpp/Database.cpp452
-rw-r--r--3rdparty/sqlitecpp/source/SQLiteCpp/Database.h594
-rw-r--r--3rdparty/sqlitecpp/source/SQLiteCpp/Exception.cpp47
-rw-r--r--3rdparty/sqlitecpp/source/SQLiteCpp/Exception.h92
-rw-r--r--3rdparty/sqlitecpp/source/SQLiteCpp/ExecuteMany.h90
-rw-r--r--3rdparty/sqlitecpp/source/SQLiteCpp/SQLiteCpp.h44
-rw-r--r--3rdparty/sqlitecpp/source/SQLiteCpp/Savepoint.cpp65
-rw-r--r--3rdparty/sqlitecpp/source/SQLiteCpp/Savepoint.h95
-rw-r--r--3rdparty/sqlitecpp/source/SQLiteCpp/Statement.cpp368
-rw-r--r--3rdparty/sqlitecpp/source/SQLiteCpp/Statement.h714
-rw-r--r--3rdparty/sqlitecpp/source/SQLiteCpp/Transaction.cpp83
-rw-r--r--3rdparty/sqlitecpp/source/SQLiteCpp/Transaction.h95
-rw-r--r--3rdparty/sqlitecpp/source/SQLiteCpp/Utils.h31
-rw-r--r--3rdparty/sqlitecpp/source/SQLiteCpp/VariadicBind.h98
20 files changed, 3547 insertions, 0 deletions
diff --git a/3rdparty/sqlitecpp/CMakeLists.txt b/3rdparty/sqlitecpp/CMakeLists.txt
new file mode 100644
index 0000000..1ba64db
--- /dev/null
+++ b/3rdparty/sqlitecpp/CMakeLists.txt
@@ -0,0 +1,10 @@
+file(GLOB_RECURSE SQLiteCpp_SOURCE ${CMAKE_CURRENT_LIST_DIR}/source/*.cpp)
+add_library(SQLiteCpp ${SQLiteCpp_SOURCE})
+target_include_directories(SQLiteCpp
+PUBLIC
+ ${CMAKE_CURRENT_LIST_DIR}/source
+)
+target_link_libraries(SQLiteCpp
+PRIVATE
+ sqlite3 # This comes from conan
+)
diff --git a/3rdparty/sqlitecpp/source/SQLiteCpp/Assertion.h b/3rdparty/sqlitecpp/source/SQLiteCpp/Assertion.h
new file mode 100644
index 0000000..b6d00be
--- /dev/null
+++ b/3rdparty/sqlitecpp/source/SQLiteCpp/Assertion.h
@@ -0,0 +1,46 @@
+/**
+ * @file Assertion.h
+ * @ingroup SQLiteCpp
+ * @brief Definition of the SQLITECPP_ASSERT() macro.
+ *
+ * Copyright (c) 2012-2021 Sebastien Rombauts ([email protected])
+ *
+ * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
+ * or copy at http://opensource.org/licenses/MIT)
+ */
+#pragma once
+
+#include <cassert>
+
+
+/**
+ * SQLITECPP_ASSERT SQLITECPP_ASSERT() is used in destructors, where exceptions shall not be thrown
+ *
+ * Define SQLITECPP_ENABLE_ASSERT_HANDLER at the project level
+ * and define a SQLite::assertion_failed() assertion handler
+ * to tell SQLiteC++ to use it instead of assert() when an assertion fail.
+*/
+#ifdef SQLITECPP_ENABLE_ASSERT_HANDLER
+
+// if an assert handler is provided by user code, use it instead of assert()
+namespace SQLite
+{
+ // declaration of the assert handler to define in user code
+ void assertion_failed(const char* apFile, const long apLine, const char* apFunc,
+ const char* apExpr, const char* apMsg);
+
+#ifdef _MSC_VER
+ #define __func__ __FUNCTION__
+#endif
+// call the assert handler provided by user code
+#define SQLITECPP_ASSERT(expression, message) \
+ if (!(expression)) SQLite::assertion_failed(__FILE__, __LINE__, __func__, #expression, message)
+} // namespace SQLite
+
+#else
+
+// if no assert handler provided by user code, use standard assert()
+// (note: in release mode assert() does nothing)
+#define SQLITECPP_ASSERT(expression, message) assert(expression && message)
+
+#endif
diff --git a/3rdparty/sqlitecpp/source/SQLiteCpp/Backup.cpp b/3rdparty/sqlitecpp/source/SQLiteCpp/Backup.cpp
new file mode 100644
index 0000000..183d314
--- /dev/null
+++ b/3rdparty/sqlitecpp/source/SQLiteCpp/Backup.cpp
@@ -0,0 +1,83 @@
+/**
+ * @file Backup.cpp
+ * @ingroup SQLiteCpp
+ * @brief Backup is used to backup a database file in a safe and online way.
+ *
+ * Copyright (c) 2015 Shibao HONG ([email protected])
+ * Copyright (c) 2015-2021 Sebastien Rombauts ([email protected])
+ *
+ * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
+ * or copy at http://opensource.org/licenses/MIT)
+ */
+#include <SQLiteCpp/Backup.h>
+
+#include <SQLiteCpp/Exception.h>
+
+#include <sqlite3.h>
+
+namespace SQLite
+{
+
+// Initialize resource for SQLite database backup
+Backup::Backup(Database& aDestDatabase,
+ const char* apDestDatabaseName,
+ Database& aSrcDatabase,
+ const char* apSrcDatabaseName)
+{
+ mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(),
+ apDestDatabaseName,
+ aSrcDatabase.getHandle(),
+ apSrcDatabaseName);
+ if (nullptr == mpSQLiteBackup)
+ {
+ // If an error occurs, the error code and message are attached to the destination database connection.
+ throw SQLite::Exception(aDestDatabase.getHandle());
+ }
+}
+
+Backup::Backup(Database& aDestDatabase,
+ const std::string& aDestDatabaseName,
+ Database& aSrcDatabase,
+ const std::string& aSrcDatabaseName) :
+ Backup(aDestDatabase, aDestDatabaseName.c_str(), aSrcDatabase, aSrcDatabaseName.c_str())
+{
+}
+
+Backup::Backup(Database &aDestDatabase, Database &aSrcDatabase) :
+ Backup(aDestDatabase, "main", aSrcDatabase, "main")
+{
+}
+
+// Release resource for SQLite database backup
+Backup::~Backup()
+{
+ if (mpSQLiteBackup)
+ {
+ sqlite3_backup_finish(mpSQLiteBackup);
+ }
+}
+
+// Execute backup step with a given number of source pages to be copied
+int Backup::executeStep(const int aNumPage /* = -1 */)
+{
+ const int res = sqlite3_backup_step(mpSQLiteBackup, aNumPage);
+ if (SQLITE_OK != res && SQLITE_DONE != res && SQLITE_BUSY != res && SQLITE_LOCKED != res)
+ {
+ throw SQLite::Exception(sqlite3_errstr(res), res);
+ }
+ return res;
+}
+
+// Get the number of remaining source pages to be copied in this backup process
+int Backup::getRemainingPageCount()
+{
+ return sqlite3_backup_remaining(mpSQLiteBackup);
+}
+
+// Get the number of total source pages to be copied in this backup process
+int Backup::getTotalPageCount()
+{
+ return sqlite3_backup_pagecount(mpSQLiteBackup);
+}
+
+} // namespace SQLite
diff --git a/3rdparty/sqlitecpp/source/SQLiteCpp/Backup.h b/3rdparty/sqlitecpp/source/SQLiteCpp/Backup.h
new file mode 100644
index 0000000..21ad662
--- /dev/null
+++ b/3rdparty/sqlitecpp/source/SQLiteCpp/Backup.h
@@ -0,0 +1,127 @@
+/**
+ * @file Backup.h
+ * @ingroup SQLiteCpp
+ * @brief Backup is used to backup a database file in a safe and online way.
+ *
+ * Copyright (c) 2015 Shibao HONG ([email protected])
+ * Copyright (c) 2015-2021 Sebastien Rombauts ([email protected])
+ *
+ * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
+ * or copy at http://opensource.org/licenses/MIT)
+ */
+#pragma once
+
+#include <SQLiteCpp/Database.h>
+
+#include <string>
+
+// Forward declaration to avoid inclusion of <sqlite3.h> in a header
+struct sqlite3_backup;
+
+namespace SQLite
+{
+
+/**
+ * @brief RAII encapsulation of a SQLite Database Backup process.
+ *
+ * A Backup object is used to backup a source database file to a destination database file
+ * in a safe and online way.
+ *
+ * See also the a reference implementation of live backup taken from the official site:
+ * https://www.sqlite.org/backup.html
+ */
+class Backup
+{
+public:
+ /**
+ * @brief Initialize a SQLite Backup object.
+ *
+ * Initialize a SQLite Backup object for the source database and destination database.
+ * The database name is "main" for the main database, "temp" for the temporary database,
+ * or the name specified after the AS keyword in an ATTACH statement for an attached database.
+ *
+ * Exception is thrown in case of error, then the Backup object is NOT constructed.
+ *
+ * @param[in] aDestDatabase Destination database connection
+ * @param[in] apDestDatabaseName Destination database name
+ * @param[in] aSrcDatabase Source database connection
+ * @param[in] apSrcDatabaseName Source database name
+ *
+ * @throw SQLite::Exception in case of error
+ */
+ Backup(Database& aDestDatabase,
+ const char* apDestDatabaseName,
+ Database& aSrcDatabase,
+ const char* apSrcDatabaseName);
+
+ /**
+ * @brief Initialize a SQLite Backup object.
+ *
+ * Initialize a SQLite Backup object for source database and destination database.
+ * The database name is "main" for the main database, "temp" for the temporary database,
+ * or the name specified after the AS keyword in an ATTACH statement for an attached database.
+ *
+ * Exception is thrown in case of error, then the Backup object is NOT constructed.
+ *
+ * @param[in] aDestDatabase Destination database connection
+ * @param[in] aDestDatabaseName Destination database name
+ * @param[in] aSrcDatabase Source database connection
+ * @param[in] aSrcDatabaseName Source database name
+ *
+ * @throw SQLite::Exception in case of error
+ */
+ Backup(Database& aDestDatabase,
+ const std::string& aDestDatabaseName,
+ Database& aSrcDatabase,
+ const std::string& aSrcDatabaseName);
+
+ /**
+ * @brief Initialize a SQLite Backup object for main databases.
+ *
+ * Initialize a SQLite Backup object for source database and destination database.
+ * Backup the main databases between the source and the destination.
+ *
+ * Exception is thrown in case of error, then the Backup object is NOT constructed.
+ *
+ * @param[in] aDestDatabase Destination database connection
+ * @param[in] aSrcDatabase Source database connection
+ *
+ * @throw SQLite::Exception in case of error
+ */
+ Backup(Database& aDestDatabase,
+ Database& aSrcDatabase);
+
+ // Backup is non-copyable
+ Backup(const Backup&) = delete;
+ Backup& operator=(const Backup&) = delete;
+
+ /// Release the SQLite Backup resource.
+ ~Backup();
+
+ /**
+ * @brief Execute a step of backup with a given number of source pages to be copied
+ *
+ * Exception is thrown when SQLITE_IOERR_XXX, SQLITE_NOMEM, or SQLITE_READONLY is returned
+ * in sqlite3_backup_step(). These errors are considered fatal, so there is no point
+ * in retrying the call to executeStep().
+ *
+ * @param[in] aNumPage The number of source pages to be copied, with a negative value meaning all remaining source pages
+ *
+ * @return SQLITE_OK/SQLITE_DONE/SQLITE_BUSY/SQLITE_LOCKED
+ *
+ * @throw SQLite::Exception in case of error
+ */
+ int executeStep(const int aNumPage = -1);
+
+ /// Return the number of source pages still to be backed up as of the most recent call to executeStep().
+ int getRemainingPageCount();
+
+ /// Return the total number of pages in the source database as of the most recent call to executeStep().
+ int getTotalPageCount();
+
+private:
+ // TODO: use std::unique_ptr with a custom deleter to call sqlite3_backup_finish()
+ sqlite3_backup* mpSQLiteBackup = nullptr; ///< Pointer to SQLite Database Backup Handle
+};
+
+} // namespace SQLite
diff --git a/3rdparty/sqlitecpp/source/SQLiteCpp/Column.cpp b/3rdparty/sqlitecpp/source/SQLiteCpp/Column.cpp
new file mode 100644
index 0000000..f5dc0d9
--- /dev/null
+++ b/3rdparty/sqlitecpp/source/SQLiteCpp/Column.cpp
@@ -0,0 +1,122 @@
+/**
+ * @file Column.cpp
+ * @ingroup SQLiteCpp
+ * @brief Encapsulation of a Column in a row of the result pointed by the prepared SQLite::Statement.
+ *
+ * Copyright (c) 2012-2021 Sebastien Rombauts ([email protected])
+ *
+ * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
+ * or copy at http://opensource.org/licenses/MIT)
+ */
+#include <SQLiteCpp/Column.h>
+
+#include <sqlite3.h>
+
+#include <iostream>
+
+
+namespace SQLite
+{
+
+const int INTEGER = SQLITE_INTEGER;
+const int FLOAT = SQLITE_FLOAT;
+const int TEXT = SQLITE_TEXT;
+const int BLOB = SQLITE_BLOB;
+const int Null = SQLITE_NULL;
+
+
+// Encapsulation of a Column in a row of the result pointed by the prepared Statement.
+Column::Column(const Statement::TStatementPtr& aStmtPtr, int aIndex) :
+ mStmtPtr(aStmtPtr),
+ mIndex(aIndex)
+{
+ if (!aStmtPtr)
+ {
+ throw SQLite::Exception("Statement was destroyed");
+ }
+}
+
+// Return the named assigned to this result column (potentially aliased)
+const char* Column::getName() const noexcept
+{
+ return sqlite3_column_name(mStmtPtr.get(), mIndex);
+}
+
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
+// Return the name of the table column that is the origin of this result column
+const char* Column::getOriginName() const noexcept
+{
+ return sqlite3_column_origin_name(mStmtPtr.get(), mIndex);
+}
+#endif
+
+// Return the integer value of the column specified by its index starting at 0
+int Column::getInt() const noexcept
+{
+ return sqlite3_column_int(mStmtPtr.get(), mIndex);
+}
+
+// Return the unsigned integer value of the column specified by its index starting at 0
+unsigned Column::getUInt() const noexcept
+{
+ return static_cast<unsigned>(getInt64());
+}
+
+// Return the 64bits integer value of the column specified by its index starting at 0
+long long Column::getInt64() const noexcept
+{
+ return sqlite3_column_int64(mStmtPtr.get(), mIndex);
+}
+
+// Return the double value of the column specified by its index starting at 0
+double Column::getDouble() const noexcept
+{
+ return sqlite3_column_double(mStmtPtr.get(), mIndex);
+}
+
+// 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
+{
+ auto pText = reinterpret_cast<const char*>(sqlite3_column_text(mStmtPtr.get(), mIndex));
+ return (pText?pText:apDefaultValue);
+}
+
+// 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
+{
+ return sqlite3_column_blob(mStmtPtr.get(), mIndex);
+}
+
+// Return a std::string to a TEXT or BLOB column
+std::string Column::getString() const
+{
+ // 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
+ auto data = static_cast<const char *>(sqlite3_column_blob(mStmtPtr.get(), mIndex));
+
+ // 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
+ return std::string(data, sqlite3_column_bytes(mStmtPtr.get(), mIndex));
+}
+
+// Return the type of the value of the column
+int Column::getType() const noexcept
+{
+ return sqlite3_column_type(mStmtPtr.get(), mIndex);
+}
+
+// Return the number of bytes used by the text value of the column
+int Column::getBytes() const noexcept
+{
+ return sqlite3_column_bytes(mStmtPtr.get(), mIndex);
+}
+
+// Standard std::ostream inserter
+std::ostream& operator<<(std::ostream& aStream, const Column& aColumn)
+{
+ aStream.write(aColumn.getText(), aColumn.getBytes());
+ return aStream;
+}
+
+
+} // namespace SQLite
diff --git a/3rdparty/sqlitecpp/source/SQLiteCpp/Column.h b/3rdparty/sqlitecpp/source/SQLiteCpp/Column.h
new file mode 100644
index 0000000..bc349f9
--- /dev/null
+++ b/3rdparty/sqlitecpp/source/SQLiteCpp/Column.h
@@ -0,0 +1,291 @@
+/**
+ * @file Column.h
+ * @ingroup SQLiteCpp
+ * @brief Encapsulation of a Column in a row of the result pointed by the prepared SQLite::Statement.
+ *
+ * Copyright (c) 2012-2021 Sebastien Rombauts ([email protected])
+ *
+ * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
+ * or copy at http://opensource.org/licenses/MIT)
+ */
+#pragma once
+
+#include <SQLiteCpp/Statement.h>
+#include <SQLiteCpp/Exception.h>
+
+#include <string>
+#include <memory>
+#include <climits> // For INT_MAX
+
+// Forward declarations to avoid inclusion of <sqlite3.h> in a header
+struct sqlite3_stmt;
+
+namespace SQLite
+{
+
+extern const int INTEGER; ///< SQLITE_INTEGER
+extern const int FLOAT; ///< SQLITE_FLOAT
+extern const int TEXT; ///< SQLITE_TEXT
+extern const int BLOB; ///< SQLITE_BLOB
+extern const int Null; ///< SQLITE_NULL
+
+/**
+ * @brief Encapsulation of a Column in a row of the result pointed by the prepared Statement.
+ *
+ * A Column is a particular field of SQLite data in the current row of result
+ * of the Statement : it points to a single cell.
+ *
+ * Its value can be expressed as a text, and, when applicable, as a numeric
+ * (integer or floating point) or a binary blob.
+ *
+ * Thread-safety: a Column 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 Column
+{
+public:
+ /**
+ * @brief Encapsulation of a Column in a Row of the result.
+ *
+ * @param[in] aStmtPtr Shared pointer to the prepared SQLite Statement Object.
+ * @param[in] aIndex Index of the column in the row of result, starting at 0
+ */
+ explicit Column(const Statement::TStatementPtr& aStmtPtr, int aIndex);
+
+ // default destructor: the finalization will be done by the destructor of the last shared pointer
+ // default copy constructor and assignment operator are perfectly suited :
+ // they copy the Statement::Ptr which in turn increments the reference counter.
+
+ /**
+ * @brief Return a pointer to the named assigned to this result column (potentially aliased)
+ *
+ * @see getOriginName() to get original column name (not aliased)
+ */
+ const char* getName() const noexcept;
+
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
+ /**
+ * @brief Return a pointer to the table column name that is the origin of this result column
+ *
+ * Require definition of the SQLITE_ENABLE_COLUMN_METADATA preprocessor macro :
+ * - when building the SQLite library itself (which is the case for the Debian libsqlite3 binary for instance),
+ * - and also when compiling this wrapper.
+ */
+ const char* getOriginName() const noexcept;
+#endif
+
+ /// Return the integer value of the column.
+ int getInt() const noexcept;
+ /// Return the 32bits unsigned integer value of the column (note that SQLite3 does not support unsigned 64bits).
+ unsigned getUInt() const noexcept;
+ /// Return the 64bits integer value of the column (note that SQLite3 does not support unsigned 64bits).
+ long long getInt64() const noexcept;
+ /// Return the double (64bits float) value of the column
+ double getDouble() const noexcept;
+ /**
+ * @brief Return a pointer to the text value (NULL terminated string) of the column.
+ *
+ * @warning The value pointed at is only valid while the statement is valid (ie. not finalized),
+ * thus you must copy it before using it beyond its scope (to a std::string for instance).
+ */
+ const char* getText(const char* apDefaultValue = "") const noexcept;
+ /**
+ * @brief Return a pointer to the binary blob value of the column.
+ *
+ * @warning The value pointed at is only valid while the statement is valid (ie. not finalized),
+ * thus you must copy it before using it beyond its scope (to a std::string for instance).
+ */
+ const void* getBlob() const noexcept;
+ /**
+ * @brief Return a std::string for a TEXT or BLOB column.
+ *
+ * Note this correctly handles strings that contain null bytes.
+ */
+ std::string getString() const;
+
+ /**
+ * @brief Return the type of the value of the column
+ *
+ * Return either SQLite::INTEGER, SQLite::FLOAT, SQLite::TEXT, SQLite::BLOB, or SQLite::Null.
+ *
+ * @warning After a type conversion (by a call to a getXxx on a Column of a Yyy type),
+ * the value returned by sqlite3_column_type() is undefined.
+ */
+ int getType() const noexcept;
+
+ /// Test if the column is an integer type value (meaningful only before any conversion)
+ bool isInteger() const noexcept
+ {
+ return (SQLite::INTEGER == getType());
+ }
+ /// Test if the column is a floating point type value (meaningful only before any conversion)
+ bool isFloat() const noexcept
+ {
+ return (SQLite::FLOAT == getType());
+ }
+ /// Test if the column is a text type value (meaningful only before any conversion)
+ bool isText() const noexcept
+ {
+ return (SQLite::TEXT == getType());
+ }
+ /// Test if the column is a binary blob type value (meaningful only before any conversion)
+ bool isBlob() const noexcept
+ {
+ return (SQLite::BLOB == getType());
+ }
+ /// Test if the column is NULL (meaningful only before any conversion)
+ bool isNull() const noexcept
+ {
+ return (SQLite::Null == getType());
+ }
+
+ /**
+ * @brief Return the number of bytes used by the text (or blob) value of the column
+ *
+ * Return either :
+ * - size in bytes (not in characters) of the string returned by getText() without the '\0' terminator
+ * - size in bytes of the string representation of the numerical value (integer or double)
+ * - size in bytes of the binary blob returned by getBlob()
+ * - 0 for a NULL value
+ */
+ int getBytes() const noexcept;
+
+ /// Alias returning the number of bytes used by the text (or blob) value of the column
+ int size() const noexcept
+ {
+ return getBytes ();
+ }
+
+ /// Inline cast operator to char
+ operator char() const
+ {
+ return static_cast<char>(getInt());
+ }
+ /// Inline cast operator to unsigned char
+ operator unsigned char() const
+ {
+ return static_cast<unsigned char>(getInt());
+ }
+ /// Inline cast operator to short
+ operator short() const
+ {
+ return static_cast<short>(getInt());
+ }
+ /// Inline cast operator to unsigned short
+ operator unsigned short() const
+ {
+ return static_cast<unsigned short>(getInt());
+ }
+
+ /// Inline cast operator to int
+ operator int() const
+ {
+ return getInt();
+ }
+ /// Inline cast operator to 32bits unsigned integer
+ operator unsigned int() const
+ {
+ return getUInt();
+ }
+#if (LONG_MAX == INT_MAX) // 4 bytes "long" type means the data model is ILP32 or LLP64 (Win64 Visual C++ and MinGW)
+ /// Inline cast operator to 32bits long
+ operator long() const
+ {
+ return getInt();
+ }
+ /// Inline cast operator to 32bits unsigned long
+ operator unsigned long() const
+ {
+ return getUInt();
+ }
+#else // 8 bytes "long" type means the data model is LP64 (Most Unix-like, Windows when using Cygwin; z/OS)
+ /// Inline cast operator to 64bits long when the data model of the system is LP64 (Linux 64 bits...)
+ operator long() const
+ {
+ return getInt64();
+ }
+#endif
+
+ /// Inline cast operator to 64bits integer
+ operator long long() const
+ {
+ return getInt64();
+ }
+ /// Inline cast operator to double
+ operator double() const
+ {
+ return getDouble();
+ }
+ /**
+ * @brief Inline cast operator to char*
+ *
+ * @see getText
+ */
+ operator const char*() const
+ {
+ return getText();
+ }
+ /**
+ * @brief Inline cast operator to void*
+ *
+ * @see getBlob
+ */
+ operator const void*() const
+ {
+ return getBlob();
+ }
+
+ /**
+ * @brief Inline cast operator to std::string
+ *
+ * Handles BLOB or TEXT, which may contain null bytes within
+ *
+ * @see getString
+ */
+ operator std::string() const
+ {
+ return getString();
+ }
+
+private:
+ Statement::TStatementPtr mStmtPtr; ///< Shared Pointer to the prepared SQLite Statement Object
+ int mIndex; ///< Index of the column in the row of result, starting at 0
+};
+
+/**
+ * @brief Standard std::ostream text inserter
+ *
+ * Insert the text value of the Column object, using getText(), into the provided stream.
+ *
+ * @param[in] aStream Stream to use
+ * @param[in] aColumn Column object to insert into the provided stream
+ *
+ * @return Reference to the stream used
+ */
+std::ostream& operator<<(std::ostream& aStream, const Column& aColumn);
+
+#if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900) // c++14: Visual Studio 2015
+
+// Create an instance of T from the first N columns, see declaration in Statement.h for full details
+template<typename T, int N>
+T Statement::getColumns()
+{
+ checkRow();
+ checkIndex(N - 1);
+ return getColumns<T>(std::make_integer_sequence<int, N>{});
+}
+
+// Helper function called by getColums<typename T, int N>
+template<typename T, const int... Is>
+T Statement::getColumns(const std::integer_sequence<int, Is...>)
+{
+ return T{Column(mpPreparedStatement, Is)...};
+}
+
+#endif
+
+} // namespace SQLite
diff --git a/3rdparty/sqlitecpp/source/SQLiteCpp/Database.cpp b/3rdparty/sqlitecpp/source/SQLiteCpp/Database.cpp
new file mode 100644
index 0000000..eb76c88
--- /dev/null
+++ b/3rdparty/sqlitecpp/source/SQLiteCpp/Database.cpp
@@ -0,0 +1,452 @@
+/**
+ * @file Database.cpp
+ * @ingroup SQLiteCpp
+ * @brief Management of a SQLite Database Connection.
+ *
+ * Copyright (c) 2012-2021 Sebastien Rombauts ([email protected])
+ *
+ * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
+ * or copy at http://opensource.org/licenses/MIT)
+ */
+#include <SQLiteCpp/Database.h>
+
+#include <SQLiteCpp/Assertion.h>
+#include <SQLiteCpp/Backup.h>
+#include <SQLiteCpp/Exception.h>
+#include <SQLiteCpp/Statement.h>
+
+#include <sqlite3.h>
+#include <fstream>
+#include <string.h>
+
+#ifndef SQLITE_DETERMINISTIC
+#define SQLITE_DETERMINISTIC 0x800
+#endif // SQLITE_DETERMINISTIC
+
+
+namespace SQLite
+{
+
+const int OPEN_READONLY = SQLITE_OPEN_READONLY;
+const int OPEN_READWRITE = SQLITE_OPEN_READWRITE;
+const int OPEN_CREATE = SQLITE_OPEN_CREATE;
+const int OPEN_URI = SQLITE_OPEN_URI;
+const int OPEN_MEMORY = SQLITE_OPEN_MEMORY;
+const int OPEN_NOMUTEX = SQLITE_OPEN_NOMUTEX;
+const int OPEN_FULLMUTEX = SQLITE_OPEN_FULLMUTEX;
+const int OPEN_SHAREDCACHE = SQLITE_OPEN_SHAREDCACHE;
+const int OPEN_PRIVATECACHE = SQLITE_OPEN_PRIVATECACHE;
+#if SQLITE_VERSION_NUMBER >= 3031000
+const int OPEN_NOFOLLOW = SQLITE_OPEN_NOFOLLOW;
+#else
+const int OPEN_NOFOLLOW = 0;
+#endif
+
+const int OK = SQLITE_OK;
+
+const char* VERSION = SQLITE_VERSION;
+const int VERSION_NUMBER = SQLITE_VERSION_NUMBER;
+
+// Return SQLite version string using runtime call to the compiled library
+const char* getLibVersion() noexcept
+{
+ return sqlite3_libversion();
+}
+
+// Return SQLite version number using runtime call to the compiled library
+int getLibVersionNumber() noexcept
+{
+ return sqlite3_libversion_number();
+}
+
+
+// Open the provided database UTF-8 filename with SQLite::OPEN_xxx provided flags.
+Database::Database(const char* apFilename,
+ const int aFlags /* = SQLite::OPEN_READONLY*/,
+ const int aBusyTimeoutMs /* = 0 */,
+ const char* apVfs /* = nullptr*/) :
+ mFilename(apFilename)
+{
+ sqlite3* handle;
+ const int ret = sqlite3_open_v2(apFilename, &handle, aFlags, apVfs);
+ mSQLitePtr.reset(handle);
+ if (SQLITE_OK != ret)
+ {
+ throw SQLite::Exception(handle, ret);
+ }
+ if (aBusyTimeoutMs > 0)
+ {
+ setBusyTimeout(aBusyTimeoutMs);
+ }
+}
+
+// Deleter functor to use with smart pointers to close the SQLite database connection in an RAII fashion.
+void Database::Deleter::operator()(sqlite3* apSQLite)
+{
+ const int ret = sqlite3_close(apSQLite); // Calling sqlite3_close() with a nullptr argument is a harmless no-op.
+
+ // Avoid unreferenced variable warning when build in release mode
+ (void) ret;
+
+ // Only case of error is SQLITE_BUSY: "database is locked" (some statements are not finalized)
+ // Never throw an exception in a destructor :
+ 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.
+ *
+ * This is useful in multithreaded program to handle case where a table is locked for writting 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 Database::setBusyTimeout(const int aBusyTimeoutMs)
+{
+ const int ret = sqlite3_busy_timeout(getHandle(), aBusyTimeoutMs);
+ check(ret);
+}
+
+// Shortcut to execute one or multiple SQL statements without results (UPDATE, INSERT, ALTER, COMMIT, CREATE...).
+// Return the number of changes.
+int Database::exec(const char* apQueries)
+{
+ const int ret = tryExec(apQueries);
+ check(ret);
+
+ // Return the number of rows modified by those SQL statements (INSERT, UPDATE or DELETE only)
+ return sqlite3_changes(getHandle());
+}
+
+int Database::tryExec(const char* apQueries) noexcept
+{
+ return sqlite3_exec(getHandle(), apQueries, nullptr, nullptr, nullptr);
+}
+
+// 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
+// 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)
+// this is an issue only for pointer type result (ie. char* and blob)
+// (use the Column copy-constructor)
+Column Database::execAndGet(const char* apQuery)
+{
+ Statement query(*this, apQuery);
+ (void)query.executeStep(); // Can return false if no result, which will throw next line in getColumn()
+ return query.getColumn(0);
+}
+
+// Shortcut to test if a table exists.
+bool Database::tableExists(const char* apTableName)
+{
+ Statement query(*this, "SELECT count(*) FROM sqlite_master WHERE type='table' AND name=?");
+ query.bind(1, apTableName);
+ (void)query.executeStep(); // Cannot return false, as the above query always return a result
+ return (1 == query.getColumn(0).getInt());
+}
+
+// Get the rowid of the most recent successful INSERT into the database from the current connection.
+long long Database::getLastInsertRowid() const noexcept
+{
+ return sqlite3_last_insert_rowid(getHandle());
+}
+
+// Get number of rows modified by last INSERT, UPDATE or DELETE statement (not DROP table).
+int Database::getChanges() const noexcept
+{
+ return sqlite3_changes(getHandle());
+}
+
+// Get total number of rows modified by all INSERT, UPDATE or DELETE statement since connection.
+int Database::getTotalChanges() const noexcept
+{
+ return sqlite3_total_changes(getHandle());
+}
+
+// Return the numeric result code for the most recent failed API call (if any).
+int Database::getErrorCode() const noexcept
+{
+ return sqlite3_errcode(getHandle());
+}
+
+// Return the extended numeric result code for the most recent failed API call (if any).
+int Database::getExtendedErrorCode() const noexcept
+{
+ return sqlite3_extended_errcode(getHandle());
+}
+
+// Return UTF-8 encoded English language explanation of the most recent failed API call (if any).
+const char* Database::getErrorMsg() const noexcept
+{
+ return sqlite3_errmsg(getHandle());
+}
+
+// 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
+void Database::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 */)
+{
+ int textRep = SQLITE_UTF8;
+ // optimization if deterministic function (e.g. of nondeterministic function random())
+ if (abDeterministic)
+ {
+ textRep = textRep | SQLITE_DETERMINISTIC;
+ }
+ const int ret = sqlite3_create_function_v2(getHandle(), apFuncName, aNbArg, textRep,
+ apApp, apFunc, apStep, apFinal, apDestroy);
+ check(ret);
+}
+
+// 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
+void Database::loadExtension(const char* apExtensionName, const char *apEntryPointName)
+{
+#ifdef SQLITE_OMIT_LOAD_EXTENSION
+ // Unused
+ (void)apExtensionName;
+ (void)apEntryPointName;
+
+ throw SQLite::Exception("sqlite extensions are disabled");
+#else
+#ifdef SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION // Since SQLite 3.13 (2016-05-18):
+ // Security warning:
+ // It is recommended that the SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION method be used to enable only this interface.
+ // The use of the sqlite3_enable_load_extension() interface should be avoided to keep the SQL load_extension()
+ // disabled and prevent SQL injections from giving attackers access to extension loading capabilities.
+ // (NOTE: not using nullptr: cannot pass object of non-POD type 'std::__1::nullptr_t' through variadic function)
+ int ret = sqlite3_db_config(getHandle(), SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, NULL); // NOTE: not using nullptr
+#else
+ int ret = sqlite3_enable_load_extension(getHandle(), 1);
+#endif
+ check(ret);
+
+ ret = sqlite3_load_extension(getHandle(), apExtensionName, apEntryPointName, 0);
+ check(ret);
+#endif
+}
+
+// Set the key for the current sqlite database instance.
+void Database::key(const std::string& aKey) const
+{
+ int passLen = static_cast<int>(aKey.length());
+#ifdef SQLITE_HAS_CODEC
+ if (passLen > 0)
+ {
+ const int ret = sqlite3_key(getHandle(), aKey.c_str(), passLen);
+ check(ret);
+ }
+#else // SQLITE_HAS_CODEC
+ if (passLen > 0)
+ {
+ throw SQLite::Exception("No encryption support, recompile with SQLITE_HAS_CODEC to enable.");
+ }
+#endif // SQLITE_HAS_CODEC
+}
+
+// Reset the key for the current sqlite database instance.
+void Database::rekey(const std::string& aNewKey) const
+{
+#ifdef SQLITE_HAS_CODEC
+ int passLen = aNewKey.length();
+ if (passLen > 0)
+ {
+ const int ret = sqlite3_rekey(getHandle(), aNewKey.c_str(), passLen);
+ check(ret);
+ }
+ else
+ {
+ const int ret = sqlite3_rekey(getHandle(), nullptr, 0);
+ check(ret);
+ }
+#else // SQLITE_HAS_CODEC
+ static_cast<void>(aNewKey); // silence unused parameter warning
+ throw SQLite::Exception("No encryption support, recompile with SQLITE_HAS_CODEC to enable.");
+#endif // SQLITE_HAS_CODEC
+}
+
+// Test if a file contains an unencrypted database.
+bool Database::isUnencrypted(const std::string& aFilename)
+{
+ if (aFilename.empty())
+ {
+ throw SQLite::Exception("Could not open database, the aFilename parameter was empty.");
+ }
+
+ std::ifstream fileBuffer(aFilename.c_str(), std::ios::in | std::ios::binary);
+ char header[16];
+ if (fileBuffer.is_open())
+ {
+ fileBuffer.seekg(0, std::ios::beg);
+ fileBuffer.getline(header, 16);
+ fileBuffer.close();
+ }
+ else
+ {
+ throw SQLite::Exception("Error opening file: " + aFilename);
+ }
+
+ return strncmp(header, "SQLite format 3\000", 16) == 0;
+}
+
+// Parse header data from a database.
+Header Database::getHeaderInfo(const std::string& aFilename)
+{
+ Header h;
+ unsigned char buf[100];
+ char* pBuf = reinterpret_cast<char*>(&buf[0]);
+ char* pHeaderStr = reinterpret_cast<char*>(&h.headerStr[0]);
+
+ if (aFilename.empty())
+ {
+ throw SQLite::Exception("Filename parameter is empty");
+ }
+
+ {
+ std::ifstream fileBuffer(aFilename.c_str(), std::ios::in | std::ios::binary);
+ if (fileBuffer.is_open())
+ {
+ fileBuffer.seekg(0, std::ios::beg);
+ fileBuffer.read(pBuf, 100);
+ fileBuffer.close();
+ if (fileBuffer.gcount() < 100)
+ {
+ throw SQLite::Exception("File " + aFilename + " is too short");
+ }
+ }
+ else
+ {
+ throw SQLite::Exception("Error opening file " + aFilename);
+ }
+ }
+
+ // If the "magic string" can't be found then header is invalid, corrupt or unreadable
+ memcpy(pHeaderStr, pBuf, 16);
+ pHeaderStr[15] = '\0';
+ if (strncmp(pHeaderStr, "SQLite format 3", 15) != 0)
+ {
+ throw SQLite::Exception("Invalid or encrypted SQLite header in file " + aFilename);
+ }
+
+ h.pageSizeBytes = (buf[16] << 8) | buf[17];
+ h.fileFormatWriteVersion = buf[18];
+ h.fileFormatReadVersion = buf[19];
+ h.reservedSpaceBytes = buf[20];
+ h.maxEmbeddedPayloadFrac = buf[21];
+ h.minEmbeddedPayloadFrac = buf[22];
+ h.leafPayloadFrac = buf[23];
+
+ h.fileChangeCounter =
+ (buf[24] << 24) |
+ (buf[25] << 16) |
+ (buf[26] << 8) |
+ (buf[27] << 0);
+
+ h.databaseSizePages =
+ (buf[28] << 24) |
+ (buf[29] << 16) |
+ (buf[30] << 8) |
+ (buf[31] << 0);
+
+ h.firstFreelistTrunkPage =
+ (buf[32] << 24) |
+ (buf[33] << 16) |
+ (buf[34] << 8) |
+ (buf[35] << 0);
+
+ h.totalFreelistPages =
+ (buf[36] << 24) |
+ (buf[37] << 16) |
+ (buf[38] << 8) |
+ (buf[39] << 0);
+
+ h.schemaCookie =
+ (buf[40] << 24) |
+ (buf[41] << 16) |
+ (buf[42] << 8) |
+ (buf[43] << 0);
+
+ h.schemaFormatNumber =
+ (buf[44] << 24) |
+ (buf[45] << 16) |
+ (buf[46] << 8) |
+ (buf[47] << 0);
+
+ h.defaultPageCacheSizeBytes =
+ (buf[48] << 24) |
+ (buf[49] << 16) |
+ (buf[50] << 8) |
+ (buf[51] << 0);
+
+ h.largestBTreePageNumber =
+ (buf[52] << 24) |
+ (buf[53] << 16) |
+ (buf[54] << 8) |
+ (buf[55] << 0);
+
+ h.databaseTextEncoding =
+ (buf[56] << 24) |
+ (buf[57] << 16) |
+ (buf[58] << 8) |
+ (buf[59] << 0);
+
+ h.userVersion =
+ (buf[60] << 24) |
+ (buf[61] << 16) |
+ (buf[62] << 8) |
+ (buf[63] << 0);
+
+ h.incrementalVaccumMode =
+ (buf[64] << 24) |
+ (buf[65] << 16) |
+ (buf[66] << 8) |
+ (buf[67] << 0);
+
+ h.applicationId =
+ (buf[68] << 24) |
+ (buf[69] << 16) |
+ (buf[70] << 8) |
+ (buf[71] << 0);
+
+ h.versionValidFor =
+ (buf[92] << 24) |
+ (buf[93] << 16) |
+ (buf[94] << 8) |
+ (buf[95] << 0);
+
+ h.sqliteVersion =
+ (buf[96] << 24) |
+ (buf[97] << 16) |
+ (buf[98] << 8) |
+ (buf[99] << 0);
+
+ return h;
+}
+
+void Database::backup(const char* apFilename, BackupType aType)
+{
+ // Open the database file identified by apFilename
+ Database otherDatabase(apFilename, SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
+
+ // For a 'Save' operation, data is copied from the current Database to the other. A 'Load' is the reverse.
+ Database& src = (aType == Save ? *this : otherDatabase);
+ Database& dest = (aType == Save ? otherDatabase : *this);
+
+ // Set up the backup procedure to copy between the "main" databases of each connection
+ Backup bkp(dest, src);
+ bkp.executeStep(); // Execute all steps at once
+
+ // RAII Finish Backup an Close the other Database
+}
+
+} // namespace SQLite
diff --git a/3rdparty/sqlitecpp/source/SQLiteCpp/Database.h b/3rdparty/sqlitecpp/source/SQLiteCpp/Database.h
new file mode 100644
index 0000000..7ee45d8
--- /dev/null
+++ b/3rdparty/sqlitecpp/source/SQLiteCpp/Database.h
@@ -0,0 +1,594 @@
+/**
+ * @file Database.h
+ * @ingroup SQLiteCpp
+ * @brief Management of a SQLite Database Connection.
+ *
+ * Copyright (c) 2012-2021 Sebastien Rombauts ([email protected])
+ *
+ * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
+ * or copy at http://opensource.org/licenses/MIT)
+ */
+#pragma once
+
+#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
+#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 less us touch std::filesystem if we're targetting earlier than 10.15
+ #else
+ #define SQLITECPP_HAVE_STD_FILESYSTEM
+ #endif
+#elif defined(_MSVC_LANG) && _MSVC_LANG >= 201703L
+ #define SQLITECPP_HAVE_STD_FILESYSTEM
+#endif
+
+#ifdef SQLITECPP_HAVE_STD_FILESYSTEM
+#include <filesystem>
+#endif // c++17 and a suitable compiler
+
+#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.
+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.
+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.
+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")
+extern const int OPEN_URI; // SQLITE_OPEN_URI
+/// Open in memory database
+extern const int OPEN_MEMORY; // SQLITE_OPEN_MEMORY
+/// Open database in multi-thread threading mode
+extern const int OPEN_NOMUTEX; // SQLITE_OPEN_NOMUTEX
+/// Open database with thread-safety in serialized threading mode
+extern const int OPEN_FULLMUTEX; // SQLITE_OPEN_FULLMUTEX
+/// Open database with shared cache enabled
+extern const int OPEN_SHAREDCACHE; // SQLITE_OPEN_SHAREDCACHE
+/// Open database with shared cache disabled
+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)
+extern const int OPEN_NOFOLLOW; // SQLITE_OPEN_NOFOLLOW
+
+
+extern const int OK; ///< SQLITE_OK (used by check() bellow)
+
+extern const char* VERSION; ///< SQLITE_VERSION string from the sqlite3.h used at compile time
+extern const int VERSION_NUMBER; ///< SQLITE_VERSION_NUMBER from the sqlite3.h used at compile time
+
+/// Return SQLite version string using runtime call to the compiled library
+const char* getLibVersion() noexcept;
+/// Return SQLite version number using runtime call to the compiled library
+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 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
+ {
+ 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] aQueries 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);
+
+ /**
+ * @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)
+ {
+ 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.
+ */
+ long long 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()
+ {
+ 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
diff --git a/3rdparty/sqlitecpp/source/SQLiteCpp/Exception.cpp b/3rdparty/sqlitecpp/source/SQLiteCpp/Exception.cpp
new file mode 100644
index 0000000..0dc644f
--- /dev/null
+++ b/3rdparty/sqlitecpp/source/SQLiteCpp/Exception.cpp
@@ -0,0 +1,47 @@
+/**
+ * @file Exception.cpp
+ * @ingroup SQLiteCpp
+ * @brief Encapsulation of the error message from SQLite3 on a std::runtime_error.
+ *
+ * Copyright (c) 2012-2021 Sebastien Rombauts ([email protected])
+ *
+ * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
+ * or copy at http://opensource.org/licenses/MIT)
+ */
+#include <SQLiteCpp/Exception.h>
+
+#include <sqlite3.h>
+
+
+namespace SQLite
+{
+
+Exception::Exception(const char* aErrorMessage, int ret) :
+ std::runtime_error(aErrorMessage),
+ mErrcode(ret),
+ mExtendedErrcode(-1)
+{
+}
+
+Exception::Exception(sqlite3* apSQLite) :
+ std::runtime_error(sqlite3_errmsg(apSQLite)),
+ mErrcode(sqlite3_errcode(apSQLite)),
+ mExtendedErrcode(sqlite3_extended_errcode(apSQLite))
+{
+}
+
+Exception::Exception(sqlite3* apSQLite, int ret) :
+ std::runtime_error(sqlite3_errmsg(apSQLite)),
+ mErrcode(ret),
+ mExtendedErrcode(sqlite3_extended_errcode(apSQLite))
+{
+}
+
+// Return a string, solely based on the error code
+const char* Exception::getErrorStr() const noexcept
+{
+ return sqlite3_errstr(mErrcode);
+}
+
+
+} // namespace SQLite
diff --git a/3rdparty/sqlitecpp/source/SQLiteCpp/Exception.h b/3rdparty/sqlitecpp/source/SQLiteCpp/Exception.h
new file mode 100644
index 0000000..efd6356
--- /dev/null
+++ b/3rdparty/sqlitecpp/source/SQLiteCpp/Exception.h
@@ -0,0 +1,92 @@
+/**
+ * @file Exception.h
+ * @ingroup SQLiteCpp
+ * @brief Encapsulation of the error message from SQLite3 on a std::runtime_error.
+ *
+ * Copyright (c) 2012-2021 Sebastien Rombauts ([email protected])
+ *
+ * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
+ * or copy at http://opensource.org/licenses/MIT)
+ */
+#pragma once
+
+#include <stdexcept>
+#include <string>
+
+// Forward declaration to avoid inclusion of <sqlite3.h> in a header
+struct sqlite3;
+
+namespace SQLite
+{
+
+
+/**
+ * @brief Encapsulation of the error message from SQLite3, based on std::runtime_error.
+ */
+class Exception : public std::runtime_error
+{
+public:
+ /**
+ * @brief Encapsulation of the error message from SQLite3, based on std::runtime_error.
+ *
+ * @param[in] aErrorMessage The string message describing the SQLite error
+ * @param[in] ret Return value from function call that failed.
+ */
+ Exception(const char* aErrorMessage, int ret);
+
+ Exception(const std::string& aErrorMessage, int ret) :
+ Exception(aErrorMessage.c_str(), ret)
+ {
+ }
+
+ /**
+ * @brief Encapsulation of the error message from SQLite3, based on std::runtime_error.
+ *
+ * @param[in] aErrorMessage The string message describing the SQLite error
+ */
+ explicit Exception(const char* aErrorMessage) :
+ Exception(aErrorMessage, -1) // 0 would be SQLITE_OK, which doesn't make sense
+ {
+ }
+ explicit Exception(const std::string& aErrorMessage) :
+ Exception(aErrorMessage.c_str(), -1) // 0 would be SQLITE_OK, which doesn't make sense
+ {
+ }
+
+ /**
+ * @brief Encapsulation of the error message from SQLite3, based on std::runtime_error.
+ *
+ * @param[in] apSQLite The SQLite object, to obtain detailed error messages from.
+ */
+ explicit Exception(sqlite3* apSQLite);
+
+ /**
+ * @brief Encapsulation of the error message from SQLite3, based on std::runtime_error.
+ *
+ * @param[in] apSQLite The SQLite object, to obtain detailed error messages from.
+ * @param[in] ret Return value from function call that failed.
+ */
+ Exception(sqlite3* apSQLite, int ret);
+
+ /// Return the result code (if any, otherwise -1).
+ int getErrorCode() const noexcept
+ {
+ return mErrcode;
+ }
+
+ /// Return the extended numeric result code (if any, otherwise -1).
+ int getExtendedErrorCode() const noexcept
+ {
+ return mExtendedErrcode;
+ }
+
+ /// Return a string, solely based on the error code
+ const char* getErrorStr() const noexcept;
+
+private:
+ int mErrcode; ///< Error code value
+ int mExtendedErrcode; ///< Detailed error code if any
+};
+
+
+} // namespace SQLite
diff --git a/3rdparty/sqlitecpp/source/SQLiteCpp/ExecuteMany.h b/3rdparty/sqlitecpp/source/SQLiteCpp/ExecuteMany.h
new file mode 100644
index 0000000..4e7dac9
--- /dev/null
+++ b/3rdparty/sqlitecpp/source/SQLiteCpp/ExecuteMany.h
@@ -0,0 +1,90 @@
+/**
+ * @file ExecuteMany.h
+ * @ingroup SQLiteCpp
+ * @brief Convenience function to execute a Statement with multiple Parameter sets
+ *
+ * Copyright (c) 2019 Maximilian Bachmann ([email protected])
+ * Copyright (c) 2019-2021 Sebastien Rombauts ([email protected])
+ *
+ * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
+ * or copy at http://opensource.org/licenses/MIT)
+ */
+#pragma once
+
+#if (__cplusplus >= 201402L) || ( defined(_MSC_VER) && (_MSC_VER >= 1900) ) // c++14: Visual Studio 2015
+
+#include <SQLiteCpp/Statement.h>
+#include <SQLiteCpp/VariadicBind.h>
+
+/// @cond
+#include <tuple>
+#include <utility>
+#include <initializer_list>
+
+namespace SQLite
+{
+/// @endcond
+
+/**
+ * \brief Convenience function to execute a Statement with multiple Parameter sets once for each parameter set given.
+ *
+ *
+ * This feature requires a c++14 capable compiler.
+ *
+ * \code{.cpp}
+ * execute_many(db, "INSERT INTO test VALUES (?, ?)",
+ * 1,
+ * std::make_tuple(2),
+ * std::make_tuple(3, "three")
+ * );
+ * \endcode
+ * @param aDatabase Database to use
+ * @param apQuery Query to use with all parameter sets
+ * @param aArg first tuple with parameters
+ * @param aParams the following tuples with parameters
+ */
+template <typename Arg, typename... Types>
+void execute_many(Database& aDatabase, const char* apQuery, Arg&& aArg, Types&&... aParams)
+{
+ SQLite::Statement query(aDatabase, apQuery);
+ bind_exec(query, std::forward<Arg>(aArg));
+ (void)std::initializer_list<int>
+ {
+ ((void)reset_bind_exec(query, std::forward<Types>(aParams)), 0)...
+ };
+}
+
+/**
+ * \brief Convenience function to reset a statement and call bind_exec to
+ * bind new values to the statement and execute it
+ *
+ * This feature requires a c++14 capable compiler.
+ *
+ * @param apQuery Query to use
+ * @param aTuple Tuple to bind
+ */
+template <typename TupleT>
+void reset_bind_exec(Statement& apQuery, TupleT&& aTuple)
+{
+ apQuery.reset();
+ bind_exec(apQuery, std::forward<TupleT>(aTuple));
+}
+
+/**
+ * \brief Convenience function to bind values a the statement and execute it
+ *
+ * This feature requires a c++14 capable compiler.
+ *
+ * @param apQuery Query to use
+ * @param aTuple Tuple to bind
+ */
+template <typename TupleT>
+void bind_exec(Statement& apQuery, TupleT&& aTuple)
+{
+ SQLite::bind(apQuery, std::forward<TupleT>(aTuple));
+ while (apQuery.executeStep()) {}
+}
+
+} // namespace SQLite
+
+#endif // c++14
diff --git a/3rdparty/sqlitecpp/source/SQLiteCpp/SQLiteCpp.h b/3rdparty/sqlitecpp/source/SQLiteCpp/SQLiteCpp.h
new file mode 100644
index 0000000..161478c
--- /dev/null
+++ b/3rdparty/sqlitecpp/source/SQLiteCpp/SQLiteCpp.h
@@ -0,0 +1,44 @@
+/**
+ * @file SQLiteCpp.h
+ * @ingroup SQLiteCpp
+ * @brief SQLiteC++ is a smart and simple C++ SQLite3 wrapper. This file is only "easy include" for other files.
+ *
+ * Include this main header file in your project to gain access to all functionality provided by the wrapper.
+ *
+ * Copyright (c) 2012-2021 Sebastien Rombauts ([email protected])
+ *
+ * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
+ * or copy at http://opensource.org/licenses/MIT)
+ */
+/**
+ * @defgroup SQLiteCpp SQLiteC++
+ * @brief SQLiteC++ is a smart and simple C++ SQLite3 wrapper. This file is only "easy include" for other files.
+ */
+#pragma once
+
+
+// Include useful headers of SQLiteC++
+#include <SQLiteCpp/Assertion.h>
+#include <SQLiteCpp/Exception.h>
+#include <SQLiteCpp/Database.h>
+#include <SQLiteCpp/Statement.h>
+#include <SQLiteCpp/Column.h>
+#include <SQLiteCpp/Transaction.h>
+
+
+/**
+ * @brief Version numbers for SQLiteC++ are provided in the same way as sqlite3.h
+ *
+ * The [SQLITECPP_VERSION] C preprocessor macro in the SQLiteC++.h header
+ * evaluates to a string literal that is the SQLite version in the
+ * format "X.Y.Z" where X is the major version number
+ * and Y is the minor version number and Z is the release number.
+ *
+ * The [SQLITECPP_VERSION_NUMBER] C preprocessor macro resolves to an integer
+ * with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are the same
+ * numbers used in [SQLITECPP_VERSION].
+ *
+ * WARNING: shall always be updated in sync with PROJECT_VERSION in CMakeLists.txt
+ */
+#define SQLITECPP_VERSION "3.01.01" // 3.1.1
+#define SQLITECPP_VERSION_NUMBER 3001001 // 3.1.1
diff --git a/3rdparty/sqlitecpp/source/SQLiteCpp/Savepoint.cpp b/3rdparty/sqlitecpp/source/SQLiteCpp/Savepoint.cpp
new file mode 100644
index 0000000..b3d13a2
--- /dev/null
+++ b/3rdparty/sqlitecpp/source/SQLiteCpp/Savepoint.cpp
@@ -0,0 +1,65 @@
+/**
+ * @file Savepoint.cpp
+ * @ingroup SQLiteCpp
+ * @brief A Savepoint is a way to group multiple SQL statements into an atomic
+ * secured operation. Similar to a transaction while allowing child savepoints.
+ *
+ * Copyright (c) 2020 Kelvin Hammond ([email protected])
+ *
+ * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt or
+ * copy at http://opensource.org/licenses/MIT)
+ */
+
+#include <SQLiteCpp/Assertion.h>
+#include <SQLiteCpp/Database.h>
+#include <SQLiteCpp/Savepoint.h>
+#include <SQLiteCpp/Statement.h>
+
+namespace SQLite {
+
+// Begins the SQLite savepoint
+Savepoint::Savepoint(Database& aDatabase, std::string aName)
+ : mDatabase(aDatabase), msName(aName), mbReleased(false) {
+ // workaround because you cannot bind to SAVEPOINT
+ // escape name for use in query
+ Statement stmt(mDatabase, "SELECT quote(?)");
+ stmt.bind(1, msName);
+ stmt.executeStep();
+ msName = stmt.getColumn(0).getText();
+
+ mDatabase.exec(std::string("SAVEPOINT ") + msName);
+}
+
+// Safely rollback the savepoint if it has not been committed.
+Savepoint::~Savepoint() {
+ if (!mbReleased) {
+ try {
+ rollback();
+ } catch (SQLite::Exception&) {
+ // Never throw an exception in a destructor: error if already rolled
+ // back or released, but no harm is caused by this.
+ }
+ }
+}
+
+// Release the savepoint and commit
+void Savepoint::release() {
+ if (!mbReleased) {
+ mDatabase.exec(std::string("RELEASE SAVEPOINT ") + msName);
+ mbReleased = true;
+ } else {
+ throw SQLite::Exception("Savepoint already released or rolled back.");
+ }
+}
+
+// Rollback the savepoint
+void Savepoint::rollback() {
+ if (!mbReleased) {
+ mDatabase.exec(std::string("ROLLBACK TO SAVEPOINT ") + msName);
+ mbReleased = true;
+ } else {
+ throw SQLite::Exception("Savepoint already released or rolled back.");
+ }
+}
+
+} // namespace SQLite
diff --git a/3rdparty/sqlitecpp/source/SQLiteCpp/Savepoint.h b/3rdparty/sqlitecpp/source/SQLiteCpp/Savepoint.h
new file mode 100644
index 0000000..d389720
--- /dev/null
+++ b/3rdparty/sqlitecpp/source/SQLiteCpp/Savepoint.h
@@ -0,0 +1,95 @@
+/**
+ * @file Savepoint.h
+ * @ingroup SQLiteCpp
+ * @brief A Savepoint is a way to group multiple SQL statements into an atomic
+ * secured operation. Similar to a transaction while allowing child savepoints.
+ *
+ * Copyright (c) 2020 Kelvin Hammond ([email protected])
+ * Copyright (c) 2020-2021 Sebastien Rombauts ([email protected])
+ *
+ * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt or
+ * copy at http://opensource.org/licenses/MIT)
+ */
+#pragma once
+
+#include <SQLiteCpp/Exception.h>
+
+namespace SQLite {
+
+// Foward declaration
+class Database;
+
+/**
+ * @brief RAII encapsulation of a SQLite Savepoint.
+ *
+ * A Savepoint is a way to group multiple SQL statements into an atomic
+ * secureced operation; either it succeeds, with all the changes commited to the
+ * database file, or if it fails, all the changes are rolled back to the initial
+ * state at the start of the savepoint.
+ *
+ * This method also offers big performances improvements compared to
+ * individually executed statements.
+ *
+ * Caveats:
+ *
+ * 1) Calling COMMIT or commiting a parent transaction or RELEASE on a parent
+ * savepoint will cause this savepoint to be released.
+ *
+ * 2) Calling ROLLBACK or rolling back a parent savepoint will cause this
+ * savepoint to be rolled back.
+ *
+ * 3) This savepoint is not saved to the database until this and all savepoints
+ * or transaction in the savepoint stack have been released or commited.
+ *
+ * See also: https://sqlite.org/lang_savepoint.html
+ *
+ * Thread-safety: a Transaction 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 Savepoint {
+ public:
+ /**
+ * @brief Begins the SQLite savepoint
+ *
+ * @param[in] aDatabase the SQLite Database Connection
+ * @param[in] aName the name of the Savepoint
+ *
+ * Exception is thrown in case of error, then the Savepoint is NOT
+ * initiated.
+ */
+ Savepoint(Database& aDatabase, std::string name);
+
+ // Savepoint is non-copyable
+ Savepoint(const Savepoint&) = delete;
+ Savepoint& operator=(const Savepoint&) = delete;
+
+ /**
+ * @brief Safely rollback the savepoint if it has not been commited.
+ */
+ ~Savepoint();
+
+ /**
+ * @brief Commit and release the savepoint.
+ */
+ void release();
+
+ /**
+ * @brief Rollback the savepoint
+ */
+ void rollback();
+
+ private:
+ Database& mDatabase; ///< Reference to the SQLite Database Connection
+ std::string msName; ///< Name of the Savepoint
+ bool mbReleased; ///< True when release has been called
+};
+} // namespace SQLite
diff --git a/3rdparty/sqlitecpp/source/SQLiteCpp/Statement.cpp b/3rdparty/sqlitecpp/source/SQLiteCpp/Statement.cpp
new file mode 100644
index 0000000..64e16d2
--- /dev/null
+++ b/3rdparty/sqlitecpp/source/SQLiteCpp/Statement.cpp
@@ -0,0 +1,368 @@
+/**
+ * @file Statement.cpp
+ * @ingroup SQLiteCpp
+ * @brief A prepared SQLite Statement is a compiled SQL query ready to be executed, pointing to a row of result.
+ *
+ * Copyright (c) 2012-2021 Sebastien Rombauts ([email protected])
+ *
+ * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
+ * or copy at http://opensource.org/licenses/MIT)
+ */
+#include <SQLiteCpp/Statement.h>
+
+#include <SQLiteCpp/Database.h>
+#include <SQLiteCpp/Column.h>
+#include <SQLiteCpp/Assertion.h>
+#include <SQLiteCpp/Exception.h>
+
+#include <sqlite3.h>
+
+namespace SQLite
+{
+
+Statement::Statement(const Database& aDatabase, const char* apQuery) :
+ mQuery(apQuery),
+ mpSQLite(aDatabase.getHandle()),
+ mpPreparedStatement(prepareStatement()) // prepare the SQL query (needs Database friendship)
+{
+ mColumnCount = sqlite3_column_count(mpPreparedStatement.get());
+}
+
+Statement::Statement(Statement&& aStatement) noexcept :
+ mQuery(std::move(aStatement.mQuery)),
+ mpSQLite(aStatement.mpSQLite),
+ mpPreparedStatement(std::move(aStatement.mpPreparedStatement)),
+ mColumnCount(aStatement.mColumnCount),
+ mbHasRow(aStatement.mbHasRow),
+ mbDone(aStatement.mbDone),
+ mColumnNames(std::move(aStatement.mColumnNames))
+{
+ aStatement.mpSQLite = nullptr;
+ aStatement.mColumnCount = 0;
+ aStatement.mbHasRow = false;
+ aStatement.mbDone = false;
+}
+
+// Reset the statement to make it ready for a new execution (see also #clearBindings() bellow)
+void Statement::reset()
+{
+ const int ret = tryReset();
+ check(ret);
+}
+
+int Statement::tryReset() noexcept
+{
+ mbHasRow = false;
+ mbDone = false;
+ return sqlite3_reset(mpPreparedStatement.get());
+}
+
+// Clears away all the bindings of a prepared statement (can be associated with #reset() above).
+void Statement::clearBindings()
+{
+ const int ret = sqlite3_clear_bindings(getPreparedStatement());
+ check(ret);
+}
+
+int Statement::getIndex(const char * const apName) const
+{
+ return sqlite3_bind_parameter_index(getPreparedStatement(), apName);
+}
+
+// Bind an 32bits int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
+void Statement::bind(const int aIndex, const int32_t aValue)
+{
+ const int ret = sqlite3_bind_int(getPreparedStatement(), aIndex, aValue);
+ check(ret);
+}
+
+// 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 uint32_t aValue)
+{
+ const int ret = sqlite3_bind_int64(getPreparedStatement(), aIndex, aValue);
+ check(ret);
+}
+
+// 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 int64_t aValue)
+{
+ const int ret = sqlite3_bind_int64(getPreparedStatement(), aIndex, aValue);
+ check(ret);
+}
+
+// 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)
+{
+ const int ret = sqlite3_bind_double(getPreparedStatement(), aIndex, aValue);
+ check(ret);
+}
+
+// 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)
+{
+ const int ret = sqlite3_bind_text(getPreparedStatement(), aIndex, aValue.c_str(),
+ static_cast<int>(aValue.size()), SQLITE_TRANSIENT);
+ check(ret);
+}
+
+// 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)
+{
+ const int ret = sqlite3_bind_text(getPreparedStatement(), aIndex, apValue, -1, SQLITE_TRANSIENT);
+ check(ret);
+}
+
+// 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)
+{
+ const int ret = sqlite3_bind_blob(getPreparedStatement(), aIndex, apValue, aSize, SQLITE_TRANSIENT);
+ check(ret);
+}
+
+// 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)
+{
+ const int ret = sqlite3_bind_text(getPreparedStatement(), aIndex, aValue.c_str(),
+ static_cast<int>(aValue.size()), SQLITE_STATIC);
+ check(ret);
+}
+
+// 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)
+{
+ const int ret = sqlite3_bind_text(getPreparedStatement(), aIndex, apValue, -1, SQLITE_STATIC);
+ check(ret);
+}
+
+// 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)
+{
+ const int ret = sqlite3_bind_blob(getPreparedStatement(), aIndex, apValue, aSize, SQLITE_STATIC);
+ check(ret);
+}
+
+// Bind a NULL value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
+void Statement::bind(const int aIndex)
+{
+ const int ret = sqlite3_bind_null(getPreparedStatement(), aIndex);
+ check(ret);
+}
+
+
+// Execute a step of the query to fetch one row of results
+bool Statement::executeStep()
+{
+ const int ret = tryExecuteStep();
+ if ((SQLITE_ROW != ret) && (SQLITE_DONE != ret)) // on row or no (more) row ready, else it's a problem
+ {
+ if (ret == sqlite3_errcode(mpSQLite))
+ {
+ throw SQLite::Exception(mpSQLite, ret);
+ }
+ else
+ {
+ throw SQLite::Exception("Statement needs to be reseted", ret);
+ }
+ }
+
+ return mbHasRow; // true only if one row is accessible by getColumn(N)
+}
+
+// Execute a one-step query with no expected result, and return the number of changes.
+int Statement::exec()
+{
+ const int ret = tryExecuteStep();
+ if (SQLITE_DONE != ret) // the statement has finished executing successfully
+ {
+ if (SQLITE_ROW == ret)
+ {
+ throw SQLite::Exception("exec() does not expect results. Use executeStep.");
+ }
+ else if (ret == sqlite3_errcode(mpSQLite))
+ {
+ throw SQLite::Exception(mpSQLite, ret);
+ }
+ else
+ {
+ throw SQLite::Exception("Statement needs to be reseted", ret);
+ }
+ }
+
+ // Return the number of rows modified by those SQL statements (INSERT, UPDATE or DELETE)
+ return sqlite3_changes(mpSQLite);
+}
+
+int Statement::tryExecuteStep() noexcept
+{
+ if (mbDone)
+ {
+ return SQLITE_MISUSE; // Statement needs to be reseted !
+ }
+
+ const int ret = sqlite3_step(mpPreparedStatement.get());
+ if (SQLITE_ROW == ret) // one row is ready : call getColumn(N) to access it
+ {
+ mbHasRow = true;
+ }
+ else
+ {
+ mbHasRow = false;
+ mbDone = SQLITE_DONE == ret; // check if the query has finished executing
+ }
+ return ret;
+}
+
+
+// Return a copy of the column data specified by its index starting at 0
+// (use the Column copy-constructor)
+Column Statement::getColumn(const int aIndex) const
+{
+ checkRow();
+ checkIndex(aIndex);
+
+ // Share the Statement Object handle with the new Column created
+ return Column(mpPreparedStatement, aIndex);
+}
+
+// Return a copy of the column data specified by its column name starting at 0
+// (use the Column copy-constructor)
+Column Statement::getColumn(const char* apName) const
+{
+ checkRow();
+ const int index = getColumnIndex(apName);
+
+ // Share the Statement Object handle with the new Column created
+ return Column(mpPreparedStatement, index);
+}
+
+// Test if the column is NULL
+bool Statement::isColumnNull(const int aIndex) const
+{
+ checkRow();
+ checkIndex(aIndex);
+ return (SQLITE_NULL == sqlite3_column_type(getPreparedStatement(), aIndex));
+}
+
+bool Statement::isColumnNull(const char* apName) const
+{
+ checkRow();
+ const int index = getColumnIndex(apName);
+ return (SQLITE_NULL == sqlite3_column_type(getPreparedStatement(), index));
+}
+
+// Return the named assigned to the specified result column (potentially aliased)
+const char* Statement::getColumnName(const int aIndex) const
+{
+ checkIndex(aIndex);
+ return sqlite3_column_name(getPreparedStatement(), aIndex);
+}
+
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
+// Return the named assigned to the specified result column (potentially aliased)
+const char* Statement::getColumnOriginName(const int aIndex) const
+{
+ checkIndex(aIndex);
+ return sqlite3_column_origin_name(getPreparedStatement(), aIndex);
+}
+#endif
+
+// Return the index of the specified (potentially aliased) column name
+int Statement::getColumnIndex(const char* apName) const
+{
+ // Build the map of column index by name on first call
+ if (mColumnNames.empty())
+ {
+ for (int i = 0; i < mColumnCount; ++i)
+ {
+ const char* pName = sqlite3_column_name(getPreparedStatement(), i);
+ mColumnNames[pName] = i;
+ }
+ }
+
+ const auto iIndex = mColumnNames.find(apName);
+ if (iIndex == mColumnNames.end())
+ {
+ throw SQLite::Exception("Unknown column name.");
+ }
+
+ return iIndex->second;
+}
+
+const char * Statement::getColumnDeclaredType(const int aIndex) const
+{
+ checkIndex(aIndex);
+ const char * result = sqlite3_column_decltype(getPreparedStatement(), aIndex);
+ if (!result)
+ {
+ throw SQLite::Exception("Could not determine declared column type.");
+ }
+ else
+ {
+ return result;
+ }
+}
+
+// Get number of rows modified by last INSERT, UPDATE or DELETE statement (not DROP table).
+int Statement::getChanges() const noexcept
+{
+ return sqlite3_changes(mpSQLite);
+}
+
+int Statement::getBindParameterCount() const noexcept
+{
+ return sqlite3_bind_parameter_count(mpPreparedStatement.get());
+}
+
+// Return the numeric result code for the most recent failed API call (if any).
+int Statement::getErrorCode() const noexcept
+{
+ return sqlite3_errcode(mpSQLite);
+}
+
+// Return the extended numeric result code for the most recent failed API call (if any).
+int Statement::getExtendedErrorCode() const noexcept
+{
+ return sqlite3_extended_errcode(mpSQLite);
+}
+
+// Return UTF-8 encoded English language explanation of the most recent failed API call (if any).
+const char* Statement::getErrorMsg() const noexcept
+{
+ return sqlite3_errmsg(mpSQLite);
+}
+
+// Return a UTF-8 string containing the SQL text of prepared statement with bound parameters expanded.
+std::string Statement::getExpandedSQL() const {
+ char* expanded = sqlite3_expanded_sql(getPreparedStatement());
+ std::string expandedString(expanded);
+ sqlite3_free(expanded);
+ return expandedString;
+}
+
+// Prepare SQLite statement object and return shared pointer to this object
+Statement::TStatementPtr Statement::prepareStatement()
+{
+ sqlite3_stmt* statement;
+ const int ret = sqlite3_prepare_v2(mpSQLite, mQuery.c_str(), static_cast<int>(mQuery.size()), &statement, nullptr);
+ if (SQLITE_OK != ret)
+ {
+ throw SQLite::Exception(mpSQLite, ret);
+ }
+ return Statement::TStatementPtr(statement, [](sqlite3_stmt* stmt)
+ {
+ sqlite3_finalize(stmt);
+ });
+}
+
+// Return prepered statement object or throw
+sqlite3_stmt* Statement::getPreparedStatement() const
+{
+ sqlite3_stmt* ret = mpPreparedStatement.get();
+ if (ret)
+ {
+ return ret;
+ }
+ throw SQLite::Exception("Statement was not prepared.");
+}
+
+} // namespace SQLite
diff --git a/3rdparty/sqlitecpp/source/SQLiteCpp/Statement.h b/3rdparty/sqlitecpp/source/SQLiteCpp/Statement.h
new file mode 100644
index 0000000..c81e215
--- /dev/null
+++ b/3rdparty/sqlitecpp/source/SQLiteCpp/Statement.h
@@ -0,0 +1,714 @@
+/**
+ * @file Statement.h
+ * @ingroup SQLiteCpp
+ * @brief A prepared SQLite Statement is a compiled SQL query ready to be executed, pointing to a row of result.
+ *
+ * Copyright (c) 2012-2021 Sebastien Rombauts ([email protected])
+ *
+ * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
+ * or copy at http://opensource.org/licenses/MIT)
+ */
+#pragma once
+
+#include <SQLiteCpp/Exception.h>
+#include <SQLiteCpp/Utils.h> // SQLITECPP_PURE_FUNC
+
+#include <string>
+#include <map>
+#include <memory>
+
+// Forward declarations to avoid inclusion of <sqlite3.h> in a header
+struct sqlite3;
+struct sqlite3_stmt;
+
+
+namespace SQLite
+{
+
+
+// Forward declaration
+class Database;
+class Column;
+
+extern const int OK; ///< SQLITE_OK
+
+/**
+ * @brief RAII encapsulation of a prepared SQLite Statement.
+ *
+ * A Statement is a compiled SQL query ready to be executed step by step
+ * to provide results one row at a time.
+ *
+ * Resource Acquisition Is Initialization (RAII) means that the Statement
+ * is compiled in the constructor and finalized in the destructor, so that there is
+ * no need to worry about memory management or the validity of the underlying SQLite Statement.
+ *
+ * Thread-safety: a Statement 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 Statement
+{
+public:
+ /**
+ * @brief Compile and register the SQL query for the provided SQLite Database Connection
+ *
+ * @param[in] aDatabase the SQLite Database Connection
+ * @param[in] apQuery an UTF-8 encoded query string
+ *
+ * Exception is thrown in case of error, then the Statement object is NOT constructed.
+ */
+ Statement(const Database& aDatabase, const char* apQuery);
+
+ /**
+ * @brief Compile and register the SQL query for the provided SQLite Database Connection
+ *
+ * @param[in] aDatabase the SQLite Database Connection
+ * @param[in] aQuery an UTF-8 encoded query string
+ *
+ * Exception is thrown in case of error, then the Statement object is NOT constructed.
+ */
+ Statement(const Database& aDatabase, const std::string& aQuery) :
+ Statement(aDatabase, aQuery.c_str())
+ {}
+
+ /**
+ * @brief Move an SQLite statement.
+ *
+ * @param[in] aStatement Statement to move
+ */
+ Statement(Statement&& aStatement) noexcept;
+ Statement& operator=(Statement&& aStatement) noexcept = default;
+
+ // Statement is non-copyable
+ Statement(const Statement&) = delete;
+ Statement& operator=(const Statement&) = delete;
+
+ /// Finalize and unregister the SQL query from the SQLite Database Connection.
+ /// The finalization will be done by the destructor of the last shared pointer
+ ~Statement() = default;
+
+ /// Reset the statement to make it ready for a new execution. Throws an exception on error.
+ void reset();
+
+ /// Reset the statement. Returns the sqlite result code instead of throwing an exception on error.
+ int tryReset() noexcept;
+
+ /**
+ * @brief Clears away all the bindings of a prepared statement.
+ *
+ * Contrary to the intuition of many, reset() does not reset the bindings on a prepared statement.
+ * Use this routine to reset all parameters to NULL.
+ */
+ void clearBindings(); // throw(SQLite::Exception)
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Bind a value to a parameter of the SQL statement,
+ // in the form "?" (unnamed), "?NNN", ":VVV", "@VVV" or "$VVV".
+ //
+ // Can use the parameter index, starting from "1", to the higher NNN value,
+ // or the complete parameter name "?NNN", ":VVV", "@VVV" or "$VVV"
+ // (prefixed with the corresponding sign "?", ":", "@" or "$")
+ //
+ // Note that for text and blob values, the SQLITE_TRANSIENT flag is used,
+ // which tell the sqlite library to make its own copy of the data before the bind() call returns.
+ // This choice is done to prevent any common misuses, like passing a pointer to a
+ // dynamic allocated and temporary variable (a std::string for instance).
+ // This is under-optimized for static data (a static text define in code)
+ // as well as for dynamic allocated buffer which could be transfer to sqlite
+ // instead of being copied.
+ // => if you know what you are doing, use bindNoCopy() instead of bind()
+
+ SQLITECPP_PURE_FUNC
+ int getIndex(const char * const apName) const;
+
+ /**
+ * @brief Bind an int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ */
+ void bind(const int aIndex, const int32_t aValue);
+ /**
+ * @brief Bind a 32bits unsigned int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ */
+ void bind(const int aIndex, const uint32_t aValue);
+ /**
+ * @brief Bind a 64bits int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ */
+ void bind(const int aIndex, const int64_t aValue);
+ /**
+ * @brief Bind a double (64bits float) value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ */
+ void bind(const int aIndex, const double aValue);
+ /**
+ * @brief Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ *
+ * @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
+ */
+ void bind(const int aIndex, const std::string& aValue);
+ /**
+ * @brief Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ *
+ * @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
+ */
+ void bind(const int aIndex, const char* apValue);
+ /**
+ * @brief Bind a binary blob value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ *
+ * @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
+ */
+ void bind(const int aIndex, const void* apValue, const int aSize);
+ /**
+ * @brief Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1).
+ *
+ * The string can contain null characters as it is binded using its size.
+ *
+ * @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement.
+ */
+ void bindNoCopy(const int aIndex, const std::string& aValue);
+ /**
+ * @brief Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ *
+ * Main usage is with null-terminated literal text (aka in code static strings)
+ *
+ * @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement.
+ */
+ void bindNoCopy(const int aIndex, const char* apValue);
+ /**
+ * @brief Bind a binary blob value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ *
+ * @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement.
+ */
+ void bindNoCopy(const int aIndex, const void* apValue, const int aSize);
+ /**
+ * @brief Bind a NULL value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ *
+ * @see clearBindings() to set all bound parameters to NULL.
+ */
+ void bind(const int aIndex);
+
+ /**
+ * @brief Bind an int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ */
+ void bind(const char* apName, const int32_t aValue)
+ {
+ bind(getIndex(apName), aValue);
+ }
+ /**
+ * @brief Bind a 32bits unsigned int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ */
+ void bind(const char* apName, const uint32_t aValue)
+ {
+ bind(getIndex(apName), aValue);
+ }
+ /**
+ * @brief Bind a 64bits int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ */
+ void bind(const char* apName, const int64_t aValue)
+ {
+ bind(getIndex(apName), aValue);
+ }
+ /**
+ * @brief Bind a double (64bits float) value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ */
+ void bind(const char* apName, const double aValue)
+ {
+ bind(getIndex(apName), aValue);
+ }
+ /**
+ * @brief Bind a string value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ *
+ * @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
+ */
+ void bind(const char* apName, const std::string& aValue)
+ {
+ bind(getIndex(apName), aValue);
+ }
+ /**
+ * @brief Bind a text value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ *
+ * @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
+ */
+ void bind(const char* apName, const char* apValue)
+ {
+ bind(getIndex(apName), apValue);
+ }
+ /**
+ * @brief Bind a binary blob value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ *
+ * @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
+ */
+ void bind(const char* apName, const void* apValue, const int aSize)
+ {
+ bind(getIndex(apName), apValue, aSize);
+ }
+ /**
+ * @brief Bind a string value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ *
+ * The string can contain null characters as it is binded using its size.
+ *
+ * @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement.
+ */
+ void bindNoCopy(const char* apName, const std::string& aValue)
+ {
+ bindNoCopy(getIndex(apName), aValue);
+ }
+ /**
+ * @brief Bind a text value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ *
+ * Main usage is with null-terminated literal text (aka in code static strings)
+ *
+ * @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement.
+ */
+ void bindNoCopy(const char* apName, const char* apValue)
+ {
+ bindNoCopy(getIndex(apName), apValue);
+ }
+ /**
+ * @brief Bind a binary blob value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ *
+ * @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement.
+ */
+ void bindNoCopy(const char* apName, const void* apValue, const int aSize)
+ {
+ bindNoCopy(getIndex(apName), apValue, aSize);
+ }
+ /**
+ * @brief Bind a NULL value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ *
+ * @see clearBindings() to set all bound parameters to NULL.
+ */
+ void bind(const char* apName) // bind NULL value
+ {
+ bind(getIndex(apName));
+ }
+
+
+ /**
+ * @brief Bind an int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ */
+ void bind(const std::string& aName, const int32_t aValue)
+ {
+ bind(aName.c_str(), aValue);
+ }
+ /**
+ * @brief Bind a 32bits unsigned int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ */
+ void bind(const std::string& aName, const uint32_t aValue)
+ {
+ bind(aName.c_str(), aValue);
+ }
+ /**
+ * @brief Bind a 64bits int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ */
+ void bind(const std::string& aName, const int64_t aValue)
+ {
+ bind(aName.c_str(), aValue);
+ }
+ /**
+ * @brief Bind a double (64bits float) value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ */
+ void bind(const std::string& aName, const double aValue)
+ {
+ bind(aName.c_str(), aValue);
+ }
+ /**
+ * @brief Bind a string value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ *
+ * @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
+ */
+ void bind(const std::string& aName, const std::string& aValue)
+ {
+ bind(aName.c_str(), aValue);
+ }
+ /**
+ * @brief Bind a text value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ *
+ * @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
+ */
+ void bind(const std::string& aName, const char* apValue)
+ {
+ bind(aName.c_str(), apValue);
+ }
+ /**
+ * @brief Bind a binary blob value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ *
+ * @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
+ */
+ void bind(const std::string& aName, const void* apValue, const int aSize)
+ {
+ bind(aName.c_str(), apValue, aSize);
+ }
+ /**
+ * @brief Bind a string value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ *
+ * The string can contain null characters as it is binded using its size.
+ *
+ * @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement.
+ */
+ void bindNoCopy(const std::string& aName, const std::string& aValue)
+ {
+ bindNoCopy(aName.c_str(), aValue);
+ }
+ /**
+ * @brief Bind a text value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ *
+ * Main usage is with null-terminated literal text (aka in code static strings)
+ *
+ * @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement.
+ */
+ void bindNoCopy(const std::string& aName, const char* apValue)
+ {
+ bindNoCopy(aName.c_str(), apValue);
+ }
+ /**
+ * @brief Bind a binary blob value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ *
+ * @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement.
+ */
+ void bindNoCopy(const std::string& aName, const void* apValue, const int aSize)
+ {
+ bindNoCopy(aName.c_str(), apValue, aSize);
+ }
+ /**
+ * @brief Bind a NULL value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
+ *
+ * @see clearBindings() to set all bound parameters to NULL.
+ */
+ void bind(const std::string& aName) // bind NULL value
+ {
+ bind(aName.c_str());
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * @brief Execute a step of the prepared query to fetch one row of results.
+ *
+ * While true is returned, a row of results is available, and can be accessed
+ * through the getColumn() method
+ *
+ * @see exec() execute a one-step prepared statement with no expected result
+ * @see tryExecuteStep() try to execute a step of the prepared query to fetch one row of results, returning the sqlite result code.
+ * @see Database::exec() is a shortcut to execute one or multiple statements without results
+ *
+ * @return - true (SQLITE_ROW) if there is another row ready : you can call getColumn(N) to get it
+ * then you have to call executeStep() again to fetch more rows until the query is finished
+ * - false (SQLITE_DONE) if the query has finished executing : there is no (more) row of result
+ * (case of a query with no result, or after N rows fetched successfully)
+ *
+ * @throw SQLite::Exception in case of error
+ */
+ bool executeStep();
+
+ /**
+ * @brief Try to execute a step of the prepared query to fetch one row of results, returning the sqlite result code.
+ *
+ *
+ *
+ * @see exec() execute a one-step prepared statement with no expected result
+ * @see executeStep() execute a step of the prepared query to fetch one row of results
+ * @see Database::exec() is a shortcut to execute one or multiple statements without results
+ *
+ * @return the sqlite result code.
+ */
+ int tryExecuteStep() noexcept;
+
+ /**
+ * @brief Execute a one-step query with no expected result, and return the number of changes.
+ *
+ * This method is useful for any kind of statements other than the Data Query Language (DQL) "SELECT" :
+ * - Data Definition Language (DDL) statements "CREATE", "ALTER" and "DROP"
+ * - Data Manipulation Language (DML) statements "INSERT", "UPDATE" and "DELETE"
+ * - Data Control Language (DCL) statements "GRANT", "REVOKE", "COMMIT" and "ROLLBACK"
+ *
+ * It is similar to Database::exec(), but using a precompiled statement, it adds :
+ * - the ability to bind() arguments to it (best way to insert data),
+ * - reusing it allows for better performances (efficient for multiple insertion).
+ *
+ * @see executeStep() execute a step of the prepared query to fetch one row of results
+ * @see tryExecuteStep() try to execute a step of the prepared query to fetch one row of results, returning the sqlite result code.
+ * @see Database::exec() is a shortcut to execute one or multiple statements without results
+ *
+ * @return number of row modified by this SQL statement (INSERT, UPDATE or DELETE)
+ *
+ * @throw SQLite::Exception in case of error, or if row of results are returned while they are not expected!
+ */
+ int exec();
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * @brief Return a copy of the column data specified by its index
+ *
+ * Can be used to access the data of the current row of result when applicable,
+ * while the executeStep() method returns true.
+ *
+ * Throw an exception if there is no row to return a Column from:
+ * - if provided index is out of bound
+ * - before any executeStep() call
+ * - after the last executeStep() returned false
+ * - after a reset() call
+ *
+ * Throw an exception if the specified index is out of the [0, getColumnCount()) range.
+ *
+ * @param[in] aIndex Index of the column, starting at 0
+ *
+ * @note This method is not const, reflecting the fact that the returned Column object will
+ * share the ownership of the underlying sqlite3_stmt.
+ *
+ * @warning The resulting Column object must not be memorized "as-is".
+ * Is is only a wrapper around the current result row, so it is only valid
+ * while the row from the Statement remains valid, that is only until next executeStep() call.
+ * Thus, you should instead extract immediately its data (getInt(), getText()...)
+ * and use or copy this data for any later usage.
+ */
+ Column getColumn(const int aIndex) const;
+
+ /**
+ * @brief Return a copy of the column data specified by its column name (less efficient than using an index)
+ *
+ * Can be used to access the data of the current row of result when applicable,
+ * while the executeStep() method returns true.
+ *
+ * Throw an exception if there is no row to return a Column from :
+ * - if provided name is not one of the aliased column names
+ * - before any executeStep() call
+ * - after the last executeStep() returned false
+ * - after a reset() call
+ *
+ * Throw an exception if the specified name is not an on of the aliased name of the columns in the result.
+ *
+ * @param[in] apName Aliased name of the column, that is, the named specified in the query (not the original name)
+ *
+ * @note Uses a map of column names to indexes, build on first call.
+ *
+ * @note This method is not const, reflecting the fact that the returned Column object will
+ * share the ownership of the underlying sqlite3_stmt.
+ *
+ * @warning The resulting Column object must not be memorized "as-is".
+ * Is is only a wrapper around the current result row, so it is only valid
+ * while the row from the Statement remains valid, that is only until next executeStep() call.
+ * Thus, you should instead extract immediately its data (getInt(), getText()...)
+ * and use or copy this data for any later usage.
+ *
+ * Throw an exception if the specified name is not one of the aliased name of the columns in the result.
+ */
+ Column getColumn(const char* apName) const;
+
+#if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900) // c++14: Visual Studio 2015
+ /**
+ * @brief Return an instance of T constructed from copies of the first N columns
+ *
+ * Can be used to access the data of the current row of result when applicable,
+ * while the executeStep() method returns true.
+ *
+ * Throw an exception if there is no row to return a Column from:
+ * - if provided column count is out of bound
+ * - before any executeStep() call
+ * - after the last executeStep() returned false
+ * - after a reset() call
+ *
+ * Throw an exception if the specified column count is out of the [0, getColumnCount()) range.
+ *
+ * @tparam T Object type to construct
+ * @tparam N Number of columns
+ *
+ * @note Requires std=C++14
+ */
+ template<typename T, int N>
+ T getColumns();
+
+private:
+ /**
+ * @brief Helper function used by getColumns<typename T, int N> to expand an integer_sequence used to generate
+ * the required Column objects
+ */
+ template<typename T, const int... Is>
+ T getColumns(const std::integer_sequence<int, Is...>);
+
+public:
+#endif
+
+ /**
+ * @brief Test if the column value is NULL
+ *
+ * @param[in] aIndex Index of the column, starting at 0
+ *
+ * @return true if the column value is NULL
+ *
+ * Throw an exception if the specified index is out of the [0, getColumnCount()) range.
+ */
+ bool isColumnNull(const int aIndex) const;
+
+ /**
+ * @brief Test if the column value is NULL
+ *
+ * @param[in] apName Aliased name of the column, that is, the named specified in the query (not the original name)
+ *
+ * @return true if the column value is NULL
+ *
+ * Throw an exception if the specified name is not one of the aliased name of the columns in the result.
+ */
+ bool isColumnNull(const char* apName) const;
+
+ /**
+ * @brief Return a pointer to the named assigned to the specified result column (potentially aliased)
+ *
+ * @param[in] aIndex Index of the column in the range [0, getColumnCount()).
+ *
+ * @see getColumnOriginName() to get original column name (not aliased)
+ *
+ * Throw an exception if the specified index is out of the [0, getColumnCount()) range.
+ */
+ const char* getColumnName(const int aIndex) const;
+
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
+ /**
+ * @brief Return a pointer to the table column name that is the origin of the specified result column
+ *
+ * Require definition of the SQLITE_ENABLE_COLUMN_METADATA preprocessor macro :
+ * - when building the SQLite library itself (which is the case for the Debian libsqlite3 binary for instance),
+ * - and also when compiling this wrapper.
+ *
+ * Throw an exception if the specified index is out of the [0, getColumnCount()) range.
+ */
+ const char* getColumnOriginName(const int aIndex) const;
+#endif
+
+ /**
+ * @brief Return the index of the specified (potentially aliased) column name
+ *
+ * @param[in] apName Aliased name of the column, that is, the named specified in the query (not the original name)
+ *
+ * @note Uses a map of column names to indexes, build on first call.
+ *
+ * Throw an exception if the specified name is not known.
+ */
+ int getColumnIndex(const char* apName) const;
+
+
+ /**
+ * @brief Return the declared type of the specified result column for a SELECT statement.
+ *
+ * This is the type given at creation of the column and not the actual data type.
+ * SQLite stores data types dynamically for each value and not per column.
+ *
+ * @param[in] aIndex Index of the column in the range [0, getColumnCount()).
+ *
+ * Throw an exception if the type can't be determined because:
+ * - the specified index is out of the [0, getColumnCount()) range
+ * - the statement is not a SELECT query
+ * - the column at aIndex is not a table column but an expression or subquery
+ */
+ const char * getColumnDeclaredType(const int aIndex) const;
+
+
+ /// Get number of rows modified by last INSERT, UPDATE or DELETE statement (not DROP table).
+ int getChanges() const noexcept;
+
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ /// Return the UTF-8 SQL Query.
+ const std::string& getQuery() const
+ {
+ return mQuery;
+ }
+
+ // Return a UTF-8 string containing the SQL text of prepared statement with bound parameters expanded.
+ std::string getExpandedSQL() const;
+
+ /// Return the number of columns in the result set returned by the prepared statement
+ int getColumnCount() const
+ {
+ return mColumnCount;
+ }
+ /// true when a row has been fetched with executeStep()
+ bool hasRow() const
+ {
+ return mbHasRow;
+ }
+ /// true when the last executeStep() had no more row to fetch
+ bool isDone() const
+ {
+ return mbDone;
+ }
+
+ /// Return the number of bind parameters in the statement
+ int getBindParameterCount() 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;
+
+ /// Shared pointer to SQLite Prepared Statement Object
+ using TStatementPtr = std::shared_ptr<sqlite3_stmt>;
+
+private:
+ /**
+ * @brief Check if a return code equals SQLITE_OK, else throw a SQLite::Exception with the SQLite error message
+ *
+ * @param[in] aRet SQLite return code to test against the SQLITE_OK expected value
+ */
+ void check(const int aRet) const
+ {
+ if (SQLite::OK != aRet)
+ {
+ throw SQLite::Exception(mpSQLite, aRet);
+ }
+ }
+
+ /**
+ * @brief Check if there is a row of result returned by executeStep(), else throw a SQLite::Exception.
+ */
+ void checkRow() const
+ {
+ if (false == mbHasRow)
+ {
+ throw SQLite::Exception("No row to get a column from. executeStep() was not called, or returned false.");
+ }
+ }
+
+ /**
+ * @brief Check if there is a Column index is in the range of columns in the result.
+ */
+ void checkIndex(const int aIndex) const
+ {
+ if ((aIndex < 0) || (aIndex >= mColumnCount))
+ {
+ throw SQLite::Exception("Column index out of range.");
+ }
+ }
+
+ /**
+ * @brief Prepare statement object.
+ *
+ * @return Shared pointer to prepared statement object
+ */
+ TStatementPtr prepareStatement();
+
+ /**
+ * @brief Return a prepared statement object.
+ *
+ * Throw an exception if the statement object was not prepared.
+ * @return raw pointer to Prepared Statement Object
+ */
+ sqlite3_stmt* getPreparedStatement() const;
+
+ std::string mQuery; //!< UTF-8 SQL Query
+ sqlite3* mpSQLite; //!< Pointer to SQLite Database Connection Handle
+ TStatementPtr mpPreparedStatement; //!< Shared Pointer to the prepared SQLite Statement Object
+ int mColumnCount{0}; //!< Number of columns in the result of the prepared statement
+ bool mbHasRow{false}; //!< true when a row has been fetched with executeStep()
+ bool mbDone{false}; //!< true when the last executeStep() had no more row to fetch
+
+ /// Map of columns index by name (mutable so getColumnIndex can be const)
+ mutable std::map<std::string, int> mColumnNames{};
+};
+
+
+} // namespace SQLite
diff --git a/3rdparty/sqlitecpp/source/SQLiteCpp/Transaction.cpp b/3rdparty/sqlitecpp/source/SQLiteCpp/Transaction.cpp
new file mode 100644
index 0000000..2a8857a
--- /dev/null
+++ b/3rdparty/sqlitecpp/source/SQLiteCpp/Transaction.cpp
@@ -0,0 +1,83 @@
+/**
+ * @file Transaction.cpp
+ * @ingroup SQLiteCpp
+ * @brief A Transaction is way to group multiple SQL statements into an atomic secured operation.
+ *
+ * Copyright (c) 2012-2019 Sebastien Rombauts ([email protected])
+ *
+ * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
+ * or copy at http://opensource.org/licenses/MIT)
+ */
+#include <SQLiteCpp/Transaction.h>
+
+#include <SQLiteCpp/Database.h>
+#include <SQLiteCpp/Assertion.h>
+
+#include <sqlite3.h>
+
+namespace SQLite
+{
+
+
+// Begins the SQLite transaction
+Transaction::Transaction(Database& aDatabase, TransactionBehavior behavior) :
+ mDatabase(aDatabase),
+ mbCommited(false)
+{
+ const char *stmt;
+ switch (behavior) {
+ case TransactionBehavior::DEFERRED:
+ stmt = "BEGIN DEFERRED";
+ break;
+ case TransactionBehavior::IMMEDIATE:
+ stmt = "BEGIN IMMEDIATE";
+ break;
+ case TransactionBehavior::EXCLUSIVE:
+ stmt = "BEGIN EXCLUSIVE";
+ break;
+ default:
+ throw SQLite::Exception("invalid/unknown transaction behavior", SQLITE_ERROR);
+ }
+ mDatabase.exec(stmt);
+}
+
+// Begins the SQLite transaction
+Transaction::Transaction(Database &aDatabase) :
+ mDatabase(aDatabase),
+ mbCommited(false)
+{
+ mDatabase.exec("BEGIN");
+}
+
+// Safely rollback the transaction if it has not been committed.
+Transaction::~Transaction()
+{
+ if (false == mbCommited)
+ {
+ try
+ {
+ mDatabase.exec("ROLLBACK");
+ }
+ catch (SQLite::Exception&)
+ {
+ // Never throw an exception in a destructor: error if already rollbacked, but no harm is caused by this.
+ }
+ }
+}
+
+// Commit the transaction.
+void Transaction::commit()
+{
+ if (false == mbCommited)
+ {
+ mDatabase.exec("COMMIT");
+ mbCommited = true;
+ }
+ else
+ {
+ throw SQLite::Exception("Transaction already committed.");
+ }
+}
+
+
+} // namespace SQLite
diff --git a/3rdparty/sqlitecpp/source/SQLiteCpp/Transaction.h b/3rdparty/sqlitecpp/source/SQLiteCpp/Transaction.h
new file mode 100644
index 0000000..d7f26ca
--- /dev/null
+++ b/3rdparty/sqlitecpp/source/SQLiteCpp/Transaction.h
@@ -0,0 +1,95 @@
+/**
+ * @file Transaction.h
+ * @ingroup SQLiteCpp
+ * @brief A Transaction is way to group multiple SQL statements into an atomic secured operation.
+ *
+ * Copyright (c) 2012-2021 Sebastien Rombauts ([email protected])
+ *
+ * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
+ * or copy at http://opensource.org/licenses/MIT)
+ */
+#pragma once
+
+#include <SQLiteCpp/Exception.h>
+
+
+namespace SQLite
+{
+
+
+// Forward declaration
+class Database;
+
+/**
+ * @brief Transaction behaviors when opening an SQLite transaction.
+ * Names correspond directly to the behavior.
+ */
+enum class TransactionBehavior {
+ DEFERRED,
+ IMMEDIATE,
+ EXCLUSIVE,
+};
+
+/**
+ * @brief RAII encapsulation of a SQLite Transaction.
+ *
+ * A Transaction is a way to group multiple SQL statements into an atomic secured operation;
+ * either it succeeds, with all the changes committed to the database file,
+ * or if it fails, all the changes are rolled back to the initial state.
+ *
+ * Resource Acquisition Is Initialization (RAII) means that the Transaction
+ * begins in the constructor and is rollbacked in the destructor, so that there is
+ * no need to worry about memory management or the validity of the underlying SQLite Connection.
+ *
+ * This method also offers big performances improvements compared to individually executed statements.
+ *
+ * Thread-safety: a Transaction 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 Transaction
+{
+public:
+ /**
+ * @brief Begins the SQLite transaction using the default transaction behavior.
+ *
+ * @param[in] aDatabase the SQLite Database Connection
+ *
+ * Exception is thrown in case of error, then the Transaction is NOT initiated.
+ */
+ explicit Transaction(Database& aDatabase);
+
+ /**
+ * @brief Begins the SQLite transaction with the specified behavior.
+ *
+ * @param[in] aDatabase the SQLite Database Connection
+ * @param[in] behavior the requested transaction behavior
+ *
+ * Exception is thrown in case of error, then the Transaction is NOT initiated.
+ */
+ explicit Transaction(Database& aDatabase, TransactionBehavior behavior);
+
+ // Transaction is non-copyable
+ Transaction(const Transaction&) = delete;
+ Transaction& operator=(const Transaction&) = delete;
+
+ /**
+ * @brief Safely rollback the transaction if it has not been committed.
+ */
+ ~Transaction();
+
+ /**
+ * @brief Commit the transaction.
+ */
+ void commit();
+
+private:
+ Database& mDatabase; ///< Reference to the SQLite Database Connection
+ bool mbCommited; ///< True when commit has been called
+};
+
+
+} // namespace SQLite
diff --git a/3rdparty/sqlitecpp/source/SQLiteCpp/Utils.h b/3rdparty/sqlitecpp/source/SQLiteCpp/Utils.h
new file mode 100644
index 0000000..f053b3f
--- /dev/null
+++ b/3rdparty/sqlitecpp/source/SQLiteCpp/Utils.h
@@ -0,0 +1,31 @@
+/**
+ * @file Utils.h
+ * @ingroup SQLiteCpp
+ * @brief Definition of the SQLITECPP_PURE_FUNC macro.
+ *
+ * Copyright (c) 2012-2020 Sebastien Rombauts ([email protected])
+ *
+ * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
+ * or copy at http://opensource.org/licenses/MIT)
+ */
+#pragma once
+
+// macro taken from https://github.com/nemequ/hedley/blob/master/hedley.h that was in public domain at this time
+#if defined(__GNUC__) || defined(__GNUG__) || defined(__clang__) ||\
+(defined(__INTEL_COMPILER) && __INTEL_COMPILER > 1600) ||\
+(defined(__ARMCC_VERSION) && __ARMCC_VERSION > 4010000) ||\
+(\
+ defined(__TI_COMPILER_VERSION__) && (\
+ __TI_COMPILER_VERSION__ > 8003000 ||\
+ (__TI_COMPILER_VERSION__ > 7003000 && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))\
+ )\
+)
+#if defined(__has_attribute)
+#if !defined(SQLITECPP_PURE_FUNC) && __has_attribute(pure)
+#define SQLITECPP_PURE_FUNC __attribute__((pure))
+#endif
+#endif
+#endif
+#if !defined(SQLITECPP_PURE_FUNC)
+#define SQLITECPP_PURE_FUNC
+#endif
diff --git a/3rdparty/sqlitecpp/source/SQLiteCpp/VariadicBind.h b/3rdparty/sqlitecpp/source/SQLiteCpp/VariadicBind.h
new file mode 100644
index 0000000..e82b436
--- /dev/null
+++ b/3rdparty/sqlitecpp/source/SQLiteCpp/VariadicBind.h
@@ -0,0 +1,98 @@
+/**
+ * @file VariadicBind.h
+ * @ingroup SQLiteCpp
+ * @brief Convenience function for Statement::bind(...)
+ *
+ * Copyright (c) 2016 Paul Dreik ([email protected])
+ * Copyright (c) 2016-2021 Sebastien Rombauts ([email protected])
+ * Copyright (c) 2019 Maximilian Bachmann ([email protected])
+ *
+ * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
+ * or copy at http://opensource.org/licenses/MIT)
+ */
+#pragma once
+
+#include <SQLiteCpp/Statement.h>
+
+#if (__cplusplus >= 201402L) || ( defined(_MSC_VER) && (_MSC_VER >= 1900) ) // c++14: Visual Studio 2015
+#include <tuple>
+#endif // c++14
+
+/// @cond
+#include <utility>
+#include <initializer_list>
+
+namespace SQLite
+{
+/// @endcond
+
+/**
+ * \brief Convenience function for calling Statement::bind(...) once for each argument given.
+ *
+ * This takes care of incrementing the index between each calls to bind.
+ *
+ * This feature requires a c++11 capable compiler.
+ *
+ * \code{.cpp}
+ * SQLite::Statement stm("SELECT * FROM MyTable WHERE colA>? && colB=? && colC<?");
+ * SQLite::bind(stm,a,b,c);
+ * //...is equivalent to
+ * stm.bind(1,a);
+ * stm.bind(2,b);
+ * stm.bind(3,c);
+ * \endcode
+ * @param query statement
+ * @param args zero or more args to bind.
+ */
+template<class ...Args>
+void bind(SQLite::Statement& query, const Args& ... args)
+{
+ int pos = 0;
+ (void)std::initializer_list<int>{
+ ((void)query.bind(++pos, std::forward<decltype(args)>(args)), 0)...
+ };
+}
+
+#if (__cplusplus >= 201402L) || ( defined(_MSC_VER) && (_MSC_VER >= 1900) ) // c++14: Visual Studio 2015
+
+/**
+ * \brief Convenience function for calling Statement::bind(...) once for each parameter of a tuple,
+ * by forwarding them to the variadic template
+ *
+ * This feature requires a c++14 capable compiler.
+ *
+ * \code{.cpp}
+ * SQLite::Statement stm("SELECT * FROM MyTable WHERE colA>? && colB=? && colC<?");
+ * SQLite::bind(stm, std::make_tuple(a, b, c));
+ * //...is equivalent to
+ * stm.bind(1,a);
+ * stm.bind(2,b);
+ * stm.bind(3,c);
+ * \endcode
+ * @param query statement
+ * @param tuple tuple with values to bind
+ */
+template <typename ... Types>
+void bind(SQLite::Statement& query, const std::tuple<Types...> &tuple)
+{
+ bind(query, tuple, std::index_sequence_for<Types...>());
+}
+
+/**
+ * \brief Convenience function for calling Statement::bind(...) once for each parameter of a tuple,
+ * by forwarding them to the variadic template. This function is just needed to convert the tuples
+ * to parameter packs
+ *
+ * This feature requires a c++14 capable compiler.
+ *
+ * @param query statement
+ * @param tuple tuple with values to bind
+ */
+template <typename ... Types, std::size_t ... Indices>
+void bind(SQLite::Statement& query, const std::tuple<Types...> &tuple, std::index_sequence<Indices...>)
+{
+ bind(query, std::get<Indices>(tuple)...);
+}
+#endif // c++14
+
+} // namespace SQLite