aboutsummaryrefslogtreecommitdiff
path: root/src/server/shared/Database/Field.h
diff options
context:
space:
mode:
authorMachiavelli <none@none>2010-09-24 22:16:21 +0200
committerMachiavelli <none@none>2010-09-24 22:16:21 +0200
commit3c6dc320308880bde4ef9eddd695db28a74aa0d9 (patch)
treef209e6c487e436fc1cd978487dddf3604ce2b594 /src/server/shared/Database/Field.h
parentb46b498141cc167163c6112e8e2bfa32fec2d7dc (diff)
Core/DBLayer:
- Rewrite Field class to be able to store both binary prepared statement data and data from adhoc query resultsets - Buffer the data of prepared statements using ResultSet and Field classes and let go of mysql c api structures after PreparedResultSet constructor. Fixes a race condition and thus a possible crash/data corruption (issue pointed out to Derex, basic suggestion by raczman) - Conform PreparedResultSet and ResultSet to the same design standards, and using Field class as data buffer class for both * NOTE: This means the fetching methods are uniform again, using ¨Field* fields = result->Fetch();¨ and access to elements trough fields[x]. * NOTE: for access to the correct row in prepared statements, ¨Field* fields = result->Fetch();¨ must ALWAYS be called inside the do { }while(result->NextRow()) loop. * NOTE: This means that Field::GetString() returns std::string object and Field::GetCString() returns const char* pointer. Still experimental and all that jazz, not recommended for production servers until feedback is given. --HG-- branch : trunk
Diffstat (limited to 'src/server/shared/Database/Field.h')
-rw-r--r--src/server/shared/Database/Field.h320
1 files changed, 276 insertions, 44 deletions
diff --git a/src/server/shared/Database/Field.h b/src/server/shared/Database/Field.h
index 2885d9eff8b..0870f1c8562 100644
--- a/src/server/shared/Database/Field.h
+++ b/src/server/shared/Database/Field.h
@@ -1,6 +1,4 @@
/*
- * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
- *
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify
@@ -18,74 +16,308 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#if !defined(FIELD_H)
-#define FIELD_H
-#include <iostream>
+#ifndef _FIELD_H
+#define _FIELD_H
+
#include "Common.h"
+#include "Log.h"
+
+#include <mysql.h>
class Field
{
+ friend class ResultSet;
+ friend class PreparedResultSet;
+
public:
+
+ bool GetBool() const // Wrapper, actually gets integer
+ {
+ return GetUInt8() == 1 ? true : false;
+ }
- enum DataTypes
+ uint8 GetUInt8() const
{
- DB_TYPE_UNKNOWN = 0x00,
- DB_TYPE_STRING = 0x01,
- DB_TYPE_INTEGER = 0x02,
- DB_TYPE_FLOAT = 0x03,
- DB_TYPE_BOOL = 0x04
- };
+ if (!data.value)
+ return 0;
- Field();
- Field(Field &f);
- Field(const char *value, enum DataTypes type);
+ #ifdef TRINITY_DEBUG
+ if (!IsNumeric())
+ {
+ sLog.outSQLDriver("Error: GetUInt8() on non-numeric field.");
+ return 0;
+ }
+ #endif
+ if (data.raw)
+ return *reinterpret_cast<uint8*>(data.value);
+ return static_cast<uint8>(atol((char*)data.value));
+ }
- ~Field();
+ int8 GetInt8() const
+ {
+ if (!data.value)
+ return 0;
+
+ #ifdef TRINITY_DEBUG
+ if (!IsNumeric())
+ {
+ sLog.outSQLDriver("Error: GeInt8() on non-numeric field.");
+ return 0;
+ }
+ #endif
+ if (data.raw)
+ return *reinterpret_cast<int8*>(data.value);
+ return static_cast<int8>(atol((char*)data.value));
+ }
+
+ uint16 GetUInt16() const
+ {
+ if (!data.value)
+ return 0;
- enum DataTypes GetType() const { return mType; }
+ #ifdef TRINITY_DEBUG
+ if (!IsNumeric())
+ {
+ sLog.outSQLDriver("Error: GetUInt16() on non-numeric field.");
+ return 0;
+ }
+ #endif
+ if (data.raw)
+ return *reinterpret_cast<uint16*>(data.value);
+ return static_cast<uint16>(atol((char*)data.value));
+ }
- const char *GetString() const { return mValue; }
- std::string GetCppString() const
+ int16 GetInt16() const
{
- return mValue ? mValue : ""; // std::string s = 0 have undefine result in C++
+ if (!data.value)
+ return 0;
+
+ #ifdef TRINITY_DEBUG
+ if (!IsNumeric())
+ {
+ sLog.outSQLDriver("Error: GetInt16() on non-numeric field.");
+ return 0;
+ }
+ #endif
+ if (data.raw)
+ return *reinterpret_cast<int16*>(data.value);
+ return static_cast<int16>(atol((char*)data.value));
}
- float GetFloat() const { return mValue ? static_cast<float>(atof(mValue)) : 0.0f; }
- bool GetBool() const { return mValue ? atoi(mValue) > 0 : false; }
- int32 GetInt32() const { return mValue ? static_cast<int32>(atol(mValue)) : int32(0); }
- uint8 GetUInt8() const { return mValue ? static_cast<uint8>(atol(mValue)) : uint8(0); }
- uint16 GetUInt16() const { return mValue ? static_cast<uint16>(atol(mValue)) : uint16(0); }
- int16 GetInt16() const { return mValue ? static_cast<int16>(atol(mValue)) : int16(0); }
- uint32 GetUInt32() const { return mValue ? static_cast<uint32>(atol(mValue)) : uint32(0); }
- uint64 GetUInt64() const
+
+ uint32 GetUInt32() const
{
- if(mValue)
+ if (!data.value)
+ return 0;
+
+ #ifdef TRINITY_DEBUG
+ if (!IsNumeric())
{
- uint64 value;
- sscanf(mValue,UI64FMTD,&value);
- return value;
+ sLog.outSQLDriver("Error: GetUInt32() on non-numeric field.");
+ return 0;
}
- else
+ #endif
+ if (data.raw)
+ return *reinterpret_cast<uint32*>(data.value);
+ return static_cast<uint32>(atol((char*)data.value));
+ }
+
+ int32 GetInt32() const
+ {
+ if (!data.value)
+ return 0;
+
+ #ifdef TRINITY_DEBUG
+ if (!IsNumeric())
+ {
+ sLog.outSQLDriver("Error: GetInt32() on non-numeric field.");
return 0;
+ }
+ #endif
+ if (data.raw)
+ return *reinterpret_cast<int32*>(data.value);
+ return static_cast<int32>(atol((char*)data.value));
}
- uint64 GetInt64() const
+
+ uint64 GetUInt64() const
{
- if(mValue)
+ if (!data.value)
+ return 0;
+
+ #ifdef TRINITY_DEBUG
+ if (!IsNumeric())
{
- int64 value;
- sscanf(mValue,SI64FMTD,&value);
- return value;
+ sLog.outSQLDriver("Error: GetUInt64() on non-numeric field.");
+ return 0;
}
- else
+ #endif
+ if (data.raw)
+ return *reinterpret_cast<uint64*>(data.value);
+ return static_cast<uint64>(atol((char*)data.value));
+ }
+
+ int64 GetInt64() const
+ {
+ if (!data.value)
+ return 0;
+
+ #ifdef TRINITY_DEBUG
+ if (!IsNumeric())
+ {
+ sLog.outSQLDriver("Error: GetInt64() on non-numeric field.");
return 0;
+ }
+ #endif
+ if (data.raw)
+ return *reinterpret_cast<int64*>(data.value);
+ return static_cast<int64>(atol((char*)data.value));
+ }
+
+ float GetFloat() const
+ {
+ if (!data.value)
+ return 0.0f;
+
+ #ifdef TRINITY_DEBUG
+ if (!IsNumeric())
+ {
+ sLog.outSQLDriver("Error: GetFloat() on non-numeric field.");
+ return 0.0f;
+ }
+ #endif
+ if (data.raw)
+ return *reinterpret_cast<float*>(data.value);
+ return static_cast<float>(atof((char*)data.value));
+ }
+
+ double GetDouble() const
+ {
+ if (!data.value)
+ return 0.0f;
+
+ #ifdef TRINITY_DEBUG
+ if (!IsNumeric())
+ {
+ sLog.outSQLDriver("Error: GetDouble() on non-numeric field.");
+ return 0.0f;
+ }
+ #endif
+ if (data.raw)
+ return *reinterpret_cast<double*>(data.value);
+ return static_cast<double>(atof((char*)data.value));
+ }
+
+ const char* GetCString() const
+ {
+ if (!data.value)
+ return NULL;
+
+ #ifdef TRINITY_DEBUG
+ if (IsNumeric())
+ {
+ sLog.outSQLDriver("Error: GetCString() on numeric field.");
+ return NULL;
+ }
+ #endif
+ return static_cast<const char*>(data.value);
+ }
+
+ std::string GetString() const
+ {
+ if (!data.value)
+ return "";
+
+ if (data.raw)
+ {
+ const char* string = GetCString();
+ if (!string)
+ string = "";
+ return std::string(string, data.length);
+ }
+ return std::string((char*)data.value);
+ }
+
+ protected:
+ Field();
+ ~Field();
+
+ struct
+ {
+ enum_field_types type; // Field type
+ void* value; // Actual data in memory
+ bool raw; // Raw bytes? (Prepared statement or adhoc)
+ uint32 length; // Length (prepared strings only)
+ } data;
+
+ void SetByteValue(void* newValue, const size_t newSize, enum_field_types newType, uint32 length);
+ void SetStructuredValue(char* newValue, enum_field_types newType, const size_t newSize);
+
+ void CleanUp()
+ {
+ delete[] (data.value);
+ data.value = NULL;
}
- void SetType(enum DataTypes type) { mType = type; }
+ static size_t SizeForType(MYSQL_FIELD* field)
+ {
+ switch (field->type)
+ {
+ case MYSQL_TYPE_NULL:
+ return 0;
+ case MYSQL_TYPE_TINY:
+ return 1;
+ case MYSQL_TYPE_YEAR:
+ case MYSQL_TYPE_SHORT:
+ return 2;
+ case MYSQL_TYPE_INT24:
+ case MYSQL_TYPE_LONG:
+ case MYSQL_TYPE_FLOAT:
+ return 4;
+ case MYSQL_TYPE_DOUBLE:
+ case MYSQL_TYPE_LONGLONG:
+ case MYSQL_TYPE_BIT:
+ return 8;
+
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_DATETIME:
+ return sizeof(MYSQL_TIME);
+
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_VAR_STRING:
+ return field->max_length + 1;
- void SetValue(const char *value);
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_NEWDECIMAL:
+ return 64;
- private:
- char *mValue;
- enum DataTypes mType;
+ case MYSQL_TYPE_GEOMETRY:
+ /*
+ Following types are not sent over the wire:
+ MYSQL_TYPE_ENUM:
+ MYSQL_TYPE_SET:
+ */
+ default:
+ sLog.outSQLDriver("SQL::SizeForType(): invalid field type %u", uint32(field->type));
+ return 0;
+ }
+ }
+
+ bool IsNumeric() const
+ {
+ return (data.type == MYSQL_TYPE_TINY ||
+ data.type == MYSQL_TYPE_SHORT ||
+ data.type == MYSQL_TYPE_INT24 ||
+ data.type == MYSQL_TYPE_LONG ||
+ data.type == MYSQL_TYPE_FLOAT ||
+ data.type == MYSQL_TYPE_DOUBLE ||
+ data.type == MYSQL_TYPE_LONGLONG );
+ }
};
+
#endif