initial import

This commit is contained in:
David Anderson
2006-04-23 01:10:06 +00:00
parent 3ba923e4c0
commit 27d8cde394
38 changed files with 11324 additions and 0 deletions

View File

@ -0,0 +1,136 @@
#ifndef _INCLUDE_SOURCEMOD_DATABASE2_H
#define _INCLUDE_SOURCEMOD_DATABASE2_H
#include <stdarg.h>
namespace SourceMod
{
class IResultRow
{
public:
/**
* This will return NULL if the entry is NULL.
* Remember that in SQL, a field can have NULL
* entries, which are not the same as 0 or "".
*/
virtual const char *GetString(unsigned int columnId) =0;
virtual double GetDouble(unsigned int columnId) =0;
virtual float GetFloat(unsigned int columnId) =0;
virtual int GetInt(unsigned int columnId) =0;
virtual bool IsNull(unsigned int columnId) =0;
/**
* NULL can be returned. The length will be zero if so.
*/
virtual const char *GetRaw(unsigned int columnId, size_t *length) =0;
};
class IResultSet
{
public:
//free the handle if necessary (see IQuery).
virtual void FreeHandle() =0;
public: //Basic stuff
virtual unsigned int RowCount() =0;
virtual unsigned int FieldCount() =0;
virtual const char *FieldNumToName(unsigned int num) =0;
virtual bool FieldNameToNum(const char *name, unsigned int *columnId) =0;
public: //iteration
/**
* Returns true if there are no more handles left.
*/
virtual bool IsDone() =0;
/**
* Returns the current row. If "IsDone()" is false
* this is guaranteed to return non-NULL.
* Handles to IResultRow are guaranteed to not leak
* (you don't need to free them), however,
* they should be considered volatile - don't cache
* them.
*/
virtual IResultRow *GetRow() =0;
/**
* Advances to the next row. Note that you need to
* call IsDone() after each call to NextRow().
*/
virtual void NextRow() =0;
};
struct QueryInfo
{
IResultSet *rs;
unsigned long long affected_rows;
int errorcode;
bool success;
};
class IQuery
{
public:
//you must free the handle when done
virtual void FreeHandle() =0;
public:
/**
* Executes the query. Specify optional error string buffer.
* If "info" is NULL, no results will be stored.
* Returns false on failure.
* Calling Execute() multiple times will cause each result handle
* to be freed in succession. That means that you do not need to
* explicitly free IResultSets when using Execute(), but their
* handles are deep-invalidated on succesive calls, and
* thus Execute() is also not thread safe.
*/
virtual bool Execute(QueryInfo *info, char *error, size_t maxlength) =0;
/**
* Same as above, except result handles are not freed for you.
*/
virtual bool ExecuteR(QueryInfo *info, char *error, size_t maxlength) =0;
};
class ISQLDriver;
class IDatabase
{
public:
/**
* Closes the database and frees the handle.
*/
virtual void FreeHandle() =0;
/**
* Returns the parent driver.
*/
virtual ISQLDriver *Driver() =0;
public:
/**
* Query preparation.
*/
virtual IQuery *PrepareQueryFmt(const char *fmt, ...) =0;
virtual IQuery *PrepareQueryFmt(const char *fmt, va_list ap) =0;
virtual IQuery *PrepareQuery(const char *query) =0;
/**
* Quotes a string properly.
* Returns 0 on success. On failure, returns
* the size of the buffer needed, or a negative number
* on internal failure.
*/
virtual int QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newsize) =0;
};
struct DatabaseInfo
{
const char *host;
const char *database;
const char *user;
const char *pass;
unsigned int port;
};
class ISQLDriver
{
public:
virtual IDatabase *Connect(DatabaseInfo *info, int *errcode, char *error, size_t maxlength) =0;
virtual const char *NameString() =0;
virtual bool IsCompatDriver(const char *namestring) =0;
};
};
#endif //_INCLUDE_SOURCEMOD_DATABASE2_H

View File

