aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/database/Database/Field.cpp10
-rw-r--r--src/server/database/Database/Field.h14
-rw-r--r--src/server/database/Database/PreparedStatement.cpp37
-rw-r--r--src/server/database/Database/PreparedStatement.h6
-rw-r--r--src/server/database/Database/QueryResult.cpp10
5 files changed, 59 insertions, 18 deletions
diff --git a/src/server/database/Database/Field.cpp b/src/server/database/Database/Field.cpp
index 20a42871b91..efddd005c06 100644
--- a/src/server/database/Database/Field.cpp
+++ b/src/server/database/Database/Field.cpp
@@ -39,7 +39,7 @@ void Field::SetByteValue(void* newValue, enum_field_types newType, uint32 length
data.raw = true;
}
-void Field::SetStructuredValue(char* newValue, enum_field_types newType)
+void Field::SetStructuredValue(char* newValue, enum_field_types newType, uint32 length)
{
if (data.value)
CleanUp();
@@ -47,10 +47,10 @@ 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;
+ data.value = new char[length + 1];
+ memcpy(data.value, newValue, length);
+ *(reinterpret_cast<char*>(data.value) + length) = '\0';
+ data.length = length;
}
data.type = newType;
diff --git a/src/server/database/Database/Field.h b/src/server/database/Database/Field.h
index 123e25dbbf3..6089c3001fb 100644
--- a/src/server/database/Database/Field.h
+++ b/src/server/database/Database/Field.h
@@ -271,7 +271,6 @@ class TC_DATABASE_API Field
}
#endif
return static_cast<char const*>(data.value);
-
}
std::string GetString() const
@@ -286,6 +285,17 @@ class TC_DATABASE_API Field
return std::string(string, 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
{
return data.value == NULL;
@@ -313,7 +323,7 @@ class TC_DATABASE_API Field
#pragma pack(pop)
void SetByteValue(void* newValue, enum_field_types newType, uint32 length);
- void SetStructuredValue(char* newValue, enum_field_types newType);
+ void SetStructuredValue(char* newValue, enum_field_types newType, uint32 length);
void CleanUp()
{
diff --git a/src/server/database/Database/PreparedStatement.cpp b/src/server/database/Database/PreparedStatement.cpp
index 119f1d4c93b..d32b3306995 100644
--- a/src/server/database/Database/PreparedStatement.cpp
+++ b/src/server/database/Database/PreparedStatement.cpp
@@ -68,7 +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);
break;
case TYPE_NULL:
m_stmt->setNull(i);
@@ -186,10 +189,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 +352,26 @@ 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];
- uint32 len = uint32(strlen(value) + 1);
- param->buffer_type = MYSQL_TYPE_VAR_STRING;
+ uint32 len = uint32(value.size());
+ param->buffer_type = MYSQL_TYPE_BLOB;
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;
+ param->buffer_type = MYSQL_TYPE_VAR_STRING;
+ }
- memcpy(param->buffer, value, len);
+ memcpy(param->buffer, value.data(), len);
}
void MySQLPreparedStatement::setNull(const uint8 index)
@@ -429,7 +447,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/database/Database/PreparedStatement.h b/src/server/database/Database/PreparedStatement.h
index faaec27014f..d7508dbae1f 100644
--- a/src/server/database/Database/PreparedStatement.h
+++ b/src/server/database/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 TC_DATABASE_API 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 TC_DATABASE_API 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/database/Database/QueryResult.cpp b/src/server/database/Database/QueryResult.cpp
index db9e737830c..44f29ce41b8 100644
--- a/src/server/database/Database/QueryResult.cpp
+++ b/src/server/database/Database/QueryResult.cpp
@@ -187,8 +187,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]);
return true;
}