I have a helper function for using prepared statements with mysql. All works well as long as i dont want to retrieve any results.
If i want to retrieve a result (e.g. simple long ID) im getting a warning from visual studio debugger that the stack is corrupted around my ID variable.
Header bool RunPreparedStatement(std::string query, std::vector paramList, std::string& errbuf, int* affected_rows, bool fetchResultID = false, int32* result_id=0, bool fetchInsertID = false, int32* last_insert_id=0);
bool RunPreparedStatement(std::string sql, std::vector<MYSQL_BIND> paramList, std::string& errStr, int* affected_rows, bool fetchResultID, int32* result_id, bool fetchInsertID, int32* last_insert_id) {
char errbuf[MYSQL_ERRMSG_SIZE];
int numParams = paramList.size();
bool fetchResult = fetchResultID;
if(numParams == 0) {
errStr = "0 parameters supplied";
return false;
}
MYSQL_STMT *stmt = mysql_stmt_init(&mysql);
if (!stmt) {
errStr = "mysql_stmt_init(), out of memory";
return false;
}
if (mysql_stmt_prepare(stmt, sql.c_str(), sql.length())) {
errStr = "mysql_stmt_prepare() failed ";
errStr.append(mysql_stmt_error(stmt));
return false;
}
int param_count= mysql_stmt_param_count(stmt);
if (param_count != numParams) /* validate parameter count */{
errStr = "invalid parameter count returned by MySQL";
return false;
}
if (mysql_stmt_bind_param(stmt, ¶mList[0])) {
errStr = "mysql_stmt_bind_param() failed ";
errStr.append(mysql_stmt_error(stmt));
return false;
}
int32 id = 0;
MYSQL_BIND resultParam1;
BindValue(&resultParam1,MYSQL_TYPE_LONGLONG,&id,0,0,0);
if(fetchResult) {
/* Bind the results buffer */
if (mysql_stmt_bind_result(stmt, &resultParam1) != 0) {
errStr = "mysql_stmt_bind_result() failed ";
errStr.append(mysql_stmt_error(stmt));
return false;
}
}
if (mysql_stmt_execute(stmt)) {
errStr = "mysql_stmt_execute() failed ";
errStr.append(mysql_stmt_error(stmt));
return false;
}
if(fetchResult) {
if (mysql_stmt_store_result(stmt) != 0) {
errStr = "Could not buffer result set ";
errStr.append(mysql_stmt_error(stmt));
return false;
}
if(mysql_stmt_fetch (stmt) == 0) {
(*result_id) = id;
// OK
*affected_rows = 1;
} else {
*affected_rows = 0;
/*errStr = "no results found ";
errStr.append(mysql_stmt_error(stmt));
return false;*/
}
} else {
*affected_rows = mysql_stmt_affected_rows(stmt);
}
if(fetchInsertID) {
*last_insert_id= mysql_stmt_insert_id(stmt);
}
if(stmt != NULL) {
// Deallocate result set
mysql_stmt_free_result(stmt); /* deallocate result set */
if (mysql_stmt_close(stmt)) {
errStr = "closing the statement failed ";
errStr.append(mysql_stmt_error(stmt));
return false;
}
}
return true;
}
I call it like this
std::string errBuf;
int affected_rows = 0;
std::string sql = "SELECT count(*) FROM name WHERE (?) like name";
std::vector<MYSQL_BIND> paramList;
std::vector<MYSQL_BIND> resultParamList;
char data[1024];
safe_strncpy(data,name,sizeof(data), __FILE__, __LINE__);
MYSQL_BIND param1;
BindValue(¶m1,MYSQL_TYPE_STRING,data,strlen(data),0,0);
paramList.push_back(param1);
int32 count = 0;
bool ret = true;
if(RunPreparedStatement(sql,paramList,errBuf,&affected_rows,true,&count)){
...
}
I previously had also a resultParamList instead of simple the ID and had the same error and thought it was related to return a list of values but that wasnt it.
Im receiving the warning as soon as the RunPreparedStatement method is finished.
RunPreparedStatementtakes 8 arguments, you're only calling it with 6.