added amb281 - multiple result sets for MySQL

This commit is contained in:
David Anderson 2007-10-22 21:31:02 +00:00
parent 2d737970d0
commit a86b1c5097
16 changed files with 150 additions and 5 deletions

View File

@ -489,6 +489,34 @@ static cell AMX_NATIVE_CALL SQL_Rewind(AMX *amx, cell *params)
return 1; return 1;
} }
static cell AMX_NATIVE_CALL SQL_NextResultSet(AMX *amx, cell *params)
{
AmxQueryInfo *qInfo = (AmxQueryInfo *)GetHandle(params[1], Handle_Query);
if (!qInfo)
{
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid query handle: %d", params[1]);
return 0;
}
IResultSet *rs = qInfo->info.rs;
if (!rs)
{
MF_LogError(amx, AMX_ERR_NATIVE, "No result set in this query!");
return 0;
}
if (rs->NextResultSet())
{
return 1;
}
else
{
qInfo->info.rs = NULL;
return 0;
}
}
static cell AMX_NATIVE_CALL SQL_QuoteString(AMX *amx, cell *params) static cell AMX_NATIVE_CALL SQL_QuoteString(AMX *amx, cell *params)
{ {
IDatabase *pDb = (IDatabase *)GetHandle(params[1], Handle_Database); IDatabase *pDb = (IDatabase *)GetHandle(params[1], Handle_Database);
@ -559,6 +587,7 @@ AMX_NATIVE_INFO g_BaseSqlNatives[] =
{"SQL_Rewind", SQL_Rewind}, {"SQL_Rewind", SQL_Rewind},
{"SQL_QuoteString", SQL_QuoteString}, {"SQL_QuoteString", SQL_QuoteString},
{"SQL_QuoteStringFmt", SQL_QuoteStringFmt}, {"SQL_QuoteStringFmt", SQL_QuoteStringFmt},
{"SQL_NextResultSet", SQL_NextResultSet},
{NULL, NULL}, {NULL, NULL},
}; };

View File

@ -61,6 +61,10 @@ namespace SourceMod
* Rewinds to the first row. * Rewinds to the first row.
*/ */
virtual void Rewind() =0; virtual void Rewind() =0;
/**
* Transitions to the next result set, if any is available.
*/
virtual bool NextResultSet() =0;
}; };
struct QueryInfo struct QueryInfo

View File

