diff options
-rw-r--r-- | src/server/shared/Database/Field.cpp | 16 | ||||
-rw-r--r-- | src/server/shared/Database/Field.h | 16 | ||||
-rw-r--r-- | src/server/shared/Database/PreparedStatement.cpp | 31 | ||||
-rw-r--r-- | src/server/shared/Database/PreparedStatement.h | 6 | ||||
-rw-r--r-- | src/server/shared/Database/QueryResult.cpp | 10 |
5 files changed, 61 insertions, 18 deletions
diff --git a/src/server/shared/Database/Field.cpp b/src/server/shared/Database/Field.cpp index 866a96b58b6..f1741f98cc3 100644 --- a/src/server/shared/Database/Field.cpp +++ b/src/server/shared/Database/Field.cpp @@ -46,7 +46,7 @@ void Field::SetByteValue(const void* newValue, const size_t newSize, enum_field_ data.raw = true; } -void Field::SetStructuredValue(char* newValue, enum_field_types newType) +void Field::SetStructuredValue(char* newValue, enum_field_types newType, uint32 length, bool isBinary) { if (data.value) CleanUp(); @@ -54,10 +54,16 @@ void Field::SetStructuredValue(char* newValue, enum_field_types newType) // This value stores somewhat structured data that needs function style casting if (newValue) { - size_t size = strlen(newValue); - data.value = new char [size+1]; - strcpy((char*)data.value, newValue); - data.length = size; + if (!isBinary) + { + data.value = new char[length + 1]; + *(reinterpret_cast<char*>(data.value) + length) = '\0'; + } + else + data.value = new char[length]; + + memcpy(data.value, newValue, length); + data.length = length; } data.type = newType; diff --git a/src/server/shared/Database/Field.h b/src/server/shared/Database/Field.h index 2e888be5ed3..99f98572a56 100644 --- a/src/server/shared/Database/Field.h +++ b/src/server/shared/Database/Field.h @@ -228,7 +228,6 @@ class Field } #endif return static_cast<char const*>(data.value); - } std::string GetString() const @@ -243,7 +242,18 @@ class Field string = ""; return std::string(string, data.length); } - return std::string((char*)data.value); + return std::string((char*)data.value, data.length); + } + + std::vector<uint8> GetBinary() const + { + std::vector<uint8> result; + if (!data.value || !data.length) + return result; + + result.resize(data.length); + memcpy(result.data(), data.value, data.length); + return result; } bool IsNull() const @@ -274,7 +284,7 @@ class Field #endif void SetByteValue(void const* newValue, size_t const newSize, enum_field_types newType, uint32 length); - void SetStructuredValue(char* newValue, enum_field_types newType); + void SetStructuredValue(char* newValue, enum_field_types newType, uint32 length, bool isBinary); void CleanUp() { diff --git a/src/server/shared/Database/PreparedStatement.cpp b/src/server/shared/Database/PreparedStatement.cpp index 23c50ac2ef8..1f036b5bf0a 100644 --- a/src/server/shared/Database/PreparedStatement.cpp +++ b/src/server/shared/Database/PreparedStatement.cpp @@ -68,8 +68,10 @@ void PreparedStatement::BindParameters() m_stmt->setDouble(i, statement_data[i].data.d); break; case TYPE_STRING: - m_stmt->setString(i, statement_data[i].str.c_str()); + m_stmt->setBinary(i, statement_data[i].binary, true); break; + case TYPE_BINARY: + m_stmt->setBinary(i, statement_data[i].binary, false); case TYPE_NULL: m_stmt->setNull(i); break; @@ -186,10 +188,20 @@ void PreparedStatement::setString(const uint8 index, const std::string& value) if (index >= statement_data.size()) statement_data.resize(index+1); - statement_data[index].str = value; + statement_data[index].binary.resize(value.length() + 1); + memcpy(statement_data[index].binary.data(), value.c_str(), value.length() + 1); statement_data[index].type = TYPE_STRING; } +void PreparedStatement::setBinary(const uint8 index, const std::vector<uint8>& value) +{ + if (index >= statement_data.size()) + statement_data.resize(index + 1); + + statement_data[index].binary = value; + statement_data[index].type = TYPE_BINARY; +} + void PreparedStatement::setNull(const uint8 index) { if (index >= statement_data.size()) @@ -339,21 +351,23 @@ void MySQLPreparedStatement::setDouble(const uint8 index, const double value) setValue(param, MYSQL_TYPE_DOUBLE, &value, sizeof(double), (value > 0.0f)); } -void MySQLPreparedStatement::setString(const uint8 index, const char* value) +void MySQLPreparedStatement::setBinary(const uint8 index, const std::vector<uint8>& value, bool isString) { CheckValidIndex(index); m_paramsSet[index] = true; MYSQL_BIND* param = &m_bind[index]; - size_t len = strlen(value) + 1; + size_t len = value.size(); param->buffer_type = MYSQL_TYPE_VAR_STRING; delete [] static_cast<char *>(param->buffer); param->buffer = new char[len]; param->buffer_length = len; param->is_null_value = 0; delete param->length; - param->length = new unsigned long(len-1); + param->length = new unsigned long(len); + if (isString) + *param->length -= 1; - memcpy(param->buffer, value, len); + memcpy(param->buffer, value.data(), len); } void MySQLPreparedStatement::setNull(const uint8 index) @@ -429,7 +443,10 @@ std::string MySQLPreparedStatement::getQueryString(std::string const& sqlPattern ss << m_stmt->statement_data[i].data.d; break; case TYPE_STRING: - ss << '\'' << m_stmt->statement_data[i].str << '\''; + ss << '\'' << (char const*)m_stmt->statement_data[i].binary.data() << '\''; + break; + case TYPE_BINARY: + ss << "BINARY"; break; case TYPE_NULL: ss << "NULL"; diff --git a/src/server/shared/Database/PreparedStatement.h b/src/server/shared/Database/PreparedStatement.h index 5af52cde016..3ab27902246 100644 --- a/src/server/shared/Database/PreparedStatement.h +++ b/src/server/shared/Database/PreparedStatement.h @@ -56,6 +56,7 @@ enum PreparedStatementValueType TYPE_FLOAT, TYPE_DOUBLE, TYPE_STRING, + TYPE_BINARY, TYPE_NULL }; @@ -63,7 +64,7 @@ struct PreparedStatementData { PreparedStatementDataUnion data; PreparedStatementValueType type; - std::string str; + std::vector<uint8> binary; }; //- Forward declare @@ -92,6 +93,7 @@ class PreparedStatement void setFloat(const uint8 index, const float value); void setDouble(const uint8 index, const double value); void setString(const uint8 index, const std::string& value); + void setBinary(const uint8 index, const std::vector<uint8>& value); void setNull(const uint8 index); protected: @@ -129,7 +131,7 @@ class MySQLPreparedStatement void setInt64(const uint8 index, const int64 value); void setFloat(const uint8 index, const float value); void setDouble(const uint8 index, const double value); - void setString(const uint8 index, const char* value); + void setBinary(const uint8 index, const std::vector<uint8>& value, bool isString); void setNull(const uint8 index); protected: diff --git a/src/server/shared/Database/QueryResult.cpp b/src/server/shared/Database/QueryResult.cpp index a7b8ec2b107..a6d9c64622a 100644 --- a/src/server/shared/Database/QueryResult.cpp +++ b/src/server/shared/Database/QueryResult.cpp @@ -163,8 +163,16 @@ bool ResultSet::NextRow() return false; } + unsigned long* lengths = mysql_fetch_lengths(_result); + if (!lengths) + { + TC_LOG_WARN("sql.sql", "%s:mysql_fetch_lengths, cannot retrieve value lengths. Error %s.", __FUNCTION__, mysql_error(_result->handle)); + CleanUp(); + return false; + } + for (uint32 i = 0; i < _fieldCount; i++) - _currentRow[i].SetStructuredValue(row[i], _fields[i].type); + _currentRow[i].SetStructuredValue(row[i], _fields[i].type, lengths[i], (_fields[i].flags & BINARY_FLAG) != 0); return true; } |