aboutsummaryrefslogtreecommitdiff
path: root/src/server/shared/Database/QueryResult.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/shared/Database/QueryResult.cpp')
-rw-r--r--src/server/shared/Database/QueryResult.cpp304
1 files changed, 115 insertions, 189 deletions
diff --git a/src/server/shared/Database/QueryResult.cpp b/src/server/shared/Database/QueryResult.cpp
index 283734b80b7..b6a4e8477c9 100644
--- a/src/server/shared/Database/QueryResult.cpp
+++ b/src/server/shared/Database/QueryResult.cpp
@@ -21,106 +21,29 @@
#include "DatabaseEnv.h"
#include "Log.h"
-ResultSet::ResultSet(MYSQL_RES *result, MYSQL_FIELD *fields, uint64 rowCount, uint32 fieldCount)
-: mFieldCount(fieldCount)
-, mRowCount(rowCount)
-, mResult(result)
+ResultSet::ResultSet(MYSQL_RES *result, MYSQL_FIELD *fields, uint64 rowCount, uint32 fieldCount) :
+m_result(result),
+m_fields(fields),
+m_rowCount(rowCount),
+m_fieldCount(fieldCount)
+{
+ m_currentRow = new Field[m_fieldCount];
+ ASSERT(m_currentRow);
+}
+
+PreparedResultSet::PreparedResultSet(MYSQL_STMT* stmt, MYSQL_RES *result, MYSQL_FIELD *fields, uint64 rowCount, uint32 fieldCount) :
+m_rBind(NULL),
+m_stmt(stmt),
+m_res(result),
+m_isNull(NULL),
+m_length(NULL),
+m_rowCount(rowCount),
+m_fieldCount(fieldCount),
+m_rowPosition(0)
{
- mCurrentRow = new Field[mFieldCount];
- ASSERT(mCurrentRow);
-
- for (uint32 i = 0; i < mFieldCount; i++)
- mCurrentRow[i].SetType(ConvertNativeType(fields[i].type));
-}
-
-ResultSet::~ResultSet()
-{
- EndQuery();
-}
-
-bool ResultSet::NextRow()
-{
- MYSQL_ROW row;
-
- if (!mResult)
- return false;
-
- row = mysql_fetch_row(mResult);
- if (!row)
- {
- EndQuery();
- return false;
- }
-
- for (uint32 i = 0; i < mFieldCount; i++)
- mCurrentRow[i].SetValue(row[i]);
-
- return true;
-}
-
-void ResultSet::EndQuery()
-{
- if (mCurrentRow)
- {
- delete [] mCurrentRow;
- mCurrentRow = 0;
- }
-
- if (mResult)
- {
- mysql_free_result(mResult);
- mResult = 0;
- }
-}
-
-enum Field::DataTypes ResultSet::ConvertNativeType(enum_field_types mysqlType) const
-{
- switch (mysqlType)
- {
- case FIELD_TYPE_TIMESTAMP:
- case FIELD_TYPE_DATE:
- case FIELD_TYPE_TIME:
- case FIELD_TYPE_DATETIME:
- case FIELD_TYPE_YEAR:
- case FIELD_TYPE_STRING:
- case FIELD_TYPE_VAR_STRING:
- case FIELD_TYPE_BLOB:
- case FIELD_TYPE_SET:
- case FIELD_TYPE_NULL:
- return Field::DB_TYPE_STRING;
- case FIELD_TYPE_TINY:
-
- case FIELD_TYPE_SHORT:
- case FIELD_TYPE_LONG:
- case FIELD_TYPE_INT24:
- case FIELD_TYPE_LONGLONG:
- case FIELD_TYPE_ENUM:
- return Field::DB_TYPE_INTEGER;
- case FIELD_TYPE_DECIMAL:
- case FIELD_TYPE_FLOAT:
- case FIELD_TYPE_DOUBLE:
- return Field::DB_TYPE_FLOAT;
- default:
- return Field::DB_TYPE_UNKNOWN;
- }
-}
-
-void ResultBind::BindResult(uint64& num_rows)
-{
- FreeBindBuffer();
-
- m_res = mysql_stmt_result_metadata(m_stmt);
if (!m_res)
return;
- m_fieldCount = mysql_stmt_field_count(m_stmt);
-
- if (m_stmt->bind_result_done)
- {
- delete[] m_stmt->bind->length;
- delete[] m_stmt->bind->is_null;
- }
-
m_rBind = new MYSQL_BIND[m_fieldCount];
m_isNull = new my_bool[m_fieldCount];
m_length = new unsigned long[m_fieldCount];
@@ -141,7 +64,7 @@ void ResultBind::BindResult(uint64& num_rows)
MYSQL_FIELD* field;
while ((field = mysql_fetch_field(m_res)))
{
- size_t size = SizeForType(field);
+ size_t size = Field::SizeForType(field);
m_rBind[i].buffer_type = field->type;
m_rBind[i].buffer = malloc(size);
@@ -165,133 +88,136 @@ void ResultBind::BindResult(uint64& num_rows)
return;
}
- num_rows = mysql_stmt_num_rows(m_stmt);
-}
-
-void ResultBind::FreeBindBuffer()
-{
- for (uint32 i = 0; i < m_fieldCount; ++i)
- free (m_rBind[i].buffer);
-}
-
-void ResultBind::CleanUp()
-{
- if (m_res)
- mysql_free_result(m_res);
+ m_rowCount = mysql_stmt_num_rows(m_stmt);
- FreeBindBuffer();
- mysql_stmt_free_result(m_stmt);
+ m_rows.resize(m_rowCount);
+ while (_NextRow())
+ {
+ m_rows[m_rowPosition] = new Field[m_fieldCount];
+ for (uint64 fIndex = 0; fIndex < m_fieldCount; ++fIndex)
+ {
+ if (!*m_rBind[fIndex].is_null)
+ m_rows[m_rowPosition][fIndex].SetByteValue( m_rBind[fIndex].buffer,
+ m_rBind[fIndex].buffer_length,
+ m_rBind[fIndex].buffer_type,
+ *m_rBind[fIndex].length );
+ else
+ switch (m_rBind[fIndex].buffer_type)
+ {
+ 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:
+ m_rows[m_rowPosition][fIndex].SetByteValue( "",
+ m_rBind[fIndex].buffer_length,
+ m_rBind[fIndex].buffer_type,
+ *m_rBind[fIndex].length );
+ break;
+ default:
+ m_rows[m_rowPosition][fIndex].SetByteValue( 0,
+ m_rBind[fIndex].buffer_length,
+ m_rBind[fIndex].buffer_type,
+ *m_rBind[fIndex].length );
+ }
+ }
+ m_rowPosition++;
+ }
+ m_rowPosition = 0;
- delete[] m_rBind;
+ /// All data is buffered, let go of mysql c api structures
+ CleanUp();
}
-bool PreparedResultSet::GetBool(uint32 index)
+ResultSet::~ResultSet()
{
- // TODO: Perhaps start storing data in genuine bool formats in tables
- return GetUInt8(index) == 1 ? true : false;
+ CleanUp();
}
-uint8 PreparedResultSet::GetUInt8(uint32 index)
+PreparedResultSet::~PreparedResultSet()
{
- if (!CheckFieldIndex(index))
- return 0;
-
- return *reinterpret_cast<uint8*>(rbind->m_rBind[index].buffer);
+ for (uint64 i = 0; i < m_rowCount; ++i)
+ delete[] m_rows[i];
}
-int8 PreparedResultSet::GetInt8(uint32 index)
+bool ResultSet::NextRow()
{
- if (!CheckFieldIndex(index))
- return 0;
-
- return *reinterpret_cast<int8*>(rbind->m_rBind[index].buffer);
-}
+ MYSQL_ROW row;
-uint16 PreparedResultSet::GetUInt16(uint32 index)
-{
- if (!CheckFieldIndex(index))
- return 0;
+ if (!m_result)
+ return false;
- return *reinterpret_cast<uint16*>(rbind->m_rBind[index].buffer);
-}
+ row = mysql_fetch_row(m_result);
+ if (!row)
+ {
+ CleanUp();
+ return false;
+ }
-int16 PreparedResultSet::GetInt16(uint32 index)
-{
- if (!CheckFieldIndex(index))
- return 0;
+ for (uint32 i = 0; i < m_fieldCount; i++)
+ m_currentRow[i].SetStructuredValue(row[i], m_fields[i].type, Field::SizeForType(&m_fields[i]));
- return *reinterpret_cast<int16*>(rbind->m_rBind[index].buffer);
+ return true;
}
-uint32 PreparedResultSet::GetUInt32(uint32 index)
+bool PreparedResultSet::NextRow()
{
- if (!CheckFieldIndex(index))
- return 0;
+ /// Only updates the m_rowPosition so upper level code knows in which element
+ /// of the rows vector to look
+ if (++m_rowPosition >= m_rowCount)
+ return false;
- return *reinterpret_cast<uint32*>(rbind->m_rBind[index].buffer);
+ return true;
}
-int32 PreparedResultSet::GetInt32(uint32 index)
+bool PreparedResultSet::_NextRow()
{
- if (!CheckFieldIndex(index))
- return 0;
-
- return *reinterpret_cast<int32*>(rbind->m_rBind[index].buffer);
-}
+ /// Only called in low-level code, namely the constructor
+ /// Will iterate over every row of data and buffer it
+ if (m_rowPosition >= m_rowCount)
+ return false;
-float PreparedResultSet::GetFloat(uint32 index)
-{
- if (!CheckFieldIndex(index))
- return 0;
+ int retval = mysql_stmt_fetch( m_stmt );
- return *reinterpret_cast<float*>(rbind->m_rBind[index].buffer);
-}
+ if (!retval || retval == MYSQL_DATA_TRUNCATED)
+ retval = true;
-uint64 PreparedResultSet::GetUInt64(uint32 index)
-{
- if (!CheckFieldIndex(index))
- return 0;
+ if (retval == MYSQL_NO_DATA)
+ retval = false;
- return *reinterpret_cast<uint64*>(rbind->m_rBind[index].buffer);
+ return retval;
}
-int64 PreparedResultSet::GetInt64(uint32 index)
+void ResultSet::CleanUp()
{
- if (!CheckFieldIndex(index))
- return 0;
+ if (m_currentRow)
+ {
+ delete [] m_currentRow;
+ m_currentRow = NULL;
+ }
- return *reinterpret_cast<int64*>(rbind->m_rBind[index].buffer);
+ if (m_result)
+ {
+ mysql_free_result(m_result);
+ m_result = NULL;
+ }
}
-std::string PreparedResultSet::GetString(uint32 index)
+void PreparedResultSet::CleanUp()
{
- if (!CheckFieldIndex(index))
- return std::string("");
-
- return std::string(static_cast<char const*>(rbind->m_rBind[index].buffer), *rbind->m_rBind[index].length);
-}
+ /// More of the in our code allocated sources are deallocated by the poorly documented mysql c api
+ if (m_res)
+ mysql_free_result(m_res);
-const char* PreparedResultSet::GetCString(uint32 index)
-{
- if (!CheckFieldIndex(index))
- return '\0';
+ FreeBindBuffer();
+ mysql_stmt_free_result(m_stmt);
- return static_cast<char const*>(rbind->m_rBind[index].buffer);
+ delete[] m_rBind;
}
-bool PreparedResultSet::NextRow()
+void PreparedResultSet::FreeBindBuffer()
{
- if (row_position >= num_rows)
- return false;
-
- int retval = mysql_stmt_fetch( rbind->m_stmt );
-
- if (!retval || retval == MYSQL_DATA_TRUNCATED)
- retval = true;
-
- if (retval == MYSQL_NO_DATA)
- retval = false;
-
- ++row_position;
- return retval;
-} \ No newline at end of file
+ for (uint32 i = 0; i < m_fieldCount; ++i)
+ free (m_rBind[i].buffer);
+}