diff options
Diffstat (limited to 'src/server/shared/Database/QueryResult.cpp')
-rw-r--r-- | src/server/shared/Database/QueryResult.cpp | 304 |
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); +} |