diff options
author | Shauren <shauren.trinity@gmail.com> | 2017-05-12 18:49:51 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2017-05-12 18:50:27 +0200 |
commit | 7e538980a2b4fc6c74bde7bd456633d954272708 (patch) | |
tree | 73454d83035b0ddd099e4bc934222df60b66f597 /src | |
parent | 8fdf0778ca340d0bbf0e70dbf091d20c838981d3 (diff) |
Core/Database: Include cleanup
Diffstat (limited to 'src')
86 files changed, 1126 insertions, 921 deletions
diff --git a/src/server/bnetserver/Main.cpp b/src/server/bnetserver/Main.cpp index 25e45b81cef..9d598d63b61 100644 --- a/src/server/bnetserver/Main.cpp +++ b/src/server/bnetserver/Main.cpp @@ -23,20 +23,23 @@ * authentication server */ -#include "SessionManager.h" #include "AppenderDB.h" +#include "Banner.h" #include "Config.h" +#include "DatabaseEnv.h" +#include "DatabaseLoader.h" +#include "GitRevision.h" +#include "LoginRESTService.h" +#include "MySQLThreading.h" #include "ProcessPriority.h" #include "RealmList.h" -#include "GitRevision.h" -#include "Banner.h" +#include "SessionManager.h" #include "SslContext.h" -#include "DatabaseLoader.h" -#include "LoginRESTService.h" -#include <iostream> +#include "Util.h" #include <boost/program_options.hpp> -#include <boost/filesystem/path.hpp> +#include <boost/filesystem/operations.hpp> #include <google/protobuf/stubs/common.h> +#include <iostream> using boost::asio::ip::tcp; using namespace boost::program_options; diff --git a/src/server/bnetserver/Server/Session.cpp b/src/server/bnetserver/Server/Session.cpp index 7fe1c4ef865..a504b6a85ea 100644 --- a/src/server/bnetserver/Server/Session.cpp +++ b/src/server/bnetserver/Server/Session.cpp @@ -18,7 +18,8 @@ #include "Session.h" #include "BattlenetRpcErrorCodes.h" #include "ByteConverter.h" -#include "Database/DatabaseEnv.h" +#include "DatabaseEnv.h" +#include "Errors.h" #include "QueryCallback.h" #include "LoginRESTService.h" #include "ProtobufJSON.h" diff --git a/src/server/database/Database/AdhocStatement.cpp b/src/server/database/Database/AdhocStatement.cpp index 644af01787b..93862db2fb4 100644 --- a/src/server/database/Database/AdhocStatement.cpp +++ b/src/server/database/Database/AdhocStatement.cpp @@ -16,7 +16,10 @@ */ #include "AdhocStatement.h" +#include "Errors.h" #include "MySQLConnection.h" +#include "QueryResult.h" +#include <cstring> /*! Basic, ad-hoc queries. */ BasicStatementTask::BasicStatementTask(const char* sql, bool async) : diff --git a/src/server/database/Database/AdhocStatement.h b/src/server/database/Database/AdhocStatement.h index e419908d175..5d85fa72cd6 100644 --- a/src/server/database/Database/AdhocStatement.h +++ b/src/server/database/Database/AdhocStatement.h @@ -18,12 +18,10 @@ #ifndef _ADHOCSTATEMENT_H #define _ADHOCSTATEMENT_H -#include <future> +#include "Define.h" +#include "DatabaseEnvFwd.h" #include "SQLOperation.h" -typedef std::future<QueryResult> QueryResultFuture; -typedef std::promise<QueryResult> QueryResultPromise; - /*! Raw, ad-hoc query. */ class TC_DATABASE_API BasicStatementTask : public SQLOperation { diff --git a/src/server/database/Database/DatabaseEnv.cpp b/src/server/database/Database/DatabaseEnv.cpp index 02541b06b0b..b5b866b43bf 100644 --- a/src/server/database/Database/DatabaseEnv.cpp +++ b/src/server/database/Database/DatabaseEnv.cpp @@ -17,7 +17,7 @@ #include "DatabaseEnv.h" -WorldDatabaseWorkerPool WorldDatabase; -CharacterDatabaseWorkerPool CharacterDatabase; -LoginDatabaseWorkerPool LoginDatabase; -HotfixDatabaseWorkerPool HotfixDatabase; +DatabaseWorkerPool<WorldDatabaseConnection> WorldDatabase; +DatabaseWorkerPool<CharacterDatabaseConnection> CharacterDatabase; +DatabaseWorkerPool<LoginDatabaseConnection> LoginDatabase; +DatabaseWorkerPool<HotfixDatabaseConnection> HotfixDatabase; diff --git a/src/server/database/Database/DatabaseEnv.h b/src/server/database/Database/DatabaseEnv.h index 317db0fce36..123d780ae3b 100644 --- a/src/server/database/Database/DatabaseEnv.h +++ b/src/server/database/Database/DatabaseEnv.h @@ -19,33 +19,27 @@ #ifndef DATABASEENV_H #define DATABASEENV_H -#include "Common.h" -#include "Errors.h" -#include "Log.h" +#include "Define.h" +#include "DatabaseWorkerPool.h" + +#include "Implementation/WorldDatabase.h" +#include "Implementation/CharacterDatabase.h" +#include "Implementation/LoginDatabase.h" +#include "Implementation/HotfixDatabase.h" #include "Field.h" +#include "PreparedStatement.h" +#include "QueryCallback.h" #include "QueryResult.h" - -#include "MySQLThreading.h" #include "Transaction.h" -#define _LIKE_ "LIKE" -#define _TABLE_SIM_ "`" -#define _CONCAT3_(A, B, C) "CONCAT( " A ", " B ", " C " )" -#define _OFFSET_ "LIMIT %d, 1" - -#include "Implementation/LoginDatabase.h" -#include "Implementation/CharacterDatabase.h" -#include "Implementation/WorldDatabase.h" -#include "Implementation/HotfixDatabase.h" - /// Accessor to the world database -TC_DATABASE_API extern WorldDatabaseWorkerPool WorldDatabase; +TC_DATABASE_API extern DatabaseWorkerPool<WorldDatabaseConnection> WorldDatabase; /// Accessor to the character database -TC_DATABASE_API extern CharacterDatabaseWorkerPool CharacterDatabase; +TC_DATABASE_API extern DatabaseWorkerPool<CharacterDatabaseConnection> CharacterDatabase; /// Accessor to the realm/login database -TC_DATABASE_API extern LoginDatabaseWorkerPool LoginDatabase; +TC_DATABASE_API extern DatabaseWorkerPool<LoginDatabaseConnection> LoginDatabase; /// Accessor to the hotfix database -TC_DATABASE_API extern HotfixDatabaseWorkerPool HotfixDatabase; +TC_DATABASE_API extern DatabaseWorkerPool<HotfixDatabaseConnection> HotfixDatabase; #endif diff --git a/src/server/database/Database/DatabaseEnvFwd.h b/src/server/database/Database/DatabaseEnvFwd.h new file mode 100644 index 00000000000..893dffaaace --- /dev/null +++ b/src/server/database/Database/DatabaseEnvFwd.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/> + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DatabaseEnvFwd_h__ +#define DatabaseEnvFwd_h__ + +#include <future> +#include <memory> + +class Field; + +class ResultSet; +typedef std::shared_ptr<ResultSet> QueryResult; +typedef std::future<QueryResult> QueryResultFuture; +typedef std::promise<QueryResult> QueryResultPromise; + +class PreparedStatement; + +class PreparedResultSet; +typedef std::shared_ptr<PreparedResultSet> PreparedQueryResult; +typedef std::future<PreparedQueryResult> PreparedQueryResultFuture; +typedef std::promise<PreparedQueryResult> PreparedQueryResultPromise; + +class QueryCallback; + +class Transaction; +typedef std::shared_ptr<Transaction> SQLTransaction; + +class SQLQueryHolder; +typedef std::future<SQLQueryHolder*> QueryResultHolderFuture; +typedef std::promise<SQLQueryHolder*> QueryResultHolderPromise; + +// mysql +typedef struct st_mysql MYSQL; +typedef struct st_mysql_res MYSQL_RES; +typedef struct st_mysql_field MYSQL_FIELD; +typedef struct st_mysql_bind MYSQL_BIND; +typedef struct st_mysql_stmt MYSQL_STMT; + +#endif // DatabaseEnvFwd_h__ diff --git a/src/server/database/Database/DatabaseLoader.cpp b/src/server/database/Database/DatabaseLoader.cpp index 9349132fa47..d7f30276be6 100644 --- a/src/server/database/Database/DatabaseLoader.cpp +++ b/src/server/database/Database/DatabaseLoader.cpp @@ -16,8 +16,10 @@ */ #include "DatabaseLoader.h" -#include "DBUpdater.h" #include "Config.h" +#include "DatabaseEnv.h" +#include "DBUpdater.h" +#include "Log.h" #include <mysqld_error.h> @@ -178,10 +180,10 @@ bool DatabaseLoader::Process(std::queue<Predicate>& queue) } template TC_DATABASE_API -DatabaseLoader& DatabaseLoader::AddDatabase<LoginDatabaseConnection>(LoginDatabaseWorkerPool&, std::string const&); +DatabaseLoader& DatabaseLoader::AddDatabase<LoginDatabaseConnection>(DatabaseWorkerPool<LoginDatabaseConnection>&, std::string const&); template TC_DATABASE_API -DatabaseLoader& DatabaseLoader::AddDatabase<CharacterDatabaseConnection>(CharacterDatabaseWorkerPool&, std::string const&); +DatabaseLoader& DatabaseLoader::AddDatabase<CharacterDatabaseConnection>(DatabaseWorkerPool<CharacterDatabaseConnection>&, std::string const&); template TC_DATABASE_API -DatabaseLoader& DatabaseLoader::AddDatabase<HotfixDatabaseConnection>(HotfixDatabaseWorkerPool&, std::string const&); +DatabaseLoader& DatabaseLoader::AddDatabase<HotfixDatabaseConnection>(DatabaseWorkerPool<HotfixDatabaseConnection>&, std::string const&); template TC_DATABASE_API -DatabaseLoader& DatabaseLoader::AddDatabase<WorldDatabaseConnection>(WorldDatabaseWorkerPool&, std::string const&); +DatabaseLoader& DatabaseLoader::AddDatabase<WorldDatabaseConnection>(DatabaseWorkerPool<WorldDatabaseConnection>&, std::string const&); diff --git a/src/server/database/Database/DatabaseLoader.h b/src/server/database/Database/DatabaseLoader.h index 1aa2e3622ac..b9f91ce265d 100644 --- a/src/server/database/Database/DatabaseLoader.h +++ b/src/server/database/Database/DatabaseLoader.h @@ -18,12 +18,15 @@ #ifndef DatabaseLoader_h__ #define DatabaseLoader_h__ -#include "DatabaseWorkerPool.h" -#include "DBUpdater.h" +#include "Define.h" #include <functional> -#include <stack> #include <queue> +#include <stack> +#include <string> + +template<class T> +class DatabaseWorkerPool; // A helper class to initiate all database worker pools, // handles updating, delays preparing of statements and cleans up on failure. diff --git a/src/server/database/Database/DatabaseWorker.cpp b/src/server/database/Database/DatabaseWorker.cpp index 54980863861..c26562b4ff1 100644 --- a/src/server/database/Database/DatabaseWorker.cpp +++ b/src/server/database/Database/DatabaseWorker.cpp @@ -15,7 +15,6 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "DatabaseEnv.h" #include "DatabaseWorker.h" #include "SQLOperation.h" #include "ProducerConsumerQueue.h" diff --git a/src/server/database/Database/DatabaseWorker.h b/src/server/database/Database/DatabaseWorker.h index 38444706656..1476a2b9e99 100644 --- a/src/server/database/Database/DatabaseWorker.h +++ b/src/server/database/Database/DatabaseWorker.h @@ -18,8 +18,12 @@ #ifndef _WORKERTHREAD_H #define _WORKERTHREAD_H +#include "Define.h" +#include <atomic> #include <thread> -#include "ProducerConsumerQueue.h" + +template <typename T> +class ProducerConsumerQueue; class MySQLConnection; class SQLOperation; @@ -37,7 +41,7 @@ class TC_DATABASE_API DatabaseWorker void WorkerThread(); std::thread _workerThread; - std::atomic_bool _cancelationToken; + std::atomic<bool> _cancelationToken; DatabaseWorker(DatabaseWorker const& right) = delete; DatabaseWorker& operator=(DatabaseWorker const& right) = delete; diff --git a/src/server/database/Database/DatabaseWorkerPool.cpp b/src/server/database/Database/DatabaseWorkerPool.cpp index aba2c573c4c..2af31c53a40 100644 --- a/src/server/database/Database/DatabaseWorkerPool.cpp +++ b/src/server/database/Database/DatabaseWorkerPool.cpp @@ -16,12 +16,37 @@ */ #include "DatabaseWorkerPool.h" -#include "DatabaseEnv.h" +#include "AdhocStatement.h" +#include "Common.h" +#include "Errors.h" +#include "Implementation/LoginDatabase.h" +#include "Implementation/WorldDatabase.h" +#include "Implementation/CharacterDatabase.h" +#include "Implementation/HotfixDatabase.h" +#include "Log.h" +#include "PreparedStatement.h" +#include "ProducerConsumerQueue.h" #include "QueryCallback.h" +#include "QueryHolder.h" +#include "QueryResult.h" +#include "SQLOperation.h" +#include "Transaction.h" +#include <mysql.h> +#include <mysqld_error.h> #define MIN_MYSQL_SERVER_VERSION 50100u #define MIN_MYSQL_CLIENT_VERSION 50100u +class PingOperation : public SQLOperation +{ + //! Operation for idle delaythreads + bool Execute() override + { + m_conn->Ping(); + return true; + } +}; + template <class T> DatabaseWorkerPool<T>::DatabaseWorkerPool() : _queue(new ProducerConsumerQueue<SQLOperation*>()), @@ -241,6 +266,12 @@ void DatabaseWorkerPool<T>::DirectCommitTransaction(SQLTransaction& transaction) } template <class T> +PreparedStatement* DatabaseWorkerPool<T>::GetPreparedStatement(PreparedStatementIndex index) +{ + return new PreparedStatement(index); +} + +template <class T> void DatabaseWorkerPool<T>::EscapeString(std::string& str) { if (str.empty()) @@ -313,6 +344,22 @@ uint32 DatabaseWorkerPool<T>::OpenConnections(InternalIndex type, uint8 numConne } template <class T> +unsigned long DatabaseWorkerPool<T>::EscapeString(char *to, const char *from, unsigned long length) +{ + if (!to || !from || !length) + return 0; + + return mysql_real_escape_string( + _connections[IDX_SYNCH].front()->GetHandle(), to, from, length); +} + +template <class T> +void DatabaseWorkerPool<T>::Enqueue(SQLOperation* op) +{ + _queue->Push(op); +} + +template <class T> T* DatabaseWorkerPool<T>::GetFreeConnection() { uint8 i = 0; @@ -330,6 +377,69 @@ T* DatabaseWorkerPool<T>::GetFreeConnection() return connection; } +template <class T> +char const* DatabaseWorkerPool<T>::GetDatabaseName() const +{ + return _connectionInfo->database.c_str(); +} + +template <class T> +void DatabaseWorkerPool<T>::Execute(const char* sql) +{ + if (Trinity::IsFormatEmptyOrNull(sql)) + return; + + BasicStatementTask* task = new BasicStatementTask(sql); + Enqueue(task); +} + +template <class T> +void DatabaseWorkerPool<T>::Execute(PreparedStatement* stmt) +{ + PreparedStatementTask* task = new PreparedStatementTask(stmt); + Enqueue(task); +} + +template <class T> +void DatabaseWorkerPool<T>::DirectExecute(const char* sql) +{ + if (Trinity::IsFormatEmptyOrNull(sql)) + return; + + T* connection = GetFreeConnection(); + connection->Execute(sql); + connection->Unlock(); +} + +template <class T> +void DatabaseWorkerPool<T>::DirectExecute(PreparedStatement* stmt) +{ + T* connection = GetFreeConnection(); + connection->Execute(stmt); + connection->Unlock(); + + //! Delete proxy-class. Not needed anymore + delete stmt; +} + +template <class T> +void DatabaseWorkerPool<T>::ExecuteOrAppend(SQLTransaction& trans, const char* sql) +{ + if (!trans) + Execute(sql); + else + trans->Append(sql); +} + +template <class T> +void DatabaseWorkerPool<T>::ExecuteOrAppend(SQLTransaction& trans, PreparedStatement* stmt) +{ + if (!trans) + Execute(stmt); + else + trans->Append(stmt); +} + template class TC_DATABASE_API DatabaseWorkerPool<LoginDatabaseConnection>; template class TC_DATABASE_API DatabaseWorkerPool<WorldDatabaseConnection>; template class TC_DATABASE_API DatabaseWorkerPool<CharacterDatabaseConnection>; diff --git a/src/server/database/Database/DatabaseWorkerPool.h b/src/server/database/Database/DatabaseWorkerPool.h index adca6b3f836..cc8d0302fb7 100644 --- a/src/server/database/Database/DatabaseWorkerPool.h +++ b/src/server/database/Database/DatabaseWorkerPool.h @@ -18,32 +18,18 @@ #ifndef _DATABASEWORKERPOOL_H #define _DATABASEWORKERPOOL_H -#include "Common.h" -#include "MySQLConnection.h" -#include "Transaction.h" -#include "DatabaseWorker.h" -#include "PreparedStatement.h" -#include "Log.h" -#include "QueryResult.h" -#include "QueryHolder.h" -#include "AdhocStatement.h" +#include "Define.h" +#include "DatabaseEnvFwd.h" #include "StringFormat.h" - -#include <mysqld_error.h> -#include <memory> #include <array> +#include <string> +#include <vector> -class QueryCallback; +template <typename T> +class ProducerConsumerQueue; -class PingOperation : public SQLOperation -{ - //! Operation for idle delaythreads - bool Execute() override - { - m_conn->Ping(); - return true; - } -}; +class SQLOperation; +struct MySQLConnectionInfo; template <class T> class DatabaseWorkerPool @@ -82,14 +68,7 @@ class DatabaseWorkerPool //! Enqueues a one-way SQL operation in string format that will be executed asynchronously. //! This method should only be used for queries that are only executed once, e.g during startup. - void Execute(const char* sql) - { - if (Trinity::IsFormatEmptyOrNull(sql)) - return; - - BasicStatementTask* task = new BasicStatementTask(sql); - Enqueue(task); - } + void Execute(const char* sql); //! Enqueues a one-way SQL operation in string format -with variable args- that will be executed asynchronously. //! This method should only be used for queries that are only executed once, e.g during startup. @@ -104,11 +83,7 @@ class DatabaseWorkerPool //! Enqueues a one-way SQL operation in prepared statement format that will be executed asynchronously. //! Statement must be prepared with CONNECTION_ASYNC flag. - void Execute(PreparedStatement* stmt) - { - PreparedStatementTask* task = new PreparedStatementTask(stmt); - Enqueue(task); - } + void Execute(PreparedStatement* stmt); /** Direct synchronous one-way statement methods. @@ -116,15 +91,7 @@ class DatabaseWorkerPool //! Directly executes a one-way SQL operation in string format, that will block the calling thread until finished. //! This method should only be used for queries that are only executed once, e.g during startup. - void DirectExecute(const char* sql) - { - if (Trinity::IsFormatEmptyOrNull(sql)) - return; - - T* connection = GetFreeConnection(); - connection->Execute(sql); - connection->Unlock(); - } + void DirectExecute(const char* sql); //! Directly executes a one-way SQL operation in string format -with variable args-, that will block the calling thread until finished. //! This method should only be used for queries that are only executed once, e.g during startup. @@ -139,15 +106,7 @@ class DatabaseWorkerPool //! Directly executes a one-way SQL operation in prepared statement format, that will block the calling thread until finished. //! Statement must be prepared with the CONNECTION_SYNCH flag. - void DirectExecute(PreparedStatement* stmt) - { - T* connection = GetFreeConnection(); - connection->Execute(stmt); - connection->Unlock(); - - //! Delete proxy-class. Not needed anymore - delete stmt; - } + void DirectExecute(PreparedStatement* stmt); /** Synchronous query (with resultset) methods. @@ -218,25 +177,13 @@ class DatabaseWorkerPool //! were appended to the transaction will be respected during execution. void DirectCommitTransaction(SQLTransaction& transaction); - //! Method used to execute prepared statements in a diverse context. + //! Method used to execute ad-hoc statements in a diverse context. //! Will be wrapped in a transaction if valid object is present, otherwise executed standalone. - void ExecuteOrAppend(SQLTransaction& trans, PreparedStatement* stmt) - { - if (!trans) - Execute(stmt); - else - trans->Append(stmt); - } + void ExecuteOrAppend(SQLTransaction& trans, const char* sql); - //! Method used to execute ad-hoc statements in a diverse context. + //! Method used to execute prepared statements in a diverse context. //! Will be wrapped in a transaction if valid object is present, otherwise executed standalone. - void ExecuteOrAppend(SQLTransaction& trans, const char* sql) - { - if (!trans) - Execute(sql); - else - trans->Append(sql); - } + void ExecuteOrAppend(SQLTransaction& trans, PreparedStatement* stmt); /** Other @@ -247,10 +194,7 @@ class DatabaseWorkerPool //! Automanaged (internally) pointer to a prepared statement object for usage in upper level code. //! Pointer is deleted in this->DirectExecute(PreparedStatement*), this->Query(PreparedStatement*) or PreparedStatementTask::~PreparedStatementTask. //! This object is not tied to the prepared statement on the MySQL context yet until execution. - PreparedStatement* GetPreparedStatement(PreparedStatementIndex index) - { - return new PreparedStatement(index); - } + PreparedStatement* GetPreparedStatement(PreparedStatementIndex index); //! Apply escape string'ing for current collation. (utf8) void EscapeString(std::string& str); @@ -261,28 +205,15 @@ class DatabaseWorkerPool private: uint32 OpenConnections(InternalIndex type, uint8 numConnections); - unsigned long EscapeString(char *to, const char *from, unsigned long length) - { - if (!to || !from || !length) - return 0; - - return mysql_real_escape_string( - _connections[IDX_SYNCH].front()->GetHandle(), to, from, length); - } + unsigned long EscapeString(char *to, const char *from, unsigned long length); - void Enqueue(SQLOperation* op) - { - _queue->Push(op); - } + void Enqueue(SQLOperation* op); //! Gets a free connection in the synchronous connection pool. //! Caller MUST call t->Unlock() after touching the MySQL context to prevent deadlocks. T* GetFreeConnection(); - char const* GetDatabaseName() const - { - return _connectionInfo->database.c_str(); - } + char const* GetDatabaseName() const; //! Queue shared by async worker threads. std::unique_ptr<ProducerConsumerQueue<SQLOperation*>> _queue; diff --git a/src/server/database/Database/Field.cpp b/src/server/database/Database/Field.cpp index 29326287e63..0f3b3de548d 100644 --- a/src/server/database/Database/Field.cpp +++ b/src/server/database/Database/Field.cpp @@ -16,11 +16,12 @@ */ #include "Field.h" +#include "Log.h" Field::Field() { data.value = NULL; - data.type = MYSQL_TYPE_NULL; + data.type = DatabaseFieldTypes::Null; data.length = 0; data.raw = false; } @@ -30,7 +31,236 @@ Field::~Field() CleanUp(); } -void Field::SetByteValue(void* newValue, enum_field_types newType, uint32 length) +uint8 Field::GetUInt8() const +{ + if (!data.value) + return 0; + +#ifdef TRINITY_DEBUG + if (!IsType(DatabaseFieldTypes::Int8)) + { + TC_LOG_WARN("sql.sql", "Warning: GetUInt8() on non-tinyint field %s.%s (%s.%s) at index %u. Using type: %s.", + meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type); + return 0; + } +#endif + + if (data.raw) + return *reinterpret_cast<uint8*>(data.value); + return static_cast<uint8>(strtoul((char*)data.value, nullptr, 10)); +} + +int8 Field::GetInt8() const +{ + if (!data.value) + return 0; + +#ifdef TRINITY_DEBUG + if (!IsType(DatabaseFieldTypes::Int8)) + { + TC_LOG_WARN("sql.sql", "Warning: GetInt8() on non-tinyint field %s.%s (%s.%s) at index %u. Using type: %s.", + meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type); + return 0; + } +#endif + + if (data.raw) + return *reinterpret_cast<int8*>(data.value); + return static_cast<int8>(strtol((char*)data.value, NULL, 10)); +} + +uint16 Field::GetUInt16() const +{ + if (!data.value) + return 0; + +#ifdef TRINITY_DEBUG + if (!IsType(DatabaseFieldTypes::Int16)) + { + TC_LOG_WARN("sql.sql", "Warning: GetUInt16() on non-smallint field %s.%s (%s.%s) at index %u. Using type: %s.", + meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type); + return 0; + } +#endif + + if (data.raw) + return *reinterpret_cast<uint16*>(data.value); + return static_cast<uint16>(strtoul((char*)data.value, nullptr, 10)); +} + +int16 Field::GetInt16() const +{ + if (!data.value) + return 0; + +#ifdef TRINITY_DEBUG + if (!IsType(DatabaseFieldTypes::Int16)) + { + TC_LOG_WARN("sql.sql", "Warning: GetInt16() on non-smallint field %s.%s (%s.%s) at index %u. Using type: %s.", + meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type); + return 0; + } +#endif + + if (data.raw) + return *reinterpret_cast<int16*>(data.value); + return static_cast<int16>(strtol((char*)data.value, NULL, 10)); +} + +uint32 Field::GetUInt32() const +{ + if (!data.value) + return 0; + +#ifdef TRINITY_DEBUG + if (!IsType(DatabaseFieldTypes::Int32)) + { + TC_LOG_WARN("sql.sql", "Warning: GetUInt32() on non-(medium)int field %s.%s (%s.%s) at index %u. Using type: %s.", + meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type); + return 0; + } +#endif + + if (data.raw) + return *reinterpret_cast<uint32*>(data.value); + return static_cast<uint32>(strtoul((char*)data.value, nullptr, 10)); +} + +int32 Field::GetInt32() const +{ + if (!data.value) + return 0; + +#ifdef TRINITY_DEBUG + if (!IsType(DatabaseFieldTypes::Int32)) + { + TC_LOG_WARN("sql.sql", "Warning: GetInt32() on non-(medium)int field %s.%s (%s.%s) at index %u. Using type: %s.", + meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type); + return 0; + } +#endif + + if (data.raw) + return *reinterpret_cast<int32*>(data.value); + return static_cast<int32>(strtol((char*)data.value, NULL, 10)); +} + +uint64 Field::GetUInt64() const +{ + if (!data.value) + return 0; + +#ifdef TRINITY_DEBUG + if (!IsType(DatabaseFieldTypes::Int64)) + { + TC_LOG_WARN("sql.sql", "Warning: GetUInt64() on non-bigint field %s.%s (%s.%s) at index %u. Using type: %s.", + meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type); + return 0; + } +#endif + + if (data.raw) + return *reinterpret_cast<uint64*>(data.value); + return static_cast<uint64>(strtoull((char*)data.value, nullptr, 10)); +} + +int64 Field::GetInt64() const +{ + if (!data.value) + return 0; + +#ifdef TRINITY_DEBUG + if (!IsType(DatabaseFieldTypes::Int64)) + { + TC_LOG_WARN("sql.sql", "Warning: GetInt64() on non-bigint field %s.%s (%s.%s) at index %u. Using type: %s.", + meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type); + return 0; + } +#endif + + if (data.raw) + return *reinterpret_cast<int64*>(data.value); + return static_cast<int64>(strtoll((char*)data.value, NULL, 10)); +} + +float Field::GetFloat() const +{ + if (!data.value) + return 0.0f; + +#ifdef TRINITY_DEBUG + if (!IsType(DatabaseFieldTypes::Float)) + { + TC_LOG_WARN("sql.sql", "Warning: GetFloat() on non-float field %s.%s (%s.%s) at index %u. Using type: %s.", + meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type); + return 0.0f; + } +#endif + + if (data.raw) + return *reinterpret_cast<float*>(data.value); + return static_cast<float>(atof((char*)data.value)); +} + +double Field::GetDouble() const +{ + if (!data.value) + return 0.0f; + +#ifdef TRINITY_DEBUG + if (!IsType(DatabaseFieldTypes::Double) && !IsType(DatabaseFieldTypes::Decimal)) + { + TC_LOG_WARN("sql.sql", "Warning: GetDouble() on non-double/non-decimal field %s.%s (%s.%s) at index %u. Using type: %s.", + meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type); + return 0.0f; + } +#endif + + if (data.raw && !IsType(DatabaseFieldTypes::Decimal)) + return *reinterpret_cast<double*>(data.value); + return static_cast<double>(atof((char*)data.value)); +} + +char const* Field::GetCString() const +{ + if (!data.value) + return NULL; + +#ifdef TRINITY_DEBUG + if (IsNumeric() && data.raw) + { + TC_LOG_WARN("sql.sql", "Error: GetCString() on numeric field %s.%s (%s.%s) at index %u. Using type: %s.", + meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type); + return NULL; + } +#endif + return static_cast<char const*>(data.value); +} + +std::string Field::GetString() const +{ + if (!data.value) + return ""; + + char const* string = GetCString(); + if (!string) + return ""; + + return std::string(string, data.length); +} + +std::vector<uint8> Field::GetBinary() const +{ + std::vector<uint8> result; + if (!data.value || !data.length) + return result; + + result.resize(data.length); + memcpy(result.data(), data.value, data.length); + return result; +} + +void Field::SetByteValue(void* newValue, DatabaseFieldTypes newType, uint32 length) { // This value stores raw bytes that have to be explicitly cast later data.value = newValue; @@ -39,7 +269,7 @@ void Field::SetByteValue(void* newValue, enum_field_types newType, uint32 length data.raw = true; } -void Field::SetStructuredValue(char* newValue, enum_field_types newType, uint32 length) +void Field::SetStructuredValue(char* newValue, DatabaseFieldTypes newType, uint32 length) { if (data.value) CleanUp(); @@ -56,3 +286,67 @@ void Field::SetStructuredValue(char* newValue, enum_field_types newType, uint32 data.type = newType; data.raw = false; } + +bool Field::IsType(DatabaseFieldTypes type) const +{ + return data.type == type; +} + +bool Field::IsNumeric() const +{ + return (data.type == DatabaseFieldTypes::Int8 || + data.type == DatabaseFieldTypes::Int16 || + data.type == DatabaseFieldTypes::Int32 || + data.type == DatabaseFieldTypes::Int64 || + data.type == DatabaseFieldTypes::Float || + data.type == DatabaseFieldTypes::Double); +} + +#ifdef TRINITY_DEBUG + +#include <mysql.h> + +static char const* FieldTypeToString(enum_field_types type) +{ + switch (type) + { + case MYSQL_TYPE_BIT: return "BIT"; + case MYSQL_TYPE_BLOB: return "BLOB"; + case MYSQL_TYPE_DATE: return "DATE"; + case MYSQL_TYPE_DATETIME: return "DATETIME"; + case MYSQL_TYPE_NEWDECIMAL: return "NEWDECIMAL"; + case MYSQL_TYPE_DECIMAL: return "DECIMAL"; + case MYSQL_TYPE_DOUBLE: return "DOUBLE"; + case MYSQL_TYPE_ENUM: return "ENUM"; + case MYSQL_TYPE_FLOAT: return "FLOAT"; + case MYSQL_TYPE_GEOMETRY: return "GEOMETRY"; + case MYSQL_TYPE_INT24: return "INT24"; + case MYSQL_TYPE_LONG: return "LONG"; + case MYSQL_TYPE_LONGLONG: return "LONGLONG"; + case MYSQL_TYPE_LONG_BLOB: return "LONG_BLOB"; + case MYSQL_TYPE_MEDIUM_BLOB: return "MEDIUM_BLOB"; + case MYSQL_TYPE_NEWDATE: return "NEWDATE"; + case MYSQL_TYPE_NULL: return "NULL"; + case MYSQL_TYPE_SET: return "SET"; + case MYSQL_TYPE_SHORT: return "SHORT"; + case MYSQL_TYPE_STRING: return "STRING"; + case MYSQL_TYPE_TIME: return "TIME"; + case MYSQL_TYPE_TIMESTAMP: return "TIMESTAMP"; + case MYSQL_TYPE_TINY: return "TINY"; + case MYSQL_TYPE_TINY_BLOB: return "TINY_BLOB"; + case MYSQL_TYPE_VAR_STRING: return "VAR_STRING"; + case MYSQL_TYPE_YEAR: return "YEAR"; + default: return "-Unknown-"; + } +} + +void Field::SetMetadata(MYSQL_FIELD* field, uint32 fieldIndex) +{ + meta.TableName = field->org_table; + meta.TableAlias = field->table; + meta.Name = field->org_name; + meta.Alias = field->name; + meta.Type = FieldTypeToString(field->type); + meta.Index = fieldIndex; +} +#endif diff --git a/src/server/database/Database/Field.h b/src/server/database/Database/Field.h index 8035dd16869..18cba2acd82 100644 --- a/src/server/database/Database/Field.h +++ b/src/server/database/Database/Field.h @@ -18,13 +18,23 @@ #ifndef _FIELD_H #define _FIELD_H -#include "Common.h" -#include "Log.h" +#include "Define.h" +#include "DatabaseEnvFwd.h" +#include <vector> -#ifdef _WIN32 -#include <winsock2.h> -#endif -#include <mysql.h> +enum class DatabaseFieldTypes : uint8 +{ + Null, + Int8, + Int16, + Int32, + Int64, + Float, + Double, + Decimal, + Date, + Binary +}; /** @class Field @@ -70,234 +80,19 @@ class TC_DATABASE_API Field return GetUInt8() == 1 ? true : false; } - uint8 GetUInt8() const - { - if (!data.value) - return 0; - - #ifdef TRINITY_DEBUG - if (!IsType(MYSQL_TYPE_TINY)) - { - TC_LOG_WARN("sql.sql", "Warning: GetUInt8() on non-tinyint field %s.%s (%s.%s) at index %u. Using type: %s.", - meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type); - return 0; - } - #endif - - if (data.raw) - return *reinterpret_cast<uint8*>(data.value); - return static_cast<uint8>(strtoul((char*)data.value, nullptr, 10)); - } - - int8 GetInt8() const - { - if (!data.value) - return 0; - - #ifdef TRINITY_DEBUG - if (!IsType(MYSQL_TYPE_TINY)) - { - TC_LOG_WARN("sql.sql", "Warning: GetInt8() on non-tinyint field %s.%s (%s.%s) at index %u. Using type: %s.", - meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type); - return 0; - } - #endif - - if (data.raw) - return *reinterpret_cast<int8*>(data.value); - return static_cast<int8>(strtol((char*)data.value, NULL, 10)); - } - - uint16 GetUInt16() const - { - if (!data.value) - return 0; - - #ifdef TRINITY_DEBUG - if (!IsType(MYSQL_TYPE_SHORT) && !IsType(MYSQL_TYPE_YEAR)) - { - TC_LOG_WARN("sql.sql", "Warning: GetUInt16() on non-smallint field %s.%s (%s.%s) at index %u. Using type: %s.", - meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type); - return 0; - } - #endif - - if (data.raw) - return *reinterpret_cast<uint16*>(data.value); - return static_cast<uint16>(strtoul((char*)data.value, nullptr, 10)); - } - - int16 GetInt16() const - { - if (!data.value) - return 0; - - #ifdef TRINITY_DEBUG - if (!IsType(MYSQL_TYPE_SHORT) && !IsType(MYSQL_TYPE_YEAR)) - { - TC_LOG_WARN("sql.sql", "Warning: GetInt16() on non-smallint field %s.%s (%s.%s) at index %u. Using type: %s.", - meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type); - return 0; - } - #endif - - if (data.raw) - return *reinterpret_cast<int16*>(data.value); - return static_cast<int16>(strtol((char*)data.value, NULL, 10)); - } - - uint32 GetUInt32() const - { - if (!data.value) - return 0; - - #ifdef TRINITY_DEBUG - if (!IsType(MYSQL_TYPE_INT24) && !IsType(MYSQL_TYPE_LONG)) - { - TC_LOG_WARN("sql.sql", "Warning: GetUInt32() on non-(medium)int field %s.%s (%s.%s) at index %u. Using type: %s.", - meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type); - return 0; - } - #endif - - if (data.raw) - return *reinterpret_cast<uint32*>(data.value); - return static_cast<uint32>(strtoul((char*)data.value, nullptr, 10)); - } - - int32 GetInt32() const - { - if (!data.value) - return 0; - - #ifdef TRINITY_DEBUG - if (!IsType(MYSQL_TYPE_INT24) && !IsType(MYSQL_TYPE_LONG)) - { - TC_LOG_WARN("sql.sql", "Warning: GetInt32() on non-(medium)int field %s.%s (%s.%s) at index %u. Using type: %s.", - meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type); - return 0; - } - #endif - - if (data.raw) - return *reinterpret_cast<int32*>(data.value); - return static_cast<int32>(strtol((char*)data.value, NULL, 10)); - } - - uint64 GetUInt64() const - { - if (!data.value) - return 0; - - #ifdef TRINITY_DEBUG - if (!IsType(MYSQL_TYPE_LONGLONG) && !IsType(MYSQL_TYPE_BIT)) - { - TC_LOG_WARN("sql.sql", "Warning: GetUInt64() on non-bigint field %s.%s (%s.%s) at index %u. Using type: %s.", - meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type); - return 0; - } - #endif - - if (data.raw) - return *reinterpret_cast<uint64*>(data.value); - return static_cast<uint64>(strtoull((char*)data.value, nullptr, 10)); - } - - int64 GetInt64() const - { - if (!data.value) - return 0; - - #ifdef TRINITY_DEBUG - if (!IsType(MYSQL_TYPE_LONGLONG) && !IsType(MYSQL_TYPE_BIT)) - { - TC_LOG_WARN("sql.sql", "Warning: GetInt64() on non-bigint field %s.%s (%s.%s) at index %u. Using type: %s.", - meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type); - return 0; - } - #endif - - if (data.raw) - return *reinterpret_cast<int64*>(data.value); - return static_cast<int64>(strtoll((char*)data.value, NULL, 10)); - } - - float GetFloat() const - { - if (!data.value) - return 0.0f; - - #ifdef TRINITY_DEBUG - if (!IsType(MYSQL_TYPE_FLOAT)) - { - TC_LOG_WARN("sql.sql", "Warning: GetFloat() on non-float field %s.%s (%s.%s) at index %u. Using type: %s.", - meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type); - return 0.0f; - } - #endif - - if (data.raw) - return *reinterpret_cast<float*>(data.value); - return static_cast<float>(atof((char*)data.value)); - } - - double GetDouble() const - { - if (!data.value) - return 0.0f; - - #ifdef TRINITY_DEBUG - if (!IsType(MYSQL_TYPE_DOUBLE) && !IsType(MYSQL_TYPE_NEWDECIMAL)) - { - TC_LOG_WARN("sql.sql", "Warning: GetDouble() on non-double/non-decimal field %s.%s (%s.%s) at index %u. Using type: %s.", - meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type); - return 0.0f; - } - #endif - - if (data.raw && !IsType(MYSQL_TYPE_NEWDECIMAL)) - return *reinterpret_cast<double*>(data.value); - return static_cast<double>(atof((char*)data.value)); - } - - char const* GetCString() const - { - if (!data.value) - return NULL; - - #ifdef TRINITY_DEBUG - if (IsNumeric()) - { - TC_LOG_WARN("sql.sql", "Error: GetCString() on numeric field %s.%s (%s.%s) at index %u. Using type: %s.", - meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type); - return NULL; - } - #endif - return static_cast<char const*>(data.value); - } - - std::string GetString() const - { - if (!data.value) - return ""; - - char const* string = GetCString(); - if (!string) - return ""; - - return std::string(string, data.length); - } - - std::vector<uint8> GetBinary() const - { - std::vector<uint8> result; - if (!data.value || !data.length) - return result; - - result.resize(data.length); - memcpy(result.data(), data.value, data.length); - return result; - } + uint8 GetUInt8() const; + int8 GetInt8() const; + uint16 GetUInt16() const; + int16 GetInt16() const; + uint32 GetUInt32() const; + int32 GetInt32() const; + uint64 GetUInt64() const; + int64 GetInt64() const; + float GetFloat() const; + double GetDouble() const; + char const* GetCString() const; + std::string GetString() const; + std::vector<uint8> GetBinary() const; bool IsNull() const { @@ -320,13 +115,13 @@ class TC_DATABASE_API Field { uint32 length; // Length (prepared strings only) void* value; // Actual data in memory - enum_field_types type; // Field type + DatabaseFieldTypes type; // Field type bool raw; // Raw bytes? (Prepared statement or ad hoc) } data; #pragma pack(pop) - void SetByteValue(void* newValue, enum_field_types newType, uint32 length); - void SetStructuredValue(char* newValue, enum_field_types newType, uint32 length); + void SetByteValue(void* newValue, DatabaseFieldTypes newType, uint32 length); + void SetStructuredValue(char* newValue, DatabaseFieldTypes newType, uint32 length); void CleanUp() { @@ -336,120 +131,14 @@ class TC_DATABASE_API Field data.value = NULL; } - static uint32 SizeForType(MYSQL_FIELD* field) - { - switch (field->type) - { - case MYSQL_TYPE_NULL: - return 0; - case MYSQL_TYPE_TINY: - return 1; - case MYSQL_TYPE_YEAR: - case MYSQL_TYPE_SHORT: - return 2; - case MYSQL_TYPE_INT24: - case MYSQL_TYPE_LONG: - case MYSQL_TYPE_FLOAT: - return 4; - case MYSQL_TYPE_DOUBLE: - case MYSQL_TYPE_LONGLONG: - case MYSQL_TYPE_BIT: - return 8; - - case MYSQL_TYPE_TIMESTAMP: - case MYSQL_TYPE_DATE: - case MYSQL_TYPE_TIME: - case MYSQL_TYPE_DATETIME: - return sizeof(MYSQL_TIME); - - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_STRING: - case MYSQL_TYPE_VAR_STRING: - return field->max_length + 1; - - case MYSQL_TYPE_DECIMAL: - case MYSQL_TYPE_NEWDECIMAL: - return 64; - - case MYSQL_TYPE_GEOMETRY: - /* - Following types are not sent over the wire: - MYSQL_TYPE_ENUM: - MYSQL_TYPE_SET: - */ - default: - TC_LOG_WARN("sql.sql", "SQL::SizeForType(): invalid field type %u", uint32(field->type)); - return 0; - } - } - - bool IsType(enum_field_types type) const - { - return data.type == type; - } + bool IsType(DatabaseFieldTypes type) const; - bool IsNumeric() const - { - return (data.type == MYSQL_TYPE_TINY || - data.type == MYSQL_TYPE_SHORT || - data.type == MYSQL_TYPE_INT24 || - data.type == MYSQL_TYPE_LONG || - data.type == MYSQL_TYPE_FLOAT || - data.type == MYSQL_TYPE_DOUBLE || - data.type == MYSQL_TYPE_LONGLONG ); - } + bool IsNumeric() const; private: #ifdef TRINITY_DEBUG - static char const* FieldTypeToString(enum_field_types type) - { - switch (type) - { - case MYSQL_TYPE_BIT: return "BIT"; - case MYSQL_TYPE_BLOB: return "BLOB"; - case MYSQL_TYPE_DATE: return "DATE"; - case MYSQL_TYPE_DATETIME: return "DATETIME"; - case MYSQL_TYPE_NEWDECIMAL: return "NEWDECIMAL"; - case MYSQL_TYPE_DECIMAL: return "DECIMAL"; - case MYSQL_TYPE_DOUBLE: return "DOUBLE"; - case MYSQL_TYPE_ENUM: return "ENUM"; - case MYSQL_TYPE_FLOAT: return "FLOAT"; - case MYSQL_TYPE_GEOMETRY: return "GEOMETRY"; - case MYSQL_TYPE_INT24: return "INT24"; - case MYSQL_TYPE_LONG: return "LONG"; - case MYSQL_TYPE_LONGLONG: return "LONGLONG"; - case MYSQL_TYPE_LONG_BLOB: return "LONG_BLOB"; - case MYSQL_TYPE_MEDIUM_BLOB: return "MEDIUM_BLOB"; - case MYSQL_TYPE_NEWDATE: return "NEWDATE"; - case MYSQL_TYPE_NULL: return "NULL"; - case MYSQL_TYPE_SET: return "SET"; - case MYSQL_TYPE_SHORT: return "SHORT"; - case MYSQL_TYPE_STRING: return "STRING"; - case MYSQL_TYPE_TIME: return "TIME"; - case MYSQL_TYPE_TIMESTAMP: return "TIMESTAMP"; - case MYSQL_TYPE_TINY: return "TINY"; - case MYSQL_TYPE_TINY_BLOB: return "TINY_BLOB"; - case MYSQL_TYPE_VAR_STRING: return "VAR_STRING"; - case MYSQL_TYPE_YEAR: return "YEAR"; - default: return "-Unknown-"; - } - } - - void SetMetadata(MYSQL_FIELD* field, uint32 fieldIndex) - { - meta.TableName = field->org_table; - meta.TableAlias = field->table; - meta.Name = field->org_name; - meta.Alias = field->name; - meta.Type = FieldTypeToString(field->type); - meta.Index = fieldIndex; - } - + void SetMetadata(MYSQL_FIELD* field, uint32 fieldIndex); Metadata meta; - #endif }; diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp index 5d5255f82f3..99f3a487829 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp @@ -16,6 +16,7 @@ */ #include "CharacterDatabase.h" +#include "PreparedStatement.h" void CharacterDatabaseConnection::DoPrepareStatements() { @@ -735,3 +736,15 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_INS_SCENARIO_INSTANCE_CRITERIA, "INSERT INTO instance_scenario_progress (id, criteria, counter, date) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_SCENARIO_INSTANCE_CRITERIA_FOR_INSTANCE, "DELETE FROM instance_scenario_progress WHERE id = ?", CONNECTION_ASYNC); } + +CharacterDatabaseConnection::CharacterDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) +{ +} + +CharacterDatabaseConnection::CharacterDatabaseConnection(ProducerConsumerQueue<SQLOperation*>* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo) +{ +} + +CharacterDatabaseConnection::~CharacterDatabaseConnection() +{ +} diff --git a/src/server/database/Database/Implementation/CharacterDatabase.h b/src/server/database/Database/Implementation/CharacterDatabase.h index 97190f9f614..c2ea5136261 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.h +++ b/src/server/database/Database/Implementation/CharacterDatabase.h @@ -18,10 +18,9 @@ #ifndef _CHARACTERDATABASE_H #define _CHARACTERDATABASE_H -#include "DatabaseWorkerPool.h" #include "MySQLConnection.h" -enum CharacterDatabaseStatements +enum CharacterDatabaseStatements : uint32 { /* Naming standard for defines: {DB}_{SEL/INS/UPD/DEL/REP}_{Summary of data changed} @@ -633,13 +632,12 @@ public: typedef CharacterDatabaseStatements Statements; //- Constructors for sync and async connections - CharacterDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) { } - CharacterDatabaseConnection(ProducerConsumerQueue<SQLOperation*>* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo) { } + CharacterDatabaseConnection(MySQLConnectionInfo& connInfo); + CharacterDatabaseConnection(ProducerConsumerQueue<SQLOperation*>* q, MySQLConnectionInfo& connInfo); + ~CharacterDatabaseConnection(); //- Loads database type specific prepared statements void DoPrepareStatements() override; }; -typedef DatabaseWorkerPool<CharacterDatabaseConnection> CharacterDatabaseWorkerPool; - #endif diff --git a/src/server/database/Database/Implementation/HotfixDatabase.cpp b/src/server/database/Database/Implementation/HotfixDatabase.cpp index 2758c76bf09..da134a3d9b0 100644 --- a/src/server/database/Database/Implementation/HotfixDatabase.cpp +++ b/src/server/database/Database/Implementation/HotfixDatabase.cpp @@ -19,6 +19,7 @@ // Autogenerated from DB2Structure.h #include "HotfixDatabase.h" +#include "PreparedStatement.h" // Force locale statments to appear exactly in locale declaration order, right after normal data fetch statement #define PREPARE_LOCALE_STMT(stmtBase, sql, con) \ @@ -978,3 +979,15 @@ void HotfixDatabaseConnection::DoPrepareStatements() PrepareStatement(HOTFIX_SEL_WORLD_SAFE_LOCS, "SELECT ID, LocX, LocY, LocZ, Facing, AreaName, MapID FROM world_safe_locs ORDER BY ID DESC", CONNECTION_SYNCH); PREPARE_LOCALE_STMT(HOTFIX_SEL_WORLD_SAFE_LOCS, "SELECT ID, AreaName_lang FROM world_safe_locs_locale WHERE locale = ?", CONNECTION_SYNCH); } + +HotfixDatabaseConnection::HotfixDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) +{ +} + +HotfixDatabaseConnection::HotfixDatabaseConnection(ProducerConsumerQueue<SQLOperation*>* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo) +{ +} + +HotfixDatabaseConnection::~HotfixDatabaseConnection() +{ +} diff --git a/src/server/database/Database/Implementation/HotfixDatabase.h b/src/server/database/Database/Implementation/HotfixDatabase.h index 141f3ddc878..4e53630805f 100644 --- a/src/server/database/Database/Implementation/HotfixDatabase.h +++ b/src/server/database/Database/Implementation/HotfixDatabase.h @@ -21,10 +21,9 @@ #ifndef _HOTFIXDATABASE_H #define _HOTFIXDATABASE_H -#include "DatabaseWorkerPool.h" #include "MySQLConnection.h" -enum HotfixDatabaseStatements +enum HotfixDatabaseStatements : uint32 { /* Naming standard for defines: {DB}_{SEL/INS/UPD/DEL/REP}_{Summary of data changed} @@ -525,13 +524,12 @@ public: typedef HotfixDatabaseStatements Statements; //- Constructors for sync and async connections - HotfixDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) { } - HotfixDatabaseConnection(ProducerConsumerQueue<SQLOperation*>* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo) { } + HotfixDatabaseConnection(MySQLConnectionInfo& connInfo); + HotfixDatabaseConnection(ProducerConsumerQueue<SQLOperation*>* q, MySQLConnectionInfo& connInfo); + ~HotfixDatabaseConnection(); //- Loads database type specific prepared statements void DoPrepareStatements() override; }; -typedef DatabaseWorkerPool<HotfixDatabaseConnection> HotfixDatabaseWorkerPool; - #endif diff --git a/src/server/database/Database/Implementation/LoginDatabase.cpp b/src/server/database/Database/Implementation/LoginDatabase.cpp index 414faafeff5..fe2d913538d 100644 --- a/src/server/database/Database/Implementation/LoginDatabase.cpp +++ b/src/server/database/Database/Implementation/LoginDatabase.cpp @@ -16,6 +16,7 @@ */ #include "LoginDatabase.h" +#include "PreparedStatement.h" void LoginDatabaseConnection::DoPrepareStatements() { @@ -176,3 +177,15 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_INS_BNET_ITEM_FAVORITE_APPEARANCE, "INSERT INTO battlenet_item_favorite_appearances (battlenetAccountId, itemModifiedAppearanceId) VALUES (?, ?)", CONNECTION_ASYNC); PrepareStatement(LOGIN_DEL_BNET_ITEM_FAVORITE_APPEARANCE, "DELETE FROM battlenet_item_favorite_appearances WHERE battlenetAccountId = ? AND itemModifiedAppearanceId = ?", CONNECTION_ASYNC); } + +LoginDatabaseConnection::LoginDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) +{ +} + +LoginDatabaseConnection::LoginDatabaseConnection(ProducerConsumerQueue<SQLOperation*>* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo) +{ +} + +LoginDatabaseConnection::~LoginDatabaseConnection() +{ +} diff --git a/src/server/database/Database/Implementation/LoginDatabase.h b/src/server/database/Database/Implementation/LoginDatabase.h index d9eb9fc157c..b58630b4ae5 100644 --- a/src/server/database/Database/Implementation/LoginDatabase.h +++ b/src/server/database/Database/Implementation/LoginDatabase.h @@ -18,10 +18,9 @@ #ifndef _LOGINDATABASE_H #define _LOGINDATABASE_H -#include "DatabaseWorkerPool.h" #include "MySQLConnection.h" -enum LoginDatabaseStatements +enum LoginDatabaseStatements : uint32 { /* Naming standard for defines: {DB}_{SEL/INS/UPD/DEL/REP}_{Summary of data changed} @@ -171,13 +170,12 @@ public: typedef LoginDatabaseStatements Statements; //- Constructors for sync and async connections - LoginDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) { } - LoginDatabaseConnection(ProducerConsumerQueue<SQLOperation*>* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo) { } + LoginDatabaseConnection(MySQLConnectionInfo& connInfo); + LoginDatabaseConnection(ProducerConsumerQueue<SQLOperation*>* q, MySQLConnectionInfo& connInfo); + ~LoginDatabaseConnection(); //- Loads database type specific prepared statements void DoPrepareStatements() override; }; -typedef DatabaseWorkerPool<LoginDatabaseConnection> LoginDatabaseWorkerPool; - #endif diff --git a/src/server/database/Database/Implementation/WorldDatabase.cpp b/src/server/database/Database/Implementation/WorldDatabase.cpp index def1e948a06..52a2ca918c1 100644 --- a/src/server/database/Database/Implementation/WorldDatabase.cpp +++ b/src/server/database/Database/Implementation/WorldDatabase.cpp @@ -16,6 +16,7 @@ */ #include "WorldDatabase.h" +#include "PreparedStatement.h" void WorldDatabaseConnection::DoPrepareStatements() { @@ -92,3 +93,15 @@ void WorldDatabaseConnection::DoPrepareStatements() PrepareStatement(WORLD_UPD_GAMEOBJECT_ZONE_AREA_DATA, "UPDATE gameobject SET zoneId = ?, areaId = ? WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(WORLD_SEL_GUILD_REWARDS_REQ_ACHIEVEMENTS, "SELECT AchievementRequired FROM guild_rewards_req_achievements WHERE ItemID = ?", CONNECTION_SYNCH); } + +WorldDatabaseConnection::WorldDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) +{ +} + +WorldDatabaseConnection::WorldDatabaseConnection(ProducerConsumerQueue<SQLOperation*>* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo) +{ +} + +WorldDatabaseConnection::~WorldDatabaseConnection() +{ +} diff --git a/src/server/database/Database/Implementation/WorldDatabase.h b/src/server/database/Database/Implementation/WorldDatabase.h index e8f1f0c16fe..425919d3379 100644 --- a/src/server/database/Database/Implementation/WorldDatabase.h +++ b/src/server/database/Database/Implementation/WorldDatabase.h @@ -18,10 +18,9 @@ #ifndef _WORLDDATABASE_H #define _WORLDDATABASE_H -#include "DatabaseWorkerPool.h" #include "MySQLConnection.h" -enum WorldDatabaseStatements +enum WorldDatabaseStatements : uint32 { /* Naming standard for defines: {DB}_{SEL/INS/UPD/DEL/REP}_{Summary of data changed} @@ -109,13 +108,12 @@ public: typedef WorldDatabaseStatements Statements; //- Constructors for sync and async connections - WorldDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) { } - WorldDatabaseConnection(ProducerConsumerQueue<SQLOperation*>* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo) { } + WorldDatabaseConnection(MySQLConnectionInfo& connInfo); + WorldDatabaseConnection(ProducerConsumerQueue<SQLOperation*>* q, MySQLConnectionInfo& connInfo); + ~WorldDatabaseConnection(); //- Loads database type specific prepared statements void DoPrepareStatements() override; }; -typedef DatabaseWorkerPool<WorldDatabaseConnection> WorldDatabaseWorkerPool; - #endif diff --git a/src/server/database/Database/MySQLConnection.cpp b/src/server/database/Database/MySQLConnection.cpp index 47ed4a97c3e..2598e3214ff 100644 --- a/src/server/database/Database/MySQLConnection.cpp +++ b/src/server/database/Database/MySQLConnection.cpp @@ -15,23 +15,34 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ - -#include "Common.h" - -#ifdef _WIN32 - #include <winsock2.h> -#endif -#include <mysql.h> -#include <errmsg.h> - #include "MySQLConnection.h" -#include "QueryResult.h" -#include "SQLOperation.h" -#include "PreparedStatement.h" +#include "Common.h" #include "DatabaseWorker.h" -#include "Timer.h" #include "Log.h" -#include "ProducerConsumerQueue.h" +#include "PreparedStatement.h" +#include "QueryResult.h" +#include "Timer.h" +#include "Transaction.h" +#include "Util.h" +#include <errmsg.h> +#include <mysql.h> +#include <mysqld_error.h> + +MySQLConnectionInfo::MySQLConnectionInfo(std::string const& infoString) +{ + Tokenizer tokens(infoString, ';'); + + if (tokens.size() != 5) + return; + + uint8 i = 0; + + host.assign(tokens[i++]); + port_or_socket.assign(tokens[i++]); + user.assign(tokens[i++]); + password.assign(tokens[i++]); + database.assign(tokens[i++]); +} MySQLConnection::MySQLConnection(MySQLConnectionInfo& connInfo) : m_reconnecting(false), @@ -360,14 +371,13 @@ void MySQLConnection::CommitTransaction() int MySQLConnection::ExecuteTransaction(SQLTransaction& transaction) { - std::list<SQLElementData> const& queries = transaction->m_queries; + std::vector<SQLElementData> const& queries = transaction->m_queries; if (queries.empty()) return -1; BeginTransaction(); - std::list<SQLElementData>::const_iterator itr; - for (itr = queries.begin(); itr != queries.end(); ++itr) + for (auto itr = queries.begin(); itr != queries.end(); ++itr) { SQLElementData const& data = *itr; switch (itr->type) @@ -410,6 +420,26 @@ int MySQLConnection::ExecuteTransaction(SQLTransaction& transaction) return 0; } +void MySQLConnection::Ping() +{ + mysql_ping(m_Mysql); +} + +uint32 MySQLConnection::GetLastError() +{ + return mysql_errno(m_Mysql); +} + +bool MySQLConnection::LockIfReady() +{ + return m_Mutex.try_lock(); +} + +void MySQLConnection::Unlock() +{ + m_Mutex.unlock(); +} + MySQLPreparedStatement* MySQLConnection::GetPreparedStatement(uint32 index) { ASSERT(index < m_stmts.size()); diff --git a/src/server/database/Database/MySQLConnection.h b/src/server/database/Database/MySQLConnection.h index 42fb976c729..3bc9aa603c7 100644 --- a/src/server/database/Database/MySQLConnection.h +++ b/src/server/database/Database/MySQLConnection.h @@ -15,19 +15,23 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "DatabaseWorkerPool.h" -#include "Transaction.h" -#include "Util.h" -#include "ProducerConsumerQueue.h" -#include <map> - #ifndef _MYSQLCONNECTION_H #define _MYSQLCONNECTION_H +#include "Define.h" +#include "DatabaseEnvFwd.h" +#include <map> +#include <memory> +#include <mutex> +#include <string> +#include <vector> + +template <typename T> +class ProducerConsumerQueue; + class DatabaseWorker; -class PreparedStatement; class MySQLPreparedStatement; -class PingOperation; +class SQLOperation; enum ConnectionFlags { @@ -38,21 +42,7 @@ enum ConnectionFlags struct TC_DATABASE_API MySQLConnectionInfo { - explicit MySQLConnectionInfo(std::string const& infoString) - { - Tokenizer tokens(infoString, ';'); - - if (tokens.size() != 5) - return; - - uint8 i = 0; - - host.assign(tokens[i++]); - port_or_socket.assign(tokens[i++]); - user.assign(tokens[i++]); - password.assign(tokens[i++]); - database.assign(tokens[i++]); - } + explicit MySQLConnectionInfo(std::string const& infoString); std::string user; std::string password; @@ -91,24 +81,17 @@ class TC_DATABASE_API MySQLConnection void CommitTransaction(); int ExecuteTransaction(SQLTransaction& transaction); - operator bool () const { return m_Mysql != NULL; } - void Ping() { mysql_ping(m_Mysql); } + void Ping(); - uint32 GetLastError() { return mysql_errno(m_Mysql); } + uint32 GetLastError(); protected: - bool LockIfReady() - { - /// Tries to acquire lock. If lock is acquired by another thread - /// the calling parent will just try another connection - return m_Mutex.try_lock(); - } - - void Unlock() - { - /// Called by parent databasepool. Will let other threads access this connection - m_Mutex.unlock(); - } + /// Tries to acquire lock. If lock is acquired by another thread + /// the calling parent will just try another connection + bool LockIfReady(); + + /// Called by parent databasepool. Will let other threads access this connection + void Unlock(); MYSQL* GetHandle() { return m_Mysql; } MySQLPreparedStatement* GetPreparedStatement(uint32 index); diff --git a/src/server/database/Database/MySQLThreading.cpp b/src/server/database/Database/MySQLThreading.cpp new file mode 100644 index 00000000000..d86f61853eb --- /dev/null +++ b/src/server/database/Database/MySQLThreading.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/> + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "MySQLThreading.h" +#include <mysql.h> + +void MySQL::Library_Init() +{ + mysql_library_init(-1, NULL, NULL); +} + +void MySQL::Library_End() +{ + mysql_library_end(); +} diff --git a/src/server/database/Database/MySQLThreading.h b/src/server/database/Database/MySQLThreading.h index 68a8c3ea7ed..deef5561e6d 100644 --- a/src/server/database/Database/MySQLThreading.h +++ b/src/server/database/Database/MySQLThreading.h @@ -18,20 +18,12 @@ #ifndef _MYSQLTHREADING_H #define _MYSQLTHREADING_H -#include "Log.h" +#include "Define.h" -class TC_DATABASE_API MySQL +namespace MySQL { - public: - static void Library_Init() - { - mysql_library_init(-1, NULL, NULL); - } - - static void Library_End() - { - mysql_library_end(); - } + void TC_DATABASE_API Library_Init(); + void TC_DATABASE_API Library_End(); }; #endif diff --git a/src/server/database/Database/PreparedStatement.cpp b/src/server/database/Database/PreparedStatement.cpp index 6e00da4e33f..a756ddf6757 100644 --- a/src/server/database/Database/PreparedStatement.cpp +++ b/src/server/database/Database/PreparedStatement.cpp @@ -16,8 +16,12 @@ */ #include "PreparedStatement.h" +#include "Errors.h" #include "MySQLConnection.h" +#include "QueryResult.h" #include "Log.h" +#include <mysql.h> +#include <sstream> PreparedStatement::PreparedStatement(uint32 index) : m_stmt(NULL), @@ -27,7 +31,7 @@ PreparedStatement::~PreparedStatement() { } void PreparedStatement::BindParameters() { - ASSERT (m_stmt); + ASSERT(m_stmt); uint8 i = 0; for (; i < statement_data.size(); i++) @@ -257,14 +261,40 @@ static bool ParamenterIndexAssertFail(uint32 stmtIndex, uint8 index, uint32 para return false; } +static void SetParameterValue(MYSQL_BIND* param, enum_field_types type, const void* value, uint32 len, bool isUnsigned) +{ + param->buffer_type = type; + delete[] static_cast<char *>(param->buffer); + param->buffer = new char[len]; + param->buffer_length = 0; + param->is_null_value = 0; + param->length = NULL; // Only != NULL for strings + param->is_unsigned = isUnsigned; + + memcpy(param->buffer, value, len); +} + //- Bind on mysql level -bool MySQLPreparedStatement::CheckValidIndex(uint8 index) +void MySQLPreparedStatement::CheckValidIndex(uint8 index) { ASSERT(index < m_paramCount || ParamenterIndexAssertFail(m_stmt->m_index, index, m_paramCount)); if (m_paramsSet[index]) TC_LOG_WARN("sql.sql", "[WARNING] Prepared Statement (id: %u) trying to bind value on already bound index (%u).", m_stmt->m_index, index); - return true; +} + +void MySQLPreparedStatement::setNull(const uint8 index) +{ + CheckValidIndex(index); + m_paramsSet[index] = true; + MYSQL_BIND* param = &m_bind[index]; + param->buffer_type = MYSQL_TYPE_NULL; + delete[] static_cast<char *>(param->buffer); + param->buffer = NULL; + param->buffer_length = 0; + param->is_null_value = 1; + delete param->length; + param->length = NULL; } void MySQLPreparedStatement::setBool(const uint8 index, const bool value) @@ -277,7 +307,7 @@ void MySQLPreparedStatement::setUInt8(const uint8 index, const uint8 value) CheckValidIndex(index); m_paramsSet[index] = true; MYSQL_BIND* param = &m_bind[index]; - setValue(param, MYSQL_TYPE_TINY, &value, sizeof(uint8), true); + SetParameterValue(param, MYSQL_TYPE_TINY, &value, sizeof(uint8), true); } void MySQLPreparedStatement::setUInt16(const uint8 index, const uint16 value) @@ -285,7 +315,7 @@ void MySQLPreparedStatement::setUInt16(const uint8 index, const uint16 value) CheckValidIndex(index); m_paramsSet[index] = true; MYSQL_BIND* param = &m_bind[index]; - setValue(param, MYSQL_TYPE_SHORT, &value, sizeof(uint16), true); + SetParameterValue(param, MYSQL_TYPE_SHORT, &value, sizeof(uint16), true); } void MySQLPreparedStatement::setUInt32(const uint8 index, const uint32 value) @@ -293,7 +323,7 @@ void MySQLPreparedStatement::setUInt32(const uint8 index, const uint32 value) CheckValidIndex(index); m_paramsSet[index] = true; MYSQL_BIND* param = &m_bind[index]; - setValue(param, MYSQL_TYPE_LONG, &value, sizeof(uint32), true); + SetParameterValue(param, MYSQL_TYPE_LONG, &value, sizeof(uint32), true); } void MySQLPreparedStatement::setUInt64(const uint8 index, const uint64 value) @@ -301,7 +331,7 @@ void MySQLPreparedStatement::setUInt64(const uint8 index, const uint64 value) CheckValidIndex(index); m_paramsSet[index] = true; MYSQL_BIND* param = &m_bind[index]; - setValue(param, MYSQL_TYPE_LONGLONG, &value, sizeof(uint64), true); + SetParameterValue(param, MYSQL_TYPE_LONGLONG, &value, sizeof(uint64), true); } void MySQLPreparedStatement::setInt8(const uint8 index, const int8 value) @@ -309,7 +339,7 @@ void MySQLPreparedStatement::setInt8(const uint8 index, const int8 value) CheckValidIndex(index); m_paramsSet[index] = true; MYSQL_BIND* param = &m_bind[index]; - setValue(param, MYSQL_TYPE_TINY, &value, sizeof(int8), false); + SetParameterValue(param, MYSQL_TYPE_TINY, &value, sizeof(int8), false); } void MySQLPreparedStatement::setInt16(const uint8 index, const int16 value) @@ -317,7 +347,7 @@ void MySQLPreparedStatement::setInt16(const uint8 index, const int16 value) CheckValidIndex(index); m_paramsSet[index] = true; MYSQL_BIND* param = &m_bind[index]; - setValue(param, MYSQL_TYPE_SHORT, &value, sizeof(int16), false); + SetParameterValue(param, MYSQL_TYPE_SHORT, &value, sizeof(int16), false); } void MySQLPreparedStatement::setInt32(const uint8 index, const int32 value) @@ -325,7 +355,7 @@ void MySQLPreparedStatement::setInt32(const uint8 index, const int32 value) CheckValidIndex(index); m_paramsSet[index] = true; MYSQL_BIND* param = &m_bind[index]; - setValue(param, MYSQL_TYPE_LONG, &value, sizeof(int32), false); + SetParameterValue(param, MYSQL_TYPE_LONG, &value, sizeof(int32), false); } void MySQLPreparedStatement::setInt64(const uint8 index, const int64 value) @@ -333,7 +363,7 @@ void MySQLPreparedStatement::setInt64(const uint8 index, const int64 value) CheckValidIndex(index); m_paramsSet[index] = true; MYSQL_BIND* param = &m_bind[index]; - setValue(param, MYSQL_TYPE_LONGLONG, &value, sizeof(int64), false); + SetParameterValue(param, MYSQL_TYPE_LONGLONG, &value, sizeof(int64), false); } void MySQLPreparedStatement::setFloat(const uint8 index, const float value) @@ -341,7 +371,7 @@ void MySQLPreparedStatement::setFloat(const uint8 index, const float value) CheckValidIndex(index); m_paramsSet[index] = true; MYSQL_BIND* param = &m_bind[index]; - setValue(param, MYSQL_TYPE_FLOAT, &value, sizeof(float), (value > 0.0f)); + SetParameterValue(param, MYSQL_TYPE_FLOAT, &value, sizeof(float), (value > 0.0f)); } void MySQLPreparedStatement::setDouble(const uint8 index, const double value) @@ -349,7 +379,7 @@ void MySQLPreparedStatement::setDouble(const uint8 index, const double value) CheckValidIndex(index); m_paramsSet[index] = true; MYSQL_BIND* param = &m_bind[index]; - setValue(param, MYSQL_TYPE_DOUBLE, &value, sizeof(double), (value > 0.0f)); + SetParameterValue(param, MYSQL_TYPE_DOUBLE, &value, sizeof(double), (value > 0.0f)); } void MySQLPreparedStatement::setBinary(const uint8 index, const std::vector<uint8>& value, bool isString) @@ -374,33 +404,6 @@ void MySQLPreparedStatement::setBinary(const uint8 index, const std::vector<uint memcpy(param->buffer, value.data(), len); } -void MySQLPreparedStatement::setNull(const uint8 index) -{ - CheckValidIndex(index); - m_paramsSet[index] = true; - MYSQL_BIND* param = &m_bind[index]; - param->buffer_type = MYSQL_TYPE_NULL; - delete [] static_cast<char *>(param->buffer); - param->buffer = NULL; - param->buffer_length = 0; - param->is_null_value = 1; - delete param->length; - param->length = NULL; -} - -void MySQLPreparedStatement::setValue(MYSQL_BIND* param, enum_field_types type, const void* value, uint32 len, bool isUnsigned) -{ - param->buffer_type = type; - delete [] static_cast<char *>(param->buffer); - param->buffer = new char[len]; - param->buffer_length = 0; - param->is_null_value = 0; - param->length = NULL; // Only != NULL for strings - param->is_unsigned = isUnsigned; - - memcpy(param->buffer, value, len); -} - std::string MySQLPreparedStatement::getQueryString(std::string const& sqlPattern) const { std::string queryString = sqlPattern; diff --git a/src/server/database/Database/PreparedStatement.h b/src/server/database/Database/PreparedStatement.h index ddc731625fa..7e39581e4d3 100644 --- a/src/server/database/Database/PreparedStatement.h +++ b/src/server/database/Database/PreparedStatement.h @@ -18,8 +18,10 @@ #ifndef _PREPAREDSTATEMENT_H #define _PREPAREDSTATEMENT_H -#include <future> +#include "Define.h" #include "SQLOperation.h" +#include <future> +#include <vector> #ifdef __APPLE__ #undef TYPE_BOOL @@ -120,6 +122,7 @@ class TC_DATABASE_API MySQLPreparedStatement MySQLPreparedStatement(MYSQL_STMT* stmt); ~MySQLPreparedStatement(); + void setNull(const uint8 index); void setBool(const uint8 index, const bool value); void setUInt8(const uint8 index, const uint8 value); void setUInt16(const uint8 index, const uint16 value); @@ -132,20 +135,16 @@ class TC_DATABASE_API MySQLPreparedStatement void setFloat(const uint8 index, const float value); void setDouble(const uint8 index, const double value); void setBinary(const uint8 index, const std::vector<uint8>& value, bool isString); - void setNull(const uint8 index); protected: MYSQL_STMT* GetSTMT() { return m_Mstmt; } MYSQL_BIND* GetBind() { return m_bind; } PreparedStatement* m_stmt; void ClearParameters(); - bool CheckValidIndex(uint8 index); + void CheckValidIndex(uint8 index); std::string getQueryString(std::string const& sqlPattern) const; private: - void setValue(MYSQL_BIND* param, enum_field_types type, const void* value, uint32 len, bool isUnsigned); - - private: MYSQL_STMT* m_Mstmt; uint32 m_paramCount; std::vector<bool> m_paramsSet; @@ -155,9 +154,6 @@ class TC_DATABASE_API MySQLPreparedStatement MySQLPreparedStatement& operator=(MySQLPreparedStatement const& right) = delete; }; -typedef std::future<PreparedQueryResult> PreparedQueryResultFuture; -typedef std::promise<PreparedQueryResult> PreparedQueryResultPromise; - //- Lower-level class, enqueuable operation class TC_DATABASE_API PreparedStatementTask : public SQLOperation { diff --git a/src/server/database/Database/QueryCallback.cpp b/src/server/database/Database/QueryCallback.cpp index 2d89e08a956..18f72975935 100644 --- a/src/server/database/Database/QueryCallback.cpp +++ b/src/server/database/Database/QueryCallback.cpp @@ -16,6 +16,7 @@ */ #include "QueryCallback.h" +#include "Errors.h" template<typename T, typename... Args> inline void Construct(T& t, Args&&... args) @@ -30,7 +31,7 @@ inline void Destroy(T& t) } template<typename T> -void ConstructActiveMember(T* obj) +inline void ConstructActiveMember(T* obj) { if (!obj->_isPrepared) Construct(obj->_string); @@ -39,7 +40,7 @@ void ConstructActiveMember(T* obj) } template<typename T> -void DestroyActiveMember(T* obj) +inline void DestroyActiveMember(T* obj) { if (!obj->_isPrepared) Destroy(obj->_string); @@ -48,7 +49,7 @@ void DestroyActiveMember(T* obj) } template<typename T> -void MoveFrom(T* to, T&& from) +inline void MoveFrom(T* to, T&& from) { ASSERT(to->_isPrepared == from._isPrepared); @@ -199,7 +200,7 @@ QueryCallback::Status QueryCallback::InvokeIfReady() { if (_string.valid() && _string.wait_for(std::chrono::seconds(0)) == std::future_status::ready) { - std::future<QueryResult> f(std::move(_string)); + QueryResultFuture f(std::move(_string)); std::function<void(QueryCallback&, QueryResult)> cb(std::move(callback._string)); cb(*this, f.get()); return checkStateAndReturnCompletion(); @@ -209,7 +210,7 @@ QueryCallback::Status QueryCallback::InvokeIfReady() { if (_prepared.valid() && _prepared.wait_for(std::chrono::seconds(0)) == std::future_status::ready) { - std::future<PreparedQueryResult> f(std::move(_prepared)); + PreparedQueryResultFuture f(std::move(_prepared)); std::function<void(QueryCallback&, PreparedQueryResult)> cb(std::move(callback._prepared)); cb(*this, f.get()); return checkStateAndReturnCompletion(); diff --git a/src/server/database/Database/QueryCallback.h b/src/server/database/Database/QueryCallback.h index 8258da37afb..ebc1538b5e9 100644 --- a/src/server/database/Database/QueryCallback.h +++ b/src/server/database/Database/QueryCallback.h @@ -18,16 +18,19 @@ #ifndef _QUERY_CALLBACK_H #define _QUERY_CALLBACK_H -#include "QueryResult.h" +#include "Define.h" +#include "DatabaseEnvFwd.h" +#include <functional> #include <future> #include <list> #include <queue> +#include <utility> class TC_DATABASE_API QueryCallback { public: - explicit QueryCallback(std::future<QueryResult>&& result); - explicit QueryCallback(std::future<PreparedQueryResult>&& result); + explicit QueryCallback(QueryResultFuture&& result); + explicit QueryCallback(PreparedQueryResultFuture&& result); QueryCallback(QueryCallback&& right); QueryCallback& operator=(QueryCallback&& right); ~QueryCallback(); @@ -60,8 +63,8 @@ private: union { - std::future<QueryResult> _string; - std::future<PreparedQueryResult> _prepared; + QueryResultFuture _string; + PreparedQueryResultFuture _prepared; }; bool _isPrepared; diff --git a/src/server/database/Database/QueryHolder.cpp b/src/server/database/Database/QueryHolder.cpp index 6a8bb701a1f..4f62ba4810c 100644 --- a/src/server/database/Database/QueryHolder.cpp +++ b/src/server/database/Database/QueryHolder.cpp @@ -19,26 +19,7 @@ #include "QueryHolder.h" #include "PreparedStatement.h" #include "Log.h" - -bool SQLQueryHolder::SetQuery(size_t index, const char *sql) -{ - if (m_queries.size() <= index) - { - TC_LOG_ERROR("sql.sql", "Query index (%u) out of range (size: %u) for query: %s", uint32(index), (uint32)m_queries.size(), sql); - return false; - } - - /// not executed yet, just stored (it's not called a holder for nothing) - SQLElementData element; - element.type = SQL_ELEMENT_RAW; - element.element.query = strdup(sql); - - SQLResultSetUnion result; - result.qresult = NULL; - - m_queries[index] = SQLResultPair(element, result); - return true; -} +#include "QueryResult.h" bool SQLQueryHolder::SetPreparedQuery(size_t index, PreparedStatement* stmt) { @@ -48,59 +29,17 @@ bool SQLQueryHolder::SetPreparedQuery(size_t index, PreparedStatement* stmt) return false; } - /// not executed yet, just stored (it's not called a holder for nothing) - SQLElementData element; - element.type = SQL_ELEMENT_PREPARED; - element.element.stmt = stmt; - - SQLResultSetUnion result; - result.presult = NULL; - - m_queries[index] = SQLResultPair(element, result); + m_queries[index].first = stmt; return true; } -QueryResult SQLQueryHolder::GetResult(size_t index) -{ - // Don't call to this function if the index is of an ad-hoc statement - if (index < m_queries.size()) - { - ResultSet* result = m_queries[index].second.qresult; - if (!result || !result->GetRowCount() || !result->NextRow()) - return QueryResult(NULL); - - return QueryResult(result); - } - else - return QueryResult(NULL); -} - PreparedQueryResult SQLQueryHolder::GetPreparedResult(size_t index) { // Don't call to this function if the index is of a prepared statement if (index < m_queries.size()) - { - PreparedResultSet* result = m_queries[index].second.presult; - if (!result || !result->GetRowCount()) - return PreparedQueryResult(NULL); - - return PreparedQueryResult(result); - } + return m_queries[index].second; else - return PreparedQueryResult(NULL); -} - -void SQLQueryHolder::SetResult(size_t index, ResultSet* result) -{ - if (result && !result->GetRowCount()) - { - delete result; - result = NULL; - } - - /// store the result in the holder - if (index < m_queries.size()) - m_queries[index].second.qresult = result; + return PreparedQueryResult(nullptr); } void SQLQueryHolder::SetPreparedResult(size_t index, PreparedResultSet* result) @@ -113,7 +52,7 @@ void SQLQueryHolder::SetPreparedResult(size_t index, PreparedResultSet* result) /// store the result in the holder if (index < m_queries.size()) - m_queries[index].second.presult = result; + m_queries[index].second = PreparedQueryResult(result); } SQLQueryHolder::~SQLQueryHolder() @@ -122,18 +61,7 @@ SQLQueryHolder::~SQLQueryHolder() { /// if the result was never used, free the resources /// results used already (getresult called) are expected to be deleted - if (SQLElementData* data = &m_queries[i].first) - { - switch (data->type) - { - case SQL_ELEMENT_RAW: - free((void*)(const_cast<char*>(data->element.query))); - break; - case SQL_ELEMENT_PREPARED: - delete data->element.stmt; - break; - } - } + delete m_queries[i].first; } } @@ -156,33 +84,10 @@ bool SQLQueryHolderTask::Execute() if (!m_holder) return false; - /// we can do this, we are friends - std::vector<SQLQueryHolder::SQLResultPair> &queries = m_holder->m_queries; - - for (size_t i = 0; i < queries.size(); i++) - { - /// execute all queries in the holder and pass the results - if (SQLElementData* data = &queries[i].first) - { - switch (data->type) - { - case SQL_ELEMENT_RAW: - { - char const* sql = data->element.query; - if (sql) - m_holder->SetResult(i, m_conn->Query(sql)); - break; - } - case SQL_ELEMENT_PREPARED: - { - PreparedStatement* stmt = data->element.stmt; - if (stmt) - m_holder->SetPreparedResult(i, m_conn->Query(stmt)); - break; - } - } - } - } + /// execute all queries in the holder and pass the results + for (size_t i = 0; i < m_holder->m_queries.size(); i++) + if (PreparedStatement* stmt = m_holder->m_queries[i].first) + m_holder->SetPreparedResult(i, m_conn->Query(stmt)); m_result.set_value(m_holder); return true; diff --git a/src/server/database/Database/QueryHolder.h b/src/server/database/Database/QueryHolder.h index c3ebb33068c..123765b01a5 100644 --- a/src/server/database/Database/QueryHolder.h +++ b/src/server/database/Database/QueryHolder.h @@ -18,34 +18,22 @@ #ifndef _QUERYHOLDER_H #define _QUERYHOLDER_H -#include <future> +#include "SQLOperation.h" class TC_DATABASE_API SQLQueryHolder { friend class SQLQueryHolderTask; private: - typedef std::pair<SQLElementData, SQLResultSetUnion> SQLResultPair; - std::vector<SQLResultPair> m_queries; + std::vector<std::pair<PreparedStatement*, PreparedQueryResult>> m_queries; public: SQLQueryHolder() { } virtual ~SQLQueryHolder(); - bool SetQuery(size_t index, const char* sql); - template<typename Format, typename... Args> - bool SetPQuery(size_t index, Format&& sql, Args&&... args) - { - return SetQuery(index, Trinity::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str()); - } bool SetPreparedQuery(size_t index, PreparedStatement* stmt); void SetSize(size_t size); - QueryResult GetResult(size_t index); PreparedQueryResult GetPreparedResult(size_t index); - void SetResult(size_t index, ResultSet* result); void SetPreparedResult(size_t index, PreparedResultSet* result); }; -typedef std::future<SQLQueryHolder*> QueryResultHolderFuture; -typedef std::promise<SQLQueryHolder*> QueryResultHolderPromise; - class TC_DATABASE_API SQLQueryHolderTask : public SQLOperation { private: diff --git a/src/server/database/Database/QueryResult.cpp b/src/server/database/Database/QueryResult.cpp index 7b6937e50b7..b44768e709d 100644 --- a/src/server/database/Database/QueryResult.cpp +++ b/src/server/database/Database/QueryResult.cpp @@ -16,8 +16,105 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "DatabaseEnv.h" +#include "QueryResult.h" +#include "Errors.h" +#include "Field.h" #include "Log.h" +#include <mysql.h> + +static uint32 SizeForType(MYSQL_FIELD* field) +{ + switch (field->type) + { + case MYSQL_TYPE_NULL: + return 0; + case MYSQL_TYPE_TINY: + return 1; + case MYSQL_TYPE_YEAR: + case MYSQL_TYPE_SHORT: + return 2; + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_FLOAT: + return 4; + case MYSQL_TYPE_DOUBLE: + case MYSQL_TYPE_LONGLONG: + case MYSQL_TYPE_BIT: + return 8; + + case MYSQL_TYPE_TIMESTAMP: + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_TIME: + case MYSQL_TYPE_DATETIME: + return sizeof(MYSQL_TIME); + + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VAR_STRING: + return field->max_length + 1; + + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_NEWDECIMAL: + return 64; + + case MYSQL_TYPE_GEOMETRY: + /* + Following types are not sent over the wire: + MYSQL_TYPE_ENUM: + MYSQL_TYPE_SET: + */ + default: + TC_LOG_WARN("sql.sql", "SQL::SizeForType(): invalid field type %u", uint32(field->type)); + return 0; + } +} + +DatabaseFieldTypes MysqlTypeToFieldType(enum_field_types type) +{ + switch (type) + { + case MYSQL_TYPE_NULL: + return DatabaseFieldTypes::Null; + case MYSQL_TYPE_TINY: + return DatabaseFieldTypes::Int8; + case MYSQL_TYPE_YEAR: + case MYSQL_TYPE_SHORT: + return DatabaseFieldTypes::Int16; + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_LONG: + return DatabaseFieldTypes::Int32; + case MYSQL_TYPE_LONGLONG: + case MYSQL_TYPE_BIT: + return DatabaseFieldTypes::Int64; + case MYSQL_TYPE_FLOAT: + return DatabaseFieldTypes::Float; + case MYSQL_TYPE_DOUBLE: + return DatabaseFieldTypes::Double; + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_NEWDECIMAL: + return DatabaseFieldTypes::Decimal; + case MYSQL_TYPE_TIMESTAMP: + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_TIME: + case MYSQL_TYPE_DATETIME: + return DatabaseFieldTypes::Date; + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VAR_STRING: + return DatabaseFieldTypes::Binary; + default: + TC_LOG_WARN("sql.sql", "MysqlTypeToFieldType(): invalid field type %u", uint32(type)); + break; + } + + return DatabaseFieldTypes::Null; +} ResultSet::ResultSet(MYSQL_RES *result, MYSQL_FIELD *fields, uint64 rowCount, uint32 fieldCount) : _rowCount(rowCount), @@ -38,9 +135,7 @@ m_rowPosition(0), m_fieldCount(fieldCount), m_rBind(NULL), m_stmt(stmt), -m_metadataResult(result), -m_isNull(NULL), -m_length(NULL) +m_metadataResult(result) { if (!m_metadataResult) return; @@ -52,8 +147,12 @@ m_length(NULL) } m_rBind = new MYSQL_BIND[m_fieldCount]; - m_isNull = new my_bool[m_fieldCount]; - m_length = new unsigned long[m_fieldCount]; + + //- for future readers wondering where the fuck this is freed - mysql_stmt_bind_result moves pointers to these + // from m_rBind to m_stmt->bind and it is later freed by the `if (m_stmt->bind_result_done)` block just above here + // MYSQL_STMT lifetime is equal to connection lifetime + my_bool* m_isNull = new my_bool[m_fieldCount]; + unsigned long* m_length = new unsigned long[m_fieldCount]; memset(m_isNull, 0, sizeof(my_bool) * m_fieldCount); memset(m_rBind, 0, sizeof(MYSQL_BIND) * m_fieldCount); @@ -76,7 +175,7 @@ m_length(NULL) std::size_t rowSize = 0; for (uint32 i = 0; i < m_fieldCount; ++i) { - uint32 size = Field::SizeForType(&field[i]); + uint32 size = SizeForType(&field[i]); rowSize += size; m_rBind[i].buffer_type = field[i].type; @@ -137,7 +236,7 @@ m_length(NULL) m_rows[uint32(m_rowPosition) * m_fieldCount + fIndex].SetByteValue( buffer, - m_rBind[fIndex].buffer_type, + MysqlTypeToFieldType(m_rBind[fIndex].buffer_type), fetched_length); // move buffer pointer to next part @@ -147,7 +246,7 @@ m_length(NULL) { m_rows[uint32(m_rowPosition) * m_fieldCount + fIndex].SetByteValue( nullptr, - m_rBind[fIndex].buffer_type, + MysqlTypeToFieldType(m_rBind[fIndex].buffer_type), *m_rBind[fIndex].length); } @@ -196,7 +295,7 @@ bool ResultSet::NextRow() } for (uint32 i = 0; i < _fieldCount; i++) - _currentRow[i].SetStructuredValue(row[i], _fields[i].type, lengths[i]); + _currentRow[i].SetStructuredValue(row[i], MysqlTypeToFieldType(_fields[i].type), lengths[i]); return true; } @@ -249,3 +348,23 @@ void PreparedResultSet::CleanUp() m_rBind = nullptr; } } + +Field const& ResultSet::operator[](std::size_t index) const +{ + ASSERT(index < _fieldCount); + return _currentRow[index]; +} + +Field* PreparedResultSet::Fetch() const +{ + ASSERT(m_rowPosition < m_rowCount); + return const_cast<Field*>(&m_rows[uint32(m_rowPosition) * m_fieldCount]); +} + +Field const& PreparedResultSet::operator[](std::size_t index) const +{ + ASSERT(m_rowPosition < m_rowCount); + ASSERT(index < m_fieldCount); + return m_rows[uint32(m_rowPosition) * m_fieldCount + index]; +} + diff --git a/src/server/database/Database/QueryResult.h b/src/server/database/Database/QueryResult.h index 5d2cc425ae8..dcfe18765fc 100644 --- a/src/server/database/Database/QueryResult.h +++ b/src/server/database/Database/QueryResult.h @@ -19,14 +19,9 @@ #ifndef QUERYRESULT_H #define QUERYRESULT_H -#include <memory> -#include "Errors.h" -#include "Field.h" - -#ifdef _WIN32 - #include <winsock2.h> -#endif -#include <mysql.h> +#include "Define.h" +#include "DatabaseEnvFwd.h" +#include <vector> class TC_DATABASE_API ResultSet { @@ -39,11 +34,7 @@ class TC_DATABASE_API ResultSet uint32 GetFieldCount() const { return _fieldCount; } Field* Fetch() const { return _currentRow; } - const Field & operator [] (uint32 index) const - { - ASSERT(index < _fieldCount); - return _currentRow[index]; - } + Field const& operator[](std::size_t index) const; protected: uint64 _rowCount; @@ -59,8 +50,6 @@ class TC_DATABASE_API ResultSet ResultSet& operator=(ResultSet const& right) = delete; }; -typedef std::shared_ptr<ResultSet> QueryResult; - class TC_DATABASE_API PreparedResultSet { public: @@ -71,18 +60,8 @@ class TC_DATABASE_API PreparedResultSet uint64 GetRowCount() const { return m_rowCount; } uint32 GetFieldCount() const { return m_fieldCount; } - Field* Fetch() const - { - ASSERT(m_rowPosition < m_rowCount); - return const_cast<Field*>(&m_rows[uint32(m_rowPosition) * m_fieldCount]); - } - - Field const& operator[](uint32 index) const - { - ASSERT(m_rowPosition < m_rowCount); - ASSERT(index < m_fieldCount); - return m_rows[uint32(m_rowPosition) * m_fieldCount + index]; - } + Field* Fetch() const; + Field const& operator[](std::size_t index) const; protected: std::vector<Field> m_rows; @@ -95,9 +74,6 @@ class TC_DATABASE_API PreparedResultSet MYSQL_STMT* m_stmt; MYSQL_RES* m_metadataResult; ///< Field metadata, returned by mysql_stmt_result_metadata - my_bool* m_isNull; - unsigned long* m_length; - void CleanUp(); bool _NextRow(); @@ -105,7 +81,4 @@ class TC_DATABASE_API PreparedResultSet PreparedResultSet& operator=(PreparedResultSet const& right) = delete; }; -typedef std::shared_ptr<PreparedResultSet> PreparedQueryResult; - #endif - diff --git a/src/server/database/Database/SQLOperation.h b/src/server/database/Database/SQLOperation.h index 1e3000600c5..b0417bb1936 100644 --- a/src/server/database/Database/SQLOperation.h +++ b/src/server/database/Database/SQLOperation.h @@ -18,10 +18,8 @@ #ifndef _SQLOPERATION_H #define _SQLOPERATION_H -#include "QueryResult.h" - -//- Forward declare (don't include header to prevent circular includes) -class PreparedStatement; +#include "Define.h" +#include "DatabaseEnvFwd.h" //- Union that holds element data union SQLElementUnion diff --git a/src/server/database/Database/Transaction.cpp b/src/server/database/Database/Transaction.cpp index 52f7062c78a..c59d6d4d8ae 100644 --- a/src/server/database/Database/Transaction.cpp +++ b/src/server/database/Database/Transaction.cpp @@ -15,8 +15,9 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "DatabaseEnv.h" #include "Transaction.h" +#include "MySQLConnection.h" +#include "PreparedStatement.h" #include <mysqld_error.h> std::mutex TransactionTask::_deadlockLock; @@ -45,9 +46,8 @@ void Transaction::Cleanup() if (_cleanedUp) return; - while (!m_queries.empty()) + for (SQLElementData const &data : m_queries) { - SQLElementData const &data = m_queries.front(); switch (data.type) { case SQL_ELEMENT_PREPARED: @@ -57,10 +57,9 @@ void Transaction::Cleanup() free((void*)(data.element.query)); break; } - - m_queries.pop_front(); } + m_queries.clear(); _cleanedUp = true; } diff --git a/src/server/database/Database/Transaction.h b/src/server/database/Database/Transaction.h index fbb96c053ce..d2c64c9451a 100644 --- a/src/server/database/Database/Transaction.h +++ b/src/server/database/Database/Transaction.h @@ -18,13 +18,12 @@ #ifndef _TRANSACTION_H #define _TRANSACTION_H +#include "Define.h" +#include "DatabaseEnvFwd.h" #include "SQLOperation.h" #include "StringFormat.h" -#include <list> #include <mutex> - -//- Forward declare (don't include header to prevent circular includes) -class PreparedStatement; +#include <vector> /*! Transactions, high level class. */ class TC_DATABASE_API Transaction @@ -47,17 +46,16 @@ class TC_DATABASE_API Transaction Append(Trinity::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str()); } - size_t GetSize() const { return m_queries.size(); } + std::size_t GetSize() const { return m_queries.size(); } protected: void Cleanup(); - std::list<SQLElementData> m_queries; + std::vector<SQLElementData> m_queries; private: bool _cleanedUp; }; -typedef std::shared_ptr<Transaction> SQLTransaction; /*! Low level class*/ class TC_DATABASE_API TransactionTask : public SQLOperation diff --git a/src/server/database/Logging/AppenderDB.cpp b/src/server/database/Logging/AppenderDB.cpp index f14bb04ddea..3552a1da4e1 100644 --- a/src/server/database/Logging/AppenderDB.cpp +++ b/src/server/database/Logging/AppenderDB.cpp @@ -16,7 +16,9 @@ */ #include "AppenderDB.h" -#include "Database/DatabaseEnv.h" +#include "DatabaseEnv.h" +#include "LogMessage.h" +#include "PreparedStatement.h" #include "LogMessage.h" AppenderDB::AppenderDB(uint8 id, std::string const& name, LogLevel level, AppenderFlags /*flags*/, std::vector<char const*> /*extraArgs*/) diff --git a/src/server/database/PrecompiledHeaders/databasePCH.h b/src/server/database/PrecompiledHeaders/databasePCH.h index d524d52ade0..60f57abf949 100644 --- a/src/server/database/PrecompiledHeaders/databasePCH.h +++ b/src/server/database/PrecompiledHeaders/databasePCH.h @@ -1,23 +1,12 @@ -#include "Config.h" -#include "Database/AdhocStatement.h" -#include "Database/DatabaseEnv.h" -#include "Database/DatabaseLoader.h" -#include "Database/DatabaseWorker.h" -#include "Database/DatabaseWorkerPool.h" -#include "Database/Field.h" -#include "Database/MySQLConnection.h" -#include "Database/MySQLThreading.h" -#include "Database/PreparedStatement.h" -#include "Database/QueryHolder.h" -#include "Database/QueryResult.h" -#include "Database/SQLOperation.h" -#include "Database/Transaction.h" -#include "Logging/Appender.h" -#include "Logging/AppenderConsole.h" -#include "Logging/AppenderDB.h" -#include "Logging/AppenderFile.h" -#include "Logging/Log.h" -#include "Logging/LogOperation.h" -#include "Logging/Logger.h" -#include "Updater/DBUpdater.h" -#include "Updater/UpdateFetcher.h" +#include "Define.h" +#include "Errors.h" +#include "Field.h" +#include "Log.h" +#include "MySQLConnection.h" +#include "PreparedStatement.h" +#include "QueryResult.h" +#include "SQLOperation.h" +#include "Transaction.h" +#include <mysql.h> +#include <string> +#include <vector> diff --git a/src/server/database/Updater/DBUpdater.cpp b/src/server/database/Updater/DBUpdater.cpp index 117c3097478..5b0d6ca9de8 100644 --- a/src/server/database/Updater/DBUpdater.cpp +++ b/src/server/database/Updater/DBUpdater.cpp @@ -16,17 +16,18 @@ */ #include "DBUpdater.h" -#include "Log.h" -#include "GitRevision.h" -#include "UpdateFetcher.h" -#include "DatabaseLoader.h" -#include "Config.h" #include "BuiltInConfig.h" +#include "Config.h" +#include "DatabaseEnv.h" +#include "DatabaseLoader.h" +#include "GitRevision.h" +#include "Log.h" +#include "QueryResult.h" #include "StartProcess.h" - +#include "UpdateFetcher.h" +#include <boost/filesystem/operations.hpp> #include <fstream> #include <iostream> -#include <unordered_map> std::string DBUpdaterUtil::GetCorrectedMySQLExecutable() { diff --git a/src/server/database/Updater/DBUpdater.h b/src/server/database/Updater/DBUpdater.h index fdc00c9d6b6..8cea468e3cd 100644 --- a/src/server/database/Updater/DBUpdater.h +++ b/src/server/database/Updater/DBUpdater.h @@ -18,10 +18,20 @@ #ifndef DBUpdater_h__ #define DBUpdater_h__ -#include "DatabaseEnv.h" - +#include "Define.h" +#include "DatabaseEnvFwd.h" #include <string> -#include <boost/filesystem.hpp> + +template <class T> +class DatabaseWorkerPool; + +namespace boost +{ + namespace filesystem + { + class path; + } +} class TC_DATABASE_API UpdateException : public std::exception { @@ -41,19 +51,6 @@ enum BaseLocation LOCATION_DOWNLOAD }; -struct TC_DATABASE_API UpdateResult -{ - UpdateResult() - : updated(0), recent(0), archived(0) { } - - UpdateResult(size_t const updated_, size_t const recent_, size_t const archived_) - : updated(updated_), recent(recent_), archived(archived_) { } - - size_t updated; - size_t recent; - size_t archived; -}; - class DBUpdaterUtil { public: diff --git a/src/server/database/Updater/UpdateFetcher.cpp b/src/server/database/Updater/UpdateFetcher.cpp index 1da370ee7b9..3155427f78e 100644 --- a/src/server/database/Updater/UpdateFetcher.cpp +++ b/src/server/database/Updater/UpdateFetcher.cpp @@ -16,28 +16,41 @@ */ #include "UpdateFetcher.h" +#include "Common.h" +#include "DBUpdater.h" +#include "Field.h" #include "Log.h" +#include "QueryResult.h" #include "Util.h" #include "SHA1.h" - +#include <boost/filesystem/operations.hpp> #include <fstream> -#include <chrono> -#include <vector> #include <sstream> -#include <exception> -#include <unordered_map> using namespace boost::filesystem; +struct UpdateFetcher::DirectoryEntry +{ + DirectoryEntry(Path const& path_, State state_) : path(path_), state(state_) { } + + Path const path; + + State const state; +}; + UpdateFetcher::UpdateFetcher(Path const& sourceDirectory, std::function<void(std::string const&)> const& apply, std::function<void(Path const& path)> const& applyFile, std::function<QueryResult(std::string const&)> const& retrieve) : - _sourceDirectory(sourceDirectory), _apply(apply), _applyFile(applyFile), + _sourceDirectory(Trinity::make_unique<Path>(sourceDirectory)), _apply(apply), _applyFile(applyFile), _retrieve(retrieve) { } +UpdateFetcher::~UpdateFetcher() +{ +} + UpdateFetcher::LocaleFileStorage UpdateFetcher::GetFileList() const { LocaleFileStorage files; @@ -95,7 +108,7 @@ UpdateFetcher::DirectoryStorage UpdateFetcher::ReceiveIncludedDirectories() cons std::string path = fields[0].GetString(); if (path.substr(0, 1) == "$") - path = _sourceDirectory.generic_string() + path.substr(1); + path = _sourceDirectory->generic_string() + path.substr(1); Path const p(path); @@ -405,3 +418,8 @@ void UpdateFetcher::UpdateState(std::string const& name, State const state) cons // Update database _apply(update); } + +bool UpdateFetcher::PathCompare::operator()(LocaleFileEntry const& left, LocaleFileEntry const& right) const +{ + return left.first.filename().string() < right.first.filename().string(); +} diff --git a/src/server/database/Updater/UpdateFetcher.h b/src/server/database/Updater/UpdateFetcher.h index 0ca18f43886..f5187d261a7 100644 --- a/src/server/database/Updater/UpdateFetcher.h +++ b/src/server/database/Updater/UpdateFetcher.h @@ -18,14 +18,35 @@ #ifndef UpdateFetcher_h__ #define UpdateFetcher_h__ -#include <DBUpdater.h> - -#include <functional> +#include "Define.h" +#include "DatabaseEnvFwd.h" +#include <set> #include <string> -#include <memory> +#include <unordered_map> #include <set> #include <vector> +namespace boost +{ + namespace filesystem + { + class path; + } +} + +struct TC_DATABASE_API UpdateResult +{ + UpdateResult() + : updated(0), recent(0), archived(0) { } + + UpdateResult(size_t const updated_, size_t const recent_, size_t const archived_) + : updated(updated_), recent(recent_), archived(archived_) { } + + size_t updated; + size_t recent; + size_t archived; +}; + class TC_DATABASE_API UpdateFetcher { typedef boost::filesystem::path Path; @@ -35,6 +56,7 @@ public: std::function<void(std::string const&)> const& apply, std::function<void(Path const& path)> const& applyFile, std::function<QueryResult(std::string const&)> const& retrieve); + ~UpdateFetcher(); UpdateResult Update(bool const redundancyChecks, bool const allowRehash, bool const archivedRedundancy, int32 const cleanDeadReferencesMaxCount) const; @@ -81,23 +103,13 @@ private: } }; - struct DirectoryEntry - { - DirectoryEntry(Path const& path_, State state_) : path(path_), state(state_) { } - - Path const path; - - State const state; - }; + struct DirectoryEntry; typedef std::pair<Path, State> LocaleFileEntry; struct PathCompare { - inline bool operator() (LocaleFileEntry const& left, LocaleFileEntry const& right) const - { - return left.first.filename().string() < right.first.filename().string(); - } + bool operator()(LocaleFileEntry const& left, LocaleFileEntry const& right) const; }; typedef std::set<LocaleFileEntry, PathCompare> LocaleFileStorage; @@ -122,7 +134,7 @@ private: void UpdateState(std::string const& name, State const state) const; - Path const _sourceDirectory; + std::unique_ptr<Path> const _sourceDirectory; std::function<void(std::string const&)> const _apply; std::function<void(Path const& path)> const _applyFile; diff --git a/src/server/game/AI/CoreAI/CombatAI.cpp b/src/server/game/AI/CoreAI/CombatAI.cpp index f4a557d25b3..d9aaf102db7 100644 --- a/src/server/game/AI/CoreAI/CombatAI.cpp +++ b/src/server/game/AI/CoreAI/CombatAI.cpp @@ -22,6 +22,7 @@ #include "Vehicle.h" #include "ObjectAccessor.h" #include "Player.h" +#include "Log.h" ///////////////// // AggressorAI diff --git a/src/server/game/AI/CreatureAISelector.cpp b/src/server/game/AI/CreatureAISelector.cpp index b18b8145013..d88a888aec6 100644 --- a/src/server/game/AI/CreatureAISelector.cpp +++ b/src/server/game/AI/CreatureAISelector.cpp @@ -19,7 +19,7 @@ #include "Creature.h" #include "CreatureAISelector.h" #include "PassiveAI.h" - +#include "Log.h" #include "MovementGenerator.h" #include "TemporarySummon.h" #include "CreatureAIFactory.h" diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp index 690b4c3f351..f1740154c07 100644 --- a/src/server/game/Accounts/AccountMgr.cpp +++ b/src/server/game/Accounts/AccountMgr.cpp @@ -19,6 +19,7 @@ #include "AccountMgr.h" #include "Config.h" #include "DatabaseEnv.h" +#include "Log.h" #include "ObjectAccessor.h" #include "Player.h" #include "ScriptMgr.h" diff --git a/src/server/game/Accounts/RBAC.cpp b/src/server/game/Accounts/RBAC.cpp index 951223a9257..5e7499cf9ab 100644 --- a/src/server/game/Accounts/RBAC.cpp +++ b/src/server/game/Accounts/RBAC.cpp @@ -19,6 +19,7 @@ #include "AccountMgr.h" #include "Log.h" #include "QueryCallback.h" +#include <sstream> namespace rbac { diff --git a/src/server/game/Battlefield/BattlefieldMgr.cpp b/src/server/game/Battlefield/BattlefieldMgr.cpp index b66d42dc521..39a9da09504 100644 --- a/src/server/game/Battlefield/BattlefieldMgr.cpp +++ b/src/server/game/Battlefield/BattlefieldMgr.cpp @@ -18,6 +18,7 @@ #include "BattlefieldMgr.h" #include "BattlefieldWG.h" #include "BattlefieldTB.h" +#include "Log.h" #include "Player.h" BattlefieldMgr::BattlefieldMgr() diff --git a/src/server/game/Battlegrounds/ArenaTeamMgr.h b/src/server/game/Battlegrounds/ArenaTeamMgr.h index fc658542ed3..f60ce5a5ded 100644 --- a/src/server/game/Battlegrounds/ArenaTeamMgr.h +++ b/src/server/game/Battlegrounds/ArenaTeamMgr.h @@ -19,6 +19,7 @@ #define _ARENATEAMMGR_H #include "ArenaTeam.h" +#include <unordered_map> class TC_GAME_API ArenaTeamMgr { diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp index 180e82755f2..e140f8a4ae9 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp @@ -21,6 +21,7 @@ #include "BattlegroundMgr.h" #include "Creature.h" #include "Language.h" +#include "Log.h" #include "Player.h" #include "Random.h" #include "Util.h" diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp index 8568e87441d..06da80850bf 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundBE.cpp @@ -17,6 +17,7 @@ */ #include "BattlegroundBE.h" +#include "Log.h" #include "Player.h" #include "WorldPacket.h" diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp index 00ab1c2e964..a3e8ad37227 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundDS.cpp @@ -18,6 +18,7 @@ #include "BattlegroundDS.h" #include "Creature.h" +#include "Log.h" #include "Player.h" #include "Random.h" #include "WorldPacket.h" diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp index 45ab8a542f4..7a0eac02418 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp @@ -21,6 +21,7 @@ #include "BattlegroundMgr.h" #include "Creature.h" #include "Language.h" +#include "Log.h" #include "Player.h" #include "Random.h" #include "Util.h" diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp index 6d77c0ab032..7aab709f4cd 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundNA.cpp @@ -17,6 +17,7 @@ */ #include "BattlegroundNA.h" +#include "Log.h" #include "Player.h" #include "WorldPacket.h" diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp index 0f0cda393c8..8fb48819011 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundRL.cpp @@ -17,6 +17,7 @@ */ #include "BattlegroundRL.h" +#include "Log.h" #include "Player.h" #include "WorldPacket.h" diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp index d90deef6024..6bf61e24914 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundRV.cpp @@ -18,6 +18,7 @@ #include "BattlegroundRV.h" #include "GameObject.h" +#include "Log.h" #include "ObjectAccessor.h" #include "Player.h" #include "WorldPacket.h" diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp index 5826715fcc3..3e1438def65 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp @@ -19,6 +19,7 @@ #include "BattlegroundWS.h" #include "GameObject.h" #include "Language.h" +#include "Log.h" #include "Object.h" #include "BattlegroundMgr.h" #include "Player.h" diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp index a28e77aecbc..c64a3bab4f0 100644 --- a/src/server/game/DataStores/DB2Stores.cpp +++ b/src/server/game/DataStores/DB2Stores.cpp @@ -24,7 +24,7 @@ #include "TransportMgr.h" #include "World.h" -// temporary hack until database includes are sorted out (don't want to pull in Windows.h everywhere from mysql.h) +// temporary hack until includes are sorted out (don't want to pull in Windows.h) #ifdef GetClassName #undef GetClassName #endif diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h index f36a2e39ba1..04bf633c2f7 100644 --- a/src/server/game/DungeonFinding/LFGMgr.h +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -23,6 +23,7 @@ #include "LFGQueue.h" #include "LFGGroupData.h" #include "LFGPlayerData.h" +#include <unordered_map> class Group; class Player; diff --git a/src/server/game/DungeonFinding/LFGScripts.cpp b/src/server/game/DungeonFinding/LFGScripts.cpp index 9faf2c88208..15c0889b27d 100644 --- a/src/server/game/DungeonFinding/LFGScripts.cpp +++ b/src/server/game/DungeonFinding/LFGScripts.cpp @@ -20,6 +20,7 @@ */ #include "Common.h" +#include "Log.h" #include "SharedDefines.h" #include "Player.h" #include "Group.h" diff --git a/src/server/game/Entities/Corpse/Corpse.cpp b/src/server/game/Entities/Corpse/Corpse.cpp index 27a8623bad0..aa8a6249cf5 100644 --- a/src/server/game/Entities/Corpse/Corpse.cpp +++ b/src/server/game/Entities/Corpse/Corpse.cpp @@ -18,6 +18,7 @@ #include "Common.h" #include "Corpse.h" +#include "Log.h" #include "Player.h" #include "UpdateData.h" #include "ObjectAccessor.h" diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index eb99ccb70c3..a11b84e1dec 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -80,6 +80,7 @@ #include "OutdoorPvPMgr.h" #include "Pet.h" #include "PetPackets.h" +#include "QueryHolder.h" #include "QuestDef.h" #include "QuestPackets.h" #include "ReputationMgr.h" diff --git a/src/server/game/Garrison/GarrisonMap.cpp b/src/server/game/Garrison/GarrisonMap.cpp index 60f1fae35e9..2654bfd58ba 100644 --- a/src/server/game/Garrison/GarrisonMap.cpp +++ b/src/server/game/Garrison/GarrisonMap.cpp @@ -16,10 +16,11 @@ */ #include "GarrisonMap.h" +#include "GameObject.h" #include "Garrison.h" +#include "Log.h" #include "ObjectAccessor.h" #include "ObjectGridLoader.h" -#include "GameObject.h" class GarrisonGridLoader { diff --git a/src/server/game/Groups/GroupMgr.cpp b/src/server/game/Groups/GroupMgr.cpp index e29b51e214a..022f02346e7 100644 --- a/src/server/game/Groups/GroupMgr.cpp +++ b/src/server/game/Groups/GroupMgr.cpp @@ -19,6 +19,7 @@ #include "GroupMgr.h" #include "DB2Stores.h" #include "InstanceSaveMgr.h" +#include "Log.h" #include "World.h" GroupMgr::GroupMgr() diff --git a/src/server/game/Handlers/BankHandler.cpp b/src/server/game/Handlers/BankHandler.cpp index 06df14ae527..3d890dc5570 100644 --- a/src/server/game/Handlers/BankHandler.cpp +++ b/src/server/game/Handlers/BankHandler.cpp @@ -16,6 +16,7 @@ */ #include "BankPackets.h" +#include "Log.h" #include "NPCPackets.h" #include "Opcodes.h" #include "Player.h" diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 5707434ff51..c9569c85e51 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -43,6 +43,7 @@ #include "PlayerDump.h" #include "Player.h" #include "QueryCallback.h" +#include "QueryHolder.h" #include "QueryPackets.h" #include "ReputationMgr.h" #include "GitRevision.h" diff --git a/src/server/game/Handlers/SceneHandler.cpp b/src/server/game/Handlers/SceneHandler.cpp index 99905965b0f..41f040239e4 100644 --- a/src/server/game/Handlers/SceneHandler.cpp +++ b/src/server/game/Handlers/SceneHandler.cpp @@ -16,6 +16,7 @@ */ #include "Common.h" +#include "Log.h" #include "ScenePackets.h" #include "WorldSession.h" #include "Player.h" diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index 1519aae3389..61eb874d882 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -20,7 +20,7 @@ #include "CreatureAISelector.h" #include "Creature.h" #include "ScriptSystem.h" - +#include "Log.h" #include "ConfusedMovementGenerator.h" #include "FleeingMovementGenerator.h" #include "HomeMovementGenerator.h" diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp index c77b8c8ad50..91d290c073d 100644 --- a/src/server/game/Quests/QuestDef.cpp +++ b/src/server/game/Quests/QuestDef.cpp @@ -18,6 +18,7 @@ #include "QuestDef.h" #include "GameTables.h" +#include "Log.h" #include "Player.h" #include "World.h" #include "QuestPackets.h" diff --git a/src/server/game/Scenarios/ScenarioMgr.cpp b/src/server/game/Scenarios/ScenarioMgr.cpp index 22d98229297..8d71092057f 100644 --- a/src/server/game/Scenarios/ScenarioMgr.cpp +++ b/src/server/game/Scenarios/ScenarioMgr.cpp @@ -19,6 +19,7 @@ #include "DatabaseEnv.h" #include "DB2Stores.h" #include "InstanceScenario.h" +#include "Log.h" #include "Map.h" #include "ScenarioPackets.h" diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index 9f912d95177..8b9312c84f2 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -2471,8 +2471,11 @@ UnitScript::UnitScript(const char* name, bool addToScripts) } WorldMapScript::WorldMapScript(const char* name, uint32 mapId) - : ScriptObject(name), MapScript<Map>(mapId) + : ScriptObject(name), MapScript<Map>(sMapStore.LookupEntry(mapId)) { + if (!GetEntry()) + TC_LOG_ERROR("scripts", "Invalid WorldMapScript for %u; no such map ID.", mapId); + if (GetEntry() && !GetEntry()->IsWorldMap()) TC_LOG_ERROR("scripts", "WorldMapScript for map %u is invalid.", mapId); @@ -2480,8 +2483,11 @@ WorldMapScript::WorldMapScript(const char* name, uint32 mapId) } InstanceMapScript::InstanceMapScript(const char* name, uint32 mapId) - : ScriptObject(name), MapScript<InstanceMap>(mapId) + : ScriptObject(name), MapScript<InstanceMap>(sMapStore.LookupEntry(mapId)) { + if (!GetEntry()) + TC_LOG_ERROR("scripts", "Invalid InstanceMapScript for %u; no such map ID.", mapId); + if (GetEntry() && !GetEntry()->IsDungeon()) TC_LOG_ERROR("scripts", "InstanceMapScript for map %u is invalid.", mapId); @@ -2489,8 +2495,11 @@ InstanceMapScript::InstanceMapScript(const char* name, uint32 mapId) } BattlegroundMapScript::BattlegroundMapScript(const char* name, uint32 mapId) - : ScriptObject(name), MapScript<BattlegroundMap>(mapId) + : ScriptObject(name), MapScript<BattlegroundMap>(sMapStore.LookupEntry(mapId)) { + if (!GetEntry()) + TC_LOG_ERROR("scripts", "Invalid BattlegroundMapScript for %u; no such map ID.", mapId); + if (GetEntry() && !GetEntry()->IsBattleground()) TC_LOG_ERROR("scripts", "BattlegroundMapScript for map %u is invalid.", mapId); diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index f4cbfff2c47..a42c3fd1f89 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -302,12 +302,7 @@ template<class TMap> class MapScript : public UpdatableScript<TMap> protected: - MapScript(uint32 mapId) - : _mapEntry(sMapStore.LookupEntry(mapId)) - { - if (!_mapEntry) - TC_LOG_ERROR("scripts", "Invalid MapScript for %u; no such map ID.", mapId); - } + MapScript(MapEntry const* mapEntry) : _mapEntry(mapEntry) { } public: diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index cd0de310b75..8a9aa4d8844 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -25,6 +25,7 @@ #include "Common.h" #include "DatabaseEnv.h" #include "QueryCallback.h" +#include "QueryHolder.h" #include "AccountMgr.h" #include "Log.h" #include "Opcodes.h" diff --git a/src/server/game/Spells/SpellHistory.h b/src/server/game/Spells/SpellHistory.h index d554dde8553..bb3c7a64586 100644 --- a/src/server/game/Spells/SpellHistory.h +++ b/src/server/game/Spells/SpellHistory.h @@ -23,6 +23,7 @@ #include "Transaction.h" #include <chrono> #include <deque> +#include <unordered_map> class Item; class Player; diff --git a/src/server/game/Tools/CharacterDatabaseCleaner.cpp b/src/server/game/Tools/CharacterDatabaseCleaner.cpp index 940c5e1428d..97d909e8645 100644 --- a/src/server/game/Tools/CharacterDatabaseCleaner.cpp +++ b/src/server/game/Tools/CharacterDatabaseCleaner.cpp @@ -20,6 +20,7 @@ #include "CriteriaHandler.h" #include "CharacterDatabaseCleaner.h" #include "DB2Stores.h" +#include "Log.h" #include "World.h" #include "Database/DatabaseEnv.h" #include "SpellMgr.h" diff --git a/src/server/game/Tools/PlayerDump.cpp b/src/server/game/Tools/PlayerDump.cpp index b072760dc0f..f5c1508fc9c 100644 --- a/src/server/game/Tools/PlayerDump.cpp +++ b/src/server/game/Tools/PlayerDump.cpp @@ -131,7 +131,7 @@ bool FindNth(std::string const& str, uint32 n, std::string::size_type& s, std::s std::string GetTableName(std::string const& str) { static std::string::size_type const s = 13; - std::string::size_type e = str.find(_TABLE_SIM_, s); + std::string::size_type e = str.find('`', s); if (e == std::string::npos) return ""; @@ -209,7 +209,7 @@ std::string CreateDumpString(char const* tableName, QueryResult result) { if (!tableName || !result) return ""; std::ostringstream ss; - ss << "INSERT INTO " << _TABLE_SIM_ << tableName << _TABLE_SIM_ << " VALUES ("; + ss << "INSERT INTO `" << tableName << "` VALUES ("; Field* fields = result->Fetch(); for (uint32 i = 0; i < result->GetFieldCount(); ++i) { diff --git a/src/server/scripts/Commands/cs_account.cpp b/src/server/scripts/Commands/cs_account.cpp index 72c571ae007..3b6010d4283 100644 --- a/src/server/scripts/Commands/cs_account.cpp +++ b/src/server/scripts/Commands/cs_account.cpp @@ -25,6 +25,7 @@ EndScriptData */ #include "AccountMgr.h" #include "Chat.h" #include "Language.h" +#include "Log.h" #include "Player.h" #include "ScriptMgr.h" diff --git a/src/server/scripts/Commands/cs_battlenet_account.cpp b/src/server/scripts/Commands/cs_battlenet_account.cpp index 5a19ef48dca..64d4647e8bf 100644 --- a/src/server/scripts/Commands/cs_battlenet_account.cpp +++ b/src/server/scripts/Commands/cs_battlenet_account.cpp @@ -19,6 +19,7 @@ #include "AccountMgr.h" #include "Chat.h" #include "Language.h" +#include "Log.h" #include "Player.h" #include "ScriptMgr.h" #include "Util.h" diff --git a/src/server/scripts/Commands/cs_go.cpp b/src/server/scripts/Commands/cs_go.cpp index 46f076bf594..edb9dc7440f 100644 --- a/src/server/scripts/Commands/cs_go.cpp +++ b/src/server/scripts/Commands/cs_go.cpp @@ -114,7 +114,7 @@ public: { std::string name = param1; WorldDatabase.EscapeString(name); - whereClause << ", creature_template WHERE creature.id = creature_template.entry AND creature_template.name " _LIKE_" '" << name << '\''; + whereClause << ", creature_template WHERE creature.id = creature_template.entry AND creature_template.name LIKE '" << name << '\''; } else whereClause << "WHERE guid = '" << guidLow << '\''; diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp index 19928261e16..016fc358468 100644 --- a/src/server/scripts/Commands/cs_gobject.cpp +++ b/src/server/scripts/Commands/cs_gobject.cpp @@ -232,7 +232,7 @@ public: WorldDatabase.EscapeString(name); result = WorldDatabase.PQuery( "SELECT guid, id, position_x, position_y, position_z, orientation, map, PhaseId, PhaseGroup, (POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ " - "FROM gameobject, gameobject_template WHERE gameobject_template.entry = gameobject.id AND map = %i AND name " _LIKE_" " _CONCAT3_("'%%'", "'%s'", "'%%'")" ORDER BY order_ ASC LIMIT 1", + "FROM gameobject LEFT JOIN gameobject_template ON gameobject_template.entry = gameobject.id WHERE map = %i AND name LIKE '%%%s%%' ORDER BY order_ ASC LIMIT 1", player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetMapId(), name.c_str()); } } diff --git a/src/server/scripts/Commands/cs_reset.cpp b/src/server/scripts/Commands/cs_reset.cpp index 743081203c0..f94a0220a3c 100644 --- a/src/server/scripts/Commands/cs_reset.cpp +++ b/src/server/scripts/Commands/cs_reset.cpp @@ -25,6 +25,7 @@ EndScriptData */ #include "AchievementMgr.h" #include "Chat.h" #include "Language.h" +#include "Log.h" #include "ObjectAccessor.h" #include "Player.h" #include "Pet.h" diff --git a/src/server/scripts/Commands/cs_server.cpp b/src/server/scripts/Commands/cs_server.cpp index 45d958462fc..b807ee30bfa 100644 --- a/src/server/scripts/Commands/cs_server.cpp +++ b/src/server/scripts/Commands/cs_server.cpp @@ -25,6 +25,7 @@ EndScriptData */ #include "Chat.h" #include "Config.h" #include "Language.h" +#include "Log.h" #include "ObjectAccessor.h" #include "Player.h" #include "ScriptMgr.h" diff --git a/src/server/shared/DataStores/DB2DatabaseLoader.cpp b/src/server/shared/DataStores/DB2DatabaseLoader.cpp index 6eed726a45d..aeb3cd46062 100644 --- a/src/server/shared/DataStores/DB2DatabaseLoader.cpp +++ b/src/server/shared/DataStores/DB2DatabaseLoader.cpp @@ -16,8 +16,11 @@ */ #include "DB2DatabaseLoader.h" -#include "Database/DatabaseEnv.h" +#include "Common.h" +#include "DatabaseEnv.h" #include "DB2Meta.h" +#include "Errors.h" +#include "Log.h" DB2LoadInfo::DB2LoadInfo() : DB2FileLoadInfo(), Statement(MAX_HOTFIXDATABASE_STATEMENTS) { diff --git a/src/server/shared/Realm/RealmList.cpp b/src/server/shared/Realm/RealmList.cpp index 12f92d9277e..c949490c63f 100644 --- a/src/server/shared/Realm/RealmList.cpp +++ b/src/server/shared/Realm/RealmList.cpp @@ -18,7 +18,8 @@ #include "RealmList.h" #include "BattlenetRpcErrorCodes.h" -#include "Database/DatabaseEnv.h" +#include "DatabaseEnv.h" +#include "Log.h" #include "ProtobufJSON.h" #include "SHA256.h" #include "BigNumber.h" diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp index 4a42305139a..12a8631f324 100644 --- a/src/server/worldserver/Main.cpp +++ b/src/server/worldserver/Main.cpp @@ -21,37 +21,38 @@ /// \file #include "Common.h" -#include "DatabaseEnv.h" +#include "AppenderDB.h" #include "AsyncAcceptor.h" -#include "RASession.h" -#include "Configuration/Config.h" -#include "OpenSSLCrypto.h" -#include "ProcessPriority.h" +#include "Banner.h" +#include "BattlegroundMgr.h" #include "BigNumber.h" -#include "World.h" -#include "MapManager.h" +#include "CliRunnable.h" +#include "Configuration/Config.h" +#include "DatabaseEnv.h" +#include "DatabaseLoader.h" +#include "GitRevision.h" #include "InstanceSaveMgr.h" +#include "MapManager.h" +#include "Metric.h" +#include "MySQLThreading.h" #include "ObjectAccessor.h" +#include "OpenSSLCrypto.h" +#include "OutdoorPvP/OutdoorPvPMgr.h" +#include "ProcessPriority.h" +#include "RASession.h" +#include "RealmList.h" +#include "ScriptLoader.h" #include "ScriptMgr.h" #include "ScriptReloadMgr.h" -#include "ScriptLoader.h" -#include "OutdoorPvP/OutdoorPvPMgr.h" -#include "BattlegroundMgr.h" #include "TCSoap.h" -#include "CliRunnable.h" -#include "Banner.h" -#include "GitRevision.h" +#include "World.h" #include "WorldSocket.h" #include "WorldSocketMgr.h" -#include "RealmList.h" -#include "DatabaseLoader.h" -#include "AppenderDB.h" -#include "Metric.h" #include <openssl/opensslv.h> #include <openssl/crypto.h> #include <boost/asio/io_service.hpp> #include <boost/asio/deadline_timer.hpp> -#include <boost/filesystem/path.hpp> +#include <boost/filesystem/operations.hpp> #include <boost/program_options.hpp> #include <google/protobuf/stubs/common.h> |