@ -0,0 +1,81 @@
#include <stdio.h>
#include "MysqlDriver.h"
#include "MysqlDatabase.h"
#include "MysqlQuery.h"
#if defined WIN32 && !defined vsnprintf
#define vsnprintf _vsnprintf
#endif
using namespace SourceMod;
MysqlDatabase::MysqlDatabase(MYSQL *mysql, MysqlDriver *drvr) :
m_pMysql(mysql), m_pParent(drvr)
{
}
MysqlDatabase::~MysqlDatabase()
{
Disconnect();
}
void MysqlDatabase::Disconnect()
{
mysql_close(m_pMysql);
m_pMysql = NULL;
}
void MysqlDatabase::FreeHandle()
{
delete this;
}
ISQLDriver *MysqlDatabase::Driver()
{
return static_cast<ISQLDriver *>(m_pParent);
}
IQuery *MysqlDatabase::PrepareQuery(const char *query)
{
MysqlQuery *mquery = new MysqlQuery(query, this);
return static_cast<IQuery *>(mquery);
}
IQuery *MysqlDatabase::PrepareQueryFmt(const char *fmt, va_list ap)
{
char buffer[4096];
vsnprintf(buffer, sizeof(buffer)-1, fmt, ap);
return PrepareQuery(buffer);
}
IQuery *MysqlDatabase::PrepareQueryFmt(const char *fmt, ...)
{
va_list ap;
IQuery *qry;
va_start(ap, fmt);
qry = PrepareQueryFmt(fmt, ap);
va_end(ap);
return qry;
}
int MysqlDatabase::QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newsize)
{
unsigned long size = static_cast<unsigned long>(strlen(str));
unsigned long needed = size*2 + 1;
if (size < needed)
return (int)needed;
needed = mysql_real_escape_string(m_pMysql, buffer, str, size);
if (newsize)
*newsize = static_cast<size_t>(needed);
return 0;
}

View File

@ -0,0 +1,34 @@
#ifndef _INCLUDE_SOURCEMOD_MYSQL_DATABASE_H
#define _INCLUDE_SOURCEMOD_MYSQL_DATABASE_H
#include "MysqlHeaders.h"
#include "MysqlDriver.h"
namespace SourceMod
{
class MysqlDriver;
class MysqlDatabase : public IDatabase
{
friend class MysqlQuery;
public:
MysqlDatabase(MYSQL *mysql, MysqlDriver *drvr);
~MysqlDatabase();
public:
void FreeHandle();
ISQLDriver *Driver();
public:
IQuery *PrepareQueryFmt(const char *fmt, ...);
IQuery *PrepareQueryFmt(const char *fmt, va_list ap);
IQuery *PrepareQuery(const char *query);
int QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newsize);
private:
void Disconnect();
private:
MYSQL *m_pMysql;
MysqlDriver *m_pParent;
};
};
#endif //_INCLUDE_SOURCEMOD_MYSQL_DATABASE_H

View File

@ -0,0 +1,57 @@
#include <stdio.h>
#include <string.h>
#include "MysqlDriver.h"
#include "MysqlDatabase.h"
#if defined WIN32
#define snprintf _snprintf
#define strncasecmp strnicmp
#endif
using namespace SourceMod;
bool MysqlDriver::IsCompatDriver(const char *namestring)
{
return (strncasecmp(namestring, "mysql", 5) == 0);
}
const char *MysqlDriver::NameString()
{
return "mysql";
}
IDatabase *MysqlDriver::Connect(DatabaseInfo *info, int *errcode, char *error, size_t maxlength)
{
MYSQL *mysql = mysql_init(NULL);
if (!mysql)
{
if (errcode)
*errcode = -1;
if (error && maxlength)
{
snprintf(error, maxlength, "Initialization failed");
}
return false;
}
if (mysql_real_connect(mysql,
info->host,
info->user,
info->pass,
info->database,
info->port,
NULL,
0) == NULL)
{
if (errcode)
*errcode = mysql_errno(mysql);
if (error && maxlength)
snprintf(error, maxlength, "%s", mysql_error(mysql));
return false;
}
MysqlDatabase *pMysql = new MysqlDatabase(mysql, this);
return static_cast<IDatabase *>(pMysql);
}

View File

@ -0,0 +1,17 @@
#ifndef _INCLUDE_SOURCEMOD_MYSQL_DRIVER_H
#define _INCLUDE_SOURCEMOD_MYSQL_DRIVER_H
#include "MysqlHeaders.h"
namespace SourceMod
{
class MysqlDriver : public ISQLDriver
{
public:
IDatabase *Connect(DatabaseInfo *info, int *errcode, char *error, size_t maxlength);
const char *NameString();
bool IsCompatDriver(const char *namestring);
};
};
#endif //_INCLUDE_SOURCEMOD_MYSQL_DRIVER_H

