posted new IDBDriver API - no natives are implemented yet, MySQL extension coming very shortly

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40864
This commit is contained in:
David Anderson 2007-05-29 08:32:12 +00:00
parent be634bb027
commit f48263b9d2
3 changed files with 456 additions and 204 deletions

View File

@ -28,7 +28,22 @@ void DBManager::OnSourceModAllInitialized()
m_DriverType = g_HandleSys.CreateType("IDriver", this, 0, NULL, &sec, g_pCoreIdent, NULL); m_DriverType = g_HandleSys.CreateType("IDriver", this, 0, NULL, &sec, g_pCoreIdent, NULL);
m_DatabaseType = g_HandleSys.CreateType("IDatabase", this, 0, NULL, NULL, g_pCoreIdent, NULL); m_DatabaseType = g_HandleSys.CreateType("IDatabase", this, 0, NULL, NULL, g_pCoreIdent, NULL);
m_QueryType = g_HandleSys.CreateType("IQuery", this, 0, NULL, NULL, g_pCoreIdent, NULL); }
void DBManager::OnSourceModShutdown()
{
g_HandleSys.RemoveType(m_DatabaseType, g_pCoreIdent);
g_HandleSys.RemoveType(m_DriverType, g_pCoreIdent);
}
unsigned int DBManager::GetInterfaceVersion()
{
return SMINTERFACE_DBI_VERSION;
}
const char *DBManager::GetInterfaceName()
{
return SMINTERFACE_DBI_NAME;
} }
void DBManager::OnHandleDestroy(HandleType_t type, void *object) void DBManager::OnHandleDestroy(HandleType_t type, void *object)
@ -39,124 +54,24 @@ void DBManager::OnHandleDestroy(HandleType_t type, void *object)
return; return;
} }
if (g_HandleSys.TypeCheck(type, m_QueryType)) if (g_HandleSys.TypeCheck(type, m_DatabaseType))
{ {
IQuery *pQuery = (IQuery *)object;
pQuery->Release();
} else if (g_HandleSys.TypeCheck(type, m_DatabaseType)) {
IDatabase *pdb = (IDatabase *)object; IDatabase *pdb = (IDatabase *)object;
pdb->Close(); pdb->Close();
} }
} }
void DBManager::AddDriver(IDBDriver *pDriver, IdentityToken_t *ident) bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool persistent, char *error, size_t maxlength)
{
if (!pDriver)
{
return;
}
if (m_drivers.size() >= HANDLESYS_MAX_SUBTYPES)
{
return;
}
db_driver *driver = new db_driver;
driver->driver = pDriver;
driver->ident = ident;
HandleSecurity sec;
sec.pIdentity = ident;
sec.pOwner = g_pCoreIdent;
driver->hDriver = g_HandleSys.CreateHandleEx(m_DriverType, driver, &sec, NULL, NULL);
driver->htDatabase = g_HandleSys.CreateType(NULL, this, m_DatabaseType, NULL, NULL, g_pCoreIdent, NULL);
driver->htQuery = g_HandleSys.CreateType(NULL, this, m_QueryType, NULL, NULL, g_pCoreIdent, NULL);
m_drivers.push_back(driver);
}
void DBManager::RemoveDriver(IDBDriver *pDriver)
{
CVector<db_driver *>::iterator iter;
for (iter = m_drivers.begin();
iter != m_drivers.end();
iter++)
{
if ((*iter)->driver == pDriver)
{
db_driver *driver = (*iter);
HandleSecurity sec;
sec.pIdentity = driver->ident;
sec.pOwner = g_pCoreIdent;
g_HandleSys.RemoveType(driver->htQuery, driver->ident);
g_HandleSys.RemoveType(driver->htDatabase, driver->ident);
g_HandleSys.FreeHandle(driver->hDriver, &sec);
delete driver;
m_drivers.erase(iter);
return;
}
}
}
const char *DBManager::GetInterfaceName()
{
return SMINTERFACE_DBI_NAME;
}
unsigned int DBManager::GetInterfaceVersion()
{
return SMINTERFACE_DBI_VERSION;
}
unsigned int DBManager::GetDriverCount()
{
return (unsigned int)m_drivers.size();
}
IDBDriver *DBManager::GetDriver(unsigned int index, IdentityToken_t **pToken)
{
if (index >= GetDriverCount())
{
return NULL;
}
if (pToken)
{
*pToken = m_drivers[index]->ident;
}
return m_drivers[index]->driver;
}
const DatabaseInfo *DBManager::FindDatabaseConf(const char *name)
{
/* :TODO: implement */
return NULL;
}
bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool persistent)
{ {
const DatabaseInfo *pInfo = FindDatabaseConf(name); const DatabaseInfo *pInfo = FindDatabaseConf(name);
unsigned int count = GetDriverCount(); for (size_t i=0; i<m_drivers.size(); i++)
for (unsigned int i=0; i<count; i++)
{ {
IDBDriver *driver = GetDriver(i); if (strcasecmp(pInfo->driver, m_drivers[i]->GetIdentifier()) == 0)
if (strcmp(driver->GetIdentifier(), pInfo->driver) == 0)
{ {
*pdr = driver; *pdr = m_drivers[i];
if (persistent) *pdb = m_drivers[i]->Connect(pInfo, persistent, error, maxlength);
{ return (*pdb == NULL);
*pdb = driver->PConnect(pInfo);
} else {
*pdb = driver->Connect(pInfo);
}
} }
} }
@ -165,3 +80,81 @@ bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool
return false; return false;
} }
void DBManager::AddDriver(IDBDriver *pDriver)
{
m_drivers.push_back(pDriver);
}
void DBManager::RemoveDriver(IDBDriver *pDriver)
{
for (size_t i=0; i<m_drivers.size(); i++)
{
if (m_drivers[i] == pDriver)
{
m_drivers.erase(m_drivers.iterAt(i));
return;
}
}
}
Handle_t DBManager::CreateHandle(DBHandleType dtype, void *ptr, IdentityToken_t *pToken)
{
HandleType_t type = 0;
if (dtype == DBHandle_Driver)
{
type = m_DriverType;
} else if (dtype == DBHandle_Database) {
type = m_DatabaseType;
} else {
return BAD_HANDLE;
}
return g_HandleSys.CreateHandle(type, ptr, pToken, g_pCoreIdent, NULL);
}
HandleError DBManager::ReadHandle(Handle_t hndl, DBHandleType dtype, void **ptr)
{
HandleType_t type = 0;
if (dtype == DBHandle_Driver)
{
type = m_DriverType;
} else if (dtype == DBHandle_Database) {
type = m_DatabaseType;
} else {
return HandleError_Type;
}
HandleSecurity sec(NULL, g_pCoreIdent);
return g_HandleSys.ReadHandle(hndl, dtype, &sec, ptr);
}
HandleError DBManager::ReleaseHandle(Handle_t hndl, DBHandleType type, IdentityToken_t *token)
{
HandleSecurity sec(token, g_pCoreIdent);
return g_HandleSys.FreeHandle(hndl, &sec);
}
unsigned int DBManager::GetDriverCount()
{
return (unsigned int)m_drivers.size();
}
IDBDriver *DBManager::GetDriver(unsigned int index)
{
if (index >= m_drivers.size())
{
return NULL;
}
return m_drivers[index];
}
const DatabaseInfo *DBManager::FindDatabaseConf(const char *name)
{
/* :TODO: */
return NULL;
}

