diff options
Diffstat (limited to 'src/database/database-postgresql.cpp')
-rw-r--r-- | src/database/database-postgresql.cpp | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/src/database/database-postgresql.cpp b/src/database/database-postgresql.cpp index a84c89fa8..85beff995 100644 --- a/src/database/database-postgresql.cpp +++ b/src/database/database-postgresql.cpp @@ -38,6 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "settings.h" #include "remoteplayer.h" #include "server/player_sao.h" +#include <cstdlib> Database_PostgreSQL::Database_PostgreSQL(const std::string &connect_string, const char *type) : @@ -812,5 +813,211 @@ void AuthDatabasePostgreSQL::writePrivileges(const AuthEntry &authEntry) } } +ModMetadataDatabasePostgreSQL::ModMetadataDatabasePostgreSQL(const std::string &connect_string): + Database_PostgreSQL(connect_string, "_mod_storage"), + ModMetadataDatabase() +{ + connectToDatabase(); +} + +void ModMetadataDatabasePostgreSQL::createDatabase() +{ + createTableIfNotExists("mod_storage", + "CREATE TABLE mod_storage (" + "modname TEXT NOT NULL," + "key BYTEA NOT NULL," + "value BYTEA NOT NULL," + "PRIMARY KEY (modname, key)" + ");"); + + infostream << "PostgreSQL: Mod Storage Database was initialized." << std::endl; +} + +void ModMetadataDatabasePostgreSQL::initStatements() +{ + prepareStatement("get_all", + "SELECT key, value FROM mod_storage WHERE modname = $1"); + prepareStatement("get_all_keys", + "SELECT key FROM mod_storage WHERE modname = $1"); + prepareStatement("get", + "SELECT value FROM mod_storage WHERE modname = $1 AND key = $2::bytea"); + prepareStatement("has", + "SELECT true FROM mod_storage WHERE modname = $1 AND key = $2::bytea"); + if (getPGVersion() < 90500) { + prepareStatement("set_insert", + "INSERT INTO mod_storage (modname, key, value) " + "SELECT $1, $2::bytea, $3::bytea " + "WHERE NOT EXISTS (" + "SELECT true FROM mod_storage WHERE modname = $1 AND key = $2::bytea" + ")"); + prepareStatement("set_update", + "UPDATE mod_storage SET value = $3::bytea WHERE modname = $1 AND key = $2::bytea"); + } else { + prepareStatement("set", + "INSERT INTO mod_storage (modname, key, value) VALUES ($1, $2::bytea, $3::bytea) " + "ON CONFLICT ON CONSTRAINT mod_storage_pkey DO " + "UPDATE SET value = $3::bytea"); + } + prepareStatement("remove", + "DELETE FROM mod_storage WHERE modname = $1 AND key = $2::bytea"); + prepareStatement("remove_all", + "DELETE FROM mod_storage WHERE modname = $1"); + prepareStatement("list", + "SELECT DISTINCT modname FROM mod_storage"); +} + +bool ModMetadataDatabasePostgreSQL::getModEntries(const std::string &modname, StringMap *storage) +{ + verifyDatabase(); + + const void *args[] = { modname.c_str() }; + const int argLen[] = { -1 }; + const int argFmt[] = { 0 }; + PGresult *results = execPrepared("get_all", ARRLEN(args), + args, argLen, argFmt, false); + + int numrows = PQntuples(results); + + for (int row = 0; row < numrows; ++row) { + std::string key(PQgetvalue(results, row, 0), PQgetlength(results, row, 0)); + std::string value(PQgetvalue(results, row, 1), PQgetlength(results, row, 1)); + storage->emplace(std::move(key), std::move(value)); + } + + PQclear(results); + + return true; +} + +bool ModMetadataDatabasePostgreSQL::getModKeys(const std::string &modname, + std::vector<std::string> *storage) +{ + verifyDatabase(); + + const void *args[] = { modname.c_str() }; + const int argLen[] = { -1 }; + const int argFmt[] = { 0 }; + PGresult *results = execPrepared("get_all_keys", ARRLEN(args), + args, argLen, argFmt, false); + + int numrows = PQntuples(results); + + storage->reserve(storage->size() + numrows); + for (int row = 0; row < numrows; ++row) + storage->emplace_back(PQgetvalue(results, row, 0), PQgetlength(results, row, 0)); + + PQclear(results); + + return true; +} + +bool ModMetadataDatabasePostgreSQL::getModEntry(const std::string &modname, + const std::string &key, std::string *value) +{ + verifyDatabase(); + + const void *args[] = { modname.c_str(), key.c_str() }; + const int argLen[] = { -1, (int)MYMIN(key.size(), INT_MAX) }; + const int argFmt[] = { 0, 1 }; + PGresult *results = execPrepared("get", ARRLEN(args), args, argLen, argFmt, false); + + int numrows = PQntuples(results); + bool found = numrows > 0; + + if (found) + value->assign(PQgetvalue(results, 0, 0), PQgetlength(results, 0, 0)); + + PQclear(results); + + return found; +} + +bool ModMetadataDatabasePostgreSQL::hasModEntry(const std::string &modname, + const std::string &key) +{ + verifyDatabase(); + + const void *args[] = { modname.c_str(), key.c_str() }; + const int argLen[] = { -1, (int)MYMIN(key.size(), INT_MAX) }; + const int argFmt[] = { 0, 1 }; + PGresult *results = execPrepared("has", ARRLEN(args), args, argLen, argFmt, false); + + int numrows = PQntuples(results); + bool found = numrows > 0; + + PQclear(results); + + return found; +} + +bool ModMetadataDatabasePostgreSQL::setModEntry(const std::string &modname, + const std::string &key, const std::string &value) +{ + verifyDatabase(); + + const void *args[] = { modname.c_str(), key.c_str(), value.c_str() }; + const int argLen[] = { + -1, + (int)MYMIN(key.size(), INT_MAX), + (int)MYMIN(value.size(), INT_MAX), + }; + const int argFmt[] = { 0, 1, 1 }; + if (getPGVersion() < 90500) { + execPrepared("set_insert", ARRLEN(args), args, argLen, argFmt); + execPrepared("set_update", ARRLEN(args), args, argLen, argFmt); + } else { + execPrepared("set", ARRLEN(args), args, argLen, argFmt); + } + + return true; +} + +bool ModMetadataDatabasePostgreSQL::removeModEntry(const std::string &modname, + const std::string &key) +{ + verifyDatabase(); + + const void *args[] = { modname.c_str(), key.c_str() }; + const int argLen[] = { -1, (int)MYMIN(key.size(), INT_MAX) }; + const int argFmt[] = { 0, 1 }; + PGresult *results = execPrepared("remove", ARRLEN(args), args, argLen, argFmt, false); + + int affected = atoi(PQcmdTuples(results)); + + PQclear(results); + + return affected > 0; +} + +bool ModMetadataDatabasePostgreSQL::removeModEntries(const std::string &modname) +{ + verifyDatabase(); + + const void *args[] = { modname.c_str() }; + const int argLen[] = { -1 }; + const int argFmt[] = { 0 }; + PGresult *results = execPrepared("remove_all", ARRLEN(args), args, argLen, argFmt, false); + + int affected = atoi(PQcmdTuples(results)); + + PQclear(results); + + return affected > 0; +} + +void ModMetadataDatabasePostgreSQL::listMods(std::vector<std::string> *res) +{ + verifyDatabase(); + + PGresult *results = execPrepared("list", 0, NULL, false); + + int numrows = PQntuples(results); + + for (int row = 0; row < numrows; ++row) + res->emplace_back(PQgetvalue(results, row, 0), PQgetlength(results, row, 0)); + + PQclear(results); +} + #endif // USE_POSTGRESQL |