diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 0990afd1b..1eff58828 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -109,6 +109,16 @@ SET(common_sources util/directory.cpp util/uuid.cpp) +SET(repositories + repositories/character_recipe_list_repository.h + repositories/criteria/content_filter_criteria.h + repositories/grid_repository.h + repositories/grid_entries_repository.h + repositories/spawngroup_repository.h + repositories/tradeskill_recipe_repository.h + repositories/instance_list_repository.h + ) + SET(common_headers any.h base_packet.h @@ -198,12 +208,6 @@ SET(common_headers queue.h races.h random.h - repositories/character_recipe_list_repository.h - repositories/criteria/content_filter_criteria.h - repositories/grid_repository.h - repositories/grid_entries_repository.h - repositories/spawngroup_repository.h - repositories/tradeskill_recipe_repository.h rdtsc.h rulesys.h ruletypes.h @@ -388,7 +392,7 @@ SOURCE_GROUP(Util FILES INCLUDE_DIRECTORIES(Patches SocketLib StackWalker) -ADD_LIBRARY(common ${common_sources} ${common_headers}) +ADD_LIBRARY(common ${common_sources} ${common_headers} ${repositories}) IF(UNIX) SET_SOURCE_FILES_PROPERTIES("SocketLib/Mime.cpp" PROPERTY COMPILE_FLAGS -Wno-unused-result) diff --git a/common/repositories/instance_list_repository.h b/common/repositories/instance_list_repository.h new file mode 100644 index 000000000..aa7f0187a --- /dev/null +++ b/common/repositories/instance_list_repository.h @@ -0,0 +1,298 @@ +/** + * EQEmulator: Everquest Server Emulator + * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY except by those people which sell it, which + * are required to give you total support for your newly bought product; + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef EQEMU_INSTANCE_LIST_REPOSITORY_H +#define EQEMU_INSTANCE_LIST_REPOSITORY_H + +#include "../database.h" +#include "../string_util.h" + +class InstanceListRepository { +public: + struct InstanceList { + int id; + int zone; + int8 version; + int8 is_global; + int start_time; + int duration; + int8 never_expires; + }; + + static std::string PrimaryKey() + { + return std::string("id"); + } + + static std::vector Columns() + { + return { + "id", + "zone", + "version", + "is_global", + "start_time", + "duration", + "never_expires", + }; + } + + static std::string ColumnsRaw() + { + return std::string(implode(", ", Columns())); + } + + static std::string InsertColumnsRaw() + { + std::vector insert_columns; + + for (auto &column : Columns()) { + if (column == PrimaryKey()) { + continue; + } + + insert_columns.push_back(column); + } + + return std::string(implode(", ", insert_columns)); + } + + static std::string TableName() + { + return std::string("instance_list"); + } + + static std::string BaseSelect() + { + return fmt::format( + "SELECT {} FROM {}", + ColumnsRaw(), + TableName() + ); + } + + static std::string BaseInsert() + { + return fmt::format( + "INSERT INTO {} ({}) ", + TableName(), + InsertColumnsRaw() + ); + } + + static InstanceList NewEntity() + { + InstanceList entry{}; + + entry.id = 0; + entry.zone = 0; + entry.version = 0; + entry.is_global = 0; + entry.start_time = 0; + entry.duration = 0; + entry.never_expires = 0; + + return entry; + } + + static InstanceList GetInstanceListEntry( + const std::vector &instance_list, + int instance_list_id + ) + { + for (auto &row : instance_list) { + if (row.id == instance_list_id) { + return row; + } + } + + return NewEntity(); + } + + static InstanceList FindOne( + int instance_list_id + ) + { + auto results = database.QueryDatabase( + fmt::format( + "{} WHERE id = {} LIMIT 1", + BaseSelect(), + instance_list_id + ) + ); + + auto row = results.begin(); + if (results.RowCount() == 1) { + InstanceList entry{}; + + entry.id = atoi(row[0]); + entry.zone = atoi(row[1]); + entry.version = atoi(row[2]); + entry.is_global = atoi(row[3]); + entry.start_time = atoi(row[4]); + entry.duration = atoi(row[5]); + entry.never_expires = atoi(row[6]); + + return entry; + } + + return NewEntity(); + } + + static int DeleteOne( + int instance_list_id + ) + { + auto results = database.QueryDatabase( + fmt::format( + "DELETE FROM {} WHERE {} = {}", + TableName(), + PrimaryKey(), + instance_list_id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static int UpdateOne( + InstanceList instance_list_entry + ) + { + std::vector update_values; + + auto columns = Columns(); + + update_values.push_back(columns[1] + " = " + std::to_string(instance_list_entry.zone)); + update_values.push_back(columns[2] + " = " + std::to_string(instance_list_entry.version)); + update_values.push_back(columns[3] + " = " + std::to_string(instance_list_entry.is_global)); + update_values.push_back(columns[4] + " = " + std::to_string(instance_list_entry.start_time)); + update_values.push_back(columns[5] + " = " + std::to_string(instance_list_entry.duration)); + update_values.push_back(columns[6] + " = " + std::to_string(instance_list_entry.never_expires)); + + auto results = database.QueryDatabase( + fmt::format( + "UPDATE {} SET {} WHERE {} = {}", + TableName(), + implode(", ", update_values), + PrimaryKey(), + instance_list_entry.id + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static InstanceList InsertOne( + InstanceList instance_list_entry + ) + { + std::vector insert_values; + + insert_values.push_back(std::to_string(instance_list_entry.zone)); + insert_values.push_back(std::to_string(instance_list_entry.version)); + insert_values.push_back(std::to_string(instance_list_entry.is_global)); + insert_values.push_back(std::to_string(instance_list_entry.start_time)); + insert_values.push_back(std::to_string(instance_list_entry.duration)); + insert_values.push_back(std::to_string(instance_list_entry.never_expires)); + + auto results = database.QueryDatabase( + fmt::format( + "{} VALUES ({})", + BaseInsert(), + implode(",", insert_values) + ) + ); + + if (results.Success()) { + instance_list_entry.id = results.LastInsertedID(); + return instance_list_entry; + } + + instance_list_entry = InstanceListRepository::NewEntity(); + + return instance_list_entry; + } + + static int InsertMany( + std::vector instance_list_entries + ) + { + std::vector insert_chunks; + + for (auto &instance_list_entry: instance_list_entries) { + std::vector insert_values; + + insert_values.push_back(std::to_string(instance_list_entry.zone)); + insert_values.push_back(std::to_string(instance_list_entry.version)); + insert_values.push_back(std::to_string(instance_list_entry.is_global)); + insert_values.push_back(std::to_string(instance_list_entry.start_time)); + insert_values.push_back(std::to_string(instance_list_entry.duration)); + insert_values.push_back(std::to_string(instance_list_entry.never_expires)); + + insert_chunks.push_back("(" + implode(",", insert_values) + ")"); + } + + std::vector insert_values; + + auto results = database.QueryDatabase( + fmt::format( + "{} VALUES {}", + BaseInsert(), + implode(",", insert_chunks) + ) + ); + + return (results.Success() ? results.RowsAffected() : 0); + } + + static std::vector All() + { + std::vector all_entries; + + auto results = database.QueryDatabase( + fmt::format( + "{}", + BaseSelect() + ) + ); + + all_entries.reserve(results.RowCount()); + + for (auto row = results.begin(); row != results.end(); ++row) { + InstanceList entry{}; + + entry.id = atoi(row[0]); + entry.zone = atoi(row[1]); + entry.version = atoi(row[2]); + entry.is_global = atoi(row[3]); + entry.start_time = atoi(row[4]); + entry.duration = atoi(row[5]); + entry.never_expires = atoi(row[6]); + + all_entries.push_back(entry); + } + + return all_entries; + } + +}; + +#endif //EQEMU_INSTANCE_LIST_REPOSITORY_H diff --git a/world/world_server_command_handler.cpp b/world/world_server_command_handler.cpp index 38991f604..0c7eb0ac1 100644 --- a/world/world_server_command_handler.cpp +++ b/world/world_server_command_handler.cpp @@ -28,6 +28,7 @@ #include "../common/content/world_content_service.h" #include "../common/repositories/criteria/content_filter_criteria.h" #include "../common/rulesys.h" +#include "../common/repositories/instance_list_repository.h" namespace WorldserverCommandHandler { @@ -57,6 +58,7 @@ namespace WorldserverCommandHandler { function_map["database:schema"] = &WorldserverCommandHandler::DatabaseGetSchema; function_map["database:dump"] = &WorldserverCommandHandler::DatabaseDump; function_map["test:test"] = &WorldserverCommandHandler::TestCommand; + function_map["test:repository"] = &WorldserverCommandHandler::TestRepository; EQEmuCommand::HandleMenu(function_map, cmd, argc, argv); } @@ -311,4 +313,96 @@ namespace WorldserverCommandHandler { ); } + /** + * @param argc + * @param argv + * @param cmd + * @param description + */ + void TestRepository(int argc, char **argv, argh::parser &cmd, std::string &description) + { + description = "Test command"; + + if (cmd[{"-h", "--help"}]) { + return; + } + + /** + * Insert one + */ + auto instance_list_entry = InstanceListRepository::NewEntity(); + + instance_list_entry.zone = 999; + instance_list_entry.version = 1; + instance_list_entry.is_global = 1; + instance_list_entry.start_time = 0; + instance_list_entry.duration = 0; + instance_list_entry.never_expires = 1; + + auto instance_list_inserted = InstanceListRepository::InsertOne(instance_list_entry); + + LogInfo("Inserted ID is [{}] zone [{}]", instance_list_inserted.id, instance_list_inserted.zone); + + /** + * Find one + */ + auto found_instance_list = InstanceListRepository::FindOne(instance_list_inserted.id); + + LogInfo("Found ID is [{}] zone [{}]", found_instance_list.id, found_instance_list.zone); + + /** + * Update one + */ + LogInfo("Updating instance id [{}] zone [{}]", found_instance_list.id, found_instance_list.zone); + + int update_instance_list_count = InstanceListRepository::UpdateOne(found_instance_list); + + found_instance_list.zone = 777; + + LogInfo( + "Updated instance id [{}] zone [{}] affected [{}]", + found_instance_list.id, + found_instance_list.zone, + update_instance_list_count + ); + + + /** + * Delete one + */ + int deleted = InstanceListRepository::DeleteOne(found_instance_list.id) ; + + LogInfo("Deleting one instance [{}] deleted count [{}]", found_instance_list.id, deleted); + + /** + * Insert many + */ + std::vector instance_lists; + + auto instance_list_entry_bulk = InstanceListRepository::NewEntity(); + + instance_list_entry_bulk.zone = 999; + instance_list_entry_bulk.version = 1; + instance_list_entry_bulk.is_global = 1; + instance_list_entry_bulk.start_time = 0; + instance_list_entry_bulk.duration = 0; + instance_list_entry_bulk.never_expires = 1; + + for (int i = 0; i < 10; i++) { + instance_lists.push_back(instance_list_entry_bulk); + } + + /** + * Fetch all + */ + int inserted_count = InstanceListRepository::InsertMany(instance_lists); + + LogInfo("Bulk insertion test, inserted [{}]", inserted_count); + + for (auto &entry: InstanceListRepository::All()) { + LogInfo("Iterating through entry id [{}] zone [{}]", entry.id, entry.zone); + } + + } + } \ No newline at end of file diff --git a/world/world_server_command_handler.h b/world/world_server_command_handler.h index 5291d7c24..66f81a130 100644 --- a/world/world_server_command_handler.h +++ b/world/world_server_command_handler.h @@ -32,6 +32,7 @@ namespace WorldserverCommandHandler { void DatabaseGetSchema(int argc, char **argv, argh::parser &cmd, std::string &description); void DatabaseDump(int argc, char **argv, argh::parser &cmd, std::string &description); void TestCommand(int argc, char **argv, argh::parser &cmd, std::string &description); + void TestRepository(int argc, char **argv, argh::parser &cmd, std::string &description); };