TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
DB2DatabaseLoader Class Reference

#include <DB2StorageLoader.h>

Public Member Functions

 DB2DatabaseLoader (std::string const &storageName)
 
char * Load (const char *format, HotfixDatabaseStatements preparedStatement, uint32 &records, char **&indexTable, char *&stringHolders, std::list< char * > &stringPool)
 
void LoadStrings (const char *format, HotfixDatabaseStatements preparedStatement, uint32 locale, char **&indexTable, std::list< char * > &stringPool)
 

Static Public Member Functions

static char * AddString (char const **holder, std::string const &value)
 

Private Attributes

std::string _storageName
 

Constructor & Destructor Documentation

DB2DatabaseLoader::DB2DatabaseLoader ( std::string const storageName)
inlineexplicit
120 : _storageName(storageName) { }
std::string _storageName
Definition: DB2StorageLoader.h:127

Member Function Documentation

char * DB2DatabaseLoader::AddString ( char const **  holder,
std::string const value 
)
static
711 {
712  if (!value.empty())
713  {
714  std::size_t existingLength = strlen(*holder);
715  if (existingLength >= value.length())
716  {
717  // Reuse existing storage if there is enough space
718  char* str = const_cast<char*>(*holder);
719  memcpy(str, value.c_str(), value.length());
720  str[value.length()] = '\0';
721  return nullptr;
722  }
723 
724  char* str = new char[value.length() + 1];
725  memcpy(str, value.c_str(), value.length());
726  str[value.length()] = '\0';
727  *holder = str;
728  return str;
729  }
730 
731  return nullptr;
732 }
const FieldDescriptor value
Definition: descriptor.h:1522

+ Here is the caller graph for this function:

