From 42ffd8aff84b96f7d32d51cf362f59568a063bb4 Mon Sep 17 00:00:00 2001 From: Rochet2 Date: Sat, 13 Sep 2014 21:37:28 +0300 Subject: [PATCH] Eluna: Implement utility GetRow() --- ElunaQueryMethods.h | 236 +++++++++++++++++++++++++++++++++++ ElunaTemplate.h | 20 +-- ElunaUtility.h | 4 + GlobalMethods.h | 69 +++++----- LuaFunctions.cpp | 15 +-- QueryMethods.h | 168 ------------------------- extensions/FunctionCache.ext | 6 +- 7 files changed, 290 insertions(+), 228 deletions(-) create mode 100644 ElunaQueryMethods.h delete mode 100644 QueryMethods.h diff --git a/ElunaQueryMethods.h b/ElunaQueryMethods.h new file mode 100644 index 0000000..5681a1f --- /dev/null +++ b/ElunaQueryMethods.h @@ -0,0 +1,236 @@ +/* +* Copyright (C) 2010 - 2014 Eluna Lua Engine +* This program is free software licensed under GPL version 3 +* Please see the included DOCS/LICENSE.md for more information +*/ + +#ifndef QUERYMETHODS_H +#define QUERYMETHODS_H + +#ifndef TRINITY +#define RESULT result +#else +#define RESULT (*result) +#endif +namespace LuaQuery +{ + /* BOOLEAN */ + int IsNull(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); +#ifndef TRINITY + if (col < RESULT->GetFieldCount()) + Eluna::Push(L, RESULT->Fetch()[col].IsNULL()); +#else + if (col < RESULT->GetFieldCount()) + Eluna::Push(L, RESULT->Fetch()[col].IsNull()); +#endif + return 1; + } + + /* GETTERS */ + int GetColumnCount(lua_State* L, ElunaQuery* result) + { + Eluna::Push(L, RESULT->GetFieldCount()); + return 1; + } + + int GetRowCount(lua_State* L, ElunaQuery* result) + { + if (RESULT->GetRowCount() > (uint32)-1) + Eluna::Push(L, (uint32)-1); + else + Eluna::Push(L, RESULT->GetRowCount()); + return 1; + } + + int GetBool(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + if (col < RESULT->GetFieldCount()) + Eluna::Push(L, RESULT->Fetch()[col].GetBool()); + return 1; + } + + int GetUInt8(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + if (col < RESULT->GetFieldCount()) + Eluna::Push(L, RESULT->Fetch()[col].GetUInt8()); + return 1; + } + + int GetUInt16(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + if (col < RESULT->GetFieldCount()) + Eluna::Push(L, RESULT->Fetch()[col].GetUInt16()); + return 1; + } + + int GetUInt32(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + if (col < RESULT->GetFieldCount()) + Eluna::Push(L, RESULT->Fetch()[col].GetUInt32()); + return 1; + } + + int GetUInt64(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + if (col < RESULT->GetFieldCount()) + Eluna::Push(L, RESULT->Fetch()[col].GetUInt64()); + return 1; + } + + int GetInt8(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + if (col < RESULT->GetFieldCount()) + Eluna::Push(L, RESULT->Fetch()[col].GetInt8()); + return 1; + } + + int GetInt16(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + if (col < RESULT->GetFieldCount()) + Eluna::Push(L, RESULT->Fetch()[col].GetInt16()); + return 1; + } + + int GetInt32(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + if (col < RESULT->GetFieldCount()) + Eluna::Push(L, RESULT->Fetch()[col].GetInt32()); + return 1; + } + + int GetInt64(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + if (col < RESULT->GetFieldCount()) + Eluna::Push(L, RESULT->Fetch()[col].GetInt64()); + return 1; + } + + int GetFloat(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + if (col < RESULT->GetFieldCount()) + Eluna::Push(L, RESULT->Fetch()[col].GetFloat()); + return 1; + } + + int GetDouble(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + if (col < RESULT->GetFieldCount()) + Eluna::Push(L, RESULT->Fetch()[col].GetDouble()); + return 1; + } + + int GetString(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + if (col < RESULT->GetFieldCount()) +#ifndef TRINITY + Eluna::Push(L, RESULT->Fetch()[col].GetCppString()); +#else + Eluna::Push(L, RESULT->Fetch()[col].GetString()); +#endif + return 1; + } + + int GetCString(lua_State* L, ElunaQuery* result) + { + uint32 col = Eluna::CHECKVAL(L, 2); + if (col < RESULT->GetFieldCount()) +#ifndef TRINITY + Eluna::Push(L, RESULT->Fetch()[col].GetString()); +#else + Eluna::Push(L, RESULT->Fetch()[col].GetCString()); +#endif + return 1; + } + + /* OTHER */ + + /** + * Advances the ElunaQuery to the next row in the result returned. + * Returns false if there was no new row, otherwise true. + * + * @return bool hadNextRow + */ + int NextRow(lua_State* L, ElunaQuery* result) + { + Eluna::Push(L, RESULT->NextRow()); + return 1; + } + + /** + * Returns a table from the current row where keys are field names and values are the row's values. + * All numerical values will be numbers and everything else is returned as a string. + * For example `SELECT entry, name FROM creature_template` would result in a table of `{ entry = 123, name = "some creature name" }` + * To move to next row see [ElunaQuery:NextRow] + * + * @return table rowData : table filled with row columns and data where `T[column] = data` + */ + int GetRow(lua_State* L, ElunaQuery* result) + { + lua_newtable(L); + int tbl = lua_gettop(L); + + uint32 col = RESULT->GetFieldCount(); + Field* row = RESULT->Fetch(); + +#ifndef TRINITY + const QueryFieldNames& names = RESULT->GetFieldNames(); +#endif + + for (uint32 i = 0; i < col; ++i) + { +#ifdef TRINITY + Eluna::Push(L, RESULT->GetFieldName(i)); + + const char* str = row[i].GetCString(); + if (row[i].IsNull() || !str) + Eluna::Push(L); +#else + Eluna::Push(L, names[i]); + + const char* str = row[i].GetString(); + if (row[i].IsNULL() || !str) + Eluna::Push(L); +#endif + else + { + // MYSQL_TYPE_LONGLONG Interpreted as string for lua + switch (row[i].GetType()) + { + case MYSQL_TYPE_TINY: + case MYSQL_TYPE_SHORT: + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_FLOAT: + case MYSQL_TYPE_DOUBLE: + Eluna::Push(L, strtod(str, NULL)); + break; + default: + Eluna::Push(L, str); + break; + } + } + + lua_settable(L, tbl); + } + + lua_settop(L, tbl); + return 1; + } +}; +#undef RESULT + +#endif diff --git a/ElunaTemplate.h b/ElunaTemplate.h index d6c4e02..64b9d98 100644 --- a/ElunaTemplate.h +++ b/ElunaTemplate.h @@ -27,13 +27,11 @@ template class ElunaTemplate { public: - static const char* tname = NULL; - static bool manageMemory = false; + static const char* tname; + static bool manageMemory; static int typeT(lua_State* L) { - ASSERT(tname); - lua_pushstring(L, tname); return 1; } @@ -44,7 +42,7 @@ public: // that will only be needed on lua side and will not be managed by TC/mangos/ static void Register(lua_State* L, const char* name, bool gc = false) { - ASSERT(!tname); + ASSERT(!tname || name); tname = name; manageMemory = gc; @@ -90,8 +88,6 @@ public: template static void SetMethods(lua_State* L, ElunaRegister* methodTable) { - ASSERT(tname); - if (!methodTable) return; @@ -126,8 +122,6 @@ public: // Remember special case ElunaTemplate::gcT static int gcT(lua_State* L) { - ASSERT(tname); - if (!manageMemory) return 0; @@ -140,8 +134,6 @@ public: static int push(lua_State* L, T const* obj) { - ASSERT(tname); - if (!obj) { lua_pushnil(L); @@ -196,8 +188,6 @@ public: static T* check(lua_State* L, int narg, bool error = true) { - ASSERT(tname); - T** ptrHold = static_cast(lua_touserdata(L, narg)); if (!ptrHold) { @@ -239,8 +229,6 @@ public: static int thunk(lua_State* L) { - ASSERT(tname); - T* obj = Eluna::CHECKOBJ(L, 1); // get self if (!obj) return 0; @@ -259,8 +247,6 @@ public: static int tostringT(lua_State* L) { - ASSERT(tname); - T* obj = Eluna::CHECKOBJ(L, 1); // get self if (obj) lua_pushfstring(L, "%s: (%p)", tname, obj); diff --git a/ElunaUtility.h b/ElunaUtility.h index 6a44dcf..ea73025 100644 --- a/ElunaUtility.h +++ b/ElunaUtility.h @@ -10,14 +10,17 @@ #include "Common.h" #include "SharedDefines.h" #ifdef TRINITY +#include "QueryResult.h" #ifdef CATA #include "Object.h" #endif #else #include "ObjectGuid.h" +#include "Database/QueryResult.h" #endif #ifdef TRINITY +typedef QueryResult ElunaQuery; #ifndef CATA typedef uint64 ObjectGuid; #endif @@ -26,6 +29,7 @@ typedef uint64 ObjectGuid; #define ELUNA_LOG_DEBUG(...) TC_LOG_DEBUG("eluna", __VA_ARGS__); #define GET_GUID GetGUID #else +typedef QueryNamedResult ElunaQuery; #define MAKE_NEW_GUID(l, e, h) ObjectGuid(h, e, l) #define GUID_ENPART(guid) ObjectGuid(guid).GetEntry() #define GUID_LOPART(guid) ObjectGuid(guid).GetCounter() diff --git a/GlobalMethods.h b/GlobalMethods.h index 2dfa4bc..087e837 100644 --- a/GlobalMethods.h +++ b/GlobalMethods.h @@ -629,19 +629,20 @@ namespace LuaGlobalFunctions { const char* query = Eluna::CHECKVAL(L, 1); - QueryResult* result = NULL; -#ifndef TRINITY - result = WorldDatabase.Query(query); +#ifdef TRINITY + ElunaQuery result = WorldDatabase.Query(query); + if (result) + Eluna::Push(L, new ElunaQuery(result)); + else + Eluna::Push(L); #else - QueryResult res = WorldDatabase.Query(query); - if (res) - result = new QueryResult(res); + ElunaQuery* result = WorldDatabase.QueryNamed(query); + if (result) + Eluna::Push(L, result); + else + Eluna::Push(L); #endif - if (result) - Eluna::Push(L, result); - else - Eluna::Push(L); - return 1; + return 1; } int WorldDBExecute(lua_State* L) @@ -655,19 +656,20 @@ namespace LuaGlobalFunctions { const char* query = Eluna::CHECKVAL(L, 1); - QueryResult* result = NULL; -#ifndef TRINITY - result = CharacterDatabase.Query(query); +#ifdef TRINITY + QueryResult result = CharacterDatabase.Query(query); + if (result) + Eluna::Push(L, new QueryResult(result)); + else + Eluna::Push(L); #else - QueryResult res = CharacterDatabase.Query(query); - if (res) - result = new QueryResult(res); + QueryNamedResult* result = CharacterDatabase.QueryNamed(query); + if (result) + Eluna::Push(L, result); + else + Eluna::Push(L); #endif - if (result) - Eluna::Push(L, result); - else - Eluna::Push(L); - return 1; + return 1; } int CharDBExecute(lua_State* L) @@ -679,20 +681,21 @@ namespace LuaGlobalFunctions int AuthDBQuery(lua_State* L) { - const char* query = Eluna::CHECKVAL(L, 1); + const char* query = Eluna::CHECKVAL(L, 1); - QueryResult* result = NULL; -#ifndef TRINITY - result = LoginDatabase.Query(query); +#ifdef TRINITY + QueryResult result = LoginDatabase.Query(query); + if (result) + Eluna::Push(L, new QueryResult(result)); + else + Eluna::Push(L); #else - QueryResult res = LoginDatabase.Query(query); - if (res) - result = new QueryResult(res); + QueryNamedResult* result = LoginDatabase.QueryNamed(query); + if (result) + Eluna::Push(L, result); + else + Eluna::Push(L); #endif - if (result) - Eluna::Push(L, result); - else - Eluna::Push(L); return 1; } diff --git a/LuaFunctions.cpp b/LuaFunctions.cpp index 753614f..293f90a 100644 --- a/LuaFunctions.cpp +++ b/LuaFunctions.cpp @@ -26,7 +26,7 @@ extern "C" #include "GroupMethods.h" #include "GuildMethods.h" #include "GameObjectMethods.h" -#include "QueryMethods.h" +#include "ElunaQueryMethods.h" #include "AuraMethods.h" #include "ItemMethods.h" #include "WorldPacketMethods.h" @@ -1081,11 +1081,12 @@ ElunaRegister VehicleMethods[] = #endif #endif -ElunaRegister QueryMethods[] = +ElunaRegister QueryMethods[] = { { "NextRow", &LuaQuery::NextRow }, // :NextRow() - Advances to next rown in the query. Returns true if there is a next row, otherwise false { "GetColumnCount", &LuaQuery::GetColumnCount }, // :GetColumnCount() - Gets the column count of the query { "GetRowCount", &LuaQuery::GetRowCount }, // :GetRowCount() - Gets the row count of the query + { "GetRow", &LuaQuery::GetRow }, { "GetBool", &LuaQuery::GetBool }, // :GetBool(column) - returns a bool from a number column (for example tinyint) { "GetUInt8", &LuaQuery::GetUInt8 }, // :GetUInt8(column) - returns the value of an unsigned tinyint column @@ -1318,12 +1319,12 @@ void RegisterFunctions(lua_State* L) ElunaTemplate::Register(L, "AuctionHouseObject"); ElunaTemplate::SetMethods(L, AuctionMethods); + ElunaTemplate::Register(L, "BattleGround"); + ElunaTemplate::SetMethods(L, BattleGroundMethods); + ElunaTemplate::Register(L, "WorldPacket", true); ElunaTemplate::SetMethods(L, PacketMethods); - ElunaTemplate::Register(L, "QueryResult", true); - ElunaTemplate::SetMethods(L, QueryMethods); - - ElunaTemplate::Register(L, "BattleGround"); - ElunaTemplate::SetMethods(L, BattleGroundMethods); + ElunaTemplate::Register(L, "ElunaQuery", true); + ElunaTemplate::SetMethods(L, QueryMethods); } diff --git a/QueryMethods.h b/QueryMethods.h deleted file mode 100644 index 91a3591..0000000 --- a/QueryMethods.h +++ /dev/null @@ -1,168 +0,0 @@ -/* -* Copyright (C) 2010 - 2014 Eluna Lua Engine -* This program is free software licensed under GPL version 3 -* Please see the included DOCS/LICENSE.md for more information -*/ - -#ifndef QUERYMETHODS_H -#define QUERYMETHODS_H - -#ifndef TRINITY -#define RESULT result -#else -#define RESULT (*result) -#endif -namespace LuaQuery -{ - /* BOOLEAN */ - int IsNull(lua_State* L, QueryResult* result) - { - uint32 col = Eluna::CHECKVAL(L, 2); -#ifndef TRINITY - if (col < RESULT->GetFieldCount()) - Eluna::Push(L, RESULT->Fetch()[col].IsNULL()); -#else - if (col < RESULT->GetFieldCount()) - Eluna::Push(L, RESULT->Fetch()[col].IsNull()); -#endif - return 1; - } - - /* GETTERS */ - int GetColumnCount(lua_State* L, QueryResult* result) - { - Eluna::Push(L, RESULT->GetFieldCount()); - return 1; - } - - int GetRowCount(lua_State* L, QueryResult* result) - { - if (RESULT->GetRowCount() > (uint32)-1) - Eluna::Push(L, (uint32)-1); - else - Eluna::Push(L, RESULT->GetRowCount()); - return 1; - } - - int GetBool(lua_State* L, QueryResult* result) - { - uint32 col = Eluna::CHECKVAL(L, 2); - if (col < RESULT->GetFieldCount()) - Eluna::Push(L, RESULT->Fetch()[col].GetBool()); - return 1; - } - - int GetUInt8(lua_State* L, QueryResult* result) - { - uint32 col = Eluna::CHECKVAL(L, 2); - if (col < RESULT->GetFieldCount()) - Eluna::Push(L, RESULT->Fetch()[col].GetUInt8()); - return 1; - } - - int GetUInt16(lua_State* L, QueryResult* result) - { - uint32 col = Eluna::CHECKVAL(L, 2); - if (col < RESULT->GetFieldCount()) - Eluna::Push(L, RESULT->Fetch()[col].GetUInt16()); - return 1; - } - - int GetUInt32(lua_State* L, QueryResult* result) - { - uint32 col = Eluna::CHECKVAL(L, 2); - if (col < RESULT->GetFieldCount()) - Eluna::Push(L, RESULT->Fetch()[col].GetUInt32()); - return 1; - } - - int GetUInt64(lua_State* L, QueryResult* result) - { - uint32 col = Eluna::CHECKVAL(L, 2); - if (col < RESULT->GetFieldCount()) - Eluna::Push(L, RESULT->Fetch()[col].GetUInt64()); - return 1; - } - - int GetInt8(lua_State* L, QueryResult* result) - { - uint32 col = Eluna::CHECKVAL(L, 2); - if (col < RESULT->GetFieldCount()) - Eluna::Push(L, RESULT->Fetch()[col].GetInt8()); - return 1; - } - - int GetInt16(lua_State* L, QueryResult* result) - { - uint32 col = Eluna::CHECKVAL(L, 2); - if (col < RESULT->GetFieldCount()) - Eluna::Push(L, RESULT->Fetch()[col].GetInt16()); - return 1; - } - - int GetInt32(lua_State* L, QueryResult* result) - { - uint32 col = Eluna::CHECKVAL(L, 2); - if (col < RESULT->GetFieldCount()) - Eluna::Push(L, RESULT->Fetch()[col].GetInt32()); - return 1; - } - - int GetInt64(lua_State* L, QueryResult* result) - { - uint32 col = Eluna::CHECKVAL(L, 2); - if (col < RESULT->GetFieldCount()) - Eluna::Push(L, RESULT->Fetch()[col].GetInt64()); - return 1; - } - - int GetFloat(lua_State* L, QueryResult* result) - { - uint32 col = Eluna::CHECKVAL(L, 2); - if (col < RESULT->GetFieldCount()) - Eluna::Push(L, RESULT->Fetch()[col].GetFloat()); - return 1; - } - - int GetDouble(lua_State* L, QueryResult* result) - { - uint32 col = Eluna::CHECKVAL(L, 2); - if (col < RESULT->GetFieldCount()) - Eluna::Push(L, RESULT->Fetch()[col].GetDouble()); - return 1; - } - - int GetString(lua_State* L, QueryResult* result) - { - uint32 col = Eluna::CHECKVAL(L, 2); - if (col < RESULT->GetFieldCount()) -#ifndef TRINITY - Eluna::Push(L, RESULT->Fetch()[col].GetCppString()); -#else - Eluna::Push(L, RESULT->Fetch()[col].GetString()); -#endif - return 1; - } - - int GetCString(lua_State* L, QueryResult* result) - { - uint32 col = Eluna::CHECKVAL(L, 2); - if (col < RESULT->GetFieldCount()) -#ifndef TRINITY - Eluna::Push(L, RESULT->Fetch()[col].GetString()); -#else - Eluna::Push(L, RESULT->Fetch()[col].GetCString()); -#endif - return 1; - } - - /* OTHER */ - int NextRow(lua_State* L, QueryResult* result) - { - Eluna::Push(L, RESULT->NextRow()); - return 1; - } -}; -#undef RESULT - -#endif diff --git a/extensions/FunctionCache.ext b/extensions/FunctionCache.ext index f80c0f3..d5c81de 100644 --- a/extensions/FunctionCache.ext +++ b/extensions/FunctionCache.ext @@ -122,9 +122,9 @@ if (GetCoreExpansion() >= 2) then table.insert(T.Vehicle, "GetEntry") end -T.QueryResult = {} -table.insert(T.QueryResult, "GetColumnCount") -table.insert(T.QueryResult, "GetRowCount") +T.ElunaQuery = {} +table.insert(T.ElunaQuery, "GetColumnCount") +table.insert(T.ElunaQuery, "GetRowCount") T.WorldPacket = {} table.insert(T.WorldPacket, "GetSize")