View File

@ -16,46 +16,38 @@
#define _INCLUDE_DATABASE_MANAGER_H_ #define _INCLUDE_DATABASE_MANAGER_H_
#include <IDBDriver.h> #include <IDBDriver.h>
#include <IHandleSys.h>
#include "sm_globals.h" #include "sm_globals.h"
#include <sh_vector.h> #include <sh_vector.h>
using namespace SourceHook; using namespace SourceHook;
struct db_driver
{
IDBDriver *driver;
IdentityToken_t *ident;
HandleType_t htDatabase;
HandleType_t htQuery;
Handle_t hDriver;
};
class DBManager : class DBManager :
public IDBManager, public IDBManager,
public SMGlobalClass, public SMGlobalClass,
public IHandleTypeDispatch public IHandleTypeDispatch
{ {
public:
const char *GetInterfaceName(); const char *GetInterfaceName();
unsigned int GetInterfaceVersion(); unsigned int GetInterfaceVersion();
public: //SMGlobalClass public: //SMGlobalClass
void OnSourceModAllInitialized(); void OnSourceModAllInitialized();
void OnSourceModShutdown();
public: //IHandleTypeDispatch public: //IHandleTypeDispatch
void OnHandleDestroy(HandleType_t type, void *object); void OnHandleDestroy(HandleType_t type, void *object);
public: //IDBManager public: //IDBManager
void AddDriver(IDBDriver *pDriver, IdentityToken_t *ident); void AddDriver(IDBDriver *pDrivera);
void RemoveDriver(IDBDriver *pDriver); void RemoveDriver(IDBDriver *pDriver);
const DatabaseInfo *FindDatabaseConf(const char *name); const DatabaseInfo *FindDatabaseConf(const char *name);
bool Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool persistent); bool Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool persistent, char *error, size_t maxlength);
unsigned int GetDriverCount(); unsigned int GetDriverCount();
IDBDriver *GetDriver(unsigned int index, IdentityToken_t **pToken=NULL); IDBDriver *GetDriver(unsigned int index);
public: Handle_t CreateHandle(DBHandleType type, void *ptr, IdentityToken_t *pToken);
db_driver *GetDriverInfo(unsigned int index); HandleError ReadHandle(Handle_t hndl, DBHandleType type, void **ptr);
HandleError ReleaseHandle(Handle_t hndl, DBHandleType type, IdentityToken_t *token);
private: private:
CVector<db_driver *> m_drivers; CVector<IDBDriver *> m_drivers;
HandleType_t m_DriverType; HandleType_t m_DriverType;
HandleType_t m_DatabaseType; HandleType_t m_DatabaseType;
HandleType_t m_QueryType;
}; };
extern DBManager g_DBMan; extern DBManager g_DBMan;

