Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
QueryResult.cpp
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#include "DatabaseEnv.h"
7#include "Log.h"
8
9ResultSet::ResultSet(MYSQL_RES* result, MYSQL_FIELD* fields, uint64 rowCount, uint32 fieldCount) :
10 _rowCount(rowCount),
11 _fieldCount(fieldCount),
12 _result(result),
13 _fields(fields)
14{
17}
18
19PreparedResultSet::PreparedResultSet(MYSQL_STMT* stmt, MYSQL_RES* result, uint64 rowCount, uint32 fieldCount) :
20 m_rowCount(rowCount),
22 m_fieldCount(fieldCount),
23 m_rBind(NULL),
24 m_stmt(stmt),
25 m_res(result),
26 m_isNull(NULL),
27 m_length(NULL)
28{
29 if (!m_res)
30 return;
31
32 if (m_stmt->bind_result_done)
33 {
34 delete[] m_stmt->bind->length;
35 delete[] m_stmt->bind->is_null;
36 }
37
38 m_rBind = new MYSQL_BIND[m_fieldCount];
39 m_isNull = new bool[m_fieldCount];
40 m_length = new unsigned long[m_fieldCount];
41
42 memset(m_isNull, 0, sizeof(bool) * m_fieldCount);
43 memset(m_rBind, 0, sizeof(MYSQL_BIND) * m_fieldCount);
44 memset(m_length, 0, sizeof(unsigned long) * m_fieldCount);
45
46 //- This is where we store the (entire) resultset
47 if (mysql_stmt_store_result(m_stmt))
48 {
49 SF_LOG_WARN("sql.sql", "%s:mysql_stmt_store_result, cannot bind result from MySQL server. Error: %s", __FUNCTION__, mysql_stmt_error(m_stmt));
50 delete[] m_rBind;
51 delete[] m_isNull;
52 delete[] m_length;
53 return;
54 }
55
56 //- This is where we prepare the buffer based on metadata
57 uint32 i = 0;
58 MYSQL_FIELD* field = mysql_fetch_field(m_res);
59 while (field)
60 {
61 size_t size = Field::SizeForType(field);
62
63 m_rBind[i].buffer_type = field->type;
64 m_rBind[i].buffer = malloc(size);
65 memset(m_rBind[i].buffer, 0, size);
66 m_rBind[i].buffer_length = size;
67 m_rBind[i].length = &m_length[i];
68 m_rBind[i].is_null = &m_isNull[i];
69 m_rBind[i].error = NULL;
70 m_rBind[i].is_unsigned = field->flags & UNSIGNED_FLAG;
71
72 ++i;
73 field = mysql_fetch_field(m_res);
74 }
75
76 //- This is where we bind the bind the buffer to the statement
77 if (mysql_stmt_bind_result(m_stmt, m_rBind))
78 {
79 SF_LOG_WARN("sql.sql", "%s:mysql_stmt_bind_result, cannot bind result from MySQL server. Error: %s", __FUNCTION__, mysql_stmt_error(m_stmt));
80 delete[] m_rBind;
81 delete[] m_isNull;
82 delete[] m_length;
83 return;
84 }
85
86 m_rowCount = mysql_stmt_num_rows(m_stmt);
87
88 m_rows.resize(uint32(m_rowCount));
89 while (_NextRow())
90 {
92 for (uint64 fIndex = 0; fIndex < m_fieldCount; ++fIndex)
93 {
94 if (!*m_rBind[fIndex].is_null)
95 m_rows[uint32(m_rowPosition)][fIndex].SetByteValue(m_rBind[fIndex].buffer,
96 m_rBind[fIndex].buffer_length,
97 m_rBind[fIndex].buffer_type,
98 *m_rBind[fIndex].length);
99 else
100 switch (m_rBind[fIndex].buffer_type)
101 {
102 case MYSQL_TYPE_TINY_BLOB:
103 case MYSQL_TYPE_MEDIUM_BLOB:
104 case MYSQL_TYPE_LONG_BLOB:
105 case MYSQL_TYPE_BLOB:
106 case MYSQL_TYPE_STRING:
107 case MYSQL_TYPE_VAR_STRING:
108 m_rows[uint32(m_rowPosition)][fIndex].SetByteValue("",
109 m_rBind[fIndex].buffer_length,
110 m_rBind[fIndex].buffer_type,
111 *m_rBind[fIndex].length);
112 break;
113 default:
114 m_rows[uint32(m_rowPosition)][fIndex].SetByteValue(0,
115 m_rBind[fIndex].buffer_length,
116 m_rBind[fIndex].buffer_type,
117 *m_rBind[fIndex].length);
118 }
119 }
121 }
122 m_rowPosition = 0;
123
125 CleanUp();
126}
127
132
134{
135 for (uint32 i = 0; i < uint32(m_rowCount); ++i)
136 delete[] m_rows[i];
137}
138
140{
141 MYSQL_ROW row;
142
143 if (!_result)
144 return false;
145
146 row = mysql_fetch_row(_result);
147 if (!row)
148 {
149 CleanUp();
150 return false;
151 }
152
153 unsigned long* lengths = mysql_fetch_lengths(_result);
154 if (!lengths)
155 {
156 CleanUp();
157 return false;
158 }
159
160 for (uint32 i = 0; i < _fieldCount; i++)
161 _currentRow[i].SetStructuredValue(row[i], _fields[i].type, lengths[i]);
162
163 return true;
164}
165
167{
170 if (++m_rowPosition >= m_rowCount)
171 return false;
172
173 return true;
174}
175
177{
181 return false;
182
183 int retval = mysql_stmt_fetch(m_stmt);
184
185 if (!retval || retval == MYSQL_DATA_TRUNCATED)
186 retval = true;
187
188 if (retval == MYSQL_NO_DATA)
189 retval = false;
190
191 return retval;
192}
193
195{
196 if (_currentRow)
197 {
198 delete[] _currentRow;
199 _currentRow = NULL;
200 }
201
202 if (_result)
203 {
204 mysql_free_result(_result);
205 _result = NULL;
206 }
207}
208
210{
212 if (m_res)
213 mysql_free_result(m_res);
214
216 mysql_stmt_free_result(m_stmt);
217
218 delete[] m_rBind;
219}
220
222{
223 for (uint32 i = 0; i < m_fieldCount; ++i)
224 free(m_rBind[i].buffer);
225}
std::uint32_t uint32
Definition Define.h:77
std::uint64_t uint64
Definition Define.h:76
#define ASSERT
Definition Errors.h:29
#define SF_LOG_WARN(filterType__,...)
Definition Log.h:140
Definition Field.h:16
static size_t SizeForType(MYSQL_FIELD *field)
Definition Field.h:292
std::vector< Field * > m_rows
Definition QueryResult.h:74
MYSQL_STMT * m_stmt
Definition QueryResult.h:81
PreparedResultSet(MYSQL_STMT *stmt, MYSQL_RES *result, uint64 rowCount, uint32 fieldCount)
MYSQL_BIND * m_rBind
Definition QueryResult.h:80
unsigned long * m_length
Definition QueryResult.h:85
MYSQL_RES * m_res
Definition QueryResult.h:82
uint32 _fieldCount
Definition QueryResult.h:38
Field * _currentRow
Definition QueryResult.h:37
uint64 _rowCount
Definition QueryResult.h:36
void CleanUp()
MYSQL_RES * _result
Definition QueryResult.h:42
bool NextRow()
ResultSet(MYSQL_RES *result, MYSQL_FIELD *fields, uint64 rowCount, uint32 fieldCount)
MYSQL_FIELD * _fields
Definition QueryResult.h:43