diff --git a/src/game/ChatCommands/Level0.cpp b/src/game/ChatCommands/Level0.cpp index 3076bf81..7c3b4640 100644 --- a/src/game/ChatCommands/Level0.cpp +++ b/src/game/ChatCommands/Level0.cpp @@ -116,7 +116,6 @@ bool ChatHandler::HandleServerInfoCommand(char* /*args*/) { SendSysMessage(LANG_USING_SCRIPT_LIB_NONE); } PSendSysMessage(LANG_USING_WORLD_DB, sWorld.GetDBVersion()); - PSendSysMessage(LANG_USING_EVENT_AI, sWorld.GetCreatureEventAIVersion()); PSendSysMessage(LANG_CONNECTED_USERS, activeClientsNum, maxActiveClientsNum, queuedClientsNum, maxQueuedClientsNum); PSendSysMessage(LANG_UPTIME, str.c_str()); diff --git a/src/game/WorldHandlers/World.cpp b/src/game/WorldHandlers/World.cpp index 0bd8d4a3..1412541c 100644 --- a/src/game/WorldHandlers/World.cpp +++ b/src/game/WorldHandlers/World.cpp @@ -84,6 +84,9 @@ // WARDEN #include "WardenCheckMgr.h" +#include +#include + INSTANTIATE_SINGLETON_1(World); extern void LoadGameObjectModelList(); @@ -2066,22 +2069,25 @@ void World::UpdateMaxSessionCounters() void World::LoadDBVersion() { - QueryResult* result = WorldDatabase.Query("SELECT version, creature_ai_version FROM db_version LIMIT 1"); + QueryResult* result = WorldDatabase.Query("SELECT version, structure, content FROM db_version ORDER BY version DESC, structure DESC, content DESC LIMIT 1"); if (result) { Field* fields = result->Fetch(); - m_DBVersion = fields[0].GetCppString(); - m_CreatureEventAIVersion = fields[1].GetCppString(); + uint32 version = fields[0].GetUInt32(); + uint32 structure = fields[1].GetUInt32(); + uint32 content = fields[2].GetUInt32(); delete result; + + std::stringstream ss; + ss << "Version: " << version << ", Structure: " << structure << ", Content: " << content; + + m_DBVersion = ss.str(); } if (m_DBVersion.empty()) { m_DBVersion = "Unknown world database."; } - - if (m_CreatureEventAIVersion.empty()) - { m_CreatureEventAIVersion = "Unknown creature EventAI."; } } void World::setConfig(eConfigUInt32Values index, char const* fieldname, uint32 defvalue) diff --git a/src/game/WorldHandlers/World.h b/src/game/WorldHandlers/World.h index f8f8ee84..47be27f3 100644 --- a/src/game/WorldHandlers/World.h +++ b/src/game/WorldHandlers/World.h @@ -601,7 +601,6 @@ class World // used World DB version void LoadDBVersion(); char const* GetDBVersion() { return m_DBVersion.c_str(); } - char const* GetCreatureEventAIVersion() { return m_CreatureEventAIVersion.c_str(); } /** @@ -692,7 +691,6 @@ class World // used versions std::string m_DBVersion; - std::string m_CreatureEventAIVersion; // List of Maps that should be force-loaded on startup std::set* m_configForceLoadMapIds; diff --git a/src/mangosd/Master.cpp b/src/mangosd/Master.cpp index c7e4a628..096d988d 100644 --- a/src/mangosd/Master.cpp +++ b/src/mangosd/Master.cpp @@ -465,7 +465,8 @@ bool Master::_StartDB() return false; } - if (!WorldDatabase.CheckRequiredField("db_version", REVISION_DB_MANGOS)) + ///- Check the World database version + if(!WorldDatabase.CheckDatabaseVersion(DATABASE_WORLD)) { ///- Wait for already started DB delay threads to end WorldDatabase.HaltDelayThread(); @@ -494,7 +495,8 @@ bool Master::_StartDB() return false; } - if (!CharacterDatabase.CheckRequiredField("character_db_version", REVISION_DB_CHARACTERS)) + ///- Check the Character database version + if (!CharacterDatabase.CheckDatabaseVersion(DATABASE_CHARACTER)) { ///- Wait for already started DB delay threads to end WorldDatabase.HaltDelayThread(); @@ -527,7 +529,8 @@ bool Master::_StartDB() return false; } - if (!LoginDatabase.CheckRequiredField("realmd_db_version", REVISION_DB_REALMD)) + ///- Check the Realm database version + if (!LoginDatabase.CheckDatabaseVersion(DATABASE_REALMD)) { ///- Wait for already started DB delay threads to end WorldDatabase.HaltDelayThread(); @@ -560,7 +563,6 @@ bool Master::_StartDB() sWorld.LoadDBVersion(); sLog.outString("Using World DB: %s", sWorld.GetDBVersion()); - sLog.outString("Using creature EventAI: %s", sWorld.GetCreatureEventAIVersion()); sLog.outString(); return true; } diff --git a/src/realmd b/src/realmd index 9c9e7ae7..da60a5b8 160000 --- a/src/realmd +++ b/src/realmd @@ -1 +1 @@ -Subproject commit 9c9e7ae7919e1cd5ce1f454520b9adf3316e2137 +Subproject commit da60a5b8481ce8e02cf24614287ebc0e4930d278 diff --git a/src/shared/Database/Database.cpp b/src/shared/Database/Database.cpp index bdc12904..44fc1c8f 100644 --- a/src/shared/Database/Database.cpp +++ b/src/shared/Database/Database.cpp @@ -25,6 +25,7 @@ #include "DatabaseEnv.h" #include "Config/Config.h" #include "Database/SqlOperations.h" +#include "revision.h" #include #include @@ -452,92 +453,78 @@ bool Database::RollbackTransaction() return true; } -bool Database::CheckRequiredField(char const* table_name, char const* required_name) +bool Database::CheckDatabaseVersion(DatabaseTypes database) { - // check required field - QueryResult* result = PQuery("SELECT %s FROM %s LIMIT 1", required_name, table_name); - if (result) - { - delete result; - return true; - } + const DBVersion& dbversion = databaseVersions[database]; - // check fail, prepare readabale error message + // Fetch the database version table information + QueryResult* result = Query("SELECT version, structure, content, description FROM db_version ORDER BY version DESC, structure DESC, content DESC LIMIT 1"); - // search current required_* field in DB - const char* db_name; - if (!strcmp(table_name, "db_version")) - { db_name = "WORLD"; } - else if (!strcmp(table_name, "character_db_version")) - { db_name = "CHARACTER"; } - else if (!strcmp(table_name, "realmd_db_version")) - { db_name = "REALMD"; } - else - { db_name = "UNKNOWN"; } - - char const* req_sql_update_name = required_name + strlen("required_"); - - QueryNamedResult* result2 = PQueryNamed("SELECT * FROM %s LIMIT 1", table_name); - if (result2) - { - QueryFieldNames const& namesMap = result2->GetFieldNames(); - std::string reqName; - for (QueryFieldNames::const_iterator itr = namesMap.begin(); itr != namesMap.end(); ++itr) - { - if (itr->substr(0, 9) == "required_") - { - reqName = *itr; - break; - } - } - - delete result2; - - std::string cur_sql_update_name = reqName.substr(strlen("required_"), reqName.npos); - - if (!reqName.empty()) - { - sLog.outErrorDb("The table `%s` in your [%s] database indicates that this database is out of date!", table_name, db_name); - sLog.outErrorDb(); - sLog.outErrorDb(" [A] You have: --> `%s.sql`", cur_sql_update_name.c_str()); - sLog.outErrorDb(); - sLog.outErrorDb(" [B] You need: --> `%s.sql`", req_sql_update_name); - sLog.outErrorDb(); - sLog.outErrorDb("You must apply all updates after [A] to [B] to use mangos with this database."); - sLog.outErrorDb("These updates are included in the sql/updates folder."); - sLog.outErrorDb("Please read the included [README] in sql/updates for instructions on updating."); - } - else - { - sLog.outErrorDb("The table `%s` in your [%s] database is missing its version info.", table_name, db_name); - sLog.outErrorDb("MaNGOS can not find the version info needed to check that the db is up to date."); - sLog.outErrorDb(); - sLog.outErrorDb("This revision of MaNGOS requires a database updated to:"); - sLog.outErrorDb("`%s.sql`", req_sql_update_name); - sLog.outErrorDb(); - - if (!strcmp(db_name, "WORLD")) - { sLog.outErrorDb("Post this error to your database provider forum or find a solution there."); } - else - { sLog.outErrorDb("Reinstall your [%s] database with the included sql file in the sql folder.", db_name); } - } - } - else - { - sLog.outErrorDb("The table `%s` in your [%s] database is missing or corrupt.", table_name, db_name); - sLog.outErrorDb("MaNGOS can not find the version info needed to check that the db is up to date."); + // db_version table does not exist or is empty + if (!result) + { + sLog.outErrorDb("The table `db_version` in your [%s] database is missing or corrupt.", dbversion.dbname.c_str()); sLog.outErrorDb(); - sLog.outErrorDb("This revision of mangos requires a database updated to:"); - sLog.outErrorDb("`%s.sql`", req_sql_update_name); + sLog.outErrorDb(" [A] You have database Version: MaNGOS can not verify your database version or its existence!"); sLog.outErrorDb(); - - if (!strcmp(db_name, "WORLD")) - { sLog.outErrorDb("Post this error to your database provider forum or find a solution there."); } - else - { sLog.outErrorDb("Reinstall your [%s] database with the included sql file in the sql folder.", db_name); } + sLog.outErrorDb(" [B] You need database Version: %u", dbversion.expected_version); + sLog.outErrorDb(" Structure: %u", dbversion.expected_structure); + sLog.outErrorDb(" Content: %u", dbversion.expected_content); + sLog.outErrorDb(" Description: %s", dbversion.description.c_str()); + sLog.outErrorDb(); + sLog.outErrorDb("Please verify your database location or your database integrity."); + return false; } - return false; + Field* fields = result->Fetch(); + uint32 version = fields[0].GetUInt32(); + uint32 structure = fields[1].GetUInt32(); + uint32 content = fields[2].GetUInt32(); + std::string description = fields[3].GetCppString(); + + delete result; + + // Structure does not match the required version + if (structure != dbversion.expected_structure) + { + sLog.outErrorDb("The table `db_version` indicates that your [%s] database does not match the expected structure!", dbversion.dbname.c_str()); + sLog.outErrorDb(); + sLog.outErrorDb(" [A] You have database Version: %u", version); + sLog.outErrorDb(" Structure: %u", structure); + sLog.outErrorDb(" Content: %u", content); + sLog.outErrorDb(" Description: %s", description.c_str()); + sLog.outErrorDb(); + sLog.outErrorDb(" [B] You need database Version: %u", dbversion.expected_version); + sLog.outErrorDb(" Structure: %u", dbversion.expected_structure); + sLog.outErrorDb(" Content: %u", dbversion.expected_content); + sLog.outErrorDb(" Description: %s", dbversion.description.c_str()); + sLog.outErrorDb(); + sLog.outErrorDb("You must apply all updates after [A] to [B] to use MaNGOS with this database."); + sLog.outErrorDb("These updates are included in the database/%s/Updates folder.", dbversion.dbname.c_str()); + return false; + } + + // DB is not up to date, but structure is correct. Send warning but start core + if (version != dbversion.expected_version || content != dbversion.expected_content) + { + sLog.outErrorDb("The table `db_version` indicates that your [%s] database does not match the expected version!", dbversion.dbname.c_str()); + sLog.outErrorDb(); + sLog.outErrorDb(" [A] You have database Version: %u", version); + sLog.outErrorDb(" Structure: %u", structure); + sLog.outErrorDb(" Content: %u", content); + sLog.outErrorDb(" Description: %s", description.c_str()); + sLog.outErrorDb(); + sLog.outErrorDb(" [B] You need database Version: %u", dbversion.expected_version); + sLog.outErrorDb(" Structure: %u", dbversion.expected_structure); + sLog.outErrorDb(" Content: %u", dbversion.expected_content); + sLog.outErrorDb(" Description: %s", dbversion.description.c_str()); + sLog.outErrorDb(); + sLog.outErrorDb("You are missing content updates or you have content updates beyond the expected core version."); + sLog.outErrorDb("It is recommended to run ALL database updates up to the required core version."); + sLog.outErrorDb("These updates are included in the database/%s/Updates folder.", dbversion.dbname.c_str()); + }; + + return true; } bool Database::ExecuteStmt(const SqlStatementID& id, SqlStmtParameters* params) diff --git a/src/shared/Database/Database.h b/src/shared/Database/Database.h index f96ca176..29d440ba 100644 --- a/src/shared/Database/Database.h +++ b/src/shared/Database/Database.h @@ -25,6 +25,7 @@ #ifndef DATABASE_H #define DATABASE_H +#include "revision.h" #include "Threading/Threading.h" #include "Utilities/UnorderedMapSet.h" #include "Database/SqlDelayThread.h" @@ -43,6 +44,29 @@ class Database; #define MAX_QUERY_LEN (32*1024) +enum DatabaseTypes +{ + DATABASE_WORLD, + DATABASE_REALMD, + DATABASE_CHARACTER, + COUNT_DATABASES, +}; + +struct DBVersion +{ + std::string dbname; + uint32 expected_version; + uint32 expected_structure; + uint32 expected_content; + std::string description; +}; + +const DBVersion databaseVersions[COUNT_DATABASES] = { + { "World", WORLD_DB_VERSION_NR, WORLD_DB_STRUCTURE_NR, WORLD_DB_CONTENT_NR, WORLD_DB_UPDATE_DESCRIPTION }, // DATABASE_WORLD + { "Realmd", REALMD_DB_VERSION_NR, REALMD_DB_STRUCTURE_NR, REALMD_DB_CONTENT_NR, WORLD_DB_UPDATE_DESCRIPTION }, // DATABASE_REALMD + { "Character", CHAR_DB_VERSION_NR, CHAR_DB_STRUCTURE_NR, CHAR_DB_CONTENT_NR, WORLD_DB_UPDATE_DESCRIPTION }, // DATABASE_CHARACTER +}; + /** * @brief * @@ -613,13 +637,12 @@ class Database void ProcessResultQueue(); /** - * @brief - * - * @param table_name - * @param required_name - * @return bool - */ - bool CheckRequiredField(char const* table_name, char const* required_name); + * @brief Function to check that the database version matches expected core version + * + * @param DatabaseTypes + * @return bool + */ + bool CheckDatabaseVersion(DatabaseTypes database); /** * @brief * diff --git a/src/shared/revision.h b/src/shared/revision.h index 4b292553..82be9b83 100644 --- a/src/shared/revision.h +++ b/src/shared/revision.h @@ -24,8 +24,20 @@ #ifndef MANGOS_H_REVISION #define MANGOS_H_REVISION -#define REVISION_NR "21000" -#define REVISION_DB_CHARACTERS "required_21000_01_warden_action" -#define REVISION_DB_MANGOS "required_21000_18_Update_for_quest_502_and_5203" -#define REVISION_DB_REALMD "required_20150722_01_realmcharacters_remove_constraint" + #define REVISION_NR "21000" + + #define REALMD_DB_VERSION_NR 21 + #define REALMD_DB_STRUCTURE_NR 1 + #define REALMD_DB_CONTENT_NR 0 + #define REALMD_DB_UPDATE_DESCRIPTION "revision_refactor" + + #define CHAR_DB_VERSION_NR 21 + #define CHAR_DB_STRUCTURE_NR 1 + #define CHAR_DB_CONTENT_NR 0 + #define CHAR_DB_UPDATE_DESCRIPTION "revision_refactor" + + #define WORLD_DB_VERSION_NR 21 + #define WORLD_DB_STRUCTURE_NR 1 + #define WORLD_DB_CONTENT_NR 0 + #define WORLD_DB_UPDATE_DESCRIPTION "revision_refactor" #endif // __REVISION_H__