sourcemod/extensions/mysql/mysql/MyStatement.cpp
David Anderson 11470d81ca added new (somewhat experimental) mysql extension and finalized the API
--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40868
2007-05-30 03:25:18 +00:00

258 lines
5.0 KiB
C++

#include "MyStatement.h"
#include "MyBoundResults.h"
MyStatement::MyStatement(MyDatabase *db, MYSQL_STMT *stmt)
: m_mysql(db->m_mysql), m_pParent(db), m_stmt(stmt), m_rs(NULL), m_Results(false)
{
m_Params = (unsigned int)mysql_stmt_param_count(m_stmt);
if (m_Params)
{
m_pushinfo = (ParamBind *)malloc(sizeof(ParamBind) * m_Params);
memset(m_pushinfo, 0, sizeof(ParamBind) * m_Params);
m_bind = (MYSQL_BIND *)malloc(sizeof(MYSQL_BIND) * m_Params);
memset(m_bind, 0, sizeof(MYSQL_BIND) * m_Params);
} else {
m_pushinfo = NULL;
m_bind = NULL;
}
m_pParent->IncRefCount();
m_pRes = mysql_stmt_result_metadata(stmt);
m_Results = false;
}
MyStatement::~MyStatement()
{
/* Free result set structures */
delete m_rs;
/* Free old blobs */
for (unsigned int i=0; i<m_Params; i++)
{
free(m_pushinfo[i].blob);
}
/* Free our allocated arrays */
free(m_pushinfo);
free(m_bind);
/* Close our mysql handles */
if (m_pRes)
{
mysql_free_result(m_pRes);
}
mysql_stmt_close(m_stmt);
/* Tell the parent database that we're done referencing it */
m_pParent->Close();
}
void MyStatement::Destroy()
{
delete this;
}
bool MyStatement::FetchMoreResults()
{
/* Multiple result sets are not supported by statements,
* thank god.
*/
return false;
}
void *MyStatement::CopyBlob(unsigned int param, const void *blobptr, size_t length)
{
void *copy_ptr = NULL;
if (m_pushinfo[param].blob != NULL)
{
if (m_pushinfo[param].length < length)
{
free(m_pushinfo[param].blob);
} else {
copy_ptr = m_pushinfo[param].blob;
}
}
if (copy_ptr == NULL)
{
copy_ptr = malloc(length);
m_pushinfo[param].blob = copy_ptr;
m_pushinfo[param].length = length;
}
memcpy(copy_ptr, blobptr, length);
return copy_ptr;
}
bool MyStatement::BindParamInt(unsigned int param, int num, bool signd)
{
if (param >= m_Params)
{
return false;
}
m_pushinfo[param].data.ival = num;
m_bind[param].buffer_type = MYSQL_TYPE_LONG;
m_bind[param].buffer = &(m_pushinfo[param].data.ival);
m_bind[param].is_unsigned = signd ? 0 : 1;
m_bind[param].length = NULL;
return true;
}
bool MyStatement::BindParamFloat(unsigned int param, float f)
{
if (param >= m_Params)
{
return false;
}
m_pushinfo[param].data.fval = f;
m_bind[param].buffer_type = MYSQL_TYPE_FLOAT;
m_bind[param].buffer = &(m_pushinfo[param].data.fval);
m_bind[param].length = NULL;
return true;
}
bool MyStatement::BindParamString(unsigned int param, const char *text, bool copy)
{
if (param >= m_Params)
{
return false;
}
const void *final_ptr;
size_t len;
if (copy)
{
len = strlen(text);
final_ptr = CopyBlob(param, text, len+1);
} else {
len = strlen(text);
final_ptr = text;
}
m_bind[param].buffer_type = MYSQL_TYPE_STRING;
m_bind[param].buffer = (void *)final_ptr;
m_bind[param].buffer_length = (unsigned long)len;
m_bind[param].length = &(m_bind[param].buffer_length);
return true;
}
bool MyStatement::BindParamBlob(unsigned int param, const void *data, size_t length, bool copy)
{
if (param >= m_Params)
{
return false;
}
const void *final_ptr;
if (copy)
{
final_ptr = CopyBlob(param, data, length);
} else {
final_ptr = data;
}
m_bind[param].buffer_type = MYSQL_TYPE_BLOB;
m_bind[param].buffer = (void *)final_ptr;
m_bind[param].buffer_length = (unsigned long)length;
m_bind[param].length = &(m_bind[param].buffer_length);
return true;
}
bool MyStatement::BindParamNull(unsigned int param)
{
if (param >= m_Params)
{
return false;
}
m_bind[param].buffer_type = MYSQL_TYPE_NULL;
return true;
}
bool MyStatement::Execute()
{
/* Clear any past result first! */
m_Results = false;
/* Bind the parameters */
if (m_Params)
{
if (mysql_stmt_bind_param(m_stmt, m_bind) != 0)
{
return false;
}
}
if (mysql_stmt_execute(m_stmt) != 0)
{
return false;
}
/* Skip away if we don't have data */
if (!m_pRes)
{
return true;
}
/* If we don't have a result manager, create one. */
if (!m_rs)
{
m_rs = new MyBoundResults(m_stmt, m_pRes);
}
/* Tell the result set to update its bind info,
* and initialize itself if necessary.
*/
if (!(m_Results = m_rs->Initialize()))
{
return false;
}
/* Try precaching the results. */
m_Results = (mysql_stmt_store_result(m_stmt) == 0);
/* Update now that the data is known. */
m_rs->Update();
/* Return indicator */
return m_Results;
}
const char *MyStatement::GetError(int *errCode/* =NULL */)
{
if (errCode)
{
*errCode = mysql_stmt_errno(m_stmt);
}
return mysql_stmt_error(m_stmt);
}
unsigned int MyStatement::GetAffectedRows()
{
return (unsigned int)mysql_stmt_affected_rows(m_stmt);
}
unsigned int MyStatement::GetInsertID()
{
return (unsigned int)mysql_stmt_insert_id(m_stmt);
}
IResultSet *MyStatement::GetResultSet()
{
return (m_Results ? m_rs : NULL);
}