diff --git a/zone/command.cpp b/zone/command.cpp index 14a2d06aa..5e1ede40d 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -248,7 +248,7 @@ int command_init(void) command_add("movechar", "[Character ID|Character Name] [Zone ID|Zone Short Name] - Move an offline character to the specified zone", AccountStatus::Guide, command_movechar) || command_add("movement", "Various movement commands", AccountStatus::GMMgmt, command_movement) || command_add("myskills", "- Show details about your current skill levels", AccountStatus::Player, command_myskills) || - command_add("mysql", "Mysql CLI, see 'help' for options.", AccountStatus::GMImpossible, command_mysql) || + command_add("mysql", "[Help|Query] [SQL Query] - Mysql CLI, see 'Help' for options.", AccountStatus::GMImpossible, command_mysql) || command_add("mystats", "- Show details about you or your pet", AccountStatus::Guide, command_mystats) || command_add("name", "[newname] - Rename your player target", AccountStatus::GMLeadAdmin, command_name) || command_add("netstats", "- Gets the network stats for a stream.", AccountStatus::GMMgmt, command_netstats) || diff --git a/zone/gm_commands/mysql.cpp b/zone/gm_commands/mysql.cpp index 67fc0f0df..3c2bb8724 100755 --- a/zone/gm_commands/mysql.cpp +++ b/zone/gm_commands/mysql.cpp @@ -2,85 +2,83 @@ void command_mysql(Client *c, const Seperator *sep) { - if (!sep->arg[1][0] || !sep->arg[2][0]) { - c->Message(Chat::White, "Usage: #mysql query \"Query here\""); + int arguments = sep->argnum; + if (!arguments) { + c->Message(Chat::White, "Usage: #mysql [Help|Query] [SQL Query]"); return; } - if (strcasecmp(sep->arg[1], "help") == 0) { - c->Message(Chat::White, "MYSQL In-Game CLI Interface:"); - c->Message(Chat::White, "Example: #mysql query \"Query goes here quoted\" -s -h"); - c->Message(Chat::White, "To use 'like \"%%something%%\" replace the %% with #"); - c->Message(Chat::White, "Example: #mysql query \"select * from table where name like \"#something#\""); - c->Message(Chat::White, "-s - Spaces select entries apart"); - c->Message(Chat::White, "-h - Colors every other select result"); + bool is_help = !strcasecmp(sep->arg[1], "help"); + bool is_query = !strcasecmp(sep->arg[1], "query"); + if ( + !is_help && + !is_query + ) { + c->Message(Chat::White, "Usage: #mysql [Help|Query] [SQL Query]"); return; } - - if (strcasecmp(sep->arg[1], "query") == 0) { - ///Parse switches here - int argnum = 3; - bool optionS = false; - bool optionH = false; - while (sep->arg[argnum] && strlen(sep->arg[argnum]) > 1) { - switch (sep->arg[argnum][1]) { - case 's': - optionS = true; - break; - case 'h': - optionH = true; - break; - default: - c->Message(Chat::Yellow, "%s, there is no option '%c'", c->GetName(), sep->arg[argnum][1]); - return; - } - ++argnum; + + if (is_help) { + c->Message(Chat::White, "Usage: #mysql query \"Query goes here quoted\""); + c->Message(Chat::White, "Note: To use 'LIKE \"%%something%%\" replace the %% with a #"); + c->Message(Chat::White, "Example: #mysql query \"SELECT * FROM items WHERE `name` LIKE \"#Apple#\""); + return; + } else if (is_query) { + if (arguments < 2) { + c->Message(Chat::White, "Usage: #mysql query \"Query goes here quoted\""); + c->Message(Chat::White, "Note: To use 'LIKE \"%%something%%\" replace the %% with a #"); + c->Message(Chat::White, "Example: #mysql query \"SELECT * FROM items WHERE `name` LIKE \"#Apple#\""); + return; } - int highlightTextIndex = 0; - std::string query(sep->arg[2]); - //swap # for % so like queries can work - std::replace(query.begin(), query.end(), '#', '%'); + std::string query = sep->arg[2]; + find_replace(query, "#", "%"); auto results = database.QueryDatabase(query); if (!results.Success()) { return; } - //Using sep->arg[2] again, replace # with %% so it doesn't screw up when sent through vsnprintf in Message - query = sep->arg[2]; - int pos = query.find('#'); - while (pos != std::string::npos) { - query.erase(pos, 1); - query.insert(pos, "%%"); - pos = query.find('#'); + query = sep->arg[2]; + find_replace(query, "#", "%%"); + + c->Message( + Chat::White, + fmt::format( + "Running Query: '{}'", + query + ).c_str() + ); + + std::vector lines; + for (auto row : results) { + for ( + int row_index = 0; + row_index < results.ColumnCount(); + row_index++ + ) { + lines.push_back( + fmt::format( + "{} | {} ", + results.FieldName(row_index), + ( + row[row_index] ? + ( + strlen(row[row_index]) ? + row[row_index] : + "Empty String" + ) : + "NULL" + ) + ) + ); + } } - c->Message(Chat::Yellow, "---Running query: '%s'", query.c_str()); - for (auto row = results.begin(); row != results.end(); ++row) { - std::stringstream lineText; - std::vector lineVec; - for (int i = 0; i < results.RowCount(); i++) { - //split lines that could overflow the buffer in Client::Message and get cut off - //This will crash MQ2 @ 4000 since their internal buffer is only 2048. - //Reducing it to 2000 fixes that but splits more results from tables with a lot of columns. - if (lineText.str().length() > 4000) { - lineVec.push_back(lineText.str()); - lineText.str(""); - } - lineText << results.FieldName(i) << ":" << "[" << (row[i] ? row[i] : "nullptr") << "] "; - } - - lineVec.push_back(lineText.str()); - - if (optionS) { //This provides spacing for the space switch - c->Message(Chat::White, " "); - } - if (optionH) { //This option will highlight every other row - highlightTextIndex = 1 - highlightTextIndex; - } - - for (int lineNum = 0; lineNum < lineVec.size(); ++lineNum) - c->Message(highlightTextIndex, lineVec[lineNum].c_str()); + for (auto line : lines) { + c->Message( + Chat::White, + line.c_str() + ); } } }