TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Field.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef _FIELD_H
19 #define _FIELD_H
20 
21 #include "Common.h"
22 #include "Log.h"
23 
24 #include <mysql.h>
25 
57 {
58  friend class ResultSet;
59  friend class PreparedResultSet;
60 
61  public:
62  Field();
63  ~Field();
64 
65  bool GetBool() const // Wrapper, actually gets integer
66  {
67  return GetUInt8() == 1 ? true : false;
68  }
69 
70  uint8 GetUInt8() const
71  {
72  if (!data.value)
73  return 0;
74 
75  #ifdef TRINITY_DEBUG
76  if (!IsType(MYSQL_TYPE_TINY))
77  {
78  TC_LOG_WARN("sql.sql", "Warning: GetUInt8() on non-tinyint field %s.%s (%s.%s) at index %u. Using type: %s.",
79  meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type);
80  return 0;
81  }
82  #endif
83 
84  if (data.raw)
85  return *reinterpret_cast<uint8*>(data.value);
86  return static_cast<uint8>(strtoul((char*)data.value, nullptr, 10));
87  }
88 
89  int8 GetInt8() const
90  {
91  if (!data.value)
92  return 0;
93 
94  #ifdef TRINITY_DEBUG
95  if (!IsType(MYSQL_TYPE_TINY))
96  {
97  TC_LOG_WARN("sql.sql", "Warning: GetInt8() on non-tinyint field %s.%s (%s.%s) at index %u. Using type: %s.",
98  meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type);
99  return 0;
100  }
101  #endif
102 
103  if (data.raw)
104  return *reinterpret_cast<int8*>(data.value);
105  return static_cast<int8>(strtol((char*)data.value, NULL, 10));
106  }
107 
109  {
110  if (!data.value)
111  return 0;
112 
113  #ifdef TRINITY_DEBUG
114  if (!IsType(MYSQL_TYPE_SHORT) && !IsType(MYSQL_TYPE_YEAR))
115  {
116  TC_LOG_WARN("sql.sql", "Warning: GetUInt16() on non-smallint field %s.%s (%s.%s) at index %u. Using type: %s.",
117  meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type);
118  return 0;
119  }
120  #endif
121 
122  if (data.raw)
123  return *reinterpret_cast<uint16*>(data.value);
124  return static_cast<uint16>(strtoul((char*)data.value, nullptr, 10));
125  }
126 
127  int16 GetInt16() const
128  {
129  if (!data.value)
130  return 0;
131 
132  #ifdef TRINITY_DEBUG
133  if (!IsType(MYSQL_TYPE_SHORT) && !IsType(MYSQL_TYPE_YEAR))
134  {
135  TC_LOG_WARN("sql.sql", "Warning: GetInt16() on non-smallint field %s.%s (%s.%s) at index %u. Using type: %s.",
136  meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type);
137  return 0;
138  }
139  #endif
140 
141  if (data.raw)
142  return *reinterpret_cast<int16*>(data.value);
143  return static_cast<int16>(strtol((char*)data.value, NULL, 10));
144  }
145 
147  {
148  if (!data.value)
149  return 0;
150 
151  #ifdef TRINITY_DEBUG
152  if (!IsType(MYSQL_TYPE_INT24) && !IsType(MYSQL_TYPE_LONG))
153  {
154  TC_LOG_WARN("sql.sql", "Warning: GetUInt32() on non-(medium)int field %s.%s (%s.%s) at index %u. Using type: %s.",
155  meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type);
156  return 0;
157  }
158  #endif
159 
160  if (data.raw)
161  return *reinterpret_cast<uint32*>(data.value);
162  return static_cast<uint32>(strtoul((char*)data.value, nullptr, 10));
163  }
164 
165  int32 GetInt32() const
166  {
167  if (!data.value)
168  return 0;
169 
170  #ifdef TRINITY_DEBUG
171  if (!IsType(MYSQL_TYPE_INT24) && !IsType(MYSQL_TYPE_LONG))
172  {
173  TC_LOG_WARN("sql.sql", "Warning: GetInt32() on non-(medium)int field %s.%s (%s.%s) at index %u. Using type: %s.",
174  meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type);
175  return 0;
176  }
177  #endif
178 
179  if (data.raw)
180  return *reinterpret_cast<int32*>(data.value);
181  return static_cast<int32>(strtol((char*)data.value, NULL, 10));
182  }
183 
185  {
186  if (!data.value)
187  return 0;
188 
189  #ifdef TRINITY_DEBUG
190  if (!IsType(MYSQL_TYPE_LONGLONG) && !IsType(MYSQL_TYPE_BIT))
191  {
192  TC_LOG_WARN("sql.sql", "Warning: GetUInt64() on non-bigint field %s.%s (%s.%s) at index %u. Using type: %s.",
193  meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type);
194  return 0;
195  }
196  #endif
197 
198  if (data.raw)
199  return *reinterpret_cast<uint64*>(data.value);
200  return static_cast<uint64>(strtoull((char*)data.value, nullptr, 10));
201  }
202 
203  int64 GetInt64() const
204  {
205  if (!data.value)
206  return 0;
207 
208  #ifdef TRINITY_DEBUG
209  if (!IsType(MYSQL_TYPE_LONGLONG) && !IsType(MYSQL_TYPE_BIT))
210  {
211  TC_LOG_WARN("sql.sql", "Warning: GetInt64() on non-bigint field %s.%s (%s.%s) at index %u. Using type: %s.",
212  meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type);
213  return 0;
214  }
215  #endif
216 
217  if (data.raw)
218  return *reinterpret_cast<int64*>(data.value);
219  return static_cast<int64>(strtoll((char*)data.value, NULL, 10));
220  }
221 
222  float GetFloat() const
223  {
224  if (!data.value)
225  return 0.0f;
226 
227  #ifdef TRINITY_DEBUG
228  if (!IsType(MYSQL_TYPE_FLOAT))
229  {
230  TC_LOG_WARN("sql.sql", "Warning: GetFloat() on non-float field %s.%s (%s.%s) at index %u. Using type: %s.",
231  meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type);
232  return 0.0f;
233  }
234  #endif
235 
236  if (data.raw)
237  return *reinterpret_cast<float*>(data.value);
238  return static_cast<float>(atof((char*)data.value));
239  }
240 
241  double GetDouble() const
242  {
243  if (!data.value)
244  return 0.0f;
245 
246  #ifdef TRINITY_DEBUG
247  if (!IsType(MYSQL_TYPE_DOUBLE) && !IsType(MYSQL_TYPE_NEWDECIMAL))
248  {
249  TC_LOG_WARN("sql.sql", "Warning: GetDouble() on non-double/non-decimal field %s.%s (%s.%s) at index %u. Using type: %s.",
250  meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type);
251  return 0.0f;
252  }
253  #endif
254 
255  if (data.raw && !IsType(MYSQL_TYPE_NEWDECIMAL))
256  return *reinterpret_cast<double*>(data.value);
257  return static_cast<double>(atof((char*)data.value));
258  }
259 
260  char const* GetCString() const
261  {
262  if (!data.value)
263  return NULL;
264 
265  #ifdef TRINITY_DEBUG
266  if (IsNumeric())
267  {
268  TC_LOG_WARN("sql.sql", "Error: GetCString() on numeric field %s.%s (%s.%s) at index %u. Using type: %s.",
269  meta.TableAlias, meta.Alias, meta.TableName, meta.Name, meta.Index, meta.Type);
270  return NULL;
271  }
272  #endif
273  return static_cast<char const*>(data.value);
274  }
275 
276  std::string GetString() const
277  {
278  if (!data.value)
279  return "";
280 
281  char const* string = GetCString();
282  if (!string)
283  return "";
284 
285  return std::string(string, data.length);
286  }
287 
288  std::vector<uint8> GetBinary() const
289  {
290  std::vector<uint8> result;
291  if (!data.value || !data.length)
292  return result;
293 
294  result.resize(data.length);
295  memcpy(result.data(), data.value, data.length);
296  return result;
297  }
298 
299  bool IsNull() const
300  {
301  return data.value == NULL;
302  }
303 
304  struct Metadata
305  {
306  char const* TableName;
307  char const* TableAlias;
308  char const* Name;
309  char const* Alias;
310  char const* Type;
312  };
313 
314  protected:
315  #pragma pack(push, 1)
316  struct
317  {
318  uint32 length; // Length (prepared strings only)
319  void* value; // Actual data in memory
320  enum_field_types type; // Field type
321  bool raw; // Raw bytes? (Prepared statement or ad hoc)
322  } data;
323  #pragma pack(pop)
324 
325  void SetByteValue(void* newValue, enum_field_types newType, uint32 length);
326  void SetStructuredValue(char* newValue, enum_field_types newType, uint32 length);
327 
328  void CleanUp()
329  {
330  // Field does not own the data if fetched with prepared statement
331  if (!data.raw)
332  delete[] ((char*)data.value);
333  data.value = NULL;
334  }
335 
336  static uint32 SizeForType(MYSQL_FIELD* field)
337  {
338  switch (field->type)
339  {
340  case MYSQL_TYPE_NULL:
341  return 0;
342  case MYSQL_TYPE_TINY:
343  return 1;
344  case MYSQL_TYPE_YEAR:
345  case MYSQL_TYPE_SHORT:
346  return 2;
347  case MYSQL_TYPE_INT24:
348  case MYSQL_TYPE_LONG:
349  case MYSQL_TYPE_FLOAT:
350  return 4;
351  case MYSQL_TYPE_DOUBLE:
352  case MYSQL_TYPE_LONGLONG:
353  case MYSQL_TYPE_BIT:
354  return 8;
355 
356  case MYSQL_TYPE_TIMESTAMP:
357  case MYSQL_TYPE_DATE:
358  case MYSQL_TYPE_TIME:
359  case MYSQL_TYPE_DATETIME:
360  return sizeof(MYSQL_TIME);
361 
362  case MYSQL_TYPE_TINY_BLOB:
363  case MYSQL_TYPE_MEDIUM_BLOB:
364  case MYSQL_TYPE_LONG_BLOB:
365  case MYSQL_TYPE_BLOB:
366  case MYSQL_TYPE_STRING:
367  case MYSQL_TYPE_VAR_STRING:
368  return field->max_length + 1;
369 
370  case MYSQL_TYPE_DECIMAL:
371  case MYSQL_TYPE_NEWDECIMAL:
372  return 64;
373 
374  case MYSQL_TYPE_GEOMETRY:
375  /*
376  Following types are not sent over the wire:
377  MYSQL_TYPE_ENUM:
378  MYSQL_TYPE_SET:
379  */
380  default:
381  TC_LOG_WARN("sql.sql", "SQL::SizeForType(): invalid field type %u", uint32(field->type));
382  return 0;
383  }
384  }
385 
386  bool IsType(enum_field_types type) const
387  {
388  return data.type == type;
389  }
390 
391  bool IsNumeric() const
392  {
393  return (data.type == MYSQL_TYPE_TINY ||
394  data.type == MYSQL_TYPE_SHORT ||
395  data.type == MYSQL_TYPE_INT24 ||
396  data.type == MYSQL_TYPE_LONG ||
397  data.type == MYSQL_TYPE_FLOAT ||
398  data.type == MYSQL_TYPE_DOUBLE ||
399  data.type == MYSQL_TYPE_LONGLONG );
400  }
401 
402  private:
403  #ifdef TRINITY_DEBUG
404  static char const* FieldTypeToString(enum_field_types type)
405  {
406  switch (type)
407  {
408  case MYSQL_TYPE_BIT: return "BIT";
409  case MYSQL_TYPE_BLOB: return "BLOB";
410  case MYSQL_TYPE_DATE: return "DATE";
411  case MYSQL_TYPE_DATETIME: return "DATETIME";
412  case MYSQL_TYPE_NEWDECIMAL: return "NEWDECIMAL";
413  case MYSQL_TYPE_DECIMAL: return "DECIMAL";
414  case MYSQL_TYPE_DOUBLE: return "DOUBLE";
415  case MYSQL_TYPE_ENUM: return "ENUM";
416  case MYSQL_TYPE_FLOAT: return "FLOAT";
417  case MYSQL_TYPE_GEOMETRY: return "GEOMETRY";
418  case MYSQL_TYPE_INT24: return "INT24";
419  case MYSQL_TYPE_LONG: return "LONG";
420  case MYSQL_TYPE_LONGLONG: return "LONGLONG";
421  case MYSQL_TYPE_LONG_BLOB: return "LONG_BLOB";
422  case MYSQL_TYPE_MEDIUM_BLOB: return "MEDIUM_BLOB";
423  case MYSQL_TYPE_NEWDATE: return "NEWDATE";
424  case MYSQL_TYPE_NULL: return "NULL";
425  case MYSQL_TYPE_SET: return "SET";
426  case MYSQL_TYPE_SHORT: return "SHORT";
427  case MYSQL_TYPE_STRING: return "STRING";
428  case MYSQL_TYPE_TIME: return "TIME";
429  case MYSQL_TYPE_TIMESTAMP: return "TIMESTAMP";
430  case MYSQL_TYPE_TINY: return "TINY";
431  case MYSQL_TYPE_TINY_BLOB: return "TINY_BLOB";
432  case MYSQL_TYPE_VAR_STRING: return "VAR_STRING";
433  case MYSQL_TYPE_YEAR: return "YEAR";
434  default: return "-Unknown-";
435  }
436  }
437 
438  void SetMetadata(MYSQL_FIELD* field, uint32 fieldIndex)
439  {
440  meta.TableName = field->org_table;
441  meta.TableAlias = field->table;
442  meta.Name = field->org_name;
443  meta.Alias = field->name;
444  meta.Type = FieldTypeToString(field->type);
445  meta.Index = fieldIndex;
446  }
447 
448  Metadata meta;
449 
450  #endif
451 };
452 
453 #endif
454 
#define TC_DATABASE_API
Definition: Define.h:122
char const * Name
Definition: Field.h:308
int8_t int8
Definition: Define.h:148
uint64 GetUInt64() const
Definition: Field.h:184
float GetFloat() const
Definition: Field.h:222
int64_t int64
Definition: Define.h:145
Class used to access individual fields of database query result.
Definition: Field.h:56
int64 GetInt64() const
Definition: Field.h:203
arena_t NULL
Definition: jemalloc_internal.h:624
uint32 Index
Definition: Field.h:311
bool IsType(enum_field_types type) const
Definition: Field.h:386
Definition: QueryResult.h:30
char const * GetCString() const
Definition: Field.h:260
std::vector< uint8 > GetBinary() const
Definition: Field.h:288
uint8 GetUInt8() const
Definition: Field.h:70
void * value
Definition: Field.h:319
int32_t int32
Definition: Define.h:146
uint32_t uint32
Definition: Define.h:150
uint64_t uint64
Definition: Define.h:149
bool raw
Definition: Field.h:321
uint16_t uint16
Definition: Define.h:151
void CleanUp()
Definition: Field.h:328
uint16 GetUInt16() const
Definition: Field.h:108
double GetDouble() const
Definition: Field.h:241
float length(float v)
Definition: vectorMath.h:208
char const * TableName
Definition: Field.h:306
int32 GetInt32() const
Definition: Field.h:165
int16 GetInt16() const
Definition: Field.h:127
Definition: Field.h:304
char const * Type
Definition: Field.h:310
bool IsNumeric() const
Definition: Field.h:391
enum_field_types type
Definition: Field.h:320
bool IsNull() const
Definition: Field.h:299
uint32 GetUInt32() const
Definition: Field.h:146
uint32 length
Definition: Field.h:318
#define TC_LOG_WARN(filterType__,...)
Definition: Log.h:204
uint8_t uint8
Definition: Define.h:152
int16_t int16
Definition: Define.h:147
uint32_t uint32
Definition: g3dmath.h:168
int8 GetInt8() const
Definition: Field.h:89
#define const
Definition: zconf.h:217
bool GetBool() const
Definition: Field.h:65
Definition: QueryResult.h:63
static uint32 SizeForType(MYSQL_FIELD *field)
Definition: Field.h:336
std::string GetString() const
Definition: Field.h:276
char const * TableAlias
Definition: Field.h:307
char const * Alias
Definition: Field.h:309