char * DB2DatabaseLoader::Load ( const char *  format,
HotfixDatabaseStatements  preparedStatement,
uint32 records,
char **&  indexTable,
char *&  stringHolders,
std::list< char * > &  stringPool 
)
485 {
486  // Even though this query is executed only once, prepared statement is used to send data from mysql server in binary format
488  if (!result)
489  return nullptr;
490 
491  uint32 const fieldCount = strlen(format);
492  if (fieldCount != result->GetFieldCount())
493  return nullptr;
494 
495  // get struct size and index pos
496  int32 indexField;
497  uint32 recordSize = DB2FileLoader::GetFormatRecordSize(format, &indexField);
498 
499  // we store flat holders pool as single memory block
500  size_t stringFields = DB2FileLoader::GetFormatStringFieldCount(format);
501 
502  // each string field at load have array of string for each locale
503  size_t stringHolderSize = sizeof(char*) * TOTAL_LOCALES;
504  size_t stringHoldersRecordPoolSize = stringFields * stringHolderSize;
505 
506  if (stringFields)
507  {
508  size_t stringHoldersPoolSize = stringHoldersRecordPoolSize * result->GetRowCount();
509  stringHolders = new char[stringHoldersPoolSize];
510 
511  // DB2 strings expected to have at least empty string
512  for (size_t i = 0; i < stringHoldersPoolSize / sizeof(char*); ++i)
513  ((char const**)stringHolders)[i] = nullStr;
514  }
515  else
516  stringHolders = nullptr;
517 
518  // Resize index table
519  // database query *MUST* contain ORDER BY `index_field` DESC clause
520  uint32 indexTableSize;
521  if (indexField >= 0)
522  {
523  indexTableSize = (*result)[indexField].GetUInt32() + 1;
524  if (indexTableSize < records)
525  indexTableSize = records;
526  }
527  else
528  indexTableSize = records + result->GetRowCount();
529 
530  if (indexTableSize > records)
531  {
532  char** tmpIdxTable = new char*[indexTableSize];
533  memset(tmpIdxTable, 0, indexTableSize * sizeof(char*));
534  memcpy(tmpIdxTable, indexTable, records * sizeof(char*));
535  delete[] indexTable;
536  indexTable = tmpIdxTable;
537  }
538 
539  char* tempDataTable = new char[result->GetRowCount() * recordSize];
540  uint32* newIndexes = new uint32[result->GetRowCount()];
541  uint32 rec = 0;
542  uint32 newRecords = 0;
543 
544  do
545  {
546  Field* fields = result->Fetch();
547  uint32 offset = 0;
548  uint32 stringFieldNumInRecord = 0;
549 
550  uint32 indexValue;
551  if (indexField >= 0)
552  indexValue = fields[indexField].GetUInt32();
553  else
554  indexValue = records + rec;
555 
556  // Attempt to overwrite existing data
557  char* dataValue = indexTable[indexValue];
558  if (!dataValue)
559  {
560  newIndexes[newRecords] = indexValue;
561  dataValue = &tempDataTable[newRecords++ * recordSize];
562  }
563 
564  for (uint32 f = 0; f < fieldCount; f++)
565  {
566  switch (format[f])
567  {
568  case FT_FLOAT:
569  *((float*)(&dataValue[offset])) = fields[f].GetFloat();
570  offset += 4;
571  break;
572  case FT_IND:
573  case FT_INT:
574  *((int32*)(&dataValue[offset])) = fields[f].GetInt32();
575  offset += 4;
576  break;
577  case FT_BYTE:
578  *((int8*)(&dataValue[offset])) = fields[f].GetInt8();
579  offset += 1;
580  break;
581  case FT_LONG:
582  *((int64*)(&dataValue[offset])) = fields[f].GetInt64();
583  offset += 8;
584  break;
585  case FT_STRING:
586  {
587  LocalizedString** slot = (LocalizedString**)(&dataValue[offset]);
588  *slot = (LocalizedString*)(&stringHolders[stringHoldersRecordPoolSize * rec + stringHolderSize * stringFieldNumInRecord]);
589  ASSERT(*slot);
590 
591  // Value in database in main table field must be for enUS locale
592  if (char* str = AddString(&(*slot)->Str[LOCALE_enUS], fields[f].GetString()))
593  stringPool.push_back(str);
594 
595  ++stringFieldNumInRecord;
596  offset += sizeof(char*);
597  break;
598  }
600  {
601  char const** slot = (char const**)(&dataValue[offset]);
602  *slot = (char*)(&stringHolders[stringHoldersRecordPoolSize * rec + stringHolderSize * stringFieldNumInRecord]);
603  ASSERT(*slot);
604 
605  // Value in database in main table field must be for enUS locale
606  if (char* str = AddString(slot, fields[f].GetString()))
607  stringPool.push_back(str);
608 
609  ++stringFieldNumInRecord;
610  offset += sizeof(char*);
611  break;
612  }
613  }
614  }
615 
616  ASSERT(offset == recordSize);
617  ++rec;
618  } while (result->NextRow());
619 
620  if (!newRecords)
621  {
622  delete[] tempDataTable;
623  delete[] newIndexes;
624  return nullptr;
625  }
626 
627  // Compact new data table to only contain new records not previously loaded from file
628  char* dataTable = new char[newRecords * recordSize];
629  memcpy(dataTable, tempDataTable, newRecords * recordSize);
630 
631  // insert new records to index table
632  for (uint32 i = 0; i < newRecords; ++i)
633  indexTable[newIndexes[i]] = &dataTable[i * recordSize];
634 
635  delete[] tempDataTable;
636  delete[] newIndexes;
637 
638  records = indexTableSize;
639 
640  return dataTable;
641 }
void format(BasicFormatter< Char > &f, const Char *&format_str, const T &value)
Definition: format.h:2963
Definition: Define.h:163
int8_t int8
Definition: Define.h:148
std::shared_ptr< PreparedResultSet > PreparedQueryResult
Definition: QueryResult.h:107
Definition: Define.h:161
static char const *const nullStr
Definition: DB2StorageLoader.cpp:341
int64_t int64
Definition: Define.h:145
Class used to access individual fields of database query result.
Definition: Field.h:56
Definition: Common.h:146
Definition: Define.h:160
static uint32 GetFormatStringFieldCount(const char *format)
Definition: DB2StorageLoader.cpp:245
Definition: Define.h:165
int32_t int32
Definition: Define.h:146
uint32_t uint32
Definition: Define.h:150
HotfixDatabaseWorkerPool HotfixDatabase
Accessor to the hotfix database.
Definition: DatabaseEnv.cpp:23
PreparedStatement * GetPreparedStatement(PreparedStatementIndex index)
Definition: DatabaseWorkerPool.h:263
Definition: Define.h:162
QueryResult Query(const char *sql, T *connection=nullptr)
Definition: DatabaseWorkerPool.cpp:113
Definition: Common.h:117
uint32 GetUInt32() const
Definition: Field.h:146
Definition: Define.h:158
#define ASSERT
Definition: Errors.h:55
static char * AddString(char const **holder, std::string const &value)
Definition: DB2StorageLoader.cpp:710
static uint32 GetFormatRecordSize(const char *format, int32 *index_pos=NULL)
Definition: DB2StorageLoader.cpp:207
Definition: Define.h:159
std::string GetString() const
Definition: Field.h:276
Definition: Common.h:130