@ -57,7 +57,7 @@ IDatabase *MysqlDriver::_Connect(DatabaseInfo *info, int *errcode, char *error,
info->database, info->database,
info->port, info->port,
NULL, NULL,
0) == NULL) CLIENT_MULTI_STATEMENTS) == NULL)
{ {
if (errcode) if (errcode)
{ {

View File

@ -19,6 +19,7 @@
#if defined WIN32 || defined _WIN32 #if defined WIN32 || defined _WIN32
#include <winsock.h> #include <winsock.h>
#endif #endif
typedef unsigned long ulong;
#include <mysql.h> #include <mysql.h>
#endif //_INCLUDE_SOURCEMOD_MYSQL_HEADERS_H #endif //_INCLUDE_SOURCEMOD_MYSQL_HEADERS_H

View File

@ -84,7 +84,9 @@ bool MysqlQuery::ExecuteR(QueryInfo *info, char *error, size_t maxlength)
{ {
snprintf(error, maxlength, "%s", mysql_error(m_pDatabase->m_pMysql)); snprintf(error, maxlength, "%s", mysql_error(m_pDatabase->m_pMysql));
} }
} else { }
else
{
MYSQL_RES *res = mysql_store_result(m_pDatabase->m_pMysql); MYSQL_RES *res = mysql_store_result(m_pDatabase->m_pMysql);
if (!res) if (!res)
{ {
@ -105,7 +107,7 @@ bool MysqlQuery::ExecuteR(QueryInfo *info, char *error, size_t maxlength)
info->errorcode = 0; info->errorcode = 0;
info->success = true; info->success = true;
info->affected_rows = mysql_affected_rows(m_pDatabase->m_pMysql); info->affected_rows = mysql_affected_rows(m_pDatabase->m_pMysql);
MysqlResultSet *rs = new MysqlResultSet(res); MysqlResultSet *rs = new MysqlResultSet(res, m_pDatabase->m_pMysql);
info->rs = rs; info->rs = rs;
} }
} }

View File

@ -61,11 +61,12 @@ int MysqlResultRow::GetInt(unsigned int columnId)
return atoi(GetStringSafe(columnId)); return atoi(GetStringSafe(columnId));
} }
MysqlResultSet::MysqlResultSet(MYSQL_RES *res) : MysqlResultSet::MysqlResultSet(MYSQL_RES *res, MYSQL *mysql) :
m_pRes(res) m_pRes(res)
{ {
m_Rows = (unsigned int)mysql_num_rows(res); m_Rows = (unsigned int)mysql_num_rows(res);
m_Columns = (unsigned int)mysql_num_fields(res); m_Columns = (unsigned int)mysql_num_fields(res);
m_pMySQL = mysql;
if (m_Rows > 0) if (m_Rows > 0)
{ {
@ -77,7 +78,49 @@ MysqlResultSet::MysqlResultSet(MYSQL_RES *res) :
MysqlResultSet::~MysqlResultSet() MysqlResultSet::~MysqlResultSet()
{ {
if (m_pRes == NULL)
{
return;
}
mysql_free_result(m_pRes); mysql_free_result(m_pRes);
while (mysql_next_result(m_pMySQL) == 0)
{
m_pRes = mysql_store_result(m_pMySQL);
if (m_pRes != NULL)
{
mysql_free_result(m_pRes);
}
}
}
bool MysqlResultSet::NextResultSet()
{
if (!mysql_more_results(m_pMySQL))
{
return false;
}
mysql_free_result(m_pRes);
if (mysql_next_result(m_pMySQL) != 0
|| (m_pRes = mysql_store_result(m_pMySQL)) == NULL)
{
m_Rows = 0;
m_pRes = NULL;
m_Columns = 0;
m_kRow.m_CurRow = NULL;
return false;
}
m_Rows = (unsigned int)mysql_num_rows(m_pRes);
m_Columns = (unsigned int)mysql_num_fields(m_pRes);
if (m_Rows > 0)
{
NextRow();
}
m_kRow.m_Columns = m_Columns;
} }
void MysqlResultSet::FreeHandle() void MysqlResultSet::FreeHandle()

View File

@ -30,7 +30,7 @@ namespace SourceMod
class MysqlResultSet : public IResultSet class MysqlResultSet : public IResultSet
{ {
public: public:
MysqlResultSet(MYSQL_RES *res); MysqlResultSet(MYSQL_RES *res, MYSQL *mysql);
~MysqlResultSet(); ~MysqlResultSet();
public: public:
void FreeHandle(); void FreeHandle();
@ -44,7 +44,9 @@ namespace SourceMod
IResultRow *GetRow(); IResultRow *GetRow();
void NextRow(); void NextRow();
void Rewind(); void Rewind();
bool NextResultSet();
private: private:
MYSQL *m_pMySQL;
MYSQL_RES *m_pRes; MYSQL_RES *m_pRes;
MysqlResultRow m_kRow; MysqlResultRow m_kRow;
unsigned int m_Columns; unsigned int m_Columns;

View File

@ -566,6 +566,11 @@ void AtomicResult::Rewind()
m_CurRow = 1; m_CurRow = 1;
} }
bool AtomicResult::NextResultSet()
{
return false;
}
AMX_NATIVE_INFO g_ThreadSqlNatives[] = AMX_NATIVE_INFO g_ThreadSqlNatives[] =
{ {
{"SQL_ThreadQuery", SQL_ThreadQuery}, {"SQL_ThreadQuery", SQL_ThreadQuery},

View File

@ -34,6 +34,7 @@ public:
virtual IResultRow *GetRow(); virtual IResultRow *GetRow();
virtual void NextRow(); virtual void NextRow();
virtual void Rewind(); virtual void Rewind();
virtual bool NextResultSet();
public: public:
virtual const char *GetString(unsigned int columnId); virtual const char *GetString(unsigned int columnId);
virtual const char *GetStringSafe(unsigned int columnId); virtual const char *GetStringSafe(unsigned int columnId);

View File

@ -489,6 +489,34 @@ static cell AMX_NATIVE_CALL SQL_Rewind(AMX *amx, cell *params)
return 1; return 1;
} }
static cell AMX_NATIVE_CALL SQL_NextResultSet(AMX *amx, cell *params)
{
AmxQueryInfo *qInfo = (AmxQueryInfo *)GetHandle(params[1], Handle_Query);
if (!qInfo)
{
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid query handle: %d", params[1]);
return 0;
}
IResultSet *rs = qInfo->info.rs;
if (!rs)
{
MF_LogError(amx, AMX_ERR_NATIVE, "No result set in this query!");
return 0;
}
if (rs->NextResultSet())
{
return 1;
}
else
{
qInfo->info.rs = NULL;
return 0;
}
}
static cell AMX_NATIVE_CALL SQL_QuoteString(AMX *amx, cell *params) static cell AMX_NATIVE_CALL SQL_QuoteString(AMX *amx, cell *params)
{ {
IDatabase *pDb = (IDatabase *)GetHandle(params[1], Handle_Database); IDatabase *pDb = (IDatabase *)GetHandle(params[1], Handle_Database);
@ -559,6 +587,7 @@ AMX_NATIVE_INFO g_BaseSqlNatives[] =
{"SQL_Rewind", SQL_Rewind}, {"SQL_Rewind", SQL_Rewind},
{"SQL_QuoteString", SQL_QuoteString}, {"SQL_QuoteString", SQL_QuoteString},
{"SQL_QuoteStringFmt", SQL_QuoteStringFmt}, {"SQL_QuoteStringFmt", SQL_QuoteStringFmt},
{"SQL_NextResultSet", SQL_NextResultSet},
{NULL, NULL}, {NULL, NULL},
}; };

View File

@ -61,6 +61,9 @@ namespace SourceMod
* Resets back to the first row. * Resets back to the first row.
*/ */
virtual void Rewind() =0; virtual void Rewind() =0;
/* Always returns false in Sqlite */
virtual bool NextResultSet() =0;
}; };
struct QueryInfo struct QueryInfo

View File

@ -164,3 +164,8 @@ void SqliteResultSet::Rewind()
m_CurRow = 1; m_CurRow = 1;
m_CurIndex = (m_CurRow * m_Columns); m_CurIndex = (m_CurRow * m_Columns);
} }
bool SqliteResultSet::NextResultSet()
{
return false;
}

