Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
Field.h
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#ifndef _FIELD_H
7#define _FIELD_H
8
9#include "Common.h"
10#include "Log.h"
11
12#include <mysql.h>
13#include <array>
14
15class Field
16{
17 friend class ResultSet;
18 friend class PreparedResultSet;
19
20public:
21 [[nodiscard]] bool GetBool() const // Wrapper, actually gets integer
22 {
23 return (GetUInt8() == 1);
24 }
25
26 [[nodiscard]] uint8 GetUInt8() const
27 {
28 if (!data.value)
29 return 0;
30
31#ifdef SKYFIRE_DEBUG
32 if (!IsType(MYSQL_TYPE_TINY))
33 {
34 SF_LOG_WARN("sql.sql", "Warning: GetUInt8() on non-tinyint field. Using type: %s.", FieldTypeToString(data.type));
35 return 0;
36 }
37#endif
38
39 if (data.raw)
40 return *reinterpret_cast<uint8*>(data.value);
41 return static_cast<uint8>(atol((char*)data.value));
42 }
43
44 [[nodiscard]] int8 GetInt8() const
45 {
46 if (!data.value)
47 return 0;
48
49#ifdef SKYFIRE_DEBUG
50 if (!IsType(MYSQL_TYPE_TINY))
51 {
52 SF_LOG_WARN("sql.sql", "Warning: GetInt8() on non-tinyint field. Using type: %s.", FieldTypeToString(data.type));
53 return 0;
54 }
55#endif
56
57 if (data.raw)
58 return *reinterpret_cast<int8*>(data.value);
59 return static_cast<int8>(atol((char*)data.value));
60 }
61
62#ifdef ELUNA
63 enum_field_types GetType() const
64 {
65 return data.type;
66 }
67#endif
68
69 [[nodiscard]] uint16 GetUInt16() const
70 {
71 if (!data.value)
72 return 0;
73
74#ifdef SKYFIRE_DEBUG
75 if (!IsType(MYSQL_TYPE_SHORT) && !IsType(MYSQL_TYPE_YEAR))
76 {
77 SF_LOG_WARN("sql.sql", "Warning: GetUInt16() on non-smallint field. Using type: %s.", FieldTypeToString(data.type));
78 return 0;
79 }
80#endif
81
82 if (data.raw)
83 return *reinterpret_cast<uint16*>(data.value);
84 return static_cast<uint16>(atol((char*)data.value));
85 }
86
87 [[nodiscard]] int16 GetInt16() const
88 {
89 if (!data.value)
90 return 0;
91
92#ifdef SKYFIRE_DEBUG
93 if (!IsType(MYSQL_TYPE_SHORT) && !IsType(MYSQL_TYPE_YEAR))
94 {
95 SF_LOG_WARN("sql.sql", "Warning: GetInt16() on non-smallint field. Using type: %s.", FieldTypeToString(data.type));
96 return 0;
97 }
98#endif
99
100 if (data.raw)
101 return *reinterpret_cast<int16*>(data.value);
102 return static_cast<int16>(atol((char*)data.value));
103 }
104
105 [[nodiscard]] uint32 GetUInt32() const
106 {
107 if (!data.value)
108 return 0;
109
110#ifdef SKYFIRE_DEBUG
111 if (!IsType(MYSQL_TYPE_INT24) && !IsType(MYSQL_TYPE_LONG))
112 {
113 SF_LOG_WARN("sql.sql", "Warning: GetUInt32() on non-(medium)int field. Using type: %s.", FieldTypeToString(data.type));
114 return 0;
115 }
116#endif
117
118 if (data.raw)
119 return *reinterpret_cast<uint32*>(data.value);
120 return static_cast<uint32>(atol((char*)data.value));
121 }
122
123 [[nodiscard]] int32 GetInt32() const
124 {
125 if (!data.value)
126 return 0;
127
128#ifdef SKYFIRE_DEBUG
129 if (!IsType(MYSQL_TYPE_INT24) && !IsType(MYSQL_TYPE_LONG))
130 {
131 SF_LOG_WARN("sql.sql", "Warning: GetInt32() on non-(medium)int field. Using type: %s.", FieldTypeToString(data.type));
132 return 0;
133 }
134#endif
135
136 if (data.raw)
137 return *reinterpret_cast<int32*>(data.value);
138 return static_cast<int32>(atol((char*)data.value));
139 }
140
141 [[nodiscard]] uint64 GetUInt64() const
142 {
143 if (!data.value)
144 return 0;
145
146#ifdef SKYFIRE_DEBUG
147 if (!IsType(MYSQL_TYPE_LONGLONG) && !IsType(MYSQL_TYPE_BIT))
148 {
149 SF_LOG_WARN("sql.sql", "Warning: GetUInt64() on non-bigint field. Using type: %s.", FieldTypeToString(data.type));
150 return 0;
151 }
152#endif
153
154 if (data.raw)
155 return *reinterpret_cast<uint64*>(data.value);
156 return static_cast<uint64>(atol((char*)data.value));
157 }
158
159 [[nodiscard]] int64 GetInt64() const
160 {
161 if (!data.value)
162 return 0;
163
164#ifdef SKYFIRE_DEBUG
165 if (!IsType(MYSQL_TYPE_LONGLONG) && !IsType(MYSQL_TYPE_BIT))
166 {
167 SF_LOG_WARN("sql.sql", "Warning: GetInt64() on non-bigint field. Using type: %s.", FieldTypeToString(data.type));
168 return 0;
169 }
170#endif
171
172 if (data.raw)
173 return *reinterpret_cast<int64*>(data.value);
174 return static_cast<int64>(strtol((char*)data.value, nullptr, 10));
175 }
176
177 [[nodiscard]] float GetFloat() const
178 {
179 if (!data.value)
180 return 0.0f;
181
182#ifdef SKYFIRE_DEBUG
183 if (!IsType(MYSQL_TYPE_FLOAT))
184 {
185 SF_LOG_WARN("sql.sql", "Warning: GetFloat() on non-float field. Using type: %s.", FieldTypeToString(data.type));
186 return 0.0f;
187 }
188#endif
189
190 if (data.raw)
191 return *reinterpret_cast<float*>(data.value);
192 return static_cast<float>(atof((char*)data.value));
193 }
194
195 [[nodiscard]] double GetDouble() const
196 {
197 if (!data.value)
198 return 0.0f;
199
200#ifdef SKYFIRE_DEBUG
201 if (!IsType(MYSQL_TYPE_DOUBLE))
202 {
203 SF_LOG_WARN("sql.sql", "Warning: GetDouble() on non-double field. Using type: %s.", FieldTypeToString(data.type));
204 return 0.0f;
205 }
206#endif
207
208 if (data.raw)
209 return *reinterpret_cast<double*>(data.value);
210 return static_cast<double>(atof((char*)data.value));
211 }
212
213 [[nodiscard]] char const* GetCString() const
214 {
215 if (!data.value)
216 return nullptr;
217
218#ifdef SKYFIRE_DEBUG
219 if (IsNumeric())
220 {
221 SF_LOG_WARN("sql.sql", "Error: GetCString() on numeric field. Using type: %s.", FieldTypeToString(data.type));
222 return nullptr;
223 }
224#endif
225 return static_cast<char const*>(data.value);
226 }
227
228 [[nodiscard]] std::string GetString() const
229 {
230 if (!data.value)
231 return "";
232
233 if (data.raw)
234 {
235 char const* string = GetCString();
236 if (!string)
237 string = "";
238 return std::string(string, data.length);
239 }
240 return std::string((char*)data.value);
241 }
242
243 [[nodiscard]] bool IsNull() const
244 {
245 if (IsBinary() && data.length == 0)
246 {
247 return true;
248 }
249 return data.value == nullptr;
250 }
251
252 [[nodiscard]] std::vector<uint8> GetBinary() const;
253 template<size_t S>
254 [[nodiscard]] std::array<uint8, S> GetBinary() const
255 {
256 std::array<uint8, S> buf;
257 GetBinarySizeChecked(buf.data(), S);
258 return buf;
259 }
260
261protected:
262 Field();
263 ~Field();
264
265#if defined(__GNUC__)
266#pragma pack(1)
267#else
268#pragma pack(push, 1)
269#endif
270 struct
271 {
272 uint32 length; // Length (prepared strings only)
273 void* value; // Actual data in memory
274 enum_field_types type; // Field type
275 bool raw; // Raw bytes? (Prepared statement or ad hoc)
277#if defined(__GNUC__)
278#pragma pack()
279#else
280#pragma pack(pop)
281#endif
282
283 void SetByteValue(void const* newValue, size_t const newSize, enum_field_types newType, uint32 length);
284 void SetStructuredValue(char* newValue, enum_field_types newType, uint32 length);
285
286 void CleanUp()
287 {
288 delete[]((char*)data.value);
289 data.value = nullptr;
290 }
291
292 static size_t SizeForType(MYSQL_FIELD* field)
293 {
294 switch (field->type)
295 {
296 case MYSQL_TYPE_NULL:
297 return 0;
298 case MYSQL_TYPE_TINY:
299 return 1;
300 case MYSQL_TYPE_YEAR:
301 case MYSQL_TYPE_SHORT:
302 return 2;
303 case MYSQL_TYPE_INT24:
304 case MYSQL_TYPE_LONG:
305 case MYSQL_TYPE_FLOAT:
306 return 4;
307 case MYSQL_TYPE_DOUBLE:
308 case MYSQL_TYPE_LONGLONG:
309 case MYSQL_TYPE_BIT:
310 return 8;
311
312 case MYSQL_TYPE_TIMESTAMP:
313 case MYSQL_TYPE_DATE:
314 case MYSQL_TYPE_TIME:
315 case MYSQL_TYPE_DATETIME:
316 return sizeof(MYSQL_TIME);
317
318 case MYSQL_TYPE_TINY_BLOB:
319 case MYSQL_TYPE_MEDIUM_BLOB:
320 case MYSQL_TYPE_LONG_BLOB:
321 case MYSQL_TYPE_BLOB:
322 case MYSQL_TYPE_STRING:
323 case MYSQL_TYPE_VAR_STRING:
324 return field->max_length + 1;
325
326 case MYSQL_TYPE_DECIMAL:
327 case MYSQL_TYPE_NEWDECIMAL:
328 return 64;
329
330 case MYSQL_TYPE_GEOMETRY:
331 /*
332 Following types are not sent over the wire:
333 MYSQL_TYPE_ENUM:
334 MYSQL_TYPE_SET:
335 */
336 default:
337 SF_LOG_WARN("sql.sql", "SQL::SizeForType(): invalid field type %u", uint32(field->type));
338 return 0;
339 }
340 }
341
342 [[nodiscard]] bool IsType(enum_field_types type) const
343 {
344 return data.type == type;
345 }
346
347 [[nodiscard]] bool IsNumeric() const
348 {
349 return (data.type == MYSQL_TYPE_TINY ||
350 data.type == MYSQL_TYPE_SHORT ||
351 data.type == MYSQL_TYPE_INT24 ||
352 data.type == MYSQL_TYPE_LONG ||
353 data.type == MYSQL_TYPE_FLOAT ||
354 data.type == MYSQL_TYPE_DOUBLE ||
355 data.type == MYSQL_TYPE_LONGLONG);
356 }
357
358 [[nodiscard]] bool IsBinary() const
359 {
360 return (
361 data.type == MYSQL_TYPE_TINY_BLOB ||
362 data.type == MYSQL_TYPE_MEDIUM_BLOB ||
363 data.type == MYSQL_TYPE_LONG_BLOB ||
364 data.type == MYSQL_TYPE_BLOB ||
365 data.type == MYSQL_TYPE_VAR_STRING ||
366 data.type == MYSQL_TYPE_STRING
367 );
368 }
369
370 void GetBinarySizeChecked(uint8* buf, size_t size) const;
371
372private:
373#ifdef SKYFIRE_DEBUG
374 static char const* FieldTypeToString(enum_field_types type)
375 {
376 switch (type)
377 {
378 case MYSQL_TYPE_BIT:
379 return "BIT";
380 case MYSQL_TYPE_BLOB:
381 return "BLOB";
382 case MYSQL_TYPE_DATE:
383 return "DATE";
384 case MYSQL_TYPE_DATETIME:
385 return "DATETIME";
386 case MYSQL_TYPE_NEWDECIMAL:
387 return "NEWDECIMAL";
388 case MYSQL_TYPE_DECIMAL:
389 return "DECIMAL";
390 case MYSQL_TYPE_DOUBLE:
391 return "DOUBLE";
392 case MYSQL_TYPE_ENUM:
393 return "ENUM";
394 case MYSQL_TYPE_FLOAT:
395 return "FLOAT";
396 case MYSQL_TYPE_GEOMETRY:
397 return "GEOMETRY";
398 case MYSQL_TYPE_INT24:
399 return "INT24";
400 case MYSQL_TYPE_LONG:
401 return "LONG";
402 case MYSQL_TYPE_LONGLONG:
403 return "LONGLONG";
404 case MYSQL_TYPE_LONG_BLOB:
405 return "LONG_BLOB";
406 case MYSQL_TYPE_MEDIUM_BLOB:
407 return "MEDIUM_BLOB";
408 case MYSQL_TYPE_NEWDATE:
409 return "NEWDATE";
410 case MYSQL_TYPE_NULL:
411 return "nullptr";
412 case MYSQL_TYPE_SET:
413 return "SET";
414 case MYSQL_TYPE_SHORT:
415 return "SHORT";
416 case MYSQL_TYPE_STRING:
417 return "STRING";
418 case MYSQL_TYPE_TIME:
419 return "TIME";
420 case MYSQL_TYPE_TIMESTAMP:
421 return "TIMESTAMP";
422 case MYSQL_TYPE_TINY:
423 return "TINY";
424 case MYSQL_TYPE_TINY_BLOB:
425 return "TINY_BLOB";
426 case MYSQL_TYPE_VAR_STRING:
427 return "VAR_STRING";
428 case MYSQL_TYPE_YEAR:
429 return "YEAR";
430 default:
431 return "-Unknown-";
432 }
433 }
434#endif
435};
436
437#endif
std::int32_t int32
Definition Define.h:73
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::int8_t int8
Definition Define.h:75
std::uint64_t uint64
Definition Define.h:76
std::int64_t int64
Definition Define.h:72
std::uint16_t uint16
Definition Define.h:78
std::int16_t int16
Definition Define.h:74
#define SF_LOG_WARN(filterType__,...)
Definition Log.h:140
uint8 GetUInt8() const
Definition Field.h:26
enum_field_types type
Definition Field.h:274
void CleanUp()
Definition Field.h:286
void SetByteValue(void const *newValue, size_t const newSize, enum_field_types newType, uint32 length)
Definition Field.cpp:22
uint32 length
Definition Field.h:272
Field()
Definition Field.cpp:9
friend class ResultSet
Definition Field.h:17
friend class PreparedResultSet
Definition Field.h:18
~Field()
Definition Field.cpp:17
std::string GetString() const
Definition Field.h:228
std::array< uint8, S > GetBinary() const
Definition Field.h:254
bool IsNull() const
Definition Field.h:243
double GetDouble() const
Definition Field.h:195
std::vector< uint8 > GetBinary() const
Definition Field.cpp:56
int64 GetInt64() const
Definition Field.h:159
void * value
Definition Field.h:273
bool raw
Definition Field.h:275
int8 GetInt8() const
Definition Field.h:44
uint64 GetUInt64() const
Definition Field.h:141
int16 GetInt16() const
Definition Field.h:87
uint16 GetUInt16() const
Definition Field.h:69
char const * GetCString() const
Definition Field.h:213
float GetFloat() const
Definition Field.h:177
bool IsBinary() const
Definition Field.h:358
struct Field::@103301115010007122255114047010240314374313114334 data
bool IsType(enum_field_types type) const
Definition Field.h:342
void GetBinarySizeChecked(uint8 *buf, size_t size) const
Definition Field.cpp:67
static size_t SizeForType(MYSQL_FIELD *field)
Definition Field.h:292
bool IsNumeric() const
Definition Field.h:347
void SetStructuredValue(char *newValue, enum_field_types newType, uint32 length)
Definition Field.cpp:38
bool GetBool() const
Definition Field.h:21
uint32 GetUInt32() const
Definition Field.h:105
int32 GetInt32() const
Definition Field.h:123