Core/FSB: implement Followship db
This commit is contained in:
@@ -0,0 +1,32 @@
|
|||||||
|
-- Followship Database Base Schema
|
||||||
|
-- Creates the followship database with standard TrinityCore update tracking tables
|
||||||
|
-- and the bot_owners table (moved from characters database, renamed from followship_bot_owners)
|
||||||
|
|
||||||
|
CREATE TABLE `updates` (
|
||||||
|
`name` varchar(200) NOT NULL COMMENT 'filename with extension of the update.',
|
||||||
|
`hash` char(40) DEFAULT '' COMMENT 'sha1 hash of the sql file.',
|
||||||
|
`state` enum('RELEASED','CUSTOM','MODULE') NOT NULL DEFAULT 'RELEASED' COMMENT 'defines if an update is released or archived.',
|
||||||
|
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'timestamp when the query was applied.',
|
||||||
|
`speed` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'time the query takes to apply in ms.',
|
||||||
|
PRIMARY KEY (`name`) USING BTREE,
|
||||||
|
UNIQUE KEY `unique_index` (`name`,`hash`) USING BTREE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='List of all applied updates in this database.';
|
||||||
|
|
||||||
|
CREATE TABLE `updates_include` (
|
||||||
|
`path` varchar(200) NOT NULL COMMENT 'directory to include. $ means relative to the source directory.',
|
||||||
|
`state` enum('RELEASED','CUSTOM','MODULE') NOT NULL DEFAULT 'RELEASED' COMMENT 'defines if the directory contains released or archived updates.',
|
||||||
|
PRIMARY KEY (`path`) USING BTREE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='List of directories containing update files.';
|
||||||
|
|
||||||
|
INSERT INTO `updates_include` (`path`, `state`) VALUES
|
||||||
|
('$/sql/updates/followship', 'RELEASED');
|
||||||
|
|
||||||
|
CREATE TABLE `bot_owners` (
|
||||||
|
`bot_id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
`bot_guid` BIGINT UNSIGNED NOT NULL,
|
||||||
|
`bot_entry` INT UNSIGNED NOT NULL,
|
||||||
|
`player_guid` BIGINT UNSIGNED NOT NULL,
|
||||||
|
`hire_expiry_time` BIGINT UNSIGNED NOT NULL,
|
||||||
|
|
||||||
|
UNIQUE KEY `uq_bot_player` (`bot_guid`, `player_guid`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
@@ -6,6 +6,8 @@ CREATE DATABASE `auth` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|||||||
|
|
||||||
CREATE DATABASE `hotfixes` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
CREATE DATABASE `hotfixes` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
CREATE DATABASE `followship` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
GRANT ALL PRIVILEGES ON `world` . * TO 'playerbot'@'localhost' WITH GRANT OPTION;
|
GRANT ALL PRIVILEGES ON `world` . * TO 'playerbot'@'localhost' WITH GRANT OPTION;
|
||||||
|
|
||||||
GRANT ALL PRIVILEGES ON `characters` . * TO 'playerbot'@'localhost' WITH GRANT OPTION;
|
GRANT ALL PRIVILEGES ON `characters` . * TO 'playerbot'@'localhost' WITH GRANT OPTION;
|
||||||
@@ -13,3 +15,5 @@ GRANT ALL PRIVILEGES ON `characters` . * TO 'playerbot'@'localhost' WITH GRANT O
|
|||||||
GRANT ALL PRIVILEGES ON `auth` . * TO 'playerbot'@'localhost' WITH GRANT OPTION;
|
GRANT ALL PRIVILEGES ON `auth` . * TO 'playerbot'@'localhost' WITH GRANT OPTION;
|
||||||
|
|
||||||
GRANT ALL PRIVILEGES ON `hotfixes` . * TO 'playerbot'@'localhost' WITH GRANT OPTION;
|
GRANT ALL PRIVILEGES ON `hotfixes` . * TO 'playerbot'@'localhost' WITH GRANT OPTION;
|
||||||
|
|
||||||
|
GRANT ALL PRIVILEGES ON `followship` . * TO 'playerbot'@'localhost' WITH GRANT OPTION;
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ REVOKE ALL PRIVILEGES ON `hotfixes` . * FROM 'trinity'@'localhost';
|
|||||||
|
|
||||||
REVOKE GRANT OPTION ON `hotfixes` . * FROM 'trinity'@'localhost';
|
REVOKE GRANT OPTION ON `hotfixes` . * FROM 'trinity'@'localhost';
|
||||||
|
|
||||||
|
REVOKE ALL PRIVILEGES ON `followship` . * FROM 'trinity'@'localhost';
|
||||||
|
|
||||||
|
REVOKE GRANT OPTION ON `followship` . * FROM 'trinity'@'localhost';
|
||||||
|
|
||||||
DROP USER 'trinity'@'localhost';
|
DROP USER 'trinity'@'localhost';
|
||||||
|
|
||||||
DROP DATABASE IF EXISTS `world`;
|
DROP DATABASE IF EXISTS `world`;
|
||||||
@@ -25,3 +29,5 @@ DROP DATABASE IF EXISTS `characters`;
|
|||||||
DROP DATABASE IF EXISTS `auth`;
|
DROP DATABASE IF EXISTS `auth`;
|
||||||
|
|
||||||
DROP DATABASE IF EXISTS `hotfixes`;
|
DROP DATABASE IF EXISTS `hotfixes`;
|
||||||
|
|
||||||
|
DROP DATABASE IF EXISTS `followship`;
|
||||||
|
|||||||
@@ -9,3 +9,5 @@ DROP DATABASE IF EXISTS `characters`;
|
|||||||
DROP DATABASE IF EXISTS `auth`;
|
DROP DATABASE IF EXISTS `auth`;
|
||||||
|
|
||||||
DROP DATABASE IF EXISTS `hotfixes`;
|
DROP DATABASE IF EXISTS `hotfixes`;
|
||||||
|
|
||||||
|
DROP DATABASE IF EXISTS `followship`;
|
||||||
|
|||||||
@@ -19,5 +19,6 @@
|
|||||||
|
|
||||||
DatabaseWorkerPool<WorldDatabaseConnection> WorldDatabase;
|
DatabaseWorkerPool<WorldDatabaseConnection> WorldDatabase;
|
||||||
DatabaseWorkerPool<CharacterDatabaseConnection> CharacterDatabase;
|
DatabaseWorkerPool<CharacterDatabaseConnection> CharacterDatabase;
|
||||||
|
DatabaseWorkerPool<FollowshipDatabaseConnection> FollowshipDatabase;
|
||||||
DatabaseWorkerPool<LoginDatabaseConnection> LoginDatabase;
|
DatabaseWorkerPool<LoginDatabaseConnection> LoginDatabase;
|
||||||
DatabaseWorkerPool<HotfixDatabaseConnection> HotfixDatabase;
|
DatabaseWorkerPool<HotfixDatabaseConnection> HotfixDatabase;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include "Implementation/LoginDatabase.h"
|
#include "Implementation/LoginDatabase.h"
|
||||||
#include "Implementation/CharacterDatabase.h"
|
#include "Implementation/CharacterDatabase.h"
|
||||||
|
#include "Implementation/FollowshipDatabase.h"
|
||||||
#include "Implementation/WorldDatabase.h"
|
#include "Implementation/WorldDatabase.h"
|
||||||
#include "Implementation/HotfixDatabase.h"
|
#include "Implementation/HotfixDatabase.h"
|
||||||
|
|
||||||
@@ -36,6 +37,8 @@
|
|||||||
TC_DATABASE_API extern DatabaseWorkerPool<WorldDatabaseConnection> WorldDatabase;
|
TC_DATABASE_API extern DatabaseWorkerPool<WorldDatabaseConnection> WorldDatabase;
|
||||||
/// Accessor to the character database
|
/// Accessor to the character database
|
||||||
TC_DATABASE_API extern DatabaseWorkerPool<CharacterDatabaseConnection> CharacterDatabase;
|
TC_DATABASE_API extern DatabaseWorkerPool<CharacterDatabaseConnection> CharacterDatabase;
|
||||||
|
/// Accessor to the followship database
|
||||||
|
TC_DATABASE_API extern DatabaseWorkerPool<FollowshipDatabaseConnection> FollowshipDatabase;
|
||||||
/// Accessor to the realm/login database
|
/// Accessor to the realm/login database
|
||||||
TC_DATABASE_API extern DatabaseWorkerPool<LoginDatabaseConnection> LoginDatabase;
|
TC_DATABASE_API extern DatabaseWorkerPool<LoginDatabaseConnection> LoginDatabase;
|
||||||
/// Accessor to the hotfix database
|
/// Accessor to the hotfix database
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ class ResultSet;
|
|||||||
using QueryResult = std::shared_ptr<ResultSet>;
|
using QueryResult = std::shared_ptr<ResultSet>;
|
||||||
|
|
||||||
class CharacterDatabaseConnection;
|
class CharacterDatabaseConnection;
|
||||||
|
class FollowshipDatabaseConnection;
|
||||||
class HotfixDatabaseConnection;
|
class HotfixDatabaseConnection;
|
||||||
class LoginDatabaseConnection;
|
class LoginDatabaseConnection;
|
||||||
class WorldDatabaseConnection;
|
class WorldDatabaseConnection;
|
||||||
@@ -38,6 +39,7 @@ template<typename T>
|
|||||||
class PreparedStatement;
|
class PreparedStatement;
|
||||||
|
|
||||||
using CharacterDatabasePreparedStatement = PreparedStatement<CharacterDatabaseConnection>;
|
using CharacterDatabasePreparedStatement = PreparedStatement<CharacterDatabaseConnection>;
|
||||||
|
using FollowshipDatabasePreparedStatement = PreparedStatement<FollowshipDatabaseConnection>;
|
||||||
using HotfixDatabasePreparedStatement = PreparedStatement<HotfixDatabaseConnection>;
|
using HotfixDatabasePreparedStatement = PreparedStatement<HotfixDatabaseConnection>;
|
||||||
using LoginDatabasePreparedStatement = PreparedStatement<LoginDatabaseConnection>;
|
using LoginDatabasePreparedStatement = PreparedStatement<LoginDatabaseConnection>;
|
||||||
using WorldDatabasePreparedStatement = PreparedStatement<WorldDatabaseConnection>;
|
using WorldDatabasePreparedStatement = PreparedStatement<WorldDatabaseConnection>;
|
||||||
@@ -62,6 +64,7 @@ template<typename T>
|
|||||||
using SQLTransaction = std::shared_ptr<Transaction<T>>;
|
using SQLTransaction = std::shared_ptr<Transaction<T>>;
|
||||||
|
|
||||||
using CharacterDatabaseTransaction = SQLTransaction<CharacterDatabaseConnection>;
|
using CharacterDatabaseTransaction = SQLTransaction<CharacterDatabaseConnection>;
|
||||||
|
using FollowshipDatabaseTransaction = SQLTransaction<FollowshipDatabaseConnection>;
|
||||||
using HotfixDatabaseTransaction = SQLTransaction<HotfixDatabaseConnection>;
|
using HotfixDatabaseTransaction = SQLTransaction<HotfixDatabaseConnection>;
|
||||||
using LoginDatabaseTransaction = SQLTransaction<LoginDatabaseConnection>;
|
using LoginDatabaseTransaction = SQLTransaction<LoginDatabaseConnection>;
|
||||||
using WorldDatabaseTransaction = SQLTransaction<WorldDatabaseConnection>;
|
using WorldDatabaseTransaction = SQLTransaction<WorldDatabaseConnection>;
|
||||||
@@ -72,6 +75,7 @@ template<typename T>
|
|||||||
class SQLQueryHolder;
|
class SQLQueryHolder;
|
||||||
|
|
||||||
using CharacterDatabaseQueryHolder = SQLQueryHolder<CharacterDatabaseConnection>;
|
using CharacterDatabaseQueryHolder = SQLQueryHolder<CharacterDatabaseConnection>;
|
||||||
|
using FollowshipDatabaseQueryHolder = SQLQueryHolder<FollowshipDatabaseConnection>;
|
||||||
using HotfixDatabaseQueryHolder = SQLQueryHolder<HotfixDatabaseConnection>;
|
using HotfixDatabaseQueryHolder = SQLQueryHolder<HotfixDatabaseConnection>;
|
||||||
using LoginDatabaseQueryHolder = SQLQueryHolder<LoginDatabaseConnection>;
|
using LoginDatabaseQueryHolder = SQLQueryHolder<LoginDatabaseConnection>;
|
||||||
using WorldDatabaseQueryHolder = SQLQueryHolder<WorldDatabaseConnection>;
|
using WorldDatabaseQueryHolder = SQLQueryHolder<WorldDatabaseConnection>;
|
||||||
|
|||||||
@@ -184,6 +184,8 @@ DatabaseLoader& DatabaseLoader::AddDatabase<LoginDatabaseConnection>(DatabaseWor
|
|||||||
template TC_DATABASE_API
|
template TC_DATABASE_API
|
||||||
DatabaseLoader& DatabaseLoader::AddDatabase<CharacterDatabaseConnection>(DatabaseWorkerPool<CharacterDatabaseConnection>&, std::string const&);
|
DatabaseLoader& DatabaseLoader::AddDatabase<CharacterDatabaseConnection>(DatabaseWorkerPool<CharacterDatabaseConnection>&, std::string const&);
|
||||||
template TC_DATABASE_API
|
template TC_DATABASE_API
|
||||||
|
DatabaseLoader& DatabaseLoader::AddDatabase<FollowshipDatabaseConnection>(DatabaseWorkerPool<FollowshipDatabaseConnection>&, std::string const&);
|
||||||
|
template TC_DATABASE_API
|
||||||
DatabaseLoader& DatabaseLoader::AddDatabase<WorldDatabaseConnection>(DatabaseWorkerPool<WorldDatabaseConnection>&, std::string const&);
|
DatabaseLoader& DatabaseLoader::AddDatabase<WorldDatabaseConnection>(DatabaseWorkerPool<WorldDatabaseConnection>&, std::string const&);
|
||||||
template TC_DATABASE_API
|
template TC_DATABASE_API
|
||||||
DatabaseLoader& DatabaseLoader::AddDatabase<HotfixDatabaseConnection>(DatabaseWorkerPool<HotfixDatabaseConnection>&, std::string const&);
|
DatabaseLoader& DatabaseLoader::AddDatabase<HotfixDatabaseConnection>(DatabaseWorkerPool<HotfixDatabaseConnection>&, std::string const&);
|
||||||
|
|||||||
@@ -46,12 +46,13 @@ public:
|
|||||||
{
|
{
|
||||||
DATABASE_NONE = 0,
|
DATABASE_NONE = 0,
|
||||||
|
|
||||||
DATABASE_LOGIN = 1,
|
DATABASE_LOGIN = 1,
|
||||||
DATABASE_CHARACTER = 2,
|
DATABASE_CHARACTER = 2,
|
||||||
DATABASE_WORLD = 4,
|
DATABASE_WORLD = 4,
|
||||||
DATABASE_HOTFIX = 8,
|
DATABASE_HOTFIX = 8,
|
||||||
|
DATABASE_FOLLOWSHIP = 16,
|
||||||
|
|
||||||
DATABASE_MASK_ALL = DATABASE_LOGIN | DATABASE_CHARACTER | DATABASE_WORLD | DATABASE_HOTFIX
|
DATABASE_MASK_ALL = DATABASE_LOGIN | DATABASE_CHARACTER | DATABASE_WORLD | DATABASE_HOTFIX | DATABASE_FOLLOWSHIP
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "Implementation/LoginDatabase.h"
|
#include "Implementation/LoginDatabase.h"
|
||||||
#include "Implementation/WorldDatabase.h"
|
#include "Implementation/WorldDatabase.h"
|
||||||
#include "Implementation/CharacterDatabase.h"
|
#include "Implementation/CharacterDatabase.h"
|
||||||
|
#include "Implementation/FollowshipDatabase.h"
|
||||||
#include "Implementation/HotfixDatabase.h"
|
#include "Implementation/HotfixDatabase.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "MySQLPreparedStatement.h"
|
#include "MySQLPreparedStatement.h"
|
||||||
@@ -619,4 +620,5 @@ void DatabaseWorkerPool<T>::ExecuteOrAppend(SQLTransaction<T>& trans, PreparedSt
|
|||||||
template class TC_DATABASE_API DatabaseWorkerPool<LoginDatabaseConnection>;
|
template class TC_DATABASE_API DatabaseWorkerPool<LoginDatabaseConnection>;
|
||||||
template class TC_DATABASE_API DatabaseWorkerPool<WorldDatabaseConnection>;
|
template class TC_DATABASE_API DatabaseWorkerPool<WorldDatabaseConnection>;
|
||||||
template class TC_DATABASE_API DatabaseWorkerPool<CharacterDatabaseConnection>;
|
template class TC_DATABASE_API DatabaseWorkerPool<CharacterDatabaseConnection>;
|
||||||
|
template class TC_DATABASE_API DatabaseWorkerPool<FollowshipDatabaseConnection>;
|
||||||
template class TC_DATABASE_API DatabaseWorkerPool<HotfixDatabaseConnection>;
|
template class TC_DATABASE_API DatabaseWorkerPool<HotfixDatabaseConnection>;
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Stefal WoW Project.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "FollowshipDatabase.h"
|
||||||
|
#include "MySQLPreparedStatement.h"
|
||||||
|
|
||||||
|
void FollowshipDatabaseConnection::DoPrepareStatements()
|
||||||
|
{
|
||||||
|
if (!m_reconnecting)
|
||||||
|
m_stmts.resize(MAX_FOLLOWSHIPDATABASE_STATEMENTS);
|
||||||
|
|
||||||
|
PrepareStatement(FSB_SEL_BOT_OWNERS_ALL,
|
||||||
|
"SELECT bot_id, bot_guid, bot_entry, player_guid, hire_expiry_time FROM bot_owners", CONNECTION_SYNCH);
|
||||||
|
|
||||||
|
PrepareStatement(FSB_SEL_BOT_OWNERS_BY_PLAYER,
|
||||||
|
"SELECT bot_id, bot_guid, bot_entry, hire_expiry_time FROM bot_owners WHERE player_guid = ?", CONNECTION_SYNCH);
|
||||||
|
|
||||||
|
PrepareStatement(FSB_SEL_BOT_OWNER_ID,
|
||||||
|
"SELECT bot_id FROM bot_owners WHERE bot_guid = ? AND player_guid = ?", CONNECTION_SYNCH);
|
||||||
|
|
||||||
|
PrepareStatement(FSB_INS_BOT_OWNER,
|
||||||
|
"INSERT INTO bot_owners (bot_guid, bot_entry, player_guid, hire_expiry_time) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||||
|
|
||||||
|
PrepareStatement(FSB_DEL_BOT_OWNER_BY_GUID,
|
||||||
|
"DELETE FROM bot_owners WHERE bot_guid = ?", CONNECTION_ASYNC);
|
||||||
|
|
||||||
|
PrepareStatement(FSB_DEL_BOT_OWNER_BY_ENTRY_PLAYER,
|
||||||
|
"DELETE FROM bot_owners WHERE bot_entry = ? AND player_guid = ?", CONNECTION_ASYNC);
|
||||||
|
}
|
||||||
|
|
||||||
|
FollowshipDatabaseConnection::FollowshipDatabaseConnection(MySQLConnectionInfo& connInfo, ConnectionFlags connectionFlags)
|
||||||
|
: MySQLConnection(connInfo, connectionFlags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FollowshipDatabaseConnection::~FollowshipDatabaseConnection()
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Stefal WoW Project.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _FOLLOWSHIPDATABASE_H
|
||||||
|
#define _FOLLOWSHIPDATABASE_H
|
||||||
|
|
||||||
|
#include "MySQLConnection.h"
|
||||||
|
|
||||||
|
enum FollowshipDatabaseStatements : uint32
|
||||||
|
{
|
||||||
|
/* Naming standard for defines:
|
||||||
|
{DB}_{SEL/INS/UPD/DEL/REP}_{Summary of data changed}
|
||||||
|
*/
|
||||||
|
|
||||||
|
FSB_SEL_BOT_OWNERS_ALL,
|
||||||
|
FSB_SEL_BOT_OWNERS_BY_PLAYER,
|
||||||
|
FSB_SEL_BOT_OWNER_ID,
|
||||||
|
FSB_INS_BOT_OWNER,
|
||||||
|
FSB_DEL_BOT_OWNER_BY_GUID,
|
||||||
|
FSB_DEL_BOT_OWNER_BY_ENTRY_PLAYER,
|
||||||
|
|
||||||
|
MAX_FOLLOWSHIPDATABASE_STATEMENTS
|
||||||
|
};
|
||||||
|
|
||||||
|
class TC_DATABASE_API FollowshipDatabaseConnection : public MySQLConnection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef FollowshipDatabaseStatements Statements;
|
||||||
|
|
||||||
|
FollowshipDatabaseConnection(MySQLConnectionInfo& connInfo, ConnectionFlags connectionFlags);
|
||||||
|
~FollowshipDatabaseConnection();
|
||||||
|
|
||||||
|
//- Loads database type specific prepared statements
|
||||||
|
void DoPrepareStatements() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -150,6 +150,32 @@ bool DBUpdater<CharacterDatabaseConnection>::IsEnabled(uint32 const updateMask)
|
|||||||
return (updateMask & DatabaseLoader::DATABASE_CHARACTER) ? true : false;
|
return (updateMask & DatabaseLoader::DATABASE_CHARACTER) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Followship Database
|
||||||
|
template<>
|
||||||
|
std::string DBUpdater<FollowshipDatabaseConnection>::GetConfigEntry()
|
||||||
|
{
|
||||||
|
return "Updates.Followship";
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
std::string DBUpdater<FollowshipDatabaseConnection>::GetTableName()
|
||||||
|
{
|
||||||
|
return "Followship";
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
std::string DBUpdater<FollowshipDatabaseConnection>::GetBaseFile()
|
||||||
|
{
|
||||||
|
return BuiltInConfig::GetSourceDirectory() +
|
||||||
|
"/sql/base/followship_database.sql";
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
bool DBUpdater<FollowshipDatabaseConnection>::IsEnabled(uint32 const updateMask)
|
||||||
|
{
|
||||||
|
return (updateMask & DatabaseLoader::DATABASE_FOLLOWSHIP) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
// Hotfix Database
|
// Hotfix Database
|
||||||
template<>
|
template<>
|
||||||
std::string DBUpdater<HotfixDatabaseConnection>::GetConfigEntry()
|
std::string DBUpdater<HotfixDatabaseConnection>::GetConfigEntry()
|
||||||
@@ -450,4 +476,5 @@ void DBUpdater<T>::ApplyFile(DatabaseWorkerPool<T>& pool, std::string const& hos
|
|||||||
template class TC_DATABASE_API DBUpdater<LoginDatabaseConnection>;
|
template class TC_DATABASE_API DBUpdater<LoginDatabaseConnection>;
|
||||||
template class TC_DATABASE_API DBUpdater<WorldDatabaseConnection>;
|
template class TC_DATABASE_API DBUpdater<WorldDatabaseConnection>;
|
||||||
template class TC_DATABASE_API DBUpdater<CharacterDatabaseConnection>;
|
template class TC_DATABASE_API DBUpdater<CharacterDatabaseConnection>;
|
||||||
|
template class TC_DATABASE_API DBUpdater<FollowshipDatabaseConnection>;
|
||||||
template class TC_DATABASE_API DBUpdater<HotfixDatabaseConnection>;
|
template class TC_DATABASE_API DBUpdater<HotfixDatabaseConnection>;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "CharacterDatabase.h"
|
#include "FollowshipDatabase.h"
|
||||||
#include "DatabaseEnv.h"
|
#include "DatabaseEnv.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
|
||||||
@@ -30,9 +30,8 @@ namespace FSBUtilsDB
|
|||||||
{
|
{
|
||||||
bool LoadAllPersistentBotsFromDB(std::vector<PlayerBotData>& outBots)
|
bool LoadAllPersistentBotsFromDB(std::vector<PlayerBotData>& outBots)
|
||||||
{
|
{
|
||||||
QueryResult result = CharacterDatabase.Query(
|
FollowshipDatabasePreparedStatement* stmt = FollowshipDatabase.GetPreparedStatement(FSB_SEL_BOT_OWNERS_ALL);
|
||||||
"SELECT bot_id, bot_guid, bot_entry, player_guid, hire_expiry_time "
|
PreparedQueryResult result = FollowshipDatabase.Query(stmt);
|
||||||
"FROM followship_bot_owners");
|
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
return false;
|
return false;
|
||||||
@@ -43,7 +42,7 @@ namespace FSBUtilsDB
|
|||||||
|
|
||||||
PlayerBotData data;
|
PlayerBotData data;
|
||||||
data.botId = fields[0].GetUInt32();
|
data.botId = fields[0].GetUInt32();
|
||||||
data.spawnId = fields[1].GetUInt64(); // rename!
|
data.spawnId = fields[1].GetUInt64();
|
||||||
data.entry = fields[2].GetUInt32();
|
data.entry = fields[2].GetUInt32();
|
||||||
data.owner = fields[3].GetUInt32();
|
data.owner = fields[3].GetUInt32();
|
||||||
data.hireExpiry = fields[4].GetUInt64();
|
data.hireExpiry = fields[4].GetUInt64();
|
||||||
@@ -59,11 +58,9 @@ namespace FSBUtilsDB
|
|||||||
{
|
{
|
||||||
outBots.clear();
|
outBots.clear();
|
||||||
|
|
||||||
QueryResult result = CharacterDatabase.PQuery(
|
FollowshipDatabasePreparedStatement* stmt = FollowshipDatabase.GetPreparedStatement(FSB_SEL_BOT_OWNERS_BY_PLAYER);
|
||||||
"SELECT bot_id, bot_guid, bot_entry, hire_expiry_time "
|
stmt->setUInt64(0, playerGuidLow);
|
||||||
"FROM followship_bot_owners "
|
PreparedQueryResult result = FollowshipDatabase.Query(stmt);
|
||||||
"WHERE player_guid = {}",
|
|
||||||
playerGuidLow);
|
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
return true; // no bots is valid
|
return true; // no bots is valid
|
||||||
@@ -74,7 +71,7 @@ namespace FSBUtilsDB
|
|||||||
|
|
||||||
PlayerBotData data;
|
PlayerBotData data;
|
||||||
data.botId = fields[0].GetUInt32();
|
data.botId = fields[0].GetUInt32();
|
||||||
data.spawnId = fields[1].GetUInt64(); // rename!
|
data.spawnId = fields[1].GetUInt64();
|
||||||
data.entry = fields[2].GetUInt32();
|
data.entry = fields[2].GetUInt32();
|
||||||
data.hireExpiry = fields[3].GetUInt64();
|
data.hireExpiry = fields[3].GetUInt64();
|
||||||
data.runtimeGuid = ObjectGuid::Empty;
|
data.runtimeGuid = ObjectGuid::Empty;
|
||||||
@@ -89,8 +86,8 @@ namespace FSBUtilsDB
|
|||||||
{
|
{
|
||||||
botOwners.clear();
|
botOwners.clear();
|
||||||
|
|
||||||
QueryResult result = CharacterDatabase.Query(
|
FollowshipDatabasePreparedStatement* stmt = FollowshipDatabase.GetPreparedStatement(FSB_SEL_BOT_OWNERS_ALL);
|
||||||
"SELECT bot_guid, player_guid, hire_expiry_time FROM followship_bot_owners");
|
PreparedQueryResult result = FollowshipDatabase.Query(stmt);
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
return true; // no bots is valid
|
return true; // no bots is valid
|
||||||
@@ -99,16 +96,17 @@ namespace FSBUtilsDB
|
|||||||
{
|
{
|
||||||
Field* fields = result->Fetch();
|
Field* fields = result->Fetch();
|
||||||
|
|
||||||
ObjectGuid::LowType spawnId = fields[0].GetUInt64(); // bot_guid
|
ObjectGuid::LowType spawnId = fields[1].GetUInt64(); // bot_guid
|
||||||
ObjectGuid::LowType ownerGuid = fields[1].GetUInt32(); // player_guid
|
ObjectGuid::LowType ownerGuid = fields[3].GetUInt32(); // player_guid
|
||||||
uint64 hireExpiry = fields[2].GetUInt64();
|
uint64 hireExpiry = fields[4].GetUInt64();
|
||||||
|
|
||||||
// Skip expired bots
|
// Skip expired bots
|
||||||
if (hireExpiry > 0 && hireExpiry <= static_cast<uint64>(time(nullptr)))
|
if (hireExpiry > 0 && hireExpiry <= static_cast<uint64>(time(nullptr)))
|
||||||
{
|
{
|
||||||
// Clean up DB entry
|
// Clean up DB entry
|
||||||
CharacterDatabase.PExecute(
|
FollowshipDatabasePreparedStatement* delStmt = FollowshipDatabase.GetPreparedStatement(FSB_DEL_BOT_OWNER_BY_GUID);
|
||||||
"DELETE FROM followship_bot_owners WHERE bot_guid = {}", spawnId);
|
delStmt->setUInt64(0, spawnId);
|
||||||
|
FollowshipDatabase.Execute(delStmt);
|
||||||
|
|
||||||
TC_LOG_DEBUG("scripts.fsb.manager",
|
TC_LOG_DEBUG("scripts.fsb.manager",
|
||||||
"FSB: LoadBotOwners from DB Removing expired bot {} (owner {})", spawnId, ownerGuid);
|
"FSB: LoadBotOwners from DB Removing expired bot {} (owner {})", spawnId, ownerGuid);
|
||||||
@@ -140,24 +138,23 @@ namespace FSBUtilsDB
|
|||||||
|
|
||||||
uint32 entry = bot->GetEntry();
|
uint32 entry = bot->GetEntry();
|
||||||
|
|
||||||
CharacterDatabase.PExecute(
|
FollowshipDatabasePreparedStatement* insStmt = FollowshipDatabase.GetPreparedStatement(FSB_INS_BOT_OWNER);
|
||||||
"INSERT INTO followship_bot_owners (bot_guid, bot_entry, player_guid, hire_expiry_time) "
|
insStmt->setUInt64(0, spawnId);
|
||||||
"VALUES ({}, {}, {}, {})",
|
insStmt->setUInt32(1, entry);
|
||||||
spawnId,
|
insStmt->setUInt32(2, playerGuidLow);
|
||||||
entry,
|
insStmt->setUInt64(3, hireExpiry);
|
||||||
playerGuidLow,
|
FollowshipDatabase.Execute(insStmt);
|
||||||
hireExpiry);
|
|
||||||
|
|
||||||
TC_LOG_DEBUG("scripts.fsb.manager", "FSB: SaveBotToDB Bot: {} was saved to DB for player: {} with expiry time: {}", bot->GetName(), player->GetName(), hireExpiry);
|
TC_LOG_DEBUG("scripts.fsb.manager", "FSB: SaveBotToDB Bot: {} was saved to DB for player: {} with expiry time: {}", bot->GetName(), player->GetName(), hireExpiry);
|
||||||
|
|
||||||
// 2?? Retry select until we get the bot_id
|
// Retry select until we get the bot_id
|
||||||
uint32 botId = 0;
|
uint32 botId = 0;
|
||||||
for (int attempts = 0; attempts < 5; ++attempts)
|
for (int attempts = 0; attempts < 5; ++attempts)
|
||||||
{
|
{
|
||||||
QueryResult result = CharacterDatabase.PQuery(
|
FollowshipDatabasePreparedStatement* selStmt = FollowshipDatabase.GetPreparedStatement(FSB_SEL_BOT_OWNER_ID);
|
||||||
"SELECT bot_id FROM followship_bot_owners "
|
selStmt->setUInt64(0, spawnId);
|
||||||
"WHERE bot_guid = {} AND player_guid = {}",
|
selStmt->setUInt32(1, playerGuidLow);
|
||||||
spawnId, playerGuidLow);
|
PreparedQueryResult result = FollowshipDatabase.Query(selStmt);
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
@@ -192,7 +189,10 @@ namespace FSBUtilsDB
|
|||||||
if (!bot_entry || !player_guid)
|
if (!bot_entry || !player_guid)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
CharacterDatabase.PExecute("DELETE FROM followship_bot_owners WHERE bot_entry = {} AND player_guid = {} ", bot_entry, player_guid);
|
FollowshipDatabasePreparedStatement* stmt = FollowshipDatabase.GetPreparedStatement(FSB_DEL_BOT_OWNER_BY_ENTRY_PLAYER);
|
||||||
|
stmt->setUInt32(0, bot_entry);
|
||||||
|
stmt->setUInt32(1, player_guid);
|
||||||
|
FollowshipDatabase.Execute(stmt);
|
||||||
|
|
||||||
TC_LOG_DEBUG("scripts.fsb.manager", "FSB: DeleteBotByEntry Deleted Bot with bot_entry: {}", bot_entry);
|
TC_LOG_DEBUG("scripts.fsb.manager", "FSB: DeleteBotByEntry Deleted Bot with bot_entry: {}", bot_entry);
|
||||||
|
|
||||||
|
|||||||
@@ -331,6 +331,7 @@ int main(int argc, char** argv)
|
|||||||
TC_METRIC_VALUE("online_players", sWorld->GetPlayerCount());
|
TC_METRIC_VALUE("online_players", sWorld->GetPlayerCount());
|
||||||
TC_METRIC_VALUE("db_queue_login", uint64(LoginDatabase.QueueSize()));
|
TC_METRIC_VALUE("db_queue_login", uint64(LoginDatabase.QueueSize()));
|
||||||
TC_METRIC_VALUE("db_queue_character", uint64(CharacterDatabase.QueueSize()));
|
TC_METRIC_VALUE("db_queue_character", uint64(CharacterDatabase.QueueSize()));
|
||||||
|
TC_METRIC_VALUE("db_queue_followship", uint64(FollowshipDatabase.QueueSize()));
|
||||||
TC_METRIC_VALUE("db_queue_world", uint64(WorldDatabase.QueueSize()));
|
TC_METRIC_VALUE("db_queue_world", uint64(WorldDatabase.QueueSize()));
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -545,6 +546,7 @@ void WorldUpdateLoop()
|
|||||||
|
|
||||||
LoginDatabase.WarnAboutSyncQueries(true);
|
LoginDatabase.WarnAboutSyncQueries(true);
|
||||||
CharacterDatabase.WarnAboutSyncQueries(true);
|
CharacterDatabase.WarnAboutSyncQueries(true);
|
||||||
|
FollowshipDatabase.WarnAboutSyncQueries(true);
|
||||||
WorldDatabase.WarnAboutSyncQueries(true);
|
WorldDatabase.WarnAboutSyncQueries(true);
|
||||||
HotfixDatabase.WarnAboutSyncQueries(true);
|
HotfixDatabase.WarnAboutSyncQueries(true);
|
||||||
|
|
||||||
@@ -579,6 +581,7 @@ void WorldUpdateLoop()
|
|||||||
|
|
||||||
LoginDatabase.WarnAboutSyncQueries(false);
|
LoginDatabase.WarnAboutSyncQueries(false);
|
||||||
CharacterDatabase.WarnAboutSyncQueries(false);
|
CharacterDatabase.WarnAboutSyncQueries(false);
|
||||||
|
FollowshipDatabase.WarnAboutSyncQueries(false);
|
||||||
WorldDatabase.WarnAboutSyncQueries(false);
|
WorldDatabase.WarnAboutSyncQueries(false);
|
||||||
HotfixDatabase.WarnAboutSyncQueries(false);
|
HotfixDatabase.WarnAboutSyncQueries(false);
|
||||||
}
|
}
|
||||||
@@ -653,6 +656,7 @@ bool StartDB()
|
|||||||
loader
|
loader
|
||||||
.AddDatabase(LoginDatabase, "Login")
|
.AddDatabase(LoginDatabase, "Login")
|
||||||
.AddDatabase(CharacterDatabase, "Character")
|
.AddDatabase(CharacterDatabase, "Character")
|
||||||
|
.AddDatabase(FollowshipDatabase, "Followship")
|
||||||
.AddDatabase(WorldDatabase, "World")
|
.AddDatabase(WorldDatabase, "World")
|
||||||
.AddDatabase(HotfixDatabase, "Hotfix");
|
.AddDatabase(HotfixDatabase, "Hotfix");
|
||||||
|
|
||||||
@@ -672,6 +676,7 @@ void StopDB()
|
|||||||
{
|
{
|
||||||
HotfixDatabase.Close();
|
HotfixDatabase.Close();
|
||||||
WorldDatabase.Close();
|
WorldDatabase.Close();
|
||||||
|
FollowshipDatabase.Close();
|
||||||
CharacterDatabase.Close();
|
CharacterDatabase.Close();
|
||||||
LoginDatabase.Close();
|
LoginDatabase.Close();
|
||||||
|
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ LogsDir = "Logs"
|
|||||||
# WorldDatabaseInfo
|
# WorldDatabaseInfo
|
||||||
# CharacterDatabaseInfo
|
# CharacterDatabaseInfo
|
||||||
# HotfixDatabaseInfo
|
# HotfixDatabaseInfo
|
||||||
|
# FollowshipDatabaseInfo
|
||||||
# Description: Database connection settings for the world server.
|
# Description: Database connection settings for the world server.
|
||||||
# Example: "hostname;port;username;password;database;ssl"
|
# Example: "hostname;port;username;password;database;ssl"
|
||||||
# ".;some_number;username;password;database" - (Use named pipes on Windows
|
# ".;some_number;username;password;database" - (Use named pipes on Windows
|
||||||
@@ -105,6 +106,7 @@ LogsDir = "Logs"
|
|||||||
# "127.0.0.1;3306;trinity;trinity;world" - (WorldDatabaseInfo)
|
# "127.0.0.1;3306;trinity;trinity;world" - (WorldDatabaseInfo)
|
||||||
# "127.0.0.1;3306;trinity;trinity;characters" - (CharacterDatabaseInfo)
|
# "127.0.0.1;3306;trinity;trinity;characters" - (CharacterDatabaseInfo)
|
||||||
# "127.0.0.1;3306;trinity;trinity;hotfixes" - (HotfixDatabaseInfo)
|
# "127.0.0.1;3306;trinity;trinity;hotfixes" - (HotfixDatabaseInfo)
|
||||||
|
# "127.0.0.1;3306;trinity;trinity;followship" - (FollowshipDatabaseInfo)
|
||||||
#
|
#
|
||||||
# Don't change hostname unless you are hosting MySQL on a different machine, if you need help
|
# Don't change hostname unless you are hosting MySQL on a different machine, if you need help
|
||||||
# with configuration allowing to connect from different machine than the one running server
|
# with configuration allowing to connect from different machine than the one running server
|
||||||
@@ -118,12 +120,14 @@ LoginDatabaseInfo = "127.0.0.1;3306;root;1234;wc_auth"
|
|||||||
WorldDatabaseInfo = "127.0.0.1;3306;root;1234;wc_world"
|
WorldDatabaseInfo = "127.0.0.1;3306;root;1234;wc_world"
|
||||||
CharacterDatabaseInfo = "127.0.0.1;3306;root;1234;wc_characters"
|
CharacterDatabaseInfo = "127.0.0.1;3306;root;1234;wc_characters"
|
||||||
HotfixDatabaseInfo = "127.0.0.1;3306;root;1234;wc_hotfixes"
|
HotfixDatabaseInfo = "127.0.0.1;3306;root;1234;wc_hotfixes"
|
||||||
|
FollowshipDatabaseInfo = "127.0.0.1;3306;root;1234;wc_followship"
|
||||||
|
|
||||||
#
|
#
|
||||||
# LoginDatabase.WorkerThreads
|
# LoginDatabase.WorkerThreads
|
||||||
# WorldDatabase.WorkerThreads
|
# WorldDatabase.WorkerThreads
|
||||||
# CharacterDatabase.WorkerThreads
|
# CharacterDatabase.WorkerThreads
|
||||||
# HotfixDatabase.WorkerThreads
|
# HotfixDatabase.WorkerThreads
|
||||||
|
# FollowshipDatabase.WorkerThreads
|
||||||
# Description: The amount of worker threads spawned to handle asynchronous (delayed) MySQL
|
# Description: The amount of worker threads spawned to handle asynchronous (delayed) MySQL
|
||||||
# statements. Each worker thread is mirrored with its own connection to the
|
# statements. Each worker thread is mirrored with its own connection to the
|
||||||
# MySQL server and their own thread on the MySQL server.
|
# MySQL server and their own thread on the MySQL server.
|
||||||
@@ -131,27 +135,32 @@ HotfixDatabaseInfo = "127.0.0.1;3306;root;1234;wc_hotfixes"
|
|||||||
# 1 - (WorldDatabase.WorkerThreads)
|
# 1 - (WorldDatabase.WorkerThreads)
|
||||||
# 1 - (CharacterDatabase.WorkerThreads)
|
# 1 - (CharacterDatabase.WorkerThreads)
|
||||||
# 1 - (HotfixDatabase.WorkerThreads)
|
# 1 - (HotfixDatabase.WorkerThreads)
|
||||||
|
# 1 - (FollowshipDatabase.WorkerThreads)
|
||||||
|
|
||||||
LoginDatabase.WorkerThreads = 4
|
LoginDatabase.WorkerThreads = 4
|
||||||
WorldDatabase.WorkerThreads = 8
|
WorldDatabase.WorkerThreads = 8
|
||||||
CharacterDatabase.WorkerThreads = 12
|
CharacterDatabase.WorkerThreads = 12
|
||||||
HotfixDatabase.WorkerThreads = 4
|
HotfixDatabase.WorkerThreads = 4
|
||||||
|
FollowshipDatabase.WorkerThreads = 1
|
||||||
|
|
||||||
#
|
#
|
||||||
# LoginDatabase.SynchThreads
|
# LoginDatabase.SynchThreads
|
||||||
# WorldDatabase.SynchThreads
|
# WorldDatabase.SynchThreads
|
||||||
# CharacterDatabase.SynchThreads
|
# CharacterDatabase.SynchThreads
|
||||||
# HotfixDatabase.SynchThreads
|
# HotfixDatabase.SynchThreads
|
||||||
|
# FollowshipDatabase.SynchThreads
|
||||||
# Description: The amount of MySQL connections spawned to handle.
|
# Description: The amount of MySQL connections spawned to handle.
|
||||||
# Default: 1 - (LoginDatabase.SynchThreads)
|
# Default: 1 - (LoginDatabase.SynchThreads)
|
||||||
# 1 - (WorldDatabase.SynchThreads)
|
# 1 - (WorldDatabase.SynchThreads)
|
||||||
# 2 - (CharacterDatabase.SynchThreads)
|
# 2 - (CharacterDatabase.SynchThreads)
|
||||||
# 1 - (HotfixDatabase.SynchThreads)
|
# 1 - (HotfixDatabase.SynchThreads)
|
||||||
|
# 1 - (FollowshipDatabase.SynchThreads)
|
||||||
|
|
||||||
LoginDatabase.SynchThreads = 4
|
LoginDatabase.SynchThreads = 4
|
||||||
WorldDatabase.SynchThreads = 8
|
WorldDatabase.SynchThreads = 8
|
||||||
CharacterDatabase.SynchThreads = 12
|
CharacterDatabase.SynchThreads = 12
|
||||||
HotfixDatabase.SynchThreads = 4
|
HotfixDatabase.SynchThreads = 4
|
||||||
|
FollowshipDatabase.SynchThreads = 1
|
||||||
|
|
||||||
#
|
#
|
||||||
# MaxPingTime
|
# MaxPingTime
|
||||||
@@ -1461,16 +1470,17 @@ TOTPMasterSecret =
|
|||||||
# Description: A mask that describes which databases shall be updated.
|
# Description: A mask that describes which databases shall be updated.
|
||||||
#
|
#
|
||||||
# Following flags are available
|
# Following flags are available
|
||||||
# DATABASE_LOGIN = 1, // Auth database
|
# DATABASE_LOGIN = 1, // Auth database
|
||||||
# DATABASE_CHARACTER = 2, // Character database
|
# DATABASE_CHARACTER = 2, // Character database
|
||||||
# DATABASE_WORLD = 4, // World database
|
# DATABASE_WORLD = 4, // World database
|
||||||
# DATABASE_HOTFIX = 8, // Hotfixes database
|
# DATABASE_HOTFIX = 8, // Hotfixes database
|
||||||
|
# DATABASE_FOLLOWSHIP = 16, // Followship database
|
||||||
#
|
#
|
||||||
# Default: 15 - (All enabled)
|
# Default: 31 - (All enabled)
|
||||||
# 4 - (Enable world only)
|
# 4 - (Enable world only)
|
||||||
# 0 - (All Disabled)
|
# 0 - (All Disabled)
|
||||||
|
|
||||||
Updates.EnableDatabases = 15
|
Updates.EnableDatabases = 31
|
||||||
|
|
||||||
#
|
#
|
||||||
# Updates.AutoSetup
|
# Updates.AutoSetup
|
||||||
|
|||||||
Reference in New Issue
Block a user