View File

@ -20,6 +20,7 @@
#define _INCLUDE_SOURCEMOD_INTERFACE_DBDRIVER_H_ #define _INCLUDE_SOURCEMOD_INTERFACE_DBDRIVER_H_
#include <IShareSys.h> #include <IShareSys.h>
#include <IHandleSys.h>
#include <string.h> #include <string.h>
#define SMINTERFACE_DBI_NAME "IDBI" #define SMINTERFACE_DBI_NAME "IDBI"
@ -38,8 +39,27 @@ namespace SourceMod
DBVal_Data = 3, /**< Field has data */ DBVal_Data = 3, /**< Field has data */
}; };
/**
* @brief Describes a primitive database type.
*/
enum DBType
{
DBType_Unknown = 0, /**< Type could not be inferred */
DBType_String, /**< NULL-terminated string (variable length) */
DBType_Blob, /**< Raw binary data (variable length) */
DBType_Integer, /**< 4-byte signed integer */
DBType_Float, /**< 4-byte floating point */
};
/** /**
* @brief Represents a one database result row. * @brief Represents a one database result row.
*
* Note that type mismatches will only occur when type safety is being
* enforced. So far this is only the case for prepared statements in
* MySQL and SQLite.
*
* Also, it is worth noting that retrieving as raw data will never cause a
* type mismatch.
*/ */
class IResultRow class IResultRow
{ {
@ -47,14 +67,33 @@ namespace SourceMod
/** /**
* @brief Retrieves a database field result as a string. * @brief Retrieves a database field result as a string.
* *
* For NULL values, the resulting string pointer will be non-NULL, * For NULL values, the resulting string pointer will be non-NULL but
* but empty. * empty. The pointer returned will become invalid after advancing to
* the next row.
* *
* @param columnId Column to use, starting from 0. * @param columnId Column to use, starting from 0.
* @param pString Pointer to store a pointer to the string. * @param pString Pointer to store a pointer to the string.
* @param length Optional pointer to store the string length.
* @return A DBResult return code. * @return A DBResult return code.
*/ */
virtual DBResult GetString(unsigned int columnId, const char **pString) =0; virtual DBResult GetString(unsigned int columnId, const char **pString, size_t *length) =0;
/**
* @brief Retrieves a database field result as a string, using a
* user-supplied buffer. If the field is NULL, an empty string
* will be copied.
*
* @param columnId Column to use, starting from 0.
* @param buffer Buffer to store string in.
* @param maxlength Maximum length of the buffer.
* @param written Optional pointer to store the number of bytes
* written, excluding the null terminator.
* @return A DBResult return code.
*/
virtual DBResult CopyString(unsigned int columnId,
char *buffer,
size_t maxlength,
size_t *written) =0;
/** /**
* @brief Retrieves a database field result as a float. * @brief Retrieves a database field result as a float.
@ -82,19 +121,51 @@ namespace SourceMod
* @brief Returns whether or not a field is NULL. * @brief Returns whether or not a field is NULL.
* *
* @param columnId Column to use, starting from 0. * @param columnId Column to use, starting from 0.
* @return A DBResult return code. * @return True if field is NULL, false otherwise.
*/ */
virtual DBResult CheckField(unsigned int columnId) =0; virtual bool IsNull(unsigned int columnId) =0;
/** /**
* @brief Retrieves field data as a raw bitstream. * @brief Returns the size of a field (text/raw/blob) in bytes.
* For strings, this returned size will not include the null
* terminator.
*
* When used on fields that are not of variable length,
* the size returned will be the number of bytes required
* to store the internal data. Note that the data size
* will correspond to the ACTUAL data type, not the
* COLUMN type.
* *
* @param columnId Column to use, starting from 0. * @param columnId Column to use, starting from 0.
* @param pData Pointer to store the raw bit stream. * @return Number of bytes required to store
* the data, or 0 on failure.
*/
virtual size_t GetDataSize(unsigned int columnId) =0;
/**
* @brief Retrieves field data as a raw bitstream. The pointer returned
* will become invalid after advancing to the next row.
*
* @param columnId Column to use, starting from 0.
* @param pData Pointer to store the raw bit stream. If the
* data is NULL, a NULL pointer will be returned.
* @param length Pointer to store the data length. * @param length Pointer to store the data length.
* @return A DBResult return code. * @return A DBResult return code.
*/ */
virtual DBResult GetRaw(unsigned int columnId, void **pData, size_t *length) =0; virtual DBResult GetBlob(unsigned int columnId, const void **pData, size_t *length) =0;
/**
* @brief Copies field data as a raw bitstream.
*
* @param columnId Column to use, starting from 0.
* @param buffer Pointer to copy the data to. If the data is
* NULL, no data will be copied.
* @param maxlength Maximum length of the buffer.
* @param written Optional pointer to store the number of bytes
* written.
* @return A DBResult return code.
*/
virtual DBResult CopyBlob(unsigned int columnId, void *buffer, size_t maxlength, size_t *written) =0;
}; };
/** /**
@ -123,7 +194,7 @@ namespace SourceMod
* @param columnId Column to use, starting from 0. * @param columnId Column to use, starting from 0.
* @return Pointer to column name, or NULL if not found. * @return Pointer to column name, or NULL if not found.
*/ */
virtual const char *ColNumToName(unsigned int columnId) =0; virtual const char *FieldNumToName(unsigned int columnId) =0;
/** /**
* @brief Converts a column name to a column id. * @brief Converts a column name to a column id.
@ -134,7 +205,7 @@ namespace SourceMod
* undefined. * undefined.
* @return True on success, false if not found. * @return True on success, false if not found.
*/ */
virtual bool ColNumToName(const char *name, unsigned int *columnId) =0; virtual bool FieldNameToNum(const char *name, unsigned int *columnId) =0;
/** /**
* @brief Returns if there is still data in the result set. * @brief Returns if there is still data in the result set.
@ -142,7 +213,7 @@ namespace SourceMod
* @return False if there is more data to be read, * @return False if there is more data to be read,
* true, otherwise. * true, otherwise.
*/ */
virtual bool IsFinished() =0; virtual bool MoreRows() =0;
/** /**
* @brief Returns a pointer to the current row and advances * @brief Returns a pointer to the current row and advances
@ -159,16 +230,149 @@ namespace SourceMod
* @return True on success, false otherwise. * @return True on success, false otherwise.
*/ */
virtual bool Rewind() =0; virtual bool Rewind() =0;
/**
* @brief Returns a field's type as it should be interpreted
* by the user.
*
* @param field Field number (starting from 0).
* @return A DBType value.
*/
virtual DBType GetFieldType(unsigned int field) =0;
/**
* @brief Returns a field's type as it will be interpreted
* by the GetDataSize() function. For example, MySQL
* for non-prepared queries will store all results as
* strings internally.
*
* @param field Field number (starting from 0).
* @return A DBType value.
*/
virtual DBType GetFieldDataType(unsigned int field) =0;
}; };
class IDatabase; class IDBDriver;
/**
* @brief Encapsulates one database query.
*/
class IQuery class IQuery
{ {
public: public:
/**
* @brief Returns a pointer to the current result set, if any.
*
* @return An IResultSet pointer on success,
* NULL if no result set exists.
*/
virtual IResultSet *GetResultSet() =0;
/**
* @brief Advances to the next result set if one exists. This
* is for checking for MORE result sets, and should not be used
* on the first result set.
*
* Multiple results only happen in certain cases, such as CALLing
* stored procedure that have a SELECTs, where MySQL will return
* both the CALL status and one or more SELECT result sets. If
* you do not process these results, they will be automatically
* processed for you. However, the behaviour of creating a new
* query from the same connection while results are left
* unprocessed is undefined, and may result in a dropped
* connection. Therefore, process all extra results or destroy the
* IQuery pointer before starting a new query.
*
* Again, this only happens in very specific cases, so there is
* no need to call this for normal queries.
*
* After calling this function, GetResultSet() must be called
* again to return the result set. The previous result set
* is automatically destroyed and will be unusable.
*
* @return True if another result set is
* available, false otherwise.
*/
virtual bool FetchMoreResults() =0;
/**
* @brief Frees resources created by this query.
*/
virtual void Destroy() =0;
};
class IPreparedQuery : public IQuery
{
public:
/**
* @brief Binds an integer parameter.
*
* @param param Parameter index, starting from 0.
* @param num Number to bind as a value.
* @param signd True to write as signed, false to write as
* unsigned.
* @return True on success, false otherwise.
*/
virtual bool BindParamInt(unsigned int param, int num, bool signd=true) =0;
/**
* @brief Binds a float parameter.
*
* @param param Parameter index, starting from 0.
* @param f Float to bind as a value.
* @return True on success, false otherwise.
*/
virtual bool BindParamFloat(unsigned int param, float f) =0;
/**
* @brief Binds an SQL NULL type as a parameter.
*
* @param param Parameter index, starting from 0.
* @return True on success, false otherwise.
*/
virtual bool BindParamNull(unsigned int param) =0;
/**
* @brief Binds a string as a parameter.
*
* @param param Parameter index, starting from 0.
* @param text Pointer to a null-terminated string.
* @param copy If true, the pointer is assumed to be
* volatile and a temporary copy may be
* made for safety.
* @return True on success, false otherwise.
*/
virtual bool BindParamString(unsigned int param, const char *text, bool copy) =0;
/**
* @brief Binds a blob of raw data as a parameter.
*
* @param param Parameter index, starting from 0.
* @param data Pointer to a blob of memory.
* @param length Number of bytes to copy.
* @param copy If true, the pointer is assumed to be
* volatile and a temporary copy may be
* made for safety.
* @return True on success, false otherwise.
*/
virtual bool BindParamBlob(unsigned int param,
const void *data,
size_t length,
bool copy) =0;
/**
* @brief Executes the query with the currently bound parameters.
* @return True on success, false otherwise.
*/
virtual bool Execute() =0;
/**
* @brief Returns the last error message from this statement.
*
* @param errCode Optional pointer to store the driver-specific
* error code.
* @return Error message string.
*/
virtual const char *GetError(int *errCode=NULL) =0;
/** /**
* @brief Number of rows affected by the last execute. * @brief Number of rows affected by the last execute.
* *
@ -177,45 +381,13 @@ namespace SourceMod
virtual unsigned int GetAffectedRows() =0; virtual unsigned int GetAffectedRows() =0;
/** /**
* @brief Retrieves the last insert ID of this query, if any. * @brief Retrieves the last insert ID on this database connection.
* *
* @return Row insertion ID of the last execute, if any. * @return Row insertion ID of the last execute, if any.
*/ */
virtual unsigned int GetInsertID() =0; virtual unsigned int GetInsertID() =0;
/**
* @brief Returns the full query string.
*
* @return String containing the original query.
*/
virtual const char *GetQueryString() =0;
/**
* @brief Returns the result set from the last Execute call.
*
* @return IResultSet from the last Execute call.
* Pointer will be NULL if there was no previous
* call, the last call failed, or the last call
* had no result set and Execute() was called with
* retEmptySet=false.
*/
virtual IResultSet *GetResultSet() =0;
/**
* @brief Returns the IDatabase object which created this pointer.
*
* @return IDatabase object which created this pointer.
*/
virtual IDatabase *GetDatabase() =0;
/**
* @brief Releases the resources associated with this query.
*/
virtual void Release() =0;
}; };
class IDBDriver;
/** /**
* @brief Encapsulates a database connection. * @brief Encapsulates a database connection.
*/ */
@ -224,11 +396,18 @@ namespace SourceMod
public: public:
/** /**
* @brief Disconnects the database and frees its associated memory. * @brief Disconnects the database and frees its associated memory.
* If this pointer was received via IDBDriver::PConnect(), Close() * Note that the actual object will not be freed until all open
* must be called once for each successful PConnect() call which * references have been closed.
* resulted in this pointer. *
* It is guaranteed that an IDatabase pointer won't be destroyed until
* all open IQuery or IPreparedQuery pointers are closed.
*
* @param Only pass true if being called from an
* IHandleTypeDispatch destructor.
* @return True if object was destroyed, false if
* references are remaining.
*/ */
virtual void Close() =0; virtual bool Close(bool fromHndlSys=false) =0;
/** /**
* @brief Error code and string returned by the last operation on this * @brief Error code and string returned by the last operation on this
@ -237,18 +416,41 @@ namespace SourceMod
* @param errorCode Optional pointer to retrieve an error code. * @param errorCode Optional pointer to retrieve an error code.
* @return Error string pointer (empty if none). * @return Error string pointer (empty if none).
*/ */
virtual const char *GetLastError(int *errorCode=NULL) =0; virtual const char *GetError(int *errorCode=NULL) =0;
/**
* @brief Prepares and executes a query in one step, and discards
* any return data.
*
* @param query Query string.
* @return True on success, false otherwise.
*/
virtual bool DoSimpleQuery(const char *query) =0;
/** /**
* @brief Prepares and executes a query in one step, and returns * @brief Prepares and executes a query in one step, and returns
* the resulting IQuery pointer. * the resultant data set.
* *
* @param fmt String format to parse. * Note: If a query contains more than one result set, each
* @param ... Format parameters. * result set must be processed before a new query is started.
* @return An IQuery pointer which must be freed, or *
* NULL if the query failed. * @param query Query string.
* @return IQuery pointer on success, NULL otherwise.
*/ */
virtual IQuery *DoQuery(const char *fmt, ...) =0; virtual IQuery *DoQuery(const char *query) =0;
/**
* @brief Prepares a query statement for multiple executions and/or
* binding marked parameters (? in MySQL/sqLite, $n in PostgreSQL).
*
* @param query Query string.
* @param error Error buffer.
* @param maxlength Maximum length of the error buffer.
* @param errCode Optional pointer to store a driver-specific error code.
* @return IPreparedQuery pointer on success, NULL
* otherwise.
*/
virtual IPreparedQuery *PrepareQuery(const char *query, char *error, size_t maxlength, int *errCode=NULL) =0;
/** /**
* Quotes a string for insertion into a query. * Quotes a string for insertion into a query.
@ -264,11 +466,25 @@ namespace SourceMod
virtual bool QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newSize) =0; virtual bool QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newSize) =0;
/** /**
* @brief Returns the parent driver. * @brief Number of rows affected by the last execute.
* *
* @return IDBDriver pointer that created this object. * @return Number of rows affected by the last execute.
*/ */
virtual IDBDriver *GetDriver() =0; virtual unsigned int GetAffectedRows() =0;
/**
* @brief Retrieves the last insert ID on this database connection.
*
* @return Row insertion ID of the last execute, if any.
*/
virtual unsigned int GetInsertID() =0;
/**
* @brief Returns an IDatabase Handle to this IDatabase.
*
* @return Handle_t of type IDatabase.
*/
virtual Handle_t GetHandle() =0;
}; };
/** /**
@ -307,35 +523,50 @@ namespace SourceMod
* @brief Initiates a database connection. * @brief Initiates a database connection.
* *
* @param info Database connection info pointer. * @param info Database connection info pointer.
* @param persistent If true, a previous persistent connection will
* be re-used if possible.
* @param error Buffer to store error message.
* @param maxlength Maximum size of the error buffer.
* @return A new IDatabase pointer, or NULL on failure. * @return A new IDatabase pointer, or NULL on failure.
*/ */
virtual IDatabase *Connect(const DatabaseInfo *info) =0; virtual IDatabase *Connect(const DatabaseInfo *info, bool persistent, char *error, size_t maxlength) =0;
/**
* @brief Initiates a database connection. If a connection to the given database
* already exists, this will re-use the old connection handle.
*
* @param info Database connection info pointer.
* @return A new IDatabase pointer, or NULL on failure.
*/
virtual IDatabase *PConnect(const DatabaseInfo *info) =0;
/** /**
* @brief Returns a case insensitive database identifier string. * @brief Returns a case insensitive database identifier string.
*
* @return String containing an identifier.
*/ */
virtual const char *GetIdentifier() =0; virtual const char *GetIdentifier() =0;
/** /**
* @brief Returns a case sensitive implementation name. * @brief Returns a case sensitive implementation name.
*
* @return String containing an implementation name.
*/ */
virtual const char *GetProductName() =0; virtual const char *GetProductName() =0;
/** /**
* @brief Returns the last connection error. * @brief Retrieves a Handle_t handle of the IDBDriver type.
* *
* @param errCode Optional pointer to store a platform-specific error code. * @return A Handle_t handle.
*/ */
virtual const char *GetLastError(int *errCode=NULL) =0; virtual Handle_t GetHandle() =0;
/**
* @brief Returns the driver's controlling identity.
*
* @return An IdentityToken_t identity.
*/
virtual IdentityToken_t *GetIdentity() =0;
};
/**
* @brief Database-related Handle types.
*/
enum DBHandleType
{
DBHandle_Driver = 0, /**< Driver Handle */
DBHandle_Database = 1, /**< Database Handle */
}; };
/** /**
@ -352,7 +583,7 @@ namespace SourceMod
* *
* @param pDriver Database driver. * @param pDriver Database driver.
*/ */
virtual void AddDriver(IDBDriver *pDriver, IdentityToken_t *pToken) =0; virtual void AddDriver(IDBDriver *pDriver) =0;
/** /**
* @brief Removes a driver from the DBI system. * @brief Removes a driver from the DBI system.
@ -379,9 +610,16 @@ namespace SourceMod
* If connection fails, NULL will be stored. * If connection fails, NULL will be stored.
* @param persistent If true, the dbmanager will attempt to PConnect * @param persistent If true, the dbmanager will attempt to PConnect
* instead of connect. * instead of connect.
* @param error Error buffer to store a driver's error message.
* @param maxlength Maximum length of the error buffer.
* @return True on success, false otherwise. * @return True on success, false otherwise.
*/ */
virtual bool Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool persistent) =0; virtual bool Connect(const char *name,
IDBDriver **pdr,
IDatabase **pdb,
bool persistent,
char *error,
size_t maxlength) =0;
/** /**
* @brief Returns the number of drivers loaded. * @brief Returns the number of drivers loaded.
@ -394,10 +632,39 @@ namespace SourceMod
* @brief Returns a driver by index. * @brief Returns a driver by index.
* *
* @param index Driver index, starting from 0. * @param index Driver index, starting from 0.
* @param pToken Optional pointer to store the driver's identity token.
* @return IDBDriver pointer for the given index. * @return IDBDriver pointer for the given index.
*/ */
virtual IDBDriver *GetDriver(unsigned int index, IdentityToken_t **pToken=NULL) =0; virtual IDBDriver *GetDriver(unsigned int index) =0;
/**
* @brief Creates a Handle_t of the IDBDriver type.
*
* @param type A DBHandleType value.
* @param ptr A pointer corrresponding to a DBHandleType object.
* @param token Identity pointer of the owning identity.
* @return A new Handle_t handle, or 0 on failure.
*/
virtual Handle_t CreateHandle(DBHandleType type, void *ptr, IdentityToken_t *pToken) =0;
/**
* @brief Reads an IDBDriver pointer from an IDBDriver handle.
*
* @param hndl Handle_t handle to read.
* @param type A DBHandleType value.
* @param ptr Pointer to store the object pointer.
* @return HandleError value.
*/
virtual HandleError ReadHandle(Handle_t hndl, DBHandleType type, void **ptr) =0;
/**
* @brief Releases an IDBDriver handle.
*
* @param hndl Handle_t handle to release.
* @param type A DBHandleType value.
* @param token Identity pointer of the owning identity.
* @return HandleError value.
*/
virtual HandleError ReleaseHandle(Handle_t hndl, DBHandleType type, IdentityToken_t *token) =0;
}; };
} }