Core/DBLayer:
- Fix a crash related to prepared resultset bind buffering. Fixes issue #3975 - Implement 64bit int fetching functions for preparedresultset NOTE: *Still* experimental, use at own risk. --HG-- branch : trunk
This commit is contained in:
@@ -108,20 +108,26 @@ enum Field::DataTypes ResultSet::ConvertNativeType(enum_field_types mysqlType) c
|
|||||||
void ResultBind::BindResult(uint32& num_rows)
|
void ResultBind::BindResult(uint32& num_rows)
|
||||||
{
|
{
|
||||||
FreeBindBuffer();
|
FreeBindBuffer();
|
||||||
m_fieldCount = mysql_stmt_field_count(m_stmt);
|
|
||||||
if (!m_fieldCount)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_rBind = new MYSQL_BIND[m_fieldCount];
|
|
||||||
memset(m_rBind, 0, sizeof(MYSQL_BIND) * m_fieldCount);
|
|
||||||
|
|
||||||
m_isNull = new my_bool[m_fieldCount];
|
|
||||||
memset(m_isNull, 0, sizeof(my_bool) * m_fieldCount);
|
|
||||||
|
|
||||||
m_length = new unsigned long[m_fieldCount];
|
|
||||||
memset(m_length, 0, sizeof(unsigned long) * m_fieldCount);
|
|
||||||
|
|
||||||
m_res = mysql_stmt_result_metadata(m_stmt);
|
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];
|
||||||
|
|
||||||
|
memset(m_isNull, 0, sizeof(my_bool) * m_fieldCount);
|
||||||
|
memset(m_rBind, 0, sizeof(MYSQL_BIND) * m_fieldCount);
|
||||||
|
memset(m_length, 0, sizeof(unsigned long) * m_fieldCount);
|
||||||
|
|
||||||
//- This is where we store the (entire) resultset
|
//- This is where we store the (entire) resultset
|
||||||
if (mysql_stmt_store_result(m_stmt))
|
if (mysql_stmt_store_result(m_stmt))
|
||||||
@@ -136,11 +142,9 @@ void ResultBind::BindResult(uint32& num_rows)
|
|||||||
while ((field = mysql_fetch_field(m_res)))
|
while ((field = mysql_fetch_field(m_res)))
|
||||||
{
|
{
|
||||||
size_t size = SizeForType(field);
|
size_t size = SizeForType(field);
|
||||||
if (size == 0)
|
|
||||||
size = field->max_length + 1;
|
|
||||||
|
|
||||||
m_rBind[i].buffer_type = field->type;
|
m_rBind[i].buffer_type = field->type;
|
||||||
m_rBind[i].buffer = new char[size];
|
m_rBind[i].buffer = malloc(size);
|
||||||
memset(m_rBind[i].buffer, 0, size);
|
memset(m_rBind[i].buffer, 0, size);
|
||||||
m_rBind[i].buffer_length = size;
|
m_rBind[i].buffer_length = size;
|
||||||
m_rBind[i].length = &m_length[i];
|
m_rBind[i].length = &m_length[i];
|
||||||
@@ -155,6 +159,9 @@ void ResultBind::BindResult(uint32& num_rows)
|
|||||||
if (mysql_stmt_bind_result(m_stmt, m_rBind))
|
if (mysql_stmt_bind_result(m_stmt, m_rBind))
|
||||||
{
|
{
|
||||||
sLog.outSQLDriver("%s:mysql_stmt_bind_result, cannot bind result from MySQL server. Error: %s", __FUNCTION__, mysql_stmt_error(m_stmt));
|
sLog.outSQLDriver("%s:mysql_stmt_bind_result, cannot bind result from MySQL server. Error: %s", __FUNCTION__, mysql_stmt_error(m_stmt));
|
||||||
|
delete[] m_rBind;
|
||||||
|
delete[] m_isNull;
|
||||||
|
delete[] m_length;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,18 +171,13 @@ void ResultBind::BindResult(uint32& num_rows)
|
|||||||
void ResultBind::FreeBindBuffer()
|
void ResultBind::FreeBindBuffer()
|
||||||
{
|
{
|
||||||
for (uint32 i = 0; i < m_fieldCount; ++i)
|
for (uint32 i = 0; i < m_fieldCount; ++i)
|
||||||
{
|
free (m_rBind[i].buffer);
|
||||||
delete[] (char *) m_rBind[i].buffer;
|
|
||||||
m_rBind[i].buffer = NULL;
|
|
||||||
}
|
|
||||||
m_rBind = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResultBind::CleanUp()
|
void ResultBind::CleanUp()
|
||||||
{
|
{
|
||||||
FreeBindBuffer();
|
FreeBindBuffer();
|
||||||
delete[] m_isNull;
|
mysql_stmt_free_result(m_stmt);
|
||||||
delete[] m_length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 PreparedResultSet::GetUInt8(uint32 index)
|
uint8 PreparedResultSet::GetUInt8(uint32 index)
|
||||||
@@ -234,6 +236,22 @@ float PreparedResultSet::GetFloat(uint32 index)
|
|||||||
return *reinterpret_cast<float*>(rbind->m_rBind[index].buffer);
|
return *reinterpret_cast<float*>(rbind->m_rBind[index].buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64 PreparedResultSet::GetUInt64(uint32 index)
|
||||||
|
{
|
||||||
|
if (!CheckFieldIndex(index))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return *reinterpret_cast<uint64*>(rbind->m_rBind[index].buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64 PreparedResultSet::GetInt64(uint32 index)
|
||||||
|
{
|
||||||
|
if (!CheckFieldIndex(index))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return *reinterpret_cast<int64*>(rbind->m_rBind[index].buffer);
|
||||||
|
}
|
||||||
|
|
||||||
std::string PreparedResultSet::GetString(uint32 index)
|
std::string PreparedResultSet::GetString(uint32 index)
|
||||||
{
|
{
|
||||||
if (!CheckFieldIndex(index))
|
if (!CheckFieldIndex(index))
|
||||||
|
|||||||
@@ -101,15 +101,17 @@ class ResultBind
|
|||||||
friend class PreparedResultSet;
|
friend class PreparedResultSet;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ResultBind(MYSQL_STMT* stmt) : m_rBind(NULL), m_stmt(stmt), m_isNull(NULL), m_length(NULL), m_fieldCount(0) {}
|
ResultBind(MYSQL_STMT* stmt) : m_rBind(NULL), m_stmt(stmt), m_isNull(NULL), m_length(NULL), m_res(NULL), m_fieldCount(0) {}
|
||||||
|
|
||||||
~ResultBind()
|
~ResultBind()
|
||||||
{
|
{
|
||||||
|
if (m_res)
|
||||||
|
mysql_free_result(m_res); // metadata
|
||||||
|
|
||||||
if (!m_fieldCount)
|
if (!m_fieldCount)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CleanUp(); // Clean up buffer
|
CleanUp(); // Clean up buffer
|
||||||
mysql_stmt_free_result(m_stmt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BindResult(uint32& num_rows);
|
void BindResult(uint32& num_rows);
|
||||||
@@ -205,6 +207,8 @@ class PreparedResultSet
|
|||||||
int16 GetInt16(uint32 index);
|
int16 GetInt16(uint32 index);
|
||||||
uint32 GetUInt32(uint32 index);
|
uint32 GetUInt32(uint32 index);
|
||||||
int32 GetInt32(uint32 index);
|
int32 GetInt32(uint32 index);
|
||||||
|
uint64 GetUInt64(uint32 index);
|
||||||
|
int64 GetInt64(uint32 index);
|
||||||
float GetFloat(uint32 index);
|
float GetFloat(uint32 index);
|
||||||
std::string GetString(uint32 index);
|
std::string GetString(uint32 index);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user