View File

@ -0,0 +1,10 @@
#ifndef _INCLUDE_SOURCEMOD_MYSQL_HEADERS_H
#define _INCLUDE_SOURCEMOD_MYSQL_HEADERS_H
#include <ISQLDriver.h>
#if defined WIN32 || defined _WIN32
#include <winsock.h>
#endif
#include <mysql.h>
#endif //_INCLUDE_SOURCEMOD_MYSQL_HEADERS_H

View File

@ -0,0 +1,95 @@
#include <stdio.h>
#include <string.h>
#include "MysqlQuery.h"
#include "MysqlDatabase.h"
#include "MysqlResultSet.h"
#if defined WIN32
#define snprintf _snprintf
#endif
using namespace SourceMod;
MysqlQuery::MysqlQuery(const char *querystring, MysqlDatabase *db) :
m_pDatabase(db)
{
m_QueryLen = strlen(querystring);
m_QueryString = new char[m_QueryLen + 1];
m_LastRes = NULL;
strcpy(m_QueryString, querystring);
}
MysqlQuery::~MysqlQuery()
{
if (m_LastRes)
{
m_LastRes->FreeHandle();
}
delete [] m_QueryString;
}
void MysqlQuery::FreeHandle()
{
delete this;
}
bool MysqlQuery::Execute(QueryInfo *info, char *error, size_t maxlength)
{
bool res = ExecuteR(info, error, maxlength);
if (m_LastRes)
m_LastRes->FreeHandle();
m_LastRes = (MysqlResultSet *)info->rs;
return res;
}
bool MysqlQuery::ExecuteR(QueryInfo *info, char *error, size_t maxlength)
{
int err;
if ( (err=mysql_real_query(m_pDatabase->m_pMysql, m_QueryString, (unsigned long)m_QueryLen)) )
{
info->errorcode = mysql_errno(m_pDatabase->m_pMysql);
info->success = false;
info->affected_rows = 0;
info->rs = NULL;
if (error && maxlength)
{
snprintf(error, maxlength, "%s", mysql_error(m_pDatabase->m_pMysql));
}
} else {
MYSQL_RES *res = mysql_store_result(m_pDatabase->m_pMysql);
if (!res)
{
if (mysql_field_count(m_pDatabase->m_pMysql) > 0)
{
//error !111!!11
info->errorcode = mysql_errno(m_pDatabase->m_pMysql);
info->success = false;
info->affected_rows = 0;
info->rs = NULL;
} else {
info->errorcode = 0;
info->success = true;
info->affected_rows = mysql_affected_rows(m_pDatabase->m_pMysql);
info->rs = NULL;
}
} else {
info->errorcode = 0;
info->success = true;
info->affected_rows = mysql_affected_rows(m_pDatabase->m_pMysql);
MysqlResultSet *rs = new MysqlResultSet(res);
info->rs = rs;
}
}
if (info->success && error && maxlength)
{
*error = '\0';
}
return info->success;
}

View File

@ -0,0 +1,28 @@
#ifndef _INCLUDE_SOURCEMOD_MYSQL_QUERY_H
#define _INCLUDE_SOURCEMOD_MYSQL_QUERY_H
#include "MysqlHeaders.h"
namespace SourceMod
{
class MysqlDatabase;
class MysqlResultSet;
class MysqlQuery : public IQuery
{
public:
MysqlQuery(const char *querystring, MysqlDatabase *db);
~MysqlQuery();
public:
void FreeHandle();
bool Execute(QueryInfo *info, char *error, size_t maxlength);
bool ExecuteR(QueryInfo *info, char *error, size_t maxlength);
private:
MysqlDatabase *m_pDatabase;
char *m_QueryString;
size_t m_QueryLen;
MysqlResultSet *m_LastRes;
};
};
#endif //_INCLUDE_SOURCEMOD_MYSQL_QUERY_H

View File

