diff options
author | Spp <spp@jorge.gr> | 2013-01-02 12:22:50 +0100 |
---|---|---|
committer | Spp <spp@jorge.gr> | 2013-01-02 12:22:50 +0100 |
commit | ebd14b4f01cc64a2a488bdbb1046897cc4da8e9a (patch) | |
tree | 2175f0dda7c795d90918291f95f84f28c3047612 /src/server/shared/Database/PreparedStatement.cpp | |
parent | 5280a77fe1e9e4a26d98b59a31715d5632238bb2 (diff) |
Core/Mysql: Multiple changes
- added support for setting NULL column values to MySQL wrapper in core
- replaced nonstandard strdup function and manual memory management with std::string
- fixed bug in MySQLPreparedStatement::getQueryString method, it failed when string parameter contained embedded '?' symbols
- fixed memory leak in MySQLPreparedStatement::setString method
Diffstat (limited to 'src/server/shared/Database/PreparedStatement.cpp')
-rw-r--r-- | src/server/shared/Database/PreparedStatement.cpp | 82 |
1 files changed, 58 insertions, 24 deletions
diff --git a/src/server/shared/Database/PreparedStatement.cpp b/src/server/shared/Database/PreparedStatement.cpp index 6403592eed2..3256c3c9db3 100644 --- a/src/server/shared/Database/PreparedStatement.cpp +++ b/src/server/shared/Database/PreparedStatement.cpp @@ -33,7 +33,7 @@ void PreparedStatement::BindParameters() { ASSERT (m_stmt); - uint8 i = 0; + uint32 i = 0; for (; i < statement_data.size(); i++) { switch (statement_data[i].type) @@ -74,6 +74,9 @@ void PreparedStatement::BindParameters() case TYPE_STRING: m_stmt->setString(i, statement_data[i].str.c_str()); break; + case TYPE_NULL: + m_stmt->setNull(i); + break; } } #ifdef _DEBUG @@ -191,6 +194,14 @@ void PreparedStatement::setString(const uint8 index, const std::string& value) statement_data[index].type = TYPE_STRING; } +void PreparedStatement::setNull(const uint8 index) +{ + if (index >= statement_data.size()) + statement_data.resize(index+1); + + statement_data[index].type = TYPE_NULL; +} + MySQLPreparedStatement::MySQLPreparedStatement(MYSQL_STMT* stmt) : m_Mstmt(stmt), m_bind(NULL) @@ -230,11 +241,16 @@ void MySQLPreparedStatement::ClearParameters() } } +static bool ParementerIndexAssertFail(uint32 stmtIndex, uint8 index, uint32 paramCount) +{ + sLog->outError(LOG_FILTER_SQL_DRIVER, "Attempted to bind parameter %u%s on a PreparedStatement %u (statement has only %u parameters)", uint32(index) + 1, (index == 1 ? "st" : (index == 2 ? "nd" : (index == 3 ? "rd" : "nd"))), stmtIndex, paramCount); + return false; +} + //- Bind on mysql level bool MySQLPreparedStatement::CheckValidIndex(uint8 index) { - if (index >= m_paramCount) - return false; + ASSERT(index < m_paramCount || ParementerIndexAssertFail(m_stmt->m_index, index, m_paramCount)); if (m_paramsSet[index]) sLog->outWarn(LOG_FILTER_SQL, "[WARNING] Prepared Statement (id: %u) trying to bind value on already bound index (%u).", m_stmt->m_index, index); @@ -337,11 +353,26 @@ void MySQLPreparedStatement::setString(const uint8 index, const char* value) param->buffer = new char[len]; param->buffer_length = len; param->is_null_value = 0; + delete param->length; param->length = new unsigned long(len-1); memcpy(param->buffer, value, len); } +void MySQLPreparedStatement::setNull(const uint8 index) +{ + CheckValidIndex(index); + m_paramsSet[index] = true; + MYSQL_BIND* param = &m_bind[index]; + param->buffer_type = MYSQL_TYPE_NULL; + delete [] static_cast<char *>(param->buffer); + param->buffer = NULL; + param->buffer_length = 0; + param->is_null_value = 1; + delete param->length; + param->length = NULL; +} + void MySQLPreparedStatement::setValue(MYSQL_BIND* param, enum_field_types type, const void* value, uint32 len, bool isUnsigned) { param->buffer_type = type; @@ -355,59 +386,62 @@ void MySQLPreparedStatement::setValue(MYSQL_BIND* param, enum_field_types type, memcpy(param->buffer, value, len); } -std::string MySQLPreparedStatement::getQueryString(const char *query) +std::string MySQLPreparedStatement::getQueryString(std::string const &sqlPattern) const { - std::string queryString = query; + std::string queryString = sqlPattern; - uint32 pos = 0; + size_t pos = 0; for (uint32 i = 0; i < m_stmt->statement_data.size(); i++) { - pos = queryString.find("?", pos); - std::stringstream replace; - - replace << '\''; + pos = queryString.find('?', pos); + std::stringstream ss; switch (m_stmt->statement_data[i].type) { case TYPE_BOOL: - replace << (m_stmt->statement_data[i].data.boolean ? '1' : '0'); + ss << uint16(m_stmt->statement_data[i].data.boolean); break; case TYPE_UI8: - replace << uint16(m_stmt->statement_data[i].data.ui8); // stringstream will append a character with that code instead of numeric representation + ss << uint16(m_stmt->statement_data[i].data.ui8); // stringstream will append a character with that code instead of numeric representation break; case TYPE_UI16: - replace << m_stmt->statement_data[i].data.ui16; + ss << m_stmt->statement_data[i].data.ui16; break; case TYPE_UI32: - replace << m_stmt->statement_data[i].data.ui32; + ss << m_stmt->statement_data[i].data.ui32; break; case TYPE_I8: - replace << int16(m_stmt->statement_data[i].data.i8); // stringstream will append a character with that code instead of numeric representation + ss << int16(m_stmt->statement_data[i].data.i8); // stringstream will append a character with that code instead of numeric representation break; case TYPE_I16: - replace << m_stmt->statement_data[i].data.i16; + ss << m_stmt->statement_data[i].data.i16; break; case TYPE_I32: - replace << m_stmt->statement_data[i].data.i32; + ss << m_stmt->statement_data[i].data.i32; break; case TYPE_UI64: - replace << m_stmt->statement_data[i].data.ui64; + ss << m_stmt->statement_data[i].data.ui64; break; case TYPE_I64: - replace << m_stmt->statement_data[i].data.i64; + ss << m_stmt->statement_data[i].data.i64; break; case TYPE_FLOAT: - replace << m_stmt->statement_data[i].data.f; + ss << m_stmt->statement_data[i].data.f; break; case TYPE_DOUBLE: - replace << m_stmt->statement_data[i].data.d; + ss << m_stmt->statement_data[i].data.d; break; case TYPE_STRING: - replace << m_stmt->statement_data[i].str; + ss << '\'' << m_stmt->statement_data[i].str << '\''; + break; + case TYPE_NULL: + ss << "NULL"; break; } - replace << '\''; - queryString.replace(pos, 1, replace.str()); + + std::string replaceStr = ss.str(); + queryString.replace(pos, 1, replaceStr); + pos += replaceStr.length(); } return queryString; |