aboutsummaryrefslogtreecommitdiff
path: root/src/server/shared/DataStores
diff options
context:
space:
mode:
authorariel- <ariel-@users.noreply.github.com>2017-06-19 23:20:06 -0300
committerariel- <ariel-@users.noreply.github.com>2017-06-19 23:20:06 -0300
commit85a7d5ce9ac68b30da2277cc91d4b70358f1880d (patch)
treedf3d2084ee2e35008903c03178039b9c986e2d08 /src/server/shared/DataStores
parent052fc24315ace866ea1cf610e85df119b68100c9 (diff)
Core: ported headers cleanup from master branch
Diffstat (limited to 'src/server/shared/DataStores')
-rw-r--r--src/server/shared/DataStores/DBCDatabaseLoader.cpp193
-rw-r--r--src/server/shared/DataStores/DBCDatabaseLoader.h43
-rw-r--r--src/server/shared/DataStores/DBCFileLoader.cpp322
-rw-r--r--src/server/shared/DataStores/DBCFileLoader.h113
-rw-r--r--src/server/shared/DataStores/DBCStorageIterator.h69
-rw-r--r--src/server/shared/DataStores/DBCStore.cpp76
-rw-r--r--src/server/shared/DataStores/DBCStore.h306
7 files changed, 431 insertions, 691 deletions
diff --git a/src/server/shared/DataStores/DBCDatabaseLoader.cpp b/src/server/shared/DataStores/DBCDatabaseLoader.cpp
new file mode 100644
index 00000000000..3ef3e8f64c0
--- /dev/null
+++ b/src/server/shared/DataStores/DBCDatabaseLoader.cpp
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "DBCDatabaseLoader.h"
+#include "Common.h"
+#include "DatabaseEnv.h"
+#include "Errors.h"
+#include "Log.h"
+#include <sstream>
+
+DBCDatabaseLoader::DBCDatabaseLoader(std::string const& storageName, std::string const& dbFormatString, std::string const& primaryKey, char const* dbcFormatString)
+ : _formatString(dbFormatString), _indexName(primaryKey), _sqlTableName(storageName), _dbcFormat(dbcFormatString), _sqlIndexPos(0), _recordSize(0)
+{
+ // Convert dbc file name to sql table name
+ std::transform(_sqlTableName.begin(), _sqlTableName.end(), _sqlTableName.begin(), ::tolower);
+ for (char& c : _sqlTableName)
+ if (c == '.')
+ c = '_';
+
+ // Get sql index position
+ int32 indexPos = -1;
+ _recordSize = DBCFileLoader::GetFormatRecordSize(_dbcFormat, &indexPos);
+ ASSERT(indexPos >= 0);
+ ASSERT(_recordSize);
+
+ uint32 uindexPos = uint32(indexPos);
+ for (uint32 x = 0; x < _formatString.size(); ++x)
+ {
+ // Count only fields present in sql
+ if (_formatString[x] == FT_SQL_PRESENT)
+ {
+ if (x == uindexPos)
+ break;
+ ++_sqlIndexPos;
+ }
+ }
+}
+
+static char const* nullStr = "";
+
+char* DBCDatabaseLoader::Load(uint32& records, char**& indexTable)
+{
+ std::ostringstream queryBuilder;
+ queryBuilder << "SELECT * FROM " << _sqlTableName
+ << " ORDER BY " << _indexName << " DESC;";
+
+ // no error if empty set
+ QueryResult result = WorldDatabase.Query(queryBuilder.str().c_str());
+ if (!result)
+ return nullptr;
+
+ // Check if sql index pos is valid
+ if (int32(result->GetFieldCount() - 1) < _sqlIndexPos)
+ {
+ ASSERT(false, "Invalid index pos for dbc:'%s'", _sqlTableName.c_str());
+ return nullptr;
+ }
+
+ // Resize index table
+ // database query *MUST* contain ORDER BY `index_field` DESC clause
+ uint32 indexTableSize = std::max(records, (*result)[_sqlIndexPos].GetUInt32() + 1);
+ if (indexTableSize > records)
+ {
+ char** tmpIdxTable = new char*[indexTableSize];
+ memset(tmpIdxTable, 0, indexTableSize * sizeof(char*));
+ memcpy(tmpIdxTable, indexTable, records * sizeof(char*));
+ delete[] indexTable;
+ indexTable = tmpIdxTable;
+ }
+
+ std::unique_ptr<char[]> dataTable = Trinity::make_unique<char[]>(result->GetRowCount() * _recordSize);
+ std::unique_ptr<uint32[]> newIndexes = Trinity::make_unique<uint32[]>(result->GetRowCount());
+ uint32 newRecords = 0;
+
+ // Insert sql data into the data array
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 offset = 0;
+
+ uint32 indexValue = fields[_sqlIndexPos].GetUInt32();
+
+ char* dataValue = indexTable[indexValue];
+ if (!dataValue)
+ {
+ newIndexes[newRecords] = indexValue;
+ dataValue = &dataTable[newRecords++ * _recordSize];
+ }
+ else
+ {
+ // Attempt to overwrite existing data
+ ASSERT(false, "Index %d already exists in dbc:'%s'", indexValue, _sqlTableName.c_str());
+ return nullptr;
+ }
+
+ uint32 columnNumber = 0;
+ uint32 sqlColumnNumber = 0;
+
+ for (; columnNumber < _formatString.size(); ++columnNumber)
+ {
+ if (_formatString[columnNumber] == FT_SQL_ABSENT)
+ {
+ switch (_dbcFormat[columnNumber])
+ {
+ case FT_FLOAT:
+ *reinterpret_cast<float*>(&dataValue[offset]) = 0.0f;
+ offset += 4;
+ break;
+ case FT_IND:
+ case FT_INT:
+ *reinterpret_cast<uint32*>(&dataValue[offset]) = uint32(0);
+ offset += 4;
+ break;
+ case FT_BYTE:
+ *reinterpret_cast<uint8*>(&dataValue[offset]) = uint8(0);
+ offset += 1;
+ break;
+ case FT_STRING:
+ *reinterpret_cast<char**>(&dataValue[offset]) = const_cast<char*>(nullStr);
+ offset += sizeof(char*);
+ break;
+ }
+ }
+ else if (_formatString[columnNumber] == FT_SQL_PRESENT)
+ {
+ bool validSqlColumn = true;
+ switch (_dbcFormat[columnNumber])
+ {
+ case FT_FLOAT:
+ *reinterpret_cast<float*>(&dataValue[offset]) = fields[sqlColumnNumber].GetFloat();
+ offset += 4;
+ break;
+ case FT_IND:
+ case FT_INT:
+ *reinterpret_cast<uint32*>(&dataValue[offset]) = fields[sqlColumnNumber].GetUInt32();
+ offset += 4;
+ break;
+ case FT_BYTE:
+ *reinterpret_cast<uint8*>(&dataValue[offset]) = fields[sqlColumnNumber].GetUInt8();
+ offset += 1;
+ break;
+ case FT_STRING:
+ ASSERT(false, "Unsupported data type in table '%s' at char %d", _sqlTableName.c_str(), columnNumber);
+ return nullptr;
+ case FT_SORT:
+ break;
+ default:
+ validSqlColumn = false;
+ break;
+ }
+ if (validSqlColumn && (columnNumber != (_formatString.size() - 1)))
+ sqlColumnNumber++;
+ }
+ else
+ {
+ ASSERT(false, "Incorrect sql format string '%s' at char %d", _sqlTableName.c_str(), columnNumber);
+ break;
+ }
+ }
+
+ if (sqlColumnNumber != (result->GetFieldCount() - 1))
+ {
+ ASSERT(false, "SQL and DBC format strings are not matching for table: '%s'", _sqlTableName.c_str());
+ return nullptr;
+ }
+
+ ASSERT(offset == _recordSize);
+ } while (result->NextRow());
+
+ ASSERT(newRecords == result->GetRowCount());
+
+ // insert new records to index table
+ for (uint32 i = 0; i < newRecords; ++i)
+ indexTable[newIndexes[i]] = &dataTable[i * _recordSize];
+
+ records = indexTableSize;
+
+ return dataTable.release();
+}
diff --git a/src/server/shared/DataStores/DBCDatabaseLoader.h b/src/server/shared/DataStores/DBCDatabaseLoader.h
new file mode 100644
index 00000000000..153a0eb4dcb
--- /dev/null
+++ b/src/server/shared/DataStores/DBCDatabaseLoader.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DBCDatabaseLoader_h__
+#define DBCDatabaseLoader_h__
+
+#include "DBCFileLoader.h"
+#include <string>
+#include <vector>
+
+struct TC_SHARED_API DBCDatabaseLoader
+{
+ DBCDatabaseLoader(std::string const& storageName, std::string const& dbFormatString, std::string const& primaryKey, char const* dbcFormatString);
+
+ char* Load(uint32& records, char**& indexTable);
+
+private:
+ std::string const& _formatString;
+ std::string const& _indexName;
+ std::string _sqlTableName;
+ char const* _dbcFormat;
+ int32 _sqlIndexPos;
+ uint32 _recordSize;
+
+ DBCDatabaseLoader(DBCDatabaseLoader const& right) = delete;
+ DBCDatabaseLoader& operator=(DBCDatabaseLoader const& right) = delete;
+};
+
+#endif // DBCDatabaseLoader_h__
diff --git a/src/server/shared/DataStores/DBCFileLoader.cpp b/src/server/shared/DataStores/DBCFileLoader.cpp
deleted file mode 100644
index 8c92260e62d..00000000000
--- a/src/server/shared/DataStores/DBCFileLoader.cpp
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "DBCFileLoader.h"
-#include "Errors.h"
-
-DBCFileLoader::DBCFileLoader() : recordSize(0), recordCount(0), fieldCount(0), stringSize(0), fieldsOffset(NULL), data(NULL), stringTable(NULL) { }
-
-bool DBCFileLoader::Load(const char* filename, const char* fmt)
-{
- uint32 header;
- if (data)
- {
- delete [] data;
- data = NULL;
- }
-
- FILE* f = fopen(filename, "rb");
- if (!f)
- return false;
-
- if (fread(&header, 4, 1, f) != 1) // Number of records
- {
- fclose(f);
- return false;
- }
-
-
- EndianConvert(header);
-
- if (header != 0x43424457) //'WDBC'
- {
- fclose(f);
- return false;
- }
-
- if (fread(&recordCount, 4, 1, f) != 1) // Number of records
- {
- fclose(f);
- return false;
- }
-
- EndianConvert(recordCount);
-
- if (fread(&fieldCount, 4, 1, f) != 1) // Number of fields
- {
- fclose(f);
- return false;
- }
-
- EndianConvert(fieldCount);
-
- if (fread(&recordSize, 4, 1, f) != 1) // Size of a record
- {
- fclose(f);
- return false;
- }
-
- EndianConvert(recordSize);
-
- if (fread(&stringSize, 4, 1, f) != 1) // String size
- {
- fclose(f);
- return false;
- }
-
- EndianConvert(stringSize);
-
- fieldsOffset = new uint32[fieldCount];
- fieldsOffset[0] = 0;
- for (uint32 i = 1; i < fieldCount; ++i)
- {
- fieldsOffset[i] = fieldsOffset[i - 1];
- if (fmt[i - 1] == 'b' || fmt[i - 1] == 'X') // byte fields
- fieldsOffset[i] += sizeof(uint8);
- else // 4 byte fields (int32/float/strings)
- fieldsOffset[i] += sizeof(uint32);
- }
-
- data = new unsigned char[recordSize * recordCount + stringSize];
- stringTable = data + recordSize*recordCount;
-
- if (fread(data, recordSize * recordCount + stringSize, 1, f) != 1)
- {
- fclose(f);
- return false;
- }
-
- fclose(f);
-
- return true;
-}
-
-DBCFileLoader::~DBCFileLoader()
-{
- delete[] data;
-
- delete[] fieldsOffset;
-}
-
-DBCFileLoader::Record DBCFileLoader::getRecord(size_t id)
-{
- assert(data);
- return Record(*this, data + id * recordSize);
-}
-
-uint32 DBCFileLoader::GetFormatRecordSize(const char* format, int32* index_pos)
-{
- uint32 recordsize = 0;
- int32 i = -1;
- for (uint32 x = 0; format[x]; ++x)
- {
- switch (format[x])
- {
- case FT_FLOAT:
- recordsize += sizeof(float);
- break;
- case FT_INT:
- recordsize += sizeof(uint32);
- break;
- case FT_STRING:
- recordsize += sizeof(char*);
- break;
- case FT_SORT:
- i = x;
- break;
- case FT_IND:
- i = x;
- recordsize += sizeof(uint32);
- break;
- case FT_BYTE:
- recordsize += sizeof(uint8);
- break;
- case FT_NA:
- case FT_NA_BYTE:
- break;
- case FT_LOGIC:
- ASSERT(false && "Attempted to load DBC files that do not have field types that match what is in the core. Check DBCfmt.h or your DBC files.");
- break;
- default:
- ASSERT(false && "Unknown field format character in DBCfmt.h");
- break;
- }
- }
-
- if (index_pos)
- *index_pos = i;
-
- return recordsize;
-}
-
-char* DBCFileLoader::AutoProduceData(const char* format, uint32& records, char**& indexTable, uint32 sqlRecordCount, uint32 sqlHighestIndex, char*& sqlDataTable)
-{
- /*
- format STRING, NA, FLOAT, NA, INT <=>
- struct{
- char* field0,
- float field1,
- int field2
- }entry;
-
- this func will generate entry[rows] data;
- */
-
- typedef char* ptr;
- if (strlen(format) != fieldCount)
- return NULL;
-
- //get struct size and index pos
- int32 i;
- uint32 recordsize = GetFormatRecordSize(format, &i);
-
- if (i >= 0)
- {
- uint32 maxi = 0;
- //find max index
- for (uint32 y = 0; y < recordCount; ++y)
- {
- uint32 ind = getRecord(y).getUInt(i);
- if (ind > maxi)
- maxi = ind;
- }
-
- // If higher index avalible from sql - use it instead of dbcs
- if (sqlHighestIndex > maxi)
- maxi = sqlHighestIndex;
-
- ++maxi;
- records = maxi;
- indexTable = new ptr[maxi];
- memset(indexTable, 0, maxi * sizeof(ptr));
- }
- else
- {
- records = recordCount + sqlRecordCount;
- indexTable = new ptr[recordCount + sqlRecordCount];
- }
-
- char* dataTable = new char[(recordCount + sqlRecordCount) * recordsize];
-
- uint32 offset = 0;
-
- for (uint32 y = 0; y < recordCount; ++y)
- {
- if (i >= 0)
- indexTable[getRecord(y).getUInt(i)] = &dataTable[offset];
- else
- indexTable[y] = &dataTable[offset];
-
- for (uint32 x=0; x < fieldCount; ++x)
- {
- switch (format[x])
- {
- case FT_FLOAT:
- *((float*)(&dataTable[offset])) = getRecord(y).getFloat(x);
- offset += sizeof(float);
- break;
- case FT_IND:
- case FT_INT:
- *((uint32*)(&dataTable[offset])) = getRecord(y).getUInt(x);
- offset += sizeof(uint32);
- break;
- case FT_BYTE:
- *((uint8*)(&dataTable[offset])) = getRecord(y).getUInt8(x);
- offset += sizeof(uint8);
- break;
- case FT_STRING:
- *((char**)(&dataTable[offset])) = NULL; // will replace non-empty or "" strings in AutoProduceStrings
- offset += sizeof(char*);
- break;
- case FT_LOGIC:
- ASSERT(false && "Attempted to load DBC files that do not have field types that match what is in the core. Check DBCfmt.h or your DBC files.");
- break;
- case FT_NA:
- case FT_NA_BYTE:
- case FT_SORT:
- break;
- default:
- ASSERT(false && "Unknown field format character in DBCfmt.h");
- break;
- }
- }
- }
-
- sqlDataTable = dataTable + offset;
-
- return dataTable;
-}
-
-char* DBCFileLoader::AutoProduceStrings(const char* format, char* dataTable)
-{
- if (strlen(format) != fieldCount)
- return NULL;
-
- char* stringPool = new char[stringSize];
- memcpy(stringPool, stringTable, stringSize);
-
- uint32 offset = 0;
-
- for (uint32 y = 0; y < recordCount; ++y)
- {
- for (uint32 x = 0; x < fieldCount; ++x)
- {
- switch (format[x])
- {
- case FT_FLOAT:
- offset += sizeof(float);
- break;
- case FT_IND:
- case FT_INT:
- offset += sizeof(uint32);
- break;
- case FT_BYTE:
- offset += sizeof(uint8);
- break;
- case FT_STRING:
- {
- // fill only not filled entries
- char** slot = (char**)(&dataTable[offset]);
- if (!*slot || !**slot)
- {
- const char * st = getRecord(y).getString(x);
- *slot=stringPool+(st-(const char*)stringTable);
- }
- offset += sizeof(char*);
- break;
- }
- case FT_LOGIC:
- ASSERT(false && "Attempted to load DBC files that does not have field types that match what is in the core. Check DBCfmt.h or your DBC files.");
- break;
- case FT_NA:
- case FT_NA_BYTE:
- case FT_SORT:
- break;
- default:
- ASSERT(false && "Unknown field format character in DBCfmt.h");
- break;
- }
- }
- }
-
- return stringPool;
-}
diff --git a/src/server/shared/DataStores/DBCFileLoader.h b/src/server/shared/DataStores/DBCFileLoader.h
deleted file mode 100644
index 1c005a9e670..00000000000
--- a/src/server/shared/DataStores/DBCFileLoader.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef DBC_FILE_LOADER_H
-#define DBC_FILE_LOADER_H
-#include "Define.h"
-#include "Utilities/ByteConverter.h"
-#include <cassert>
-
-enum DbcFieldFormat
-{
- FT_NA='x', //not used or unknown, 4 byte size
- FT_NA_BYTE='X', //not used or unknown, byte
- FT_STRING='s', //char*
- FT_FLOAT='f', //float
- FT_INT='i', //uint32
- FT_BYTE='b', //uint8
- FT_SORT='d', //sorted by this field, field is not included
- FT_IND='n', //the same, but parsed to data
- FT_LOGIC='l', //Logical (boolean)
- FT_SQL_PRESENT='p', //Used in sql format to mark column present in sql dbc
- FT_SQL_ABSENT='a' //Used in sql format to mark column absent in sql dbc
-};
-
-class TC_SHARED_API DBCFileLoader
-{
- public:
- DBCFileLoader();
- ~DBCFileLoader();
-
- bool Load(const char *filename, const char *fmt);
-
- class Record
- {
- public:
- float getFloat(size_t field) const
- {
- assert(field < file.fieldCount);
- float val = *reinterpret_cast<float*>(offset+file.GetOffset(field));
- EndianConvert(val);
- return val;
- }
- uint32 getUInt(size_t field) const
- {
- assert(field < file.fieldCount);
- uint32 val = *reinterpret_cast<uint32*>(offset+file.GetOffset(field));
- EndianConvert(val);
- return val;
- }
- uint8 getUInt8(size_t field) const
- {
- assert(field < file.fieldCount);
- return *reinterpret_cast<uint8*>(offset+file.GetOffset(field));
- }
-
- const char *getString(size_t field) const
- {
- assert(field < file.fieldCount);
- size_t stringOffset = getUInt(field);
- assert(stringOffset < file.stringSize);
- return reinterpret_cast<char*>(file.stringTable + stringOffset);
- }
-
- private:
- Record(DBCFileLoader &file_, unsigned char *offset_): offset(offset_), file(file_) { }
- unsigned char *offset;
- DBCFileLoader &file;
-
- friend class DBCFileLoader;
-
- };
-
- // Get record by id
- Record getRecord(size_t id);
- /// Get begin iterator over records
-
- uint32 GetNumRows() const { return recordCount; }
- uint32 GetRowSize() const { return recordSize; }
- uint32 GetCols() const { return fieldCount; }
- uint32 GetOffset(size_t id) const { return (fieldsOffset != NULL && id < fieldCount) ? fieldsOffset[id] : 0; }
- bool IsLoaded() const { return data != NULL; }
- char* AutoProduceData(const char* fmt, uint32& count, char**& indexTable, uint32 sqlRecordCount, uint32 sqlHighestIndex, char *& sqlDataTable);
- char* AutoProduceStrings(const char* fmt, char* dataTable);
- static uint32 GetFormatRecordSize(const char * format, int32 * index_pos = NULL);
- private:
-
- uint32 recordSize;
- uint32 recordCount;
- uint32 fieldCount;
- uint32 stringSize;
- uint32 *fieldsOffset;
- unsigned char *data;
- unsigned char *stringTable;
-
- DBCFileLoader(DBCFileLoader const& right) = delete;
- DBCFileLoader& operator=(DBCFileLoader const& right) = delete;
-};
-#endif
diff --git a/src/server/shared/DataStores/DBCStorageIterator.h b/src/server/shared/DataStores/DBCStorageIterator.h
new file mode 100644
index 00000000000..be1e58db967
--- /dev/null
+++ b/src/server/shared/DataStores/DBCStorageIterator.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DBCStorageIterator_h__
+#define DBCStorageIterator_h__
+
+#include "Define.h"
+#include <iterator>
+
+template <class T>
+class DBCStorageIterator : public std::iterator<std::forward_iterator_tag, T>
+{
+ public:
+ DBCStorageIterator() : _index(nullptr), _pos(0), _end(0) { }
+ DBCStorageIterator(T** index, uint32 size, uint32 pos = 0) : _index(index), _pos(pos), _end(size)
+ {
+ if (_pos < _end)
+ {
+ while (_pos < _end && !_index[_pos])
+ ++_pos;
+ }
+ }
+
+ T const* operator->() { return _index[_pos]; }
+ T const* operator*() { return _index[_pos]; }
+
+ bool operator==(DBCStorageIterator const& right) const { /*ASSERT(_index == right._index, "Iterator belongs to a different container")*/ return _pos == right._pos; }
+ bool operator!=(DBCStorageIterator const& right) const { return !(*this == right); }
+
+ DBCStorageIterator& operator++()
+ {
+ if (_pos < _end)
+ {
+ do
+ ++_pos;
+ while (_pos < _end && !_index[_pos]);
+ }
+
+ return *this;
+ }
+
+ DBCStorageIterator operator++(int)
+ {
+ DBCStorageIterator tmp = *this;
+ ++*this;
+ return tmp;
+ }
+
+ private:
+ T** _index;
+ uint32 _pos;
+ uint32 _end;
+};
+
+#endif // DBCStorageIterator_h__
diff --git a/src/server/shared/DataStores/DBCStore.cpp b/src/server/shared/DataStores/DBCStore.cpp
new file mode 100644
index 00000000000..30cae057f90
--- /dev/null
+++ b/src/server/shared/DataStores/DBCStore.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "DBCStore.h"
+#include "DBCDatabaseLoader.h"
+
+DBCStorageBase::DBCStorageBase(char const* fmt) : _fieldCount(0), _fileFormat(fmt), _dataTable(nullptr), _indexTableSize(0)
+{
+}
+
+DBCStorageBase::~DBCStorageBase()
+{
+ delete[] _dataTable;
+ delete[] _dataTableEx;
+ for (char* strings : _stringPool)
+ delete[] strings;
+}
+
+bool DBCStorageBase::Load(std::string const& path, char**& indexTable)
+{
+ indexTable = nullptr;
+
+ DBCFileLoader dbc;
+ // Check if load was sucessful, only then continue
+ if (!dbc.Load(path.c_str(), _fileFormat))
+ return false;
+
+ _fieldCount = dbc.GetCols();
+
+ // load raw non-string data
+ _dataTable = dbc.AutoProduceData(_fileFormat, _indexTableSize, indexTable);
+
+ // load strings from dbc data
+ if (char* stringBlock = dbc.AutoProduceStrings(_fileFormat, _dataTable))
+ _stringPool.push_back(stringBlock);
+
+ // error in dbc file at loading if NULL
+ return indexTable != nullptr;
+}
+
+bool DBCStorageBase::LoadStringsFrom(std::string const& path, char** indexTable)
+{
+ // DBC must be already loaded using Load
+ if (!indexTable)
+ return false;
+
+ DBCFileLoader dbc;
+ // Check if load was successful, only then continue
+ if (!dbc.Load(path.c_str(), _fileFormat))
+ return false;
+
+ // load strings from another locale dbc data
+ if (char* stringBlock = dbc.AutoProduceStrings(_fileFormat, _dataTable))
+ _stringPool.push_back(stringBlock);
+
+ return true;
+}
+
+void DBCStorageBase::LoadFromDB(std::string const& path, std::string const& dbFormat, std::string const& primaryKey, char**& indexTable)
+{
+ _dataTableEx = DBCDatabaseLoader(path, dbFormat, primaryKey, _fileFormat).Load(_indexTableSize, indexTable);
+}
diff --git a/src/server/shared/DataStores/DBCStore.h b/src/server/shared/DataStores/DBCStore.h
index b11bb0b74d4..e04f434cf89 100644
--- a/src/server/shared/DataStores/DBCStore.h
+++ b/src/server/shared/DataStores/DBCStore.h
@@ -19,289 +19,83 @@
#ifndef DBCSTORE_H
#define DBCSTORE_H
-#include "DBCFileLoader.h"
-#include "Logging/Log.h"
-#include "Field.h"
-#include "DatabaseWorkerPool.h"
-#include "Implementation/WorldDatabase.h"
-#include "DatabaseEnv.h"
+#include "Common.h"
+#include "DBCStorageIterator.h"
+#include <vector>
-struct SqlDbc
+ /// Interface class for common access
+class TC_SHARED_API DBCStorageBase
{
- std::string const* formatString;
- std::string const* indexName;
- std::string sqlTableName;
- int32 indexPos;
- int32 sqlIndexPos;
- SqlDbc(std::string const* _filename, std::string const* _format, std::string const* _idname, char const* fmt)
- : formatString(_format), indexName (_idname), sqlIndexPos(0)
- {
- // Convert dbc file name to sql table name
- sqlTableName = *_filename;
- for (uint32 i = 0; i< sqlTableName.size(); ++i)
- {
- if (isalpha(sqlTableName[i]))
- sqlTableName[i] = char(tolower(sqlTableName[i]));
- else if (sqlTableName[i] == '.')
- sqlTableName[i] = '_';
- }
-
- // Get sql index position
- DBCFileLoader::GetFormatRecordSize(fmt, &indexPos);
- if (indexPos >= 0)
- {
- uint32 uindexPos = uint32(indexPos);
- for (uint32 x = 0; x < formatString->size(); ++x)
- {
- // Count only fields present in sql
- if ((*formatString)[x] == FT_SQL_PRESENT)
- {
- if (x == uindexPos)
- break;
- ++sqlIndexPos;
- }
- }
- }
- }
-
-private:
- SqlDbc(SqlDbc const& right) = delete;
- SqlDbc& operator=(SqlDbc const& right) = delete;
+ public:
+ DBCStorageBase(char const* fmt);
+ virtual ~DBCStorageBase();
+
+ char const* GetFormat() const { return _fileFormat; }
+ uint32 GetFieldCount() const { return _fieldCount; }
+
+ virtual bool Load(std::string const& path) = 0;
+ virtual bool LoadStringsFrom(std::string const& path) = 0;
+ virtual void LoadFromDB(std::string const& path, std::string const& dbFormat, std::string const& primaryKey) = 0;
+
+ protected:
+ bool Load(std::string const& path, char**& indexTable);
+ bool LoadStringsFrom(std::string const& path, char** indexTable);
+ void LoadFromDB(std::string const& path, std::string const& dbFormat, std::string const& primaryKey, char**& indexTable);
+
+ uint32 _fieldCount;
+ char const* _fileFormat;
+ char* _dataTable;
+ char* _dataTableEx;
+ std::vector<char*> _stringPool;
+ uint32 _indexTableSize;
};
-template<class T>
-class DBCStorage
+template <class T>
+class DBCStorage : public DBCStorageBase
{
- typedef std::list<char*> StringPoolList;
public:
- explicit DBCStorage(char const* f)
- : fmt(f), nCount(0), fieldCount(0), dataTable(NULL)
- {
- indexTable.asT = NULL;
- }
+ typedef DBCStorageIterator<T> iterator;
- ~DBCStorage() { Clear(); }
-
- T const* LookupEntry(uint32 id) const
+ explicit DBCStorage(char const* fmt) : DBCStorageBase(fmt)
{
- return (id >= nCount) ? NULL : indexTable.asT[id];
+ _indexTable.AsT = nullptr;
}
- T const* AssertEntry(uint32 id) const
+ ~DBCStorage()
{
- T const* entry = LookupEntry(id);
- ASSERT(entry);
- return entry;
+ delete[] reinterpret_cast<char*>(_indexTable.AsT);
}
- uint32 GetNumRows() const { return nCount; }
- char const* GetFormat() const { return fmt; }
- uint32 GetFieldCount() const { return fieldCount; }
-
- bool Load(char const* fn, SqlDbc* sql)
- {
- DBCFileLoader dbc;
- // Check if load was sucessful, only then continue
- if (!dbc.Load(fn, fmt))
- return false;
-
- uint32 sqlRecordCount = 0;
- uint32 sqlHighestIndex = 0;
- Field* fields = NULL;
- QueryResult result = QueryResult(NULL);
- // Load data from sql
- if (sql)
- {
- std::string query = "SELECT * FROM " + sql->sqlTableName;
- if (sql->indexPos >= 0)
- query +=" ORDER BY " + *sql->indexName + " DESC";
- query += ';';
-
-
- result = WorldDatabase.Query(query.c_str());
- if (result)
- {
- sqlRecordCount = uint32(result->GetRowCount());
- if (sql->indexPos >= 0)
- {
- fields = result->Fetch();
- sqlHighestIndex = fields[sql->sqlIndexPos].GetUInt32();
- }
-
- // Check if sql index pos is valid
- if (int32(result->GetFieldCount() - 1) < sql->sqlIndexPos)
- {
- TC_LOG_ERROR("server.loading", "Invalid index pos for dbc:'%s'", sql->sqlTableName.c_str());
- return false;
- }
- }
- }
-
- char* sqlDataTable = NULL;
- fieldCount = dbc.GetCols();
-
- dataTable = reinterpret_cast<T*>(dbc.AutoProduceData(fmt, nCount, indexTable.asChar,
- sqlRecordCount, sqlHighestIndex, sqlDataTable));
+ T const* LookupEntry(uint32 id) const { return (id >= _indexTableSize) ? nullptr : _indexTable.AsT[id]; }
+ T const* AssertEntry(uint32 id) const { return ASSERT_NOTNULL(LookupEntry(id)); }
- stringPoolList.push_back(dbc.AutoProduceStrings(fmt, reinterpret_cast<char*>(dataTable)));
+ uint32 GetNumRows() const { return _indexTableSize; }
- // Insert sql data into arrays
- if (result)
- {
- if (indexTable.asT)
- {
- uint32 offset = 0;
- uint32 rowIndex = dbc.GetNumRows();
- do
- {
- if (!fields)
- fields = result->Fetch();
-
- if (sql->indexPos >= 0)
- {
- uint32 id = fields[sql->sqlIndexPos].GetUInt32();
- if (indexTable.asT[id])
- {
- TC_LOG_ERROR("server.loading", "Index %d already exists in dbc:'%s'", id, sql->sqlTableName.c_str());
- return false;
- }
-
- indexTable.asT[id] = reinterpret_cast<T*>(&sqlDataTable[offset]);
- }
- else
- indexTable.asT[rowIndex]= reinterpret_cast<T*>(&sqlDataTable[offset]);
-
- uint32 columnNumber = 0;
- uint32 sqlColumnNumber = 0;
-
- for (; columnNumber < sql->formatString->size(); ++columnNumber)
- {
- if ((*sql->formatString)[columnNumber] == FT_SQL_ABSENT)
- {
- switch (fmt[columnNumber])
- {
- case FT_FLOAT:
- *reinterpret_cast<float*>(&sqlDataTable[offset]) = 0.0f;
- offset += 4;
- break;
- case FT_IND:
- case FT_INT:
- *reinterpret_cast<uint32*>(&sqlDataTable[offset]) = uint32(0);
- offset += 4;
- break;
- case FT_BYTE:
- *reinterpret_cast<uint8*>(&sqlDataTable[offset]) = uint8(0);
- offset += 1;
- break;
- case FT_STRING:
- // Beginning of the pool - empty string
- *reinterpret_cast<char**>(&sqlDataTable[offset]) = stringPoolList.back();
- offset += sizeof(char*);
- break;
- }
- }
- else if ((*sql->formatString)[columnNumber] == FT_SQL_PRESENT)
- {
- bool validSqlColumn = true;
- switch (fmt[columnNumber])
- {
- case FT_FLOAT:
- *reinterpret_cast<float*>(&sqlDataTable[offset]) = fields[sqlColumnNumber].GetFloat();
- offset += 4;
- break;
- case FT_IND:
- case FT_INT:
- *reinterpret_cast<uint32*>(&sqlDataTable[offset]) = fields[sqlColumnNumber].GetUInt32();
- offset += 4;
- break;
- case FT_BYTE:
- *reinterpret_cast<uint8*>(&sqlDataTable[offset]) = fields[sqlColumnNumber].GetUInt8();
- offset += 1;
- break;
- case FT_STRING:
- TC_LOG_ERROR("server.loading", "Unsupported data type in table '%s' at char %d", sql->sqlTableName.c_str(), columnNumber);
- return false;
- case FT_SORT:
- break;
- default:
- validSqlColumn = false;
- break;
- }
- if (validSqlColumn && (columnNumber != (sql->formatString->size()-1)))
- sqlColumnNumber++;
- }
- else
- {
- TC_LOG_ERROR("server.loading", "Incorrect sql format string '%s' at char %d", sql->sqlTableName.c_str(), columnNumber);
- return false;
- }
- }
-
- if (sqlColumnNumber != (result->GetFieldCount() - 1))
- {
- TC_LOG_ERROR("server.loading", "SQL and DBC format strings are not matching for table: '%s'", sql->sqlTableName.c_str());
- return false;
- }
-
- fields = NULL;
- ++rowIndex;
- } while (result->NextRow());
- }
- }
-
- // error in dbc file at loading if NULL
- return indexTable.asT != NULL;
+ bool Load(std::string const& path) override
+ {
+ return DBCStorageBase::Load(path, _indexTable.AsChar);
}
- bool LoadStringsFrom(char const* fn)
+ bool LoadStringsFrom(std::string const& path) override
{
- // DBC must be already loaded using Load
- if (!indexTable.asT)
- return false;
-
- DBCFileLoader dbc;
- // Check if load was successful, only then continue
- if (!dbc.Load(fn, fmt))
- return false;
-
- stringPoolList.push_back(dbc.AutoProduceStrings(fmt, reinterpret_cast<char*>(dataTable)));
-
- return true;
+ return DBCStorageBase::LoadStringsFrom(path, _indexTable.AsChar);
}
- void Clear()
+ void LoadFromDB(std::string const& path, std::string const& dbFormat, std::string const& primaryKey) override
{
- if (!indexTable.asT)
- return;
-
- delete[] reinterpret_cast<char*>(indexTable.asT);
- indexTable.asT = NULL;
- delete[] reinterpret_cast<char*>(dataTable);
- dataTable = NULL;
-
- while (!stringPoolList.empty())
- {
- delete[] stringPoolList.front();
- stringPoolList.pop_front();
- }
-
- nCount = 0;
+ DBCStorageBase::LoadFromDB(path, dbFormat, primaryKey, _indexTable.AsChar);
}
- private:
- char const* fmt;
- uint32 nCount;
- uint32 fieldCount;
+ iterator begin() { return iterator(_indexTable.AsT, _indexTableSize); }
+ iterator end() { return iterator(_indexTable.AsT, _indexTableSize, _indexTableSize); }
+ private:
union
{
- T** asT;
- char** asChar;
+ T** AsT;
+ char** AsChar;
}
- indexTable;
-
- T* dataTable;
- StringPoolList stringPoolList;
+ _indexTable;
DBCStorage(DBCStorage const& right) = delete;
DBCStorage& operator=(DBCStorage const& right) = delete;