diff --git a/src/common/repository/KeyValueRepositoryFile.hxx b/src/common/repository/KeyValueRepositoryFile.hxx index 46a2a9941..23bccb891 100644 --- a/src/common/repository/KeyValueRepositoryFile.hxx +++ b/src/common/repository/KeyValueRepositoryFile.hxx @@ -40,7 +40,7 @@ class KeyValueRepositoryFile : public KeyValueRepository { }; /////////////////////////////////////////////////////////////////////////////// -// IMPLEMEMNTATION +// IMPLEMENTATION /////////////////////////////////////////////////////////////////////////////// // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/common/repository/sqlite/CompositeKeyValueRepositorySqlite.cxx b/src/common/repository/sqlite/CompositeKeyValueRepositorySqlite.cxx index 02bcf797c..c4dab8e33 100644 --- a/src/common/repository/sqlite/CompositeKeyValueRepositorySqlite.cxx +++ b/src/common/repository/sqlite/CompositeKeyValueRepositorySqlite.cxx @@ -21,8 +21,14 @@ #include "bspf.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CompositeKeyValueRepositorySqlite::CompositeKeyValueRepositorySqlite(SqliteDatabase& db, const string& tableName) - : myTableName{tableName}, myDb{db} +CompositeKeyValueRepositorySqlite::CompositeKeyValueRepositorySqlite( + SqliteDatabase& db, + const string& tableName, + const string& colKey1, + const string& colKey2, + const string& colValue +) + : myDb{db}, myTableName{tableName}, myColKey1(colKey1), myColKey2(colKey2), myColValue(colValue) {} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -73,16 +79,61 @@ void CompositeKeyValueRepositorySqlite::remove(const string& key) void CompositeKeyValueRepositorySqlite::initialize() { myDb.exec( - "CREATE TABLE IF NOT EXISTS `" + myTableName + "` (`key1` TEXT, `key2` TEXT, `value` TEXT, PRIMARY KEY (`key1`, `key2`)) WITHOUT ROWID" + "CREATE TABLE IF NOT EXISTS `%s` (`%s` TEXT, `%s` TEXT, `%s` TEXT, PRIMARY KEY (`%s`, `%s`)) WITHOUT ROWID", + myTableName.c_str(), + myColKey1.c_str(), + myColKey2.c_str(), + myColValue.c_str(), + myColKey1.c_str(), + myColKey2.c_str() ); - myStmtInsert = make_unique(myDb, "INSERT OR REPLACE INTO `" + myTableName + "` VALUES (?, ?, ?)"); - myStmtSelect = make_unique(myDb, "SELECT `key2`, `VALUE` FROM `" + myTableName + "` WHERE `key1` = ?"); - myStmtCountSet = make_unique(myDb, "SELECT COUNT(*) FROM `" + myTableName + "` WHERE `key1` = ?"); - myStmtDelete = make_unique(myDb, "DELETE FROM `" + myTableName + "` WHERE `key1` = ? AND `key2` = ?"); - myStmtDeleteSet = make_unique(myDb, "DELETE FROM `" + myTableName + "` WHERE `key1` = ?"); - myStmtSelectOne = make_unique(myDb, "SELECT `value` FROM `" + myTableName + "` WHERE `key1` = ? AND `key2` = ?"); - myStmtCount = make_unique(myDb, "SELECT COUNT(`key1`) FROM `" + myTableName + "` WHERE `key1` = ? AND `key2` = ?"); + myStmtInsert = make_unique(myDb, + "INSERT OR REPLACE INTO `%s` VALUES (?, ?, ?)", + myTableName.c_str() + ); + + myStmtSelect = make_unique(myDb, + "SELECT `%s`, `%s` FROM `%s` WHERE `%s` = ?", + myColKey2.c_str(), + myColValue.c_str(), + myTableName.c_str(), + myColKey1.c_str() + ); + + myStmtCountSet = make_unique(myDb, + "SELECT COUNT(*) FROM `%s` WHERE `%s` = ?", + myTableName.c_str(), + myColKey1.c_str() + ); + + myStmtDelete = make_unique(myDb, + "DELETE FROM `%s` WHERE `%s` = ? AND `%s` = ?", + myTableName.c_str(), + myColKey1.c_str(), + myColKey2.c_str() + ); + + myStmtDeleteSet = make_unique(myDb, + "DELETE FROM `%s` WHERE `%s` = ?", + myTableName.c_str(), + myColKey1.c_str() + ); + + myStmtSelectOne = make_unique(myDb, + "SELECT `%s` FROM `%s` WHERE `%s` = ? AND `%s` = ?", + myColValue.c_str(), + myTableName.c_str(), + myColKey1.c_str(), + myColKey2.c_str() + ); + + myStmtCount = make_unique(myDb, + "SELECT COUNT(*) FROM `%s` WHERE `%s` = ? AND `%s` = ?", + myTableName.c_str(), + myColKey1.c_str(), + myColKey2.c_str() + ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/common/repository/sqlite/CompositeKeyValueRepositorySqlite.hxx b/src/common/repository/sqlite/CompositeKeyValueRepositorySqlite.hxx index 33dcb5024..4d9a17be7 100644 --- a/src/common/repository/sqlite/CompositeKeyValueRepositorySqlite.hxx +++ b/src/common/repository/sqlite/CompositeKeyValueRepositorySqlite.hxx @@ -27,7 +27,13 @@ class CompositeKeyValueRepositorySqlite : public CompositeKeyValueRepository { public: - CompositeKeyValueRepositorySqlite(SqliteDatabase& db, const string& tableName); + CompositeKeyValueRepositorySqlite( + SqliteDatabase& db, + const string& tableName, + const string& colKey1, + const string& colKey2, + const string& colValue + ); shared_ptr get(const string& key) override; @@ -68,8 +74,11 @@ class CompositeKeyValueRepositorySqlite : public CompositeKeyValueRepository { private: - string myTableName; SqliteDatabase& myDb; + string myTableName; + string myColKey1; + string myColKey2; + string myColValue; unique_ptr myStmtInsert; unique_ptr myStmtSelect; diff --git a/src/common/repository/sqlite/KeyValueRepositorySqlite.cxx b/src/common/repository/sqlite/KeyValueRepositorySqlite.cxx index 1a18272f2..c25de5832 100644 --- a/src/common/repository/sqlite/KeyValueRepositorySqlite.cxx +++ b/src/common/repository/sqlite/KeyValueRepositorySqlite.cxx @@ -20,9 +20,12 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - KeyValueRepositorySqlite::KeyValueRepositorySqlite( - SqliteDatabase& db, const string& tableName) - : myTableName{tableName}, - myDb{db} + SqliteDatabase& db, const string& tableName, const string& colKey, const string& colValue +) + : myDb{db}, + myTableName{tableName}, + myColKey{colKey}, + myColValue{colValue} { } @@ -81,12 +84,42 @@ SqliteDatabase& KeyValueRepositorySqlite::database() void KeyValueRepositorySqlite::initialize() { myDb.exec( - "CREATE TABLE IF NOT EXISTS `" + myTableName + "` (`key` TEXT PRIMARY KEY, `value` TEXT) WITHOUT ROWID" + "CREATE TABLE IF NOT EXISTS `%s` (`%s` TEXT PRIMARY KEY, `%s` TEXT) WITHOUT ROWID", + myTableName.c_str(), + myColKey.c_str(), + myColValue.c_str() ); - myStmtInsert = make_unique(myDb, "INSERT OR REPLACE INTO `" + myTableName + "` VALUES (?, ?)"); - myStmtSelect = make_unique(myDb, "SELECT `key`, `value` FROM `" + myTableName + "`"); - myStmtDelete = make_unique(myDb, "DELETE FROM `" + myTableName + "` WHERE `key` = ?"); - myStmtSelectOne = make_unique(myDb, "SELECT `value` FROM `" + myTableName + "` WHERE `key` = ?"); - myStmtCount = make_unique(myDb, "SELECT COUNT(`key`) FROM `" + myTableName + "` WHERE `key` = ?"); + myStmtInsert = make_unique(myDb, + "INSERT OR REPLACE INTO `%s` VALUES (?, ?)", + myTableName.c_str() + ); + + myStmtSelect = make_unique(myDb, + "SELECT `%s`, `%s` FROM `%s`", + myColKey.c_str(), + myColValue.c_str(), + myTableName.c_str() + ); + + myStmtDelete = make_unique(myDb, + "DELETE FROM `%s` WHERE `%s` = ?", + myTableName.c_str(), + myColKey.c_str() + ); + + myStmtSelectOne = make_unique(myDb, + "SELECT `%s` FROM `%s` WHERE `%s` = ?", + myColValue.c_str(), + myTableName.c_str(), + myColKey.c_str() + ); + + myStmtCount = make_unique( + myDb, + "SELECT COUNT(`%s`) FROM `%s` WHERE `%s` = ?", + myColKey.c_str(), + myTableName.c_str(), + myColKey.c_str() + ); } diff --git a/src/common/repository/sqlite/KeyValueRepositorySqlite.hxx b/src/common/repository/sqlite/KeyValueRepositorySqlite.hxx index 062176548..27591fe65 100644 --- a/src/common/repository/sqlite/KeyValueRepositorySqlite.hxx +++ b/src/common/repository/sqlite/KeyValueRepositorySqlite.hxx @@ -27,7 +27,7 @@ class KeyValueRepositorySqlite : public AbstractKeyValueRepositorySqlite { public: - KeyValueRepositorySqlite(SqliteDatabase& db, const string& tableName); + KeyValueRepositorySqlite(SqliteDatabase& db, const string& tableName, const string& colKey, const string& colValue); void initialize(); @@ -42,8 +42,10 @@ class KeyValueRepositorySqlite : public AbstractKeyValueRepositorySqlite private: - string myTableName; SqliteDatabase& myDb; + string myTableName; + string myColKey; + string myColValue; unique_ptr myStmtInsert; unique_ptr myStmtSelect; diff --git a/src/common/repository/sqlite/SettingsDb.cxx b/src/common/repository/sqlite/SettingsDb.cxx index 37a16535e..d32da3e71 100644 --- a/src/common/repository/sqlite/SettingsDb.cxx +++ b/src/common/repository/sqlite/SettingsDb.cxx @@ -33,10 +33,10 @@ bool SettingsDb::initialize() myDb = make_unique(myDatabaseDirectory, myDatabaseName); myDb->initialize(); - mySettingsRepository = make_unique(*myDb, "settings"); + mySettingsRepository = make_unique(*myDb, "settings", "setting", "value"); mySettingsRepository->initialize(); - myPropertyRepositoryHost = make_unique(*myDb, "properties"); + myPropertyRepositoryHost = make_unique(*myDb, "properties", "md5", "properties"); myPropertyRepositoryHost->initialize(); myPropertyRepository = make_unique(*myPropertyRepositoryHost); diff --git a/src/common/repository/sqlite/SqliteDatabase.hxx b/src/common/repository/sqlite/SqliteDatabase.hxx index ad1beeea3..71316a4b4 100644 --- a/src/common/repository/sqlite/SqliteDatabase.hxx +++ b/src/common/repository/sqlite/SqliteDatabase.hxx @@ -38,6 +38,9 @@ class SqliteDatabase void exec(const string &sql) const; + template + void exec(const string& sql, T arg1, Ts... args) const; + private: string myDatabaseFile; @@ -52,4 +55,24 @@ class SqliteDatabase SqliteDatabase& operator=(SqliteDatabase&&) = delete; }; +/////////////////////////////////////////////////////////////////////////////// +// IMPLEMENTATION +/////////////////////////////////////////////////////////////////////////////// + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wformat-nonliteral" + +template +void SqliteDatabase::exec(const string& sql, T arg1, Ts... args) const +{ + char buffer[512]; + + if (snprintf(buffer, 512, sql.c_str(), arg1, args...) >= 512) + throw new runtime_error("SQL statement too long"); + + exec(buffer); +} + +#pragma clang diagnostic pop + #endif // SQLITE_DATABASE_HXX diff --git a/src/common/repository/sqlite/SqliteStatement.cxx b/src/common/repository/sqlite/SqliteStatement.cxx index 4c2c4d513..ea6ae1dc9 100644 --- a/src/common/repository/sqlite/SqliteStatement.cxx +++ b/src/common/repository/sqlite/SqliteStatement.cxx @@ -21,8 +21,14 @@ SqliteStatement::SqliteStatement(sqlite3* handle, const string& sql) : myHandle{handle} { - if (sqlite3_prepare_v2(handle, sql.c_str(), -1, &myStmt, nullptr) != SQLITE_OK) - throw SqliteError(handle); + initialize(sql); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void SqliteStatement::initialize(const string& sql) +{ + if (sqlite3_prepare_v2(myHandle, sql.c_str(), -1, &myStmt, nullptr) != SQLITE_OK) + throw SqliteError(myHandle); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/common/repository/sqlite/SqliteStatement.hxx b/src/common/repository/sqlite/SqliteStatement.hxx index 07ad29f3d..42b91be90 100644 --- a/src/common/repository/sqlite/SqliteStatement.hxx +++ b/src/common/repository/sqlite/SqliteStatement.hxx @@ -27,6 +27,9 @@ class SqliteStatement { SqliteStatement(sqlite3* handle, const string& sql); + template + SqliteStatement(sqlite3* handle, const string& sql, T arg1, Ts... args); + ~SqliteStatement(); operator sqlite3_stmt*() const { return myStmt; } @@ -41,6 +44,10 @@ class SqliteStatement { Int32 columnInt(int index) const; + private: + + void initialize(const string& sql); + private: sqlite3_stmt* myStmt{nullptr}; @@ -52,8 +59,29 @@ class SqliteStatement { SqliteStatement() = delete; SqliteStatement(const SqliteStatement&) = delete; SqliteStatement(SqliteStatement&&) = delete; - SqliteStatement& operator=(const SqliteStatement&) = delete; SqliteStatement& operator=(SqliteStatement&&) = delete; + SqliteStatement& operator=(const SqliteStatement&) = delete; }; +/////////////////////////////////////////////////////////////////////////////// +// IMPLEMENTATION +/////////////////////////////////////////////////////////////////////////////// + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wformat-nonliteral" + +template +SqliteStatement::SqliteStatement(sqlite3* handle, const string& sql, T arg1, Ts... args) + : myHandle{handle} +{ + char buffer[512]; + + if (snprintf(buffer, 512, sql.c_str(), arg1, args...) >= 512) + throw runtime_error("SQL statement too long"); + + initialize(buffer); +} + +#pragma clang diagnostic pop + #endif // SQLITE_STATEMENT_HXX