posted new IDBDriver API - no natives are implemented yet, MySQL extension coming very shortly
posted new IDBDriver API - no natives are implemented yet, MySQL extension coming very shortly
1.1 --- a/core/Database.cpp Tue May 29 08:30:13 2007 +0000
1.2 +++ b/core/Database.cpp Tue May 29 08:32:12 2007 +0000
1.3 @@ -28,7 +28,22 @@
1.4
1.5 m_DriverType = g_HandleSys.CreateType("IDriver", this, 0, NULL, &sec, g_pCoreIdent, NULL);
1.6 m_DatabaseType = g_HandleSys.CreateType("IDatabase", this, 0, NULL, NULL, g_pCoreIdent, NULL);
1.7 - m_QueryType = g_HandleSys.CreateType("IQuery", this, 0, NULL, NULL, g_pCoreIdent, NULL);
1.8 +}
1.9 +
1.10 +void DBManager::OnSourceModShutdown()
1.11 +{
1.12 + g_HandleSys.RemoveType(m_DatabaseType, g_pCoreIdent);
1.13 + g_HandleSys.RemoveType(m_DriverType, g_pCoreIdent);
1.14 +}
1.15 +
1.16 +unsigned int DBManager::GetInterfaceVersion()
1.17 +{
1.18 + return SMINTERFACE_DBI_VERSION;
1.19 +}
1.20 +
1.21 +const char *DBManager::GetInterfaceName()
1.22 +{
1.23 + return SMINTERFACE_DBI_NAME;
1.24 }
1.25
1.26 void DBManager::OnHandleDestroy(HandleType_t type, void *object)
1.27 @@ -39,124 +54,24 @@
1.28 return;
1.29 }
1.30
1.31 - if (g_HandleSys.TypeCheck(type, m_QueryType))
1.32 + if (g_HandleSys.TypeCheck(type, m_DatabaseType))
1.33 {
1.34 - IQuery *pQuery = (IQuery *)object;
1.35 - pQuery->Release();
1.36 - } else if (g_HandleSys.TypeCheck(type, m_DatabaseType)) {
1.37 IDatabase *pdb = (IDatabase *)object;
1.38 pdb->Close();
1.39 }
1.40 }
1.41
1.42 -void DBManager::AddDriver(IDBDriver *pDriver, IdentityToken_t *ident)
1.43 -{
1.44 - if (!pDriver)
1.45 - {
1.46 - return;
1.47 - }
1.48 -
1.49 - if (m_drivers.size() >= HANDLESYS_MAX_SUBTYPES)
1.50 - {
1.51 - return;
1.52 - }
1.53 -
1.54 - db_driver *driver = new db_driver;
1.55 -
1.56 - driver->driver = pDriver;
1.57 - driver->ident = ident;
1.58 -
1.59 - HandleSecurity sec;
1.60 -
1.61 - sec.pIdentity = ident;
1.62 - sec.pOwner = g_pCoreIdent;
1.63 - driver->hDriver = g_HandleSys.CreateHandleEx(m_DriverType, driver, &sec, NULL, NULL);
1.64 -
1.65 - driver->htDatabase = g_HandleSys.CreateType(NULL, this, m_DatabaseType, NULL, NULL, g_pCoreIdent, NULL);
1.66 - driver->htQuery = g_HandleSys.CreateType(NULL, this, m_QueryType, NULL, NULL, g_pCoreIdent, NULL);
1.67 -
1.68 - m_drivers.push_back(driver);
1.69 -}
1.70 -
1.71 -void DBManager::RemoveDriver(IDBDriver *pDriver)
1.72 -{
1.73 - CVector<db_driver *>::iterator iter;
1.74 - for (iter = m_drivers.begin();
1.75 - iter != m_drivers.end();
1.76 - iter++)
1.77 - {
1.78 - if ((*iter)->driver == pDriver)
1.79 - {
1.80 - db_driver *driver = (*iter);
1.81 - HandleSecurity sec;
1.82 -
1.83 - sec.pIdentity = driver->ident;
1.84 - sec.pOwner = g_pCoreIdent;
1.85 - g_HandleSys.RemoveType(driver->htQuery, driver->ident);
1.86 - g_HandleSys.RemoveType(driver->htDatabase, driver->ident);
1.87 - g_HandleSys.FreeHandle(driver->hDriver, &sec);
1.88 -
1.89 - delete driver;
1.90 - m_drivers.erase(iter);
1.91 -
1.92 - return;
1.93 - }
1.94 - }
1.95 -}
1.96 -
1.97 -const char *DBManager::GetInterfaceName()
1.98 -{
1.99 - return SMINTERFACE_DBI_NAME;
1.100 -}
1.101 -
1.102 -unsigned int DBManager::GetInterfaceVersion()
1.103 -{
1.104 - return SMINTERFACE_DBI_VERSION;
1.105 -}
1.106 -
1.107 -unsigned int DBManager::GetDriverCount()
1.108 -{
1.109 - return (unsigned int)m_drivers.size();
1.110 -}
1.111 -
1.112 -IDBDriver *DBManager::GetDriver(unsigned int index, IdentityToken_t **pToken)
1.113 -{
1.114 - if (index >= GetDriverCount())
1.115 - {
1.116 - return NULL;
1.117 - }
1.118 -
1.119 - if (pToken)
1.120 - {
1.121 - *pToken = m_drivers[index]->ident;
1.122 - }
1.123 -
1.124 - return m_drivers[index]->driver;
1.125 -}
1.126 -
1.127 -const DatabaseInfo *DBManager::FindDatabaseConf(const char *name)
1.128 -{
1.129 - /* :TODO: implement */
1.130 - return NULL;
1.131 -}
1.132 -
1.133 -bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool persistent)
1.134 +bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool persistent, char *error, size_t maxlength)
1.135 {
1.136 const DatabaseInfo *pInfo = FindDatabaseConf(name);
1.137
1.138 - unsigned int count = GetDriverCount();
1.139 - for (unsigned int i=0; i<count; i++)
1.140 + for (size_t i=0; i<m_drivers.size(); i++)
1.141 {
1.142 - IDBDriver *driver = GetDriver(i);
1.143 - if (strcmp(driver->GetIdentifier(), pInfo->driver) == 0)
1.144 + if (strcasecmp(pInfo->driver, m_drivers[i]->GetIdentifier()) == 0)
1.145 {
1.146 - *pdr = driver;
1.147 - if (persistent)
1.148 - {
1.149 - *pdb = driver->PConnect(pInfo);
1.150 - } else {
1.151 - *pdb = driver->Connect(pInfo);
1.152 - }
1.153 + *pdr = m_drivers[i];
1.154 + *pdb = m_drivers[i]->Connect(pInfo, persistent, error, maxlength);
1.155 + return (*pdb == NULL);
1.156 }
1.157 }
1.158
1.159 @@ -165,3 +80,81 @@
1.160
1.161 return false;
1.162 }
1.163 +
1.164 +void DBManager::AddDriver(IDBDriver *pDriver)
1.165 +{
1.166 + m_drivers.push_back(pDriver);
1.167 +}
1.168 +
1.169 +void DBManager::RemoveDriver(IDBDriver *pDriver)
1.170 +{
1.171 + for (size_t i=0; i<m_drivers.size(); i++)
1.172 + {
1.173 + if (m_drivers[i] == pDriver)
1.174 + {
1.175 + m_drivers.erase(m_drivers.iterAt(i));
1.176 + return;
1.177 + }
1.178 + }
1.179 +}
1.180 +
1.181 +Handle_t DBManager::CreateHandle(DBHandleType dtype, void *ptr, IdentityToken_t *pToken)
1.182 +{
1.183 + HandleType_t type = 0;
1.184 +
1.185 + if (dtype == DBHandle_Driver)
1.186 + {
1.187 + type = m_DriverType;
1.188 + } else if (dtype == DBHandle_Database) {
1.189 + type = m_DatabaseType;
1.190 + } else {
1.191 + return BAD_HANDLE;
1.192 + }
1.193 +
1.194 + return g_HandleSys.CreateHandle(type, ptr, pToken, g_pCoreIdent, NULL);
1.195 +}
1.196 +
1.197 +HandleError DBManager::ReadHandle(Handle_t hndl, DBHandleType dtype, void **ptr)
1.198 +{
1.199 + HandleType_t type = 0;
1.200 +
1.201 + if (dtype == DBHandle_Driver)
1.202 + {
1.203 + type = m_DriverType;
1.204 + } else if (dtype == DBHandle_Database) {
1.205 + type = m_DatabaseType;
1.206 + } else {
1.207 + return HandleError_Type;
1.208 + }
1.209 +
1.210 + HandleSecurity sec(NULL, g_pCoreIdent);
1.211 +
1.212 + return g_HandleSys.ReadHandle(hndl, dtype, &sec, ptr);
1.213 +}
1.214 +
1.215 +HandleError DBManager::ReleaseHandle(Handle_t hndl, DBHandleType type, IdentityToken_t *token)
1.216 +{
1.217 + HandleSecurity sec(token, g_pCoreIdent);
1.218 + return g_HandleSys.FreeHandle(hndl, &sec);
1.219 +}
1.220 +
1.221 +unsigned int DBManager::GetDriverCount()
1.222 +{
1.223 + return (unsigned int)m_drivers.size();
1.224 +}
1.225 +
1.226 +IDBDriver *DBManager::GetDriver(unsigned int index)
1.227 +{
1.228 + if (index >= m_drivers.size())
1.229 + {
1.230 + return NULL;
1.231 + }
1.232 +
1.233 + return m_drivers[index];
1.234 +}
1.235 +
1.236 +const DatabaseInfo *DBManager::FindDatabaseConf(const char *name)
1.237 +{
1.238 + /* :TODO: */
1.239 + return NULL;
1.240 +}
2.1 --- a/core/Database.h Tue May 29 08:30:13 2007 +0000
2.2 +++ b/core/Database.h Tue May 29 08:32:12 2007 +0000
2.3 @@ -16,46 +16,38 @@
2.4 #define _INCLUDE_DATABASE_MANAGER_H_
2.5
2.6 #include <IDBDriver.h>
2.7 -#include <IHandleSys.h>
2.8 #include "sm_globals.h"
2.9 #include <sh_vector.h>
2.10
2.11 using namespace SourceHook;
2.12
2.13 -struct db_driver
2.14 -{
2.15 - IDBDriver *driver;
2.16 - IdentityToken_t *ident;
2.17 - HandleType_t htDatabase;
2.18 - HandleType_t htQuery;
2.19 - Handle_t hDriver;
2.20 -};
2.21 -
2.22 class DBManager :
2.23 public IDBManager,
2.24 public SMGlobalClass,
2.25 public IHandleTypeDispatch
2.26 {
2.27 +public:
2.28 const char *GetInterfaceName();
2.29 unsigned int GetInterfaceVersion();
2.30 public: //SMGlobalClass
2.31 void OnSourceModAllInitialized();
2.32 + void OnSourceModShutdown();
2.33 public: //IHandleTypeDispatch
2.34 void OnHandleDestroy(HandleType_t type, void *object);
2.35 public: //IDBManager
2.36 - void AddDriver(IDBDriver *pDriver, IdentityToken_t *ident);
2.37 + void AddDriver(IDBDriver *pDrivera);
2.38 void RemoveDriver(IDBDriver *pDriver);
2.39 const DatabaseInfo *FindDatabaseConf(const char *name);
2.40 - bool Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool persistent);
2.41 + bool Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool persistent, char *error, size_t maxlength);
2.42 unsigned int GetDriverCount();
2.43 - IDBDriver *GetDriver(unsigned int index, IdentityToken_t **pToken=NULL);
2.44 -public:
2.45 - db_driver *GetDriverInfo(unsigned int index);
2.46 + IDBDriver *GetDriver(unsigned int index);
2.47 + Handle_t CreateHandle(DBHandleType type, void *ptr, IdentityToken_t *pToken);
2.48 + HandleError ReadHandle(Handle_t hndl, DBHandleType type, void **ptr);
2.49 + HandleError ReleaseHandle(Handle_t hndl, DBHandleType type, IdentityToken_t *token);
2.50 private:
2.51 - CVector<db_driver *> m_drivers;
2.52 + CVector<IDBDriver *> m_drivers;
2.53 HandleType_t m_DriverType;
2.54 HandleType_t m_DatabaseType;
2.55 - HandleType_t m_QueryType;
2.56 };
2.57
2.58 extern DBManager g_DBMan;
3.1 --- a/public/IDBDriver.h Tue May 29 08:30:13 2007 +0000
3.2 +++ b/public/IDBDriver.h Tue May 29 08:32:12 2007 +0000
3.3 @@ -20,6 +20,7 @@
3.4 #define _INCLUDE_SOURCEMOD_INTERFACE_DBDRIVER_H_
3.5
3.6 #include <IShareSys.h>
3.7 +#include <IHandleSys.h>
3.8 #include <string.h>
3.9
3.10 #define SMINTERFACE_DBI_NAME "IDBI"
3.11 @@ -39,7 +40,26 @@
3.12 };
3.13
3.14 /**
3.15 + * @brief Describes a primitive database type.
3.16 + */
3.17 + enum DBType
3.18 + {
3.19 + DBType_Unknown = 0, /**< Type could not be inferred */
3.20 + DBType_String, /**< NULL-terminated string (variable length) */
3.21 + DBType_Blob, /**< Raw binary data (variable length) */
3.22 + DBType_Integer, /**< 4-byte signed integer */
3.23 + DBType_Float, /**< 4-byte floating point */
3.24 + };
3.25 +
3.26 + /**
3.27 * @brief Represents a one database result row.
3.28 + *
3.29 + * Note that type mismatches will only occur when type safety is being
3.30 + * enforced. So far this is only the case for prepared statements in
3.31 + * MySQL and SQLite.
3.32 + *
3.33 + * Also, it is worth noting that retrieving as raw data will never cause a
3.34 + * type mismatch.
3.35 */
3.36 class IResultRow
3.37 {
3.38 @@ -47,14 +67,33 @@
3.39 /**
3.40 * @brief Retrieves a database field result as a string.
3.41 *
3.42 - * For NULL values, the resulting string pointer will be non-NULL,
3.43 - * but empty.
3.44 + * For NULL values, the resulting string pointer will be non-NULL but
3.45 + * empty. The pointer returned will become invalid after advancing to
3.46 + * the next row.
3.47 *
3.48 * @param columnId Column to use, starting from 0.
3.49 * @param pString Pointer to store a pointer to the string.
3.50 + * @param length Optional pointer to store the string length.
3.51 * @return A DBResult return code.
3.52 */
3.53 - virtual DBResult GetString(unsigned int columnId, const char **pString) =0;
3.54 + virtual DBResult GetString(unsigned int columnId, const char **pString, size_t *length) =0;
3.55 +
3.56 + /**
3.57 + * @brief Retrieves a database field result as a string, using a
3.58 + * user-supplied buffer. If the field is NULL, an empty string
3.59 + * will be copied.
3.60 + *
3.61 + * @param columnId Column to use, starting from 0.
3.62 + * @param buffer Buffer to store string in.
3.63 + * @param maxlength Maximum length of the buffer.
3.64 + * @param written Optional pointer to store the number of bytes
3.65 + * written, excluding the null terminator.
3.66 + * @return A DBResult return code.
3.67 + */
3.68 + virtual DBResult CopyString(unsigned int columnId,
3.69 + char *buffer,
3.70 + size_t maxlength,
3.71 + size_t *written) =0;
3.72
3.73 /**
3.74 * @brief Retrieves a database field result as a float.
3.75 @@ -82,19 +121,51 @@
3.76 * @brief Returns whether or not a field is NULL.
3.77 *
3.78 * @param columnId Column to use, starting from 0.
3.79 - * @return A DBResult return code.
3.80 + * @return True if field is NULL, false otherwise.
3.81 */
3.82 - virtual DBResult CheckField(unsigned int columnId) =0;
3.83 + virtual bool IsNull(unsigned int columnId) =0;
3.84
3.85 /**
3.86 - * @brief Retrieves field data as a raw bitstream.
3.87 + * @brief Returns the size of a field (text/raw/blob) in bytes.
3.88 + * For strings, this returned size will not include the null
3.89 + * terminator.
3.90 + *
3.91 + * When used on fields that are not of variable length,
3.92 + * the size returned will be the number of bytes required
3.93 + * to store the internal data. Note that the data size
3.94 + * will correspond to the ACTUAL data type, not the
3.95 + * COLUMN type.
3.96 *
3.97 * @param columnId Column to use, starting from 0.
3.98 - * @param pData Pointer to store the raw bit stream.
3.99 + * @return Number of bytes required to store
3.100 + * the data, or 0 on failure.
3.101 + */
3.102 + virtual size_t GetDataSize(unsigned int columnId) =0;
3.103 +
3.104 + /**
3.105 + * @brief Retrieves field data as a raw bitstream. The pointer returned
3.106 + * will become invalid after advancing to the next row.
3.107 + *
3.108 + * @param columnId Column to use, starting from 0.
3.109 + * @param pData Pointer to store the raw bit stream. If the
3.110 + * data is NULL, a NULL pointer will be returned.
3.111 * @param length Pointer to store the data length.
3.112 * @return A DBResult return code.
3.113 */
3.114 - virtual DBResult GetRaw(unsigned int columnId, void **pData, size_t *length) =0;
3.115 + virtual DBResult GetBlob(unsigned int columnId, const void **pData, size_t *length) =0;
3.116 +
3.117 + /**
3.118 + * @brief Copies field data as a raw bitstream.
3.119 + *
3.120 + * @param columnId Column to use, starting from 0.
3.121 + * @param buffer Pointer to copy the data to. If the data is
3.122 + * NULL, no data will be copied.
3.123 + * @param maxlength Maximum length of the buffer.
3.124 + * @param written Optional pointer to store the number of bytes
3.125 + * written.
3.126 + * @return A DBResult return code.
3.127 + */
3.128 + virtual DBResult CopyBlob(unsigned int columnId, void *buffer, size_t maxlength, size_t *written) =0;
3.129 };
3.130
3.131 /**
3.132 @@ -123,7 +194,7 @@
3.133 * @param columnId Column to use, starting from 0.
3.134 * @return Pointer to column name, or NULL if not found.
3.135 */
3.136 - virtual const char *ColNumToName(unsigned int columnId) =0;
3.137 + virtual const char *FieldNumToName(unsigned int columnId) =0;
3.138
3.139 /**
3.140 * @brief Converts a column name to a column id.
3.141 @@ -134,7 +205,7 @@
3.142 * undefined.
3.143 * @return True on success, false if not found.
3.144 */
3.145 - virtual bool ColNumToName(const char *name, unsigned int *columnId) =0;
3.146 + virtual bool FieldNameToNum(const char *name, unsigned int *columnId) =0;
3.147
3.148 /**
3.149 * @brief Returns if there is still data in the result set.
3.150 @@ -142,7 +213,7 @@
3.151 * @return False if there is more data to be read,
3.152 * true, otherwise.
3.153 */
3.154 - virtual bool IsFinished() =0;
3.155 + virtual bool MoreRows() =0;
3.156
3.157 /**
3.158 * @brief Returns a pointer to the current row and advances
3.159 @@ -159,17 +230,150 @@
3.160 * @return True on success, false otherwise.
3.161 */
3.162 virtual bool Rewind() =0;
3.163 +
3.164 + /**
3.165 + * @brief Returns a field's type as it should be interpreted
3.166 + * by the user.
3.167 + *
3.168 + * @param field Field number (starting from 0).
3.169 + * @return A DBType value.
3.170 + */
3.171 + virtual DBType GetFieldType(unsigned int field) =0;
3.172 +
3.173 + /**
3.174 + * @brief Returns a field's type as it will be interpreted
3.175 + * by the GetDataSize() function. For example, MySQL
3.176 + * for non-prepared queries will store all results as
3.177 + * strings internally.
3.178 + *
3.179 + * @param field Field number (starting from 0).
3.180 + * @return A DBType value.
3.181 + */
3.182 + virtual DBType GetFieldDataType(unsigned int field) =0;
3.183 };
3.184
3.185 - class IDatabase;
3.186 + class IDBDriver;
3.187
3.188 - /**
3.189 - * @brief Encapsulates one database query.
3.190 - */
3.191 class IQuery
3.192 {
3.193 public:
3.194 /**
3.195 + * @brief Returns a pointer to the current result set, if any.
3.196 + *
3.197 + * @return An IResultSet pointer on success,
3.198 + * NULL if no result set exists.
3.199 + */
3.200 + virtual IResultSet *GetResultSet() =0;
3.201 +
3.202 + /**
3.203 + * @brief Advances to the next result set if one exists. This
3.204 + * is for checking for MORE result sets, and should not be used
3.205 + * on the first result set.
3.206 + *
3.207 + * Multiple results only happen in certain cases, such as CALLing
3.208 + * stored procedure that have a SELECTs, where MySQL will return
3.209 + * both the CALL status and one or more SELECT result sets. If
3.210 + * you do not process these results, they will be automatically
3.211 + * processed for you. However, the behaviour of creating a new
3.212 + * query from the same connection while results are left
3.213 + * unprocessed is undefined, and may result in a dropped
3.214 + * connection. Therefore, process all extra results or destroy the
3.215 + * IQuery pointer before starting a new query.
3.216 + *
3.217 + * Again, this only happens in very specific cases, so there is
3.218 + * no need to call this for normal queries.
3.219 + *
3.220 + * After calling this function, GetResultSet() must be called
3.221 + * again to return the result set. The previous result set
3.222 + * is automatically destroyed and will be unusable.
3.223 + *
3.224 + * @return True if another result set is
3.225 + * available, false otherwise.
3.226 + */
3.227 + virtual bool FetchMoreResults() =0;
3.228 +
3.229 + /**
3.230 + * @brief Frees resources created by this query.
3.231 + */
3.232 + virtual void Destroy() =0;
3.233 + };
3.234 +
3.235 + class IPreparedQuery : public IQuery
3.236 + {
3.237 + public:
3.238 + /**
3.239 + * @brief Binds an integer parameter.
3.240 + *
3.241 + * @param param Parameter index, starting from 0.
3.242 + * @param num Number to bind as a value.
3.243 + * @param signd True to write as signed, false to write as
3.244 + * unsigned.
3.245 + * @return True on success, false otherwise.
3.246 + */
3.247 + virtual bool BindParamInt(unsigned int param, int num, bool signd=true) =0;
3.248 +
3.249 + /**
3.250 + * @brief Binds a float parameter.
3.251 + *
3.252 + * @param param Parameter index, starting from 0.
3.253 + * @param f Float to bind as a value.
3.254 + * @return True on success, false otherwise.
3.255 + */
3.256 + virtual bool BindParamFloat(unsigned int param, float f) =0;
3.257 +
3.258 + /**
3.259 + * @brief Binds an SQL NULL type as a parameter.
3.260 + *
3.261 + * @param param Parameter index, starting from 0.
3.262 + * @return True on success, false otherwise.
3.263 + */
3.264 + virtual bool BindParamNull(unsigned int param) =0;
3.265 +
3.266 + /**
3.267 + * @brief Binds a string as a parameter.
3.268 + *
3.269 + * @param param Parameter index, starting from 0.
3.270 + * @param text Pointer to a null-terminated string.
3.271 + * @param copy If true, the pointer is assumed to be
3.272 + * volatile and a temporary copy may be
3.273 + * made for safety.
3.274 + * @return True on success, false otherwise.
3.275 + */
3.276 + virtual bool BindParamString(unsigned int param, const char *text, bool copy) =0;
3.277 +
3.278 + /**
3.279 + * @brief Binds a blob of raw data as a parameter.
3.280 + *
3.281 + * @param param Parameter index, starting from 0.
3.282 + * @param data Pointer to a blob of memory.
3.283 + * @param length Number of bytes to copy.
3.284 + * @param copy If true, the pointer is assumed to be
3.285 + * volatile and a temporary copy may be
3.286 + * made for safety.
3.287 + * @return True on success, false otherwise.
3.288 + */
3.289 + virtual bool BindParamBlob(unsigned int param,
3.290 + const void *data,
3.291 + size_t length,
3.292 + bool copy) =0;
3.293 +
3.294 + /**
3.295 + * @brief Executes the query with the currently bound parameters.
3.296 +
3.297 + * @return True on success, false otherwise.
3.298 + */
3.299 + virtual bool Execute() =0;
3.300 +
3.301 + /**
3.302 + * @brief Returns the last error message from this statement.
3.303 + *
3.304 + * @param errCode Optional pointer to store the driver-specific
3.305 + * error code.
3.306 + * @return Error message string.
3.307 + */
3.308 + virtual const char *GetError(int *errCode=NULL) =0;
3.309 +
3.310 + /**
3.311 * @brief Number of rows affected by the last execute.
3.312 *
3.313 * @return Number of rows affected by the last execute.
3.314 @@ -177,45 +381,13 @@
3.315 virtual unsigned int GetAffectedRows() =0;
3.316
3.317 /**
3.318 - * @brief Retrieves the last insert ID of this query, if any.
3.319 + * @brief Retrieves the last insert ID on this database connection.
3.320 *
3.321 * @return Row insertion ID of the last execute, if any.
3.322 */
3.323 virtual unsigned int GetInsertID() =0;
3.324 -
3.325 - /**
3.326 - * @brief Returns the full query string.
3.327 - *
3.328 - * @return String containing the original query.
3.329 - */
3.330 - virtual const char *GetQueryString() =0;
3.331 -
3.332 - /**
3.333 - * @brief Returns the result set from the last Execute call.
3.334 - *
3.335 - * @return IResultSet from the last Execute call.
3.336 - * Pointer will be NULL if there was no previous
3.337 - * call, the last call failed, or the last call
3.338 - * had no result set and Execute() was called with
3.339 - * retEmptySet=false.
3.340 - */
3.341 - virtual IResultSet *GetResultSet() =0;
3.342 -
3.343 - /**
3.344 - * @brief Returns the IDatabase object which created this pointer.
3.345 - *
3.346 - * @return IDatabase object which created this pointer.
3.347 - */
3.348 - virtual IDatabase *GetDatabase() =0;
3.349 -
3.350 - /**
3.351 - * @brief Releases the resources associated with this query.
3.352 - */
3.353 - virtual void Release() =0;
3.354 };
3.355
3.356 - class IDBDriver;
3.357 -
3.358 /**
3.359 * @brief Encapsulates a database connection.
3.360 */
3.361 @@ -224,11 +396,18 @@
3.362 public:
3.363 /**
3.364 * @brief Disconnects the database and frees its associated memory.
3.365 - * If this pointer was received via IDBDriver::PConnect(), Close()
3.366 - * must be called once for each successful PConnect() call which
3.367 - * resulted in this pointer.
3.368 + * Note that the actual object will not be freed until all open
3.369 + * references have been closed.
3.370 + *
3.371 + * It is guaranteed that an IDatabase pointer won't be destroyed until
3.372 + * all open IQuery or IPreparedQuery pointers are closed.
3.373 + *
3.374 + * @param Only pass true if being called from an
3.375 + * IHandleTypeDispatch destructor.
3.376 + * @return True if object was destroyed, false if
3.377 + * references are remaining.
3.378 */
3.379 - virtual void Close() =0;
3.380 + virtual bool Close(bool fromHndlSys=false) =0;
3.381
3.382 /**
3.383 * @brief Error code and string returned by the last operation on this
3.384 @@ -237,18 +416,41 @@
3.385 * @param errorCode Optional pointer to retrieve an error code.
3.386 * @return Error string pointer (empty if none).
3.387 */
3.388 - virtual const char *GetLastError(int *errorCode=NULL) =0;
3.389 + virtual const char *GetError(int *errorCode=NULL) =0;
3.390 +
3.391 + /**
3.392 + * @brief Prepares and executes a query in one step, and discards
3.393 + * any return data.
3.394 + *
3.395 + * @param query Query string.
3.396 + * @return True on success, false otherwise.
3.397 + */
3.398 + virtual bool DoSimpleQuery(const char *query) =0;
3.399
3.400 /**
3.401 * @brief Prepares and executes a query in one step, and returns
3.402 - * the resulting IQuery pointer.
3.403 + * the resultant data set.
3.404 + *
3.405 + * Note: If a query contains more than one result set, each
3.406 + * result set must be processed before a new query is started.
3.407 *
3.408 - * @param fmt String format to parse.
3.409 - * @param ... Format parameters.
3.410 - * @return An IQuery pointer which must be freed, or
3.411 - * NULL if the query failed.
3.412 + * @param query Query string.
3.413 + * @return IQuery pointer on success, NULL otherwise.
3.414 */
3.415 - virtual IQuery *DoQuery(const char *fmt, ...) =0;
3.416 + virtual IQuery *DoQuery(const char *query) =0;
3.417 +
3.418 + /**
3.419 + * @brief Prepares a query statement for multiple executions and/or
3.420 + * binding marked parameters (? in MySQL/sqLite, $n in PostgreSQL).
3.421 + *
3.422 + * @param query Query string.
3.423 + * @param error Error buffer.
3.424 + * @param maxlength Maximum length of the error buffer.
3.425 + * @param errCode Optional pointer to store a driver-specific error code.
3.426 + * @return IPreparedQuery pointer on success, NULL
3.427 + * otherwise.
3.428 + */
3.429 + virtual IPreparedQuery *PrepareQuery(const char *query, char *error, size_t maxlength, int *errCode=NULL) =0;
3.430
3.431 /**
3.432 * Quotes a string for insertion into a query.
3.433 @@ -264,11 +466,25 @@
3.434 virtual bool QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newSize) =0;
3.435
3.436 /**
3.437 - * @brief Returns the parent driver.
3.438 + * @brief Number of rows affected by the last execute.
3.439 + *
3.440 + * @return Number of rows affected by the last execute.
3.441 + */
3.442 + virtual unsigned int GetAffectedRows() =0;
3.443 +
3.444 + /**
3.445 + * @brief Retrieves the last insert ID on this database connection.
3.446 *
3.447 - * @return IDBDriver pointer that created this object.
3.448 + * @return Row insertion ID of the last execute, if any.
3.449 */
3.450 - virtual IDBDriver *GetDriver() =0;
3.451 + virtual unsigned int GetInsertID() =0;
3.452 +
3.453 + /**
3.454 + * @brief Returns an IDatabase Handle to this IDatabase.
3.455 + *
3.456 + * @return Handle_t of type IDatabase.
3.457 + */
3.458 + virtual Handle_t GetHandle() =0;
3.459 };
3.460
3.461 /**
3.462 @@ -307,35 +523,50 @@
3.463 * @brief Initiates a database connection.
3.464 *
3.465 * @param info Database connection info pointer.
3.466 + * @param persistent If true, a previous persistent connection will
3.467 + * be re-used if possible.
3.468 + * @param error Buffer to store error message.
3.469 + * @param maxlength Maximum size of the error buffer.
3.470 * @return A new IDatabase pointer, or NULL on failure.
3.471 */
3.472 - virtual IDatabase *Connect(const DatabaseInfo *info) =0;
3.473 -
3.474 - /**
3.475 - * @brief Initiates a database connection. If a connection to the given database
3.476 - * already exists, this will re-use the old connection handle.
3.477 - *
3.478 - * @param info Database connection info pointer.
3.479 - * @return A new IDatabase pointer, or NULL on failure.
3.480 - */
3.481 - virtual IDatabase *PConnect(const DatabaseInfo *info) =0;
3.482 + virtual IDatabase *Connect(const DatabaseInfo *info, bool persistent, char *error, size_t maxlength) =0;
3.483
3.484 /**
3.485 * @brief Returns a case insensitive database identifier string.
3.486 + *
3.487 + * @return String containing an identifier.
3.488 */
3.489 virtual const char *GetIdentifier() =0;
3.490
3.491 /**
3.492 * @brief Returns a case sensitive implementation name.
3.493 + *
3.494 + * @return String containing an implementation name.
3.495 */
3.496 virtual const char *GetProductName() =0;
3.497
3.498 /**
3.499 - * @brief Returns the last connection error.
3.500 + * @brief Retrieves a Handle_t handle of the IDBDriver type.
3.501 + *
3.502 + * @return A Handle_t handle.
3.503 + */
3.504 + virtual Handle_t GetHandle() =0;
3.505 +
3.506 + /**
3.507 + * @brief Returns the driver's controlling identity.
3.508 *
3.509 - * @param errCode Optional pointer to store a platform-specific error code.
3.510 + * @return An IdentityToken_t identity.
3.511 */
3.512 - virtual const char *GetLastError(int *errCode=NULL) =0;
3.513 + virtual IdentityToken_t *GetIdentity() =0;
3.514 + };
3.515 +
3.516 + /**
3.517 + * @brief Database-related Handle types.
3.518 + */
3.519 + enum DBHandleType
3.520 + {
3.521 + DBHandle_Driver = 0, /**< Driver Handle */
3.522 + DBHandle_Database = 1, /**< Database Handle */
3.523 };
3.524
3.525 /**
3.526 @@ -352,7 +583,7 @@
3.527 *
3.528 * @param pDriver Database driver.
3.529 */
3.530 - virtual void AddDriver(IDBDriver *pDriver, IdentityToken_t *pToken) =0;
3.531 + virtual void AddDriver(IDBDriver *pDriver) =0;
3.532
3.533 /**
3.534 * @brief Removes a driver from the DBI system.
3.535 @@ -379,9 +610,16 @@
3.536 * If connection fails, NULL will be stored.
3.537 * @param persistent If true, the dbmanager will attempt to PConnect
3.538 * instead of connect.
3.539 + * @param error Error buffer to store a driver's error message.
3.540 + * @param maxlength Maximum length of the error buffer.
3.541 * @return True on success, false otherwise.
3.542 */
3.543 - virtual bool Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool persistent) =0;
3.544 + virtual bool Connect(const char *name,
3.545 + IDBDriver **pdr,
3.546 + IDatabase **pdb,
3.547 + bool persistent,
3.548 + char *error,
3.549 + size_t maxlength) =0;
3.550
3.551 /**
3.552 * @brief Returns the number of drivers loaded.
3.553 @@ -394,10 +632,39 @@
3.554 * @brief Returns a driver by index.
3.555 *
3.556 * @param index Driver index, starting from 0.
3.557 - * @param pToken Optional pointer to store the driver's identity token.
3.558 * @return IDBDriver pointer for the given index.
3.559 */
3.560 - virtual IDBDriver *GetDriver(unsigned int index, IdentityToken_t **pToken=NULL) =0;
3.561 + virtual IDBDriver *GetDriver(unsigned int index) =0;
3.562 +
3.563 + /**
3.564 + * @brief Creates a Handle_t of the IDBDriver type.
3.565 + *
3.566 + * @param type A DBHandleType value.
3.567 + * @param ptr A pointer corrresponding to a DBHandleType object.
3.568 + * @param token Identity pointer of the owning identity.
3.569 + * @return A new Handle_t handle, or 0 on failure.
3.570 + */
3.571 + virtual Handle_t CreateHandle(DBHandleType type, void *ptr, IdentityToken_t *pToken) =0;
3.572 +
3.573 + /**
3.574 + * @brief Reads an IDBDriver pointer from an IDBDriver handle.
3.575 + *
3.576 + * @param hndl Handle_t handle to read.
3.577 + * @param type A DBHandleType value.
3.578 + * @param ptr Pointer to store the object pointer.
3.579 + * @return HandleError value.
3.580 + */
3.581 + virtual HandleError ReadHandle(Handle_t hndl, DBHandleType type, void **ptr) =0;
3.582 +
3.583 + /**
3.584 + * @brief Releases an IDBDriver handle.
3.585 + *
3.586 + * @param hndl Handle_t handle to release.
3.587 + * @param type A DBHandleType value.
3.588 + * @param token Identity pointer of the owning identity.
3.589 + * @return HandleError value.
3.590 + */
3.591 + virtual HandleError ReleaseHandle(Handle_t hndl, DBHandleType type, IdentityToken_t *token) =0;
3.592 };
3.593 }
3.594