Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
DBCStore.h
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#ifndef DBCSTORE_H
7#define DBCSTORE_H
8
9#include "DatabaseEnv.h"
10#include "DatabaseWorkerPool.h"
11#include "DBCFileLoader.h"
12#include "Field.h"
14#include "Log.h"
15
16struct SqlDbc
17{
18 std::string const* formatString;
19 std::string const* indexName;
20 std::string sqlTableName;
23 SqlDbc(std::string const* _filename, std::string const* _format, std::string const* _idname, char const* fmt)
24 : formatString(_format), indexName(_idname), sqlIndexPos(0)
25 {
26 // Convert dbc file name to sql table name
27 sqlTableName = *_filename;
28 for (uint32 i = 0; i < sqlTableName.size(); ++i)
29 {
30 if (isalpha(sqlTableName[i]))
31 sqlTableName[i] = char(tolower(sqlTableName[i]));
32 else if (sqlTableName[i] == '.')
33 sqlTableName[i] = '_';
34 }
35
36 // Get sql index position
38 if (indexPos >= 0)
39 {
40 uint32 uindexPos = uint32(indexPos);
41 for (uint32 x = 0; x < formatString->size(); ++x)
42 {
43 // Count only fields present in sql
44 if ((*formatString)[x] == FT_SQL_PRESENT)
45 {
46 if (x == uindexPos)
47 break;
49 }
50 }
51 }
52 }
53private:
54 SqlDbc(SqlDbc const& right) = delete;
55 SqlDbc& operator=(SqlDbc const& right) = delete;
56};
57
58template<class T>
60{
61 typedef std::list<char*> StringPoolList;
62public:
63 explicit DBCStorage(char const* f)
64 : fmt(f), nCount(0), fieldCount(0), dataTable(NULL)
65 {
66 indexTable.asT = NULL;
67 }
68
70
71 T const* LookupEntry(uint32 id) const
72 {
73 return (id >= nCount) ? NULL : indexTable.asT[id];
74 }
75
76 uint32 GetNumRows() const { return nCount; }
77 char const* GetFormat() const { return fmt; }
78 uint32 GetFieldCount() const { return fieldCount; }
79
80 bool Load(char const* fn, SqlDbc* sql)
81 {
82 DBCFileLoader dbc;
83 // Check if load was sucessful, only then continue
84 if (!dbc.Load(fn, fmt))
85 return false;
86
87 uint32 sqlRecordCount = 0;
88 uint32 sqlHighestIndex = 0;
89 Field* fields = NULL;
90 QueryResult result = QueryResult(NULL);
91 // Load data from sql
92 if (sql)
93 {
94 std::string query = "SELECT * FROM " + sql->sqlTableName;
95 if (sql->indexPos >= 0)
96 query += " ORDER BY " + *sql->indexName + " DESC";
97 query += ';';
98
99
100 result = WorldDatabase.Query(query.c_str());
101 if (result)
102 {
103 sqlRecordCount = uint32(result->GetRowCount());
104 if (sql->indexPos >= 0)
105 {
106 fields = result->Fetch();
107 sqlHighestIndex = fields[sql->sqlIndexPos].GetUInt32();
108 }
109
110 // Check if sql index pos is valid
111 if (int32(result->GetFieldCount() - 1) < sql->sqlIndexPos)
112 {
113 SF_LOG_ERROR("server.loading", "Invalid index pos for dbc:'%s'", sql->sqlTableName.c_str());
114 return false;
115 }
116 }
117 }
118
119 char* sqlDataTable;
120 fieldCount = dbc.GetCols();
121
122 dataTable = reinterpret_cast<T*>(dbc.AutoProduceData(fmt, nCount, indexTable.asChar,
123 sqlRecordCount, sqlHighestIndex, sqlDataTable));
124
125 stringPoolList.push_back(dbc.AutoProduceStrings(fmt, reinterpret_cast<char*>(dataTable)));
126
127 // Insert sql data into arrays
128 if (result)
129 {
130 if (indexTable.asT)
131 {
132 uint32 offset = 0;
133 uint32 rowIndex = dbc.GetNumRows();
134 do
135 {
136 if (!fields)
137 fields = result->Fetch();
138
139 if (sql->indexPos >= 0)
140 {
141 uint32 id = fields[sql->sqlIndexPos].GetUInt32();
142 if (indexTable.asT[id])
143 {
144 SF_LOG_ERROR("server.loading", "Index %d already exists in dbc:'%s'", id, sql->sqlTableName.c_str());
145 return false;
146 }
147
148 indexTable.asT[id] = reinterpret_cast<T*>(&sqlDataTable[offset]);
149 }
150 else
151 indexTable.asT[rowIndex] = reinterpret_cast<T*>(&sqlDataTable[offset]);
152
153 uint32 columnNumber = 0;
154 uint32 sqlColumnNumber = 0;
155
156 for (; columnNumber < sql->formatString->size(); ++columnNumber)
157 {
158 if ((*sql->formatString)[columnNumber] == FT_SQL_ABSENT)
159 {
160 switch (fmt[columnNumber])
161 {
162 case FT_FLOAT:
163 *reinterpret_cast<float*>(&sqlDataTable[offset]) = 0.0f;
164 offset += 4;
165 break;
166 case FT_IND:
167 case FT_INT:
168 *reinterpret_cast<uint32*>(&sqlDataTable[offset]) = uint32(0);
169 offset += 4;
170 break;
171 case FT_BYTE:
172 *reinterpret_cast<uint8*>(&sqlDataTable[offset]) = uint8(0);
173 offset += 1;
174 break;
175 case FT_STRING:
176 // Beginning of the pool - empty string
177 *reinterpret_cast<char**>(&sqlDataTable[offset]) = stringPoolList.back();
178 offset += sizeof(char*);
179 break;
180 }
181 }
182 else if ((*sql->formatString)[columnNumber] == FT_SQL_PRESENT)
183 {
184 bool validSqlColumn = true;
185 switch (fmt[columnNumber])
186 {
187 case FT_FLOAT:
188 *reinterpret_cast<float*>(&sqlDataTable[offset]) = fields[sqlColumnNumber].GetFloat();
189 offset += 4;
190 break;
191 case FT_IND:
192 case FT_INT:
193 *reinterpret_cast<uint32*>(&sqlDataTable[offset]) = fields[sqlColumnNumber].GetUInt32();
194 offset += 4;
195 break;
196 case FT_BYTE:
197 *reinterpret_cast<uint8*>(&sqlDataTable[offset]) = fields[sqlColumnNumber].GetUInt8();
198 offset += 1;
199 break;
200 case FT_STRING:
201 SF_LOG_ERROR("server.loading", "Unsupported data type in table '%s' at char %d", sql->sqlTableName.c_str(), columnNumber);
202 return false;
203 case FT_SORT:
204 break;
205 default:
206 validSqlColumn = false;
207 break;
208 }
209 if (validSqlColumn && (columnNumber != (sql->formatString->size() - 1)))
210 sqlColumnNumber++;
211 }
212 else
213 {
214 SF_LOG_ERROR("server.loading", "Incorrect sql format string '%s' at char %d", sql->sqlTableName.c_str(), columnNumber);
215 return false;
216 }
217 }
218
219 if (sqlColumnNumber != (result->GetFieldCount() - 1))
220 {
221 SF_LOG_ERROR("server.loading", "SQL and DBC format strings are not matching for table: '%s'", sql->sqlTableName.c_str());
222 return false;
223 }
224
225 fields = NULL;
226 ++rowIndex;
227 } while (result->NextRow());
228 }
229 }
230
231 // error in dbc file at loading if NULL
232 return indexTable.asT != NULL;
233 }
234
235 bool LoadStringsFrom(char const* fn)
236 {
237 // DBC must be already loaded using Load
238 if (!indexTable.asT)
239 return false;
240
241 DBCFileLoader dbc;
242 // Check if load was successful, only then continue
243 if (!dbc.Load(fn, fmt))
244 return false;
245
246 stringPoolList.push_back(dbc.AutoProduceStrings(fmt, reinterpret_cast<char*>(dataTable)));
247
248 return true;
249 }
250
251 void Clear()
252 {
253 if (!indexTable.asT)
254 return;
255
256 delete[] reinterpret_cast<char*>(indexTable.asT);
257 indexTable.asT = NULL;
258 delete[] reinterpret_cast<char*>(dataTable);
259 dataTable = NULL;
260
261 while (!stringPoolList.empty())
262 {
263 delete[] stringPoolList.front();
264 stringPoolList.pop_front();
265 }
266
267 nCount = 0;
268 }
269
270private:
271 char const* fmt;
274
275 union
276 {
277 T** asT;
278 char** asChar;
279 }
281
284 DBCStorage(DBCStorage const& right) = delete;
285 DBCStorage& operator=(DBCStorage const& right) = delete;
286};
287
288#endif
std::int32_t int32
Definition Define.h:73
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
@ FT_IND
Definition Define.h:90
@ FT_FLOAT
Definition Define.h:86
@ FT_STRING
Definition Define.h:85
@ FT_SORT
Definition Define.h:89
@ FT_INT
Definition Define.h:87
@ FT_BYTE
Definition Define.h:88
@ FT_SQL_ABSENT
Definition Define.h:92
@ FT_SQL_PRESENT
Definition Define.h:91
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
Skyfire::AutoPtr< ResultSet, Skyfire::Mutex > QueryResult
Definition QueryResult.h:48
bool Load(const char *filename, const char *fmt)
uint32 GetCols() const
char * AutoProduceData(std::string fmt, uint32 &count, char **&indexTable, uint32 sqlRecordCount, uint32 sqlHighestIndex, char *&sqlDataTable)
static uint32 GetFormatRecordSize(std::string format, int32 *index_pos=NULL)
uint32 GetNumRows() const
Get begin iterator over records.
char * AutoProduceStrings(std::string fmt, char *dataTable)
char ** asChar
Definition DBCStore.h:278
~DBCStorage()
Definition DBCStore.h:69
char const * GetFormat() const
Definition DBCStore.h:77
bool LoadStringsFrom(char const *fn)
Definition DBCStore.h:235
uint32 GetFieldCount() const
Definition DBCStore.h:78
uint32 nCount
Definition DBCStore.h:272
std::list< char * > StringPoolList
Definition DBCStore.h:61
T const * LookupEntry(uint32 id) const
Definition DBCStore.h:71
DBCStorage(char const *f)
Definition DBCStore.h:63
char const * fmt
Definition DBCStore.h:271
T * dataTable
Definition DBCStore.h:282
uint32 GetNumRows() const
Definition DBCStore.h:76
void Clear()
Definition DBCStore.h:251
DBCStorage & operator=(DBCStorage const &right)=delete
union DBCStorage::@073150077035204212161176146331126274070346246236 indexTable
bool Load(char const *fn, SqlDbc *sql)
Definition DBCStore.h:80
DBCStorage(DBCStorage const &right)=delete
uint32 fieldCount
Definition DBCStore.h:273
StringPoolList stringPoolList
Definition DBCStore.h:283
Definition Field.h:16
uint32 GetUInt32() const
Definition Field.h:105
WorldDatabaseWorkerPool WorldDatabase
Accessor to the world database.
Definition Main.cpp:40
std::string const * indexName
Definition DBCStore.h:19
int32 indexPos
Definition DBCStore.h:21
SqlDbc & operator=(SqlDbc const &right)=delete
SqlDbc(std::string const *_filename, std::string const *_format, std::string const *_idname, char const *fmt)
Definition DBCStore.h:23
int32 sqlIndexPos
Definition DBCStore.h:22
SqlDbc(SqlDbc const &right)=delete
std::string const * formatString
Definition DBCStore.h:18
std::string sqlTableName
Definition DBCStore.h:20