TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
DBCStore.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
3  * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation; either version 2 of the License, or (at your
8  * option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef DBCSTORE_H
20 #define DBCSTORE_H
21 
22 #include "DBCFileLoader.h"
23 #include "DBStorageIterator.h"
24 #include "Log.h"
25 #include "Field.h"
26 #include "DatabaseWorkerPool.h"
28 #include "DatabaseEnv.h"
29 
30 struct SqlDbc
31 {
32  std::string const* formatString;
33  std::string const* indexName;
34  std::string sqlTableName;
37  SqlDbc(std::string const* _filename, std::string const* _format, std::string const* _idname, char const* fmt)
38  : formatString(_format), indexName (_idname), sqlIndexPos(0)
39  {
40  // Convert dbc file name to sql table name
41  sqlTableName = *_filename;
42  for (uint32 i = 0; i< sqlTableName.size(); ++i)
43  {
44  if (isalpha(sqlTableName[i]))
45  sqlTableName[i] = char(tolower(sqlTableName[i]));
46  else if (sqlTableName[i] == '.')
47  sqlTableName[i] = '_';
48  }
49 
50  // Get sql index position
51  DBCFileLoader::GetFormatRecordSize(fmt, &indexPos);
52  if (indexPos >= 0)
53  {
54  uint32 uindexPos = uint32(indexPos);
55  for (uint32 x = 0; x < formatString->size(); ++x)
56  {
57  // Count only fields present in sql
58  if ((*formatString)[x] == FT_SQL_PRESENT)
59  {
60  if (x == uindexPos)
61  break;
62  ++sqlIndexPos;
63  }
64  }
65  }
66  }
67 
68 private:
69  SqlDbc(SqlDbc const& right) = delete;
70  SqlDbc& operator=(SqlDbc const& right) = delete;
71 };
72 
73 template<class T>
75 {
76  typedef std::list<char*> StringPoolList;
77 
78  public:
80 
81  explicit DBCStorage(char const* f)
82  : fmt(f), nCount(0), fieldCount(0), dataTable(NULL)
83  {
84  indexTable.asT = NULL;
85  }
86 
87  ~DBCStorage() { Clear(); }
88 
89  T const* LookupEntry(uint32 id) const
90  {
91  return (id >= nCount) ? NULL : indexTable.asT[id];
92  }
93 
94  T const* AssertEntry(uint32 id) const
95  {
96  T const* entry = LookupEntry(id);
97  ASSERT(entry);
98  return entry;
99  }
100 
101  uint32 GetNumRows() const { return nCount; }
102  char const* GetFormat() const { return fmt; }
103  uint32 GetFieldCount() const { return fieldCount; }
104 
105  bool Load(char const* fn, SqlDbc* sql)
106  {
107  DBCFileLoader dbc;
108  // Check if load was successful, only then continue
109  if (!dbc.Load(fn, fmt))
110  return false;
111 
112  uint32 sqlRecordCount = 0;
113  uint32 sqlHighestIndex = 0;
114  Field* fields = NULL;
115  QueryResult result = QueryResult(NULL);
116  // Load data from sql
117  if (sql)
118  {
119  std::string query = "SELECT * FROM " + sql->sqlTableName;
120  if (sql->indexPos >= 0)
121  query +=" ORDER BY " + *sql->indexName + " DESC";
122  query += ';';
123 
124 
125  result = WorldDatabase.Query(query.c_str());
126  if (result)
127  {
128  sqlRecordCount = uint32(result->GetRowCount());
129  if (sql->indexPos >= 0)
130  {
131  fields = result->Fetch();
132  sqlHighestIndex = fields[sql->sqlIndexPos].GetUInt32();
133  }
134 
135  // Check if sql index pos is valid
136  if (int32(result->GetFieldCount() - 1) < sql->sqlIndexPos)
137  {
138  TC_LOG_ERROR("server.loading", "Invalid index pos for dbc:'%s'", sql->sqlTableName.c_str());
139  return false;
140  }
141  }
142  }
143 
144  char* sqlDataTable = NULL;
145  fieldCount = dbc.GetCols();
146 
147  dataTable = reinterpret_cast<T*>(dbc.AutoProduceData(fmt, nCount, indexTable.asChar,
148  sqlRecordCount, sqlHighestIndex, sqlDataTable));
149 
150  stringPoolList.push_back(dbc.AutoProduceStrings(fmt, reinterpret_cast<char*>(dataTable)));
151 
152  // Insert sql data into arrays
153  if (result)
154  {
155  if (indexTable.asT)
156  {
157  uint32 offset = 0;
158  uint32 rowIndex = dbc.GetNumRows();
159  do
160  {
161  if (!fields)
162  fields = result->Fetch();
163 
164  if (sql->indexPos >= 0)
165  {
166  uint32 id = fields[sql->sqlIndexPos].GetUInt32();
167  if (indexTable.asT[id])
168  {
169  TC_LOG_ERROR("server.loading", "Index %d already exists in dbc:'%s'", id, sql->sqlTableName.c_str());
170  return false;
171  }
172 
173  indexTable.asT[id] = reinterpret_cast<T*>(&sqlDataTable[offset]);
174  }
175  else
176  indexTable.asT[rowIndex]= reinterpret_cast<T*>(&sqlDataTable[offset]);
177 
178  uint32 columnNumber = 0;
179  uint32 sqlColumnNumber = 0;
180 
181  for (; columnNumber < sql->formatString->size(); ++columnNumber)
182  {
183  if ((*sql->formatString)[columnNumber] == FT_SQL_ABSENT)
184  {
185  switch (fmt[columnNumber])
186  {
187  case FT_FLOAT:
188  *reinterpret_cast<float*>(&sqlDataTable[offset]) = 0.0f;
189  offset += 4;
190  break;
191  case FT_IND:
192  case FT_INT:
193  *reinterpret_cast<uint32*>(&sqlDataTable[offset]) = uint32(0);
194  offset += 4;
195  break;
196  case FT_BYTE:
197  *reinterpret_cast<uint8*>(&sqlDataTable[offset]) = uint8(0);
198  offset += 1;
199  break;
200  case FT_LONG:
201  *reinterpret_cast<uint64*>(&sqlDataTable[offset]) = uint64(0);
202  offset += 8;
203  break;
204  case FT_STRING:
205  // Beginning of the pool - empty string
206  *reinterpret_cast<char**>(&sqlDataTable[offset]) = stringPoolList.back();
207  offset += sizeof(char*);
208  break;
209  }
210  }
211  else if ((*sql->formatString)[columnNumber] == FT_SQL_PRESENT)
212  {
213  bool validSqlColumn = true;
214  switch (fmt[columnNumber])
215  {
216  case FT_FLOAT:
217  *reinterpret_cast<float*>(&sqlDataTable[offset]) = fields[sqlColumnNumber].GetFloat();
218  offset += 4;
219  break;
220  case FT_IND:
221  case FT_INT:
222  *reinterpret_cast<uint32*>(&sqlDataTable[offset]) = fields[sqlColumnNumber].GetUInt32();
223  offset += 4;
224  break;
225  case FT_BYTE:
226  *reinterpret_cast<uint8*>(&sqlDataTable[offset]) = fields[sqlColumnNumber].GetUInt8();
227  offset += 1;
228  break;
229  case FT_LONG:
230  *reinterpret_cast<uint64*>(&sqlDataTable[offset]) = fields[sqlColumnNumber].GetUInt64();
231  offset += 8;
232  break;
233  case FT_STRING:
234  TC_LOG_ERROR("server.loading", "Unsupported data type in table '%s' at char %d", sql->sqlTableName.c_str(), columnNumber);
235  return false;
236  case FT_SORT:
237  break;
238  default:
239  validSqlColumn = false;
240  break;
241  }
242  if (validSqlColumn && (columnNumber != (sql->formatString->size()-1)))
243  sqlColumnNumber++;
244  }
245  else
246  {
247  TC_LOG_ERROR("server.loading", "Incorrect sql format string '%s' at char %d", sql->sqlTableName.c_str(), columnNumber);
248  return false;
249  }
250  }
251 
252  if (sqlColumnNumber != (result->GetFieldCount() - 1))
253  {
254  TC_LOG_ERROR("server.loading", "SQL and DBC format strings are not matching for table: '%s'", sql->sqlTableName.c_str());
255  return false;
256  }
257 
258  fields = NULL;
259  ++rowIndex;
260  } while (result->NextRow());
261  }
262  }
263 
264  // error in dbc file at loading if NULL
265  return indexTable.asT != NULL;
266  }
267 
268  bool LoadStringsFrom(char const* fn)
269  {
270  // DBC must be already loaded using Load
271  if (!indexTable.asT)
272  return false;
273 
274  DBCFileLoader dbc;
275  // Check if load was successful, only then continue
276  if (!dbc.Load(fn, fmt))
277  return false;
278 
279  stringPoolList.push_back(dbc.AutoProduceStrings(fmt, reinterpret_cast<char*>(dataTable)));
280 
281  return true;
282  }
283 
284  void Clear()
285  {
286  if (!indexTable.asT)
287  return;
288 
289  delete[] reinterpret_cast<char*>(indexTable.asT);
290  indexTable.asT = NULL;
291  delete[] reinterpret_cast<char*>(dataTable);
292  dataTable = NULL;
293 
294  while (!stringPoolList.empty())
295  {
296  delete[] stringPoolList.front();
297  stringPoolList.pop_front();
298  }
299 
300  nCount = 0;
301  }
302 
303  iterator begin() { return iterator(indexTable.asT, nCount); }
304  iterator end() { return iterator(indexTable.asT, nCount, nCount); }
305 
306  private:
307  char const* fmt;
310 
311  union
312  {
313  T** asT;
314  char** asChar;
315  }
316  indexTable;
317 
319  StringPoolList stringPoolList;
320 
321  DBCStorage(DBCStorage const& right) = delete;
322  DBCStorage& operator=(DBCStorage const& right) = delete;
323 };
324 
325 #endif
Definition: Define.h:163
std::string const * indexName
Definition: DBCStore.h:33
int32 sqlIndexPos
Definition: DBCStore.h:36
uint32 fieldCount
Definition: DBCStore.h:309
StringPoolList stringPoolList
Definition: DBCStore.h:319
Definition: Define.h:161
std::list< char * > StringPoolList
Definition: DBCStore.h:76
Definition: DBCStore.h:74
Class used to access individual fields of database query result.
Definition: Field.h:56
iterator begin()
Definition: DBCStore.h:303
Definition: Define.h:160
DBCStorage & operator=(DBCStorage const &right)=delete
void Clear()
Definition: DBCStore.h:284
Definition: DBCStore.h:30
std::string const * formatString
Definition: DBCStore.h:32
char const * fmt
Definition: DBCStore.h:307
arena_t NULL
Definition: jemalloc_internal.h:624
WorldDatabaseWorkerPool WorldDatabase
Accessor to the world database.
Definition: DatabaseEnv.cpp:20
char ** asChar
Definition: DBCStore.h:314
uint64_t uint64
Definition: g3dmath.h:170
char * query(struct soap *soap)
Definition: httpget.cpp:244
char const * GetFormat() const
Definition: DBCStore.h:102
bool LoadStringsFrom(char const *fn)
Definition: DBCStore.h:268
iterator end()
Definition: DBCStore.h:304
~DBCStorage()
Definition: DBCStore.h:87
bool Load(const char *filename, const char *fmt)
Definition: DBCFileLoader.cpp:28
SqlDbc(std::string const *_filename, std::string const *_format, std::string const *_idname, char const *fmt)
Definition: DBCStore.h:37
Definition: DBCFileLoader.h:26
Definition: DBStorageIterator.h:25
Definition: Define.h:167
int32 indexPos
Definition: DBCStore.h:35
std::string sqlTableName
Definition: DBCStore.h:34
uint32 GetFieldCount() const
Definition: DBCStore.h:103
char * AutoProduceStrings(const char *fmt, char *dataTable)
Definition: DBCFileLoader.cpp:272
uint32 GetNumRows() const
Get begin iterator over records.
Definition: DBCFileLoader.h:84
Definition: Define.h:165
int32_t int32
Definition: Define.h:146
uint32_t uint32
Definition: Define.h:150
uint64_t uint64
Definition: Define.h:149
std::shared_ptr< ResultSet > QueryResult
Definition: QueryResult.h:61
T ** asT
Definition: DBCStore.h:313
T const * AssertEntry(uint32 id) const
Definition: DBCStore.h:94
SqlDbc & operator=(SqlDbc const &right)=delete
bool Load(char const *fn, SqlDbc *sql)
Definition: DBCStore.h:105
DBStorageIterator< T > iterator
Definition: DBCStore.h:79
char * AutoProduceData(const char *fmt, uint32 &count, char **&indexTable, uint32 sqlRecordCount, uint32 sqlHighestIndex, char *&sqlDataTable)
Definition: DBCFileLoader.cpp:173
uint32 GetNumRows() const
Definition: DBCStore.h:101
Definition: Define.h:162
T * dataTable
Definition: DBCStore.h:318
uint8_t uint8
Definition: g3dmath.h:164
uint32 GetCols() const
Definition: DBCFileLoader.h:86
static uint32 GetFormatRecordSize(const char *format, int32 *index_pos=NULL)
Definition: DBCFileLoader.cpp:128
DBCStorage(char const *f)
Definition: DBCStore.h:81
QueryResult Query(const char *sql, T *connection=nullptr)
Definition: DatabaseWorkerPool.cpp:113
uint32 GetUInt32() const
Definition: Field.h:146
int32_t int32
Definition: g3dmath.h:167
Definition: Define.h:158
uint8_t uint8
Definition: Define.h:152
#define ASSERT
Definition: Errors.h:55
T const * LookupEntry(uint32 id) const
Definition: DBCStore.h:89
Definition: format.h:285
union DBCStorage::@339 indexTable
Definition: Define.h:164
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:207
uint32_t uint32
Definition: g3dmath.h:168
G3D::int16 x
Definition: Vector2int16.h:37
Definition: Define.h:166
uint32 nCount
Definition: DBCStore.h:308