@ -0,0 +1,148 @@
#include <stdlib.h>
#include "MysqlResultSet.h"
using namespace SourceMod;
MysqlResultRow::MysqlResultRow() :
m_Columns(0), m_CurRow(NULL)
{
}
const char *MysqlResultRow::GetRaw(unsigned int columnId, size_t *length)
{
if (columnId >= m_Columns)
{
if (length)
*length = 0;
return NULL;
}
*length = static_cast<size_t>(m_Lengths[columnId]);
return m_CurRow[columnId];
}
bool MysqlResultRow::IsNull(unsigned int columnId)
{
if (columnId >= m_Columns)
return true;
return (m_CurRow[columnId] == NULL);
}
const char *MysqlResultRow::GetStringSafe(unsigned int columnId)
{
if (columnId >= m_Columns)
return "";
return (m_CurRow[columnId] ? m_CurRow[columnId] : "");
}
const char *MysqlResultRow::GetString(unsigned int columnId)
{
if (columnId >= m_Columns)
return NULL;
return m_CurRow[columnId];
}
double MysqlResultRow::GetDouble(unsigned int columnId)
{
return atof(GetStringSafe(columnId));
}
float MysqlResultRow::GetFloat(unsigned int columnId)
{
return (float)atof(GetStringSafe(columnId));
}
int MysqlResultRow::GetInt(unsigned int columnId)
{
return atoi(GetStringSafe(columnId));
}
MysqlResultSet::MysqlResultSet(MYSQL_RES *res) :
m_pRes(res)
{
m_Rows = (unsigned int)mysql_num_rows(res);
m_Columns = (unsigned int)mysql_num_fields(res);
if (m_Rows > 0)
{
NextRow();
}
m_kRow.m_Columns = m_Columns;
}
MysqlResultSet::~MysqlResultSet()
{
mysql_free_result(m_pRes);
}
void MysqlResultSet::FreeHandle()
{
delete this;
}
IResultRow *MysqlResultSet::GetRow()
{
return static_cast<IResultRow *>(&m_kRow);
}
unsigned int MysqlResultSet::RowCount()
{
return m_Rows;
}
const char *MysqlResultSet::FieldNumToName(unsigned int num)
{
if (num >= m_Columns)
return NULL;
MYSQL_FIELD *field = mysql_fetch_field_direct(m_pRes, num);
if (!field || !field->name)
return "";
return field->name;
}
bool MysqlResultSet::FieldNameToNum(const char *name, unsigned int *columnId)
{
MYSQL_FIELD *field;
for (unsigned int i=0; i<m_Columns; i++)
{
field = mysql_fetch_field_direct(m_pRes, i);
if (!field || !field->name)
continue;
if (strcmp(name, field->name) == 0)
{
if (columnId)
*columnId = i;
return true;
}
}
return false;
}
unsigned int MysqlResultSet::FieldCount()
{
return m_Columns;
}
bool MysqlResultSet::IsDone()
{
return (m_kRow.m_CurRow == NULL);
}
void MysqlResultSet::NextRow()
{
MYSQL_ROW row = mysql_fetch_row(m_pRes);
m_kRow.m_CurRow = row;
if (row)
{
unsigned long *lengths = mysql_fetch_lengths(m_pRes);
m_kRow.m_Lengths = lengths;
}
}

View File

@ -0,0 +1,54 @@
#ifndef _INCLUDE_SOURCEMOD_MYSQL_RESULTSET_H
#define _INCLUDE_SOURCEMOD_MYSQL_RESULTSET_H
#include "MysqlHeaders.h"
namespace SourceMod
{
class MysqlResultSet;
class MysqlResultRow : public IResultRow
{
friend class MysqlResultSet;
public:
MysqlResultRow();
public:
const char *GetString(unsigned int columnId);
double GetDouble(unsigned int columnId);
float GetFloat(unsigned int columnId);
int GetInt(unsigned int columnId);
bool IsNull(unsigned int columnId);
const char *GetRaw(unsigned int columnId, size_t *length);
private:
const char *GetStringSafe(unsigned int columnId);
private:
MYSQL_ROW m_CurRow;
unsigned long *m_Lengths;
unsigned int m_Columns;
};
class MysqlResultSet : public IResultSet
{
public:
MysqlResultSet(MYSQL_RES *res);
~MysqlResultSet();
public:
void FreeHandle();
public:
unsigned int RowCount();
unsigned int FieldCount();
const char *FieldNumToName(unsigned int num);
bool FieldNameToNum(const char *name, unsigned int *columnId);
public:
bool IsDone();
IResultRow *GetRow();
void NextRow();
private:
MYSQL_RES *m_pRes;
MysqlResultRow m_kRow;
unsigned int m_Columns;
unsigned int m_Rows;
};
};
#endif //_INCLUDE_SOURCEMOD_MYSQL_RESULTSET_H