+ Here is the call graph for this function:

void DB2DatabaseLoader::LoadStrings ( const char *  format,
HotfixDatabaseStatements  preparedStatement,
uint32  locale,
char **&  indexTable,
std::list< char * > &  stringPool 
)
644 {
645  PreparedStatement* stmt = HotfixDatabase.GetPreparedStatement(preparedStatement);
646  stmt->setString(0, localeNames[locale]);
648  if (!result)
649  return;
650 
652  if (result->GetFieldCount() != stringFields + 1 /*ID*/)
653  return;
654 
655  uint32 const fieldCount = strlen(format);
656  int32 indexField;
657  uint32 recordSize = DB2FileLoader::GetFormatRecordSize(format, &indexField);
658  ASSERT(indexField >= 0, "DB2Storage must be indexed to load localized strings");
659 
660  do
661  {
662  Field* fields = result->Fetch();
663  uint32 offset = 0;
664  uint32 stringFieldNumInRecord = 0;
665  uint32 indexValue = fields[0].GetUInt32();
666 
667  // Attempt to overwrite existing data
668  if (char* dataValue = indexTable[indexValue])
669  {
670  for (uint32 x = 0; x < fieldCount; x++)
671  {
672  switch (format[x])
673  {
674  case FT_FLOAT:
675  case FT_IND:
676  case FT_INT:
677  offset += 4;
678  break;
679  case FT_BYTE:
680  offset += 1;
681  break;
682  case FT_LONG:
683  offset += 8;
684  break;
685  case FT_STRING:
686  {
687  // fill only not filled entries
688  LocalizedString* db2str = *(LocalizedString**)(&dataValue[offset]);
689  if (db2str->Str[locale] == nullStr)
690  if (char* str = AddString(&db2str->Str[locale], fields[1 + stringFieldNumInRecord].GetString()))
691  stringPool.push_back(str);
692 
693  ++stringFieldNumInRecord;
694  offset += sizeof(char*);
695  break;
696  }
697  }
698  }
699 
700  ASSERT(offset == recordSize);
701  }
702  else
703  TC_LOG_ERROR("sql.sql", "Hotfix locale table for storage %s references row that does not exist %u!", _storageName.c_str(), indexValue);
704 
705  } while (result->NextRow());
706 
707  return;
708 }
void format(BasicFormatter< Char > &f, const Char *&format_str, const T &value)
Definition: format.h:2963
Definition: Define.h:163
std::shared_ptr< PreparedResultSet > PreparedQueryResult
Definition: QueryResult.h:107
Definition: Define.h:161
static char const *const nullStr
Definition: DB2StorageLoader.cpp:341
Class used to access individual fields of database query result.
Definition: Field.h:56
Definition: Common.h:146
Definition: Define.h:160
void setString(const uint8 index, const std::string &value)
Definition: PreparedStatement.cpp:187
Definition: PreparedStatement.h:74
static uint32 GetFormatLocalizedStringFieldCount(const char *format)
Definition: DB2StorageLoader.cpp:255
char const * Str[TOTAL_LOCALES]
Definition: Common.h:148
Definition: Define.h:165
int32_t int32
Definition: Define.h:146
uint32_t uint32
Definition: Define.h:150
HotfixDatabaseWorkerPool HotfixDatabase
Accessor to the hotfix database.
Definition: DatabaseEnv.cpp:23
PreparedStatement * GetPreparedStatement(PreparedStatementIndex index)
Definition: DatabaseWorkerPool.h:263
Definition: Define.h:162
TC_COMMON_API char const * localeNames[TOTAL_LOCALES]
Definition: Common.cpp:21
std::string _storageName
Definition: DB2StorageLoader.h:127
QueryResult Query(const char *sql, T *connection=nullptr)
Definition: DatabaseWorkerPool.cpp:113
uint32 GetUInt32() const
Definition: Field.h:146
Definition: Define.h:158
#define ASSERT
Definition: Errors.h:55
static char * AddString(char const **holder, std::string const &value)
Definition: DB2StorageLoader.cpp:710
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:207
G3D::int16 x
Definition: Vector2int16.h:37
static uint32 GetFormatRecordSize(const char *format, int32 *index_pos=NULL)
Definition: DB2StorageLoader.cpp:207
std::string GetString() const
Definition: Field.h:276

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Member Data Documentation

std::string DB2DatabaseLoader::_storageName
private

The documentation for this class was generated from the following files: