From 074bd3a08fbb4422251913b013219c681316f5d8 Mon Sep 17 00:00:00 2001 From: Wyk3d Date: Sat, 15 Nov 2008 20:30:06 +0200 Subject: [PATCH] [6827] Added an interface for defining custom SQLStorage loaders. --- src/shared/Database/Makefile.am | 1 + src/shared/Database/SQLStorage.cpp | 138 ++--------------- src/shared/Database/SQLStorage.h | 64 ++++++-- src/shared/Database/SQLStorageImpl.h | 214 +++++++++++++++++++++++++++ src/shared/revision_nr.h | 2 +- win/VC71/shared.vcproj | 3 + win/VC80/shared.vcproj | 4 + win/VC90/shared.vcproj | 4 + 8 files changed, 294 insertions(+), 136 deletions(-) create mode 100644 src/shared/Database/SQLStorageImpl.h diff --git a/src/shared/Database/Makefile.am b/src/shared/Database/Makefile.am index d967e1ea0..d28f9b960 100644 --- a/src/shared/Database/Makefile.am +++ b/src/shared/Database/Makefile.am @@ -55,6 +55,7 @@ libmangosdatabase_a_SOURCES = \ QueryResultSqlite.h \ SQLStorage.cpp \ SQLStorage.h \ + SQLStorageImpl.h \ SqlDelayThread.cpp \ SqlDelayThread.h \ SqlOperations.cpp \ diff --git a/src/shared/Database/SQLStorage.cpp b/src/shared/Database/SQLStorage.cpp index 9c980dcb8..b504a178d 100644 --- a/src/shared/Database/SQLStorage.cpp +++ b/src/shared/Database/SQLStorage.cpp @@ -17,9 +17,7 @@ */ #include "SQLStorage.h" -#include "ProgressBar.h" -#include "Log.h" -#include "dbcfile.h" +#include "SQLStorageImpl.h" #ifdef DO_POSTGRESQL extern DatabasePostgre WorldDatabase; @@ -53,139 +51,27 @@ void SQLStorage::Free () { uint32 offset=0; for(uint32 x=0;xFetch(); - RecordCount=fields[0].GetUInt32(); - delete result; - } - else - RecordCount = 0; - - result = WorldDatabase.PQuery("SELECT * FROM %s",table); - - if(!result) - { - sLog.outError("%s table is empty!\n",table); - RecordCount = 0; - return; - } - - uint32 recordsize=0; - uint32 offset=0; - - if(iNumFields!=result->GetFieldCount()) - { - RecordCount = 0; - sLog.outError("Error in %s table, probably sql file format was updated (there should be %d fields in sql).\n",table,iNumFields); - delete result; - exit(1); // Stop server at loading broken or non-compatible table. - } - - //get struct size - uint32 sc=0; - uint32 bo=0; - uint32 bb=0; - for(uint32 x=0;xFetch(); - bar.step(); - char *p=(char*)&_data[recordsize*count]; - newIndex[fields[0].GetUInt32()]=p; - - offset=0; - for(uint32 x=0;x0); - offset+=sizeof(bool); - break; - case FT_BYTE: - *((char*)(&p[offset]))=(fields[x].GetUInt8()); - offset+=sizeof(char); - break; - case FT_INT: - *((uint32*)(&p[offset]))=fields[x].GetUInt32(); - offset+=sizeof(uint32); - break; - case FT_FLOAT: - *((float*)(&p[offset]))=fields[x].GetFloat(); - offset+=sizeof(float); - break; - case FT_STRING: - char const* tmp = fields[x].GetString(); - char* st; - if(!tmp) - { - st=new char[1]; - *st=0; - } - else - { - uint32 l=strlen(tmp)+1; - st=new char[l]; - memcpy(st,tmp,l); - } - *((char**)(&p[offset]))=st; - offset+=sizeof(char*); - break; - } - ++count; - }while( result->NextRow() ); - - delete result; - - pIndex =newIndex; - MaxEntry=maxi; - data=_data; -} + SQLStorageLoader loader; + loader.Load(*this); +} \ No newline at end of file diff --git a/src/shared/Database/SQLStorage.h b/src/shared/Database/SQLStorage.h index 6a06eb01a..69275c155 100644 --- a/src/shared/Database/SQLStorage.h +++ b/src/shared/Database/SQLStorage.h @@ -24,18 +24,26 @@ class SQLStorage { + template + friend struct SQLStorageLoaderBase; + public: - SQLStorage(const char*fmt,const char * _entry_field,const char * sqlname) + SQLStorage(const char* fmt, const char * _entry_field, const char * sqlname) { - format=fmt; - entry_field = _entry_field; - table=sqlname; - data=NULL; - pIndex=NULL; - iNumFields =strlen(fmt); - MaxEntry = 0; + src_format = fmt; + dst_format = fmt; + init(_entry_field, sqlname); } + + SQLStorage(const char* src_fmt, const char* dst_fmt, const char * _entry_field, const char * sqlname) + { + src_format = src_fmt; + dst_format = dst_fmt; + init(_entry_field, sqlname); + } + + ~SQLStorage() { Free(); @@ -54,15 +62,53 @@ class SQLStorage uint32 RecordCount; uint32 MaxEntry; uint32 iNumFields; + void Load(); void Free(); + private: + void init(const char * _entry_field, const char * sqlname) + { + entry_field = _entry_field; + table=sqlname; + data=NULL; + pIndex=NULL; + iNumFields = strlen(src_format); + MaxEntry = 0; + } + char** pIndex; char *data; - const char *format; + const char *src_format; + const char *dst_format; const char *table; const char *entry_field; //bool HasString; }; + +template +struct SQLStorageLoaderBase +{ + public: + void Load(SQLStorage &storage); + + template + void convert(uint32 field_pos, S src, D &dst); + template + void convert_to_str(uint32 field_pos, S src, char * & dst); + template + void convert_from_str(uint32 field_pos, char * src, D& dst); + void convert_str_to_str(uint32 field_pos, char *src, char *&dst); + + private: + template + void storeValue(V value, SQLStorage &store, char *p, int x, uint32 &offset); + void storeValue(char * value, SQLStorage &store, char *p, int x, uint32 &offset); +}; + +struct SQLStorageLoader : public SQLStorageLoaderBase +{ +}; + #endif diff --git a/src/shared/Database/SQLStorageImpl.h b/src/shared/Database/SQLStorageImpl.h new file mode 100644 index 000000000..4f10c6eee --- /dev/null +++ b/src/shared/Database/SQLStorageImpl.h @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ProgressBar.h" +#include "Log.h" +#include "dbcfile.h" + +template +template +void SQLStorageLoaderBase::convert(uint32 field_pos, S src, D &dst) +{ + dst = D(src); +} + +template +void SQLStorageLoaderBase::convert_str_to_str(uint32 field_pos, char *src, char *&dst) +{ + if(!src) + { + dst = new char[1]; + *dst = 0; + } + else + { + uint32 l = strlen(src) + 1; + dst = new char[l]; + memcpy(dst, src, l); + } +} + +template +template +void SQLStorageLoaderBase::convert_to_str(uint32 field_pos, S src, char * & dst) +{ + dst = new char[1]; + *dst = 0; +} + +template +template +void SQLStorageLoaderBase::convert_from_str(uint32 field_pos, char * src, D& dst) +{ + dst = 0; +} + +template +template +void SQLStorageLoaderBase::storeValue(V value, SQLStorage &store, char *p, int x, uint32 &offset) +{ + T * subclass = (static_cast(this)); + switch(store.dst_format[x]) + { + case FT_LOGIC: + subclass->convert(x, value, *((bool*)(&p[offset])) ); + offset+=sizeof(bool); + break; + case FT_BYTE: + subclass->convert(x, value, *((char*)(&p[offset])) ); + offset+=sizeof(char); + break; + case FT_INT: + subclass->convert(x, value, *((uint32*)(&p[offset])) ); + offset+=sizeof(uint32); + break; + case FT_FLOAT: + subclass->convert(x, value, *((float*)(&p[offset])) ); + offset+=sizeof(float); + break; + case FT_STRING: + subclass->convert_to_str(x, value, *((char**)(&p[offset])) ); + offset+=sizeof(char*); + break; + } +} + +template +void SQLStorageLoaderBase::storeValue(char * value, SQLStorage &store, char *p, int x, uint32 &offset) +{ + T * subclass = (static_cast(this)); + switch(store.dst_format[x]) + { + case FT_LOGIC: + subclass->convert_from_str(x, value, *((bool*)(&p[offset])) ); + offset+=sizeof(bool); + break; + case FT_BYTE: + subclass->convert_from_str(x, value, *((char*)(&p[offset])) ); + offset+=sizeof(char); + break; + case FT_INT: + subclass->convert_from_str(x, value, *((uint32*)(&p[offset])) ); + offset+=sizeof(uint32); + break; + case FT_FLOAT: + subclass->convert_from_str(x, value, *((float*)(&p[offset])) ); + offset+=sizeof(float); + break; + case FT_STRING: + subclass->convert_str_to_str(x, value, *((char**)(&p[offset])) ); + offset+=sizeof(char*); + break; + } +} + +template +void SQLStorageLoaderBase::Load(SQLStorage &store) +{ + uint32 maxi; + Field *fields; + QueryResult *result = WorldDatabase.PQuery("SELECT MAX(%s) FROM %s", store.entry_field, store.table); + if(!result) + { + sLog.outError("Error loading %s table (not exist?)\n", store.table); + exit(1); // Stop server at loading non exited table or not accessable table + } + + maxi = (*result)[0].GetUInt32()+1; + delete result; + + result = WorldDatabase.PQuery("SELECT COUNT(*) FROM %s", store.table); + if(result) + { + fields = result->Fetch(); + store.RecordCount = fields[0].GetUInt32(); + delete result; + } + else + store.RecordCount = 0; + + result = WorldDatabase.PQuery("SELECT * FROM %s", store.table); + + if(!result) + { + sLog.outError("%s table is empty!\n", store.table); + store.RecordCount = 0; + return; + } + + uint32 recordsize = 0; + uint32 offset = 0; + + if(store.iNumFields != result->GetFieldCount()) + { + store.RecordCount = 0; + sLog.outError("Error in %s table, probably sql file format was updated (there should be %d fields in sql).\n", store.table, store.iNumFields); + delete result; + exit(1); // Stop server at loading broken or non-compatible table. + } + + //get struct size + uint32 sc=0; + uint32 bo=0; + uint32 bb=0; + for(uint32 x=0; x< store.iNumFields; x++) + if(store.dst_format[x]==FT_STRING) + ++sc; + else if (store.dst_format[x]==FT_LOGIC) + ++bo; + else if (store.dst_format[x]==FT_BYTE) + ++bb; + recordsize=(store.iNumFields-sc-bo-bb)*4+sc*sizeof(char*)+bo*sizeof(bool)+bb*sizeof(char); + + char** newIndex=new char*[maxi]; + memset(newIndex,0,maxi*sizeof(char*)); + + char * _data= new char[store.RecordCount *recordsize]; + uint32 count=0; + barGoLink bar( store.RecordCount ); + do + { + fields = result->Fetch(); + bar.step(); + char *p=(char*)&_data[recordsize*count]; + newIndex[fields[0].GetUInt32()]=p; + + offset=0; + for(uint32 x = 0; x < store.iNumFields; x++) + switch(store.src_format[x]) + { + case FT_LOGIC: + storeValue((bool)(fields[x].GetUInt32() > 0), store, p, x, offset); break; + case FT_BYTE: + storeValue((char)fields[x].GetUInt8(), store, p, x, offset); break; + case FT_INT: + storeValue((uint32)fields[x].GetUInt32(), store, p, x, offset); break; + case FT_FLOAT: + storeValue((float)fields[x].GetFloat(), store, p, x, offset); break; + case FT_STRING: + storeValue((char*)fields[x].GetString(), store, p, x, offset); break; + } + ++count; + }while( result->NextRow() ); + + delete result; + + store.pIndex = newIndex; + store.MaxEntry = maxi; + store.data = _data; +} diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 6c2212faa..b7d979b8c 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6826" + #define REVISION_NR "6827" #endif // __REVISION_NR_H__ diff --git a/win/VC71/shared.vcproj b/win/VC71/shared.vcproj index 5321788cb..deefd9881 100644 --- a/win/VC71/shared.vcproj +++ b/win/VC71/shared.vcproj @@ -192,6 +192,9 @@ + + + + diff --git a/win/VC90/shared.vcproj b/win/VC90/shared.vcproj index f6ad561c0..3254e559c 100644 --- a/win/VC90/shared.vcproj +++ b/win/VC90/shared.vcproj @@ -436,6 +436,10 @@ RelativePath="..\..\src\shared\Database\SQLStorage.h" > + +