View File

@ -39,6 +39,7 @@ namespace SourceMod
int GetInt(unsigned int columnId); int GetInt(unsigned int columnId);
bool IsNull(unsigned int columnId); bool IsNull(unsigned int columnId);
const char *GetRaw(unsigned int columnId, size_t *length); const char *GetRaw(unsigned int columnId, size_t *length);
bool NextResultSet();
private: private:
const char *GetStringSafe(unsigned int columnId); const char *GetStringSafe(unsigned int columnId);
private: private:

View File

@ -560,6 +560,11 @@ void AtomicResult::Rewind()
m_CurRow = 1; m_CurRow = 1;
} }
bool AtomicResult::NextResultSet()
{
return false;
}
AMX_NATIVE_INFO g_ThreadSqlNatives[] = AMX_NATIVE_INFO g_ThreadSqlNatives[] =
{ {
{"SQL_ThreadQuery", SQL_ThreadQuery}, {"SQL_ThreadQuery", SQL_ThreadQuery},

View File

@ -42,6 +42,7 @@ public:
virtual int GetInt(unsigned int columnId); virtual int GetInt(unsigned int columnId);
virtual bool IsNull(unsigned int columnId); virtual bool IsNull(unsigned int columnId);
virtual const char *GetRaw(unsigned int columnId, size_t *length); virtual const char *GetRaw(unsigned int columnId, size_t *length);
virtual bool NextResultSet();
public: public:
void CopyFrom(IResultSet *rs); void CopyFrom(IResultSet *rs);
private: private:

View File

@ -247,6 +247,20 @@ native SQL_SetAffinity(const driver[]);
*/ */
native SQL_GetQueryString(Handle:query, buffer[], maxlength); native SQL_GetQueryString(Handle:query, buffer[], maxlength);
/**
* For queries which return multiple result sets, this advances to the next
* result set if one is available. Otherwise, the current result set is
* destroyed and will no longer be accessible.
*
* This function will always return false on SQLite, and when using threaded
* queries in MySQL. Nonetheless, it has the same effect of removing the last
* result set.
*
* @param query Query Handle.
* @return True on success, false on failure.
*/
native bool:SQL_NextResultSet(Handle:query);
/** /**
* This function can be used to find out if a table in a Sqlite database exists. * This function can be used to find out if a table in a Sqlite database exists.
* (updated for newer API) * (updated for newer API)