dvander@666: /**
dvander@666: * vim: set ts=4 :
ds@1330: * =============================================================================
dvander@1226: * SourceMod
ds@1947: * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
ds@1330: * =============================================================================
dvander@666: *
ds@1330: * This program is free software; you can redistribute it and/or modify it under
ds@1330: * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330: * Free Software Foundation.
dvander@666: *
ds@1330: * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
ds@1330: * details.
dvander@1226: *
ds@1330: * You should have received a copy of the GNU General Public License along with
ds@1330: * this program. If not, see .
dvander@1226: *
ds@1330: * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330: * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330: * by the Valve Corporation. You must obey the GNU General Public License in
ds@1330: * all respects for all other code used. Additionally, AlliedModders LLC grants
ds@1330: * this exception to all derivative works. AlliedModders LLC defines further
ds@1330: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330: * or .
dvander@666: *
dvander@666: * Version: $Id$
dvander@666: */
dvander@666:
dvander@666: #ifndef _INCLUDE_SOURCEMOD_INTERFACE_DBDRIVER_H_
dvander@666: #define _INCLUDE_SOURCEMOD_INTERFACE_DBDRIVER_H_
dvander@666:
dvander@666: #include
dvander@858: #include
dvander@666: #include
dvander@666:
dvander@1680: /**
dvander@1680: * @file IDBDriver.h
dvander@1680: * @brief Defines interfaces for interacting with relational databases.
dvander@1680: */
dvander@1680:
dvander@666: #define SMINTERFACE_DBI_NAME "IDBI"
dvander@2134: #define SMINTERFACE_DBI_VERSION 7
dvander@666:
dvander@666: namespace SourceMod
dvander@666: {
dvander@666: /**
dvander@666: * @brief Describes a database field value.
dvander@666: */
dvander@666: enum DBResult
dvander@666: {
dvander@666: DBVal_Error = 0, /**< Column number/field is invalid */
dvander@666: DBVal_TypeMismatch = 1, /**< You cannot retrieve this data with this type */
dvander@666: DBVal_Null = 2, /**< Field has no data (NULL) */
dvander@666: DBVal_Data = 3, /**< Field has data */
dvander@666: };
dvander@666:
dvander@666: /**
dvander@858: * @brief Describes a primitive database type.
dvander@858: */
dvander@858: enum DBType
dvander@858: {
dvander@858: DBType_Unknown = 0, /**< Type could not be inferred */
dvander@858: DBType_String, /**< NULL-terminated string (variable length) */
dvander@858: DBType_Blob, /**< Raw binary data (variable length) */
dvander@858: DBType_Integer, /**< 4-byte signed integer */
dvander@858: DBType_Float, /**< 4-byte floating point */
dvander@1203: DBType_NULL, /**< NULL (no data) */
dvander@1203: /* --------- */
dvander@1203: DBTypes_TOTAL, /**< Total number of database types known */
dvander@858: };
dvander@858:
dvander@858: /**
dvander@666: * @brief Represents a one database result row.
dvander@858: *
dvander@858: * Note that type mismatches will only occur when type safety is being
dvander@858: * enforced. So far this is only the case for prepared statements in
dvander@858: * MySQL and SQLite.
dvander@858: *
dvander@858: * Also, it is worth noting that retrieving as raw data will never cause a
dvander@858: * type mismatch.
dvander@666: */
dvander@666: class IResultRow
dvander@666: {
dvander@666: public:
dvander@666: /**
dvander@666: * @brief Retrieves a database field result as a string.
dvander@666: *
dvander@858: * For NULL values, the resulting string pointer will be non-NULL but
dvander@858: * empty. The pointer returned will become invalid after advancing to
dvander@858: * the next row.
dvander@666: *
dvander@666: * @param columnId Column to use, starting from 0.
dvander@666: * @param pString Pointer to store a pointer to the string.
dvander@858: * @param length Optional pointer to store the string length.
dvander@666: * @return A DBResult return code.
dvander@666: */
dvander@858: virtual DBResult GetString(unsigned int columnId, const char **pString, size_t *length) =0;
dvander@858:
dvander@858: /**
dvander@858: * @brief Retrieves a database field result as a string, using a
dvander@858: * user-supplied buffer. If the field is NULL, an empty string
dvander@858: * will be copied.
dvander@858: *
dvander@858: * @param columnId Column to use, starting from 0.
dvander@858: * @param buffer Buffer to store string in.
dvander@858: * @param maxlength Maximum length of the buffer.
dvander@858: * @param written Optional pointer to store the number of bytes
dvander@858: * written, excluding the null terminator.
dvander@858: * @return A DBResult return code.
dvander@858: */
dvander@858: virtual DBResult CopyString(unsigned int columnId,
dvander@858: char *buffer,
dvander@858: size_t maxlength,
dvander@858: size_t *written) =0;
dvander@666:
dvander@666: /**
dvander@666: * @brief Retrieves a database field result as a float.
dvander@666: *
dvander@666: * For NULL entries, the returned float value will be 0.0.
dvander@666: *
dvander@666: * @param columnId Column to use, starting from 0.
dvander@666: * @param pFloat Pointer to a floating point number to set.
dvander@666: * @return A DBResult return code.
dvander@666: */
dvander@666: virtual DBResult GetFloat(unsigned int columnId, float *pFloat) =0;
dvander@666:
dvander@666: /**
dvander@666: * @brief Retrieves a database field result as an integer.
dvander@666: *
dvander@666: * For NULL entries, the returned integer value will be 0.
dvander@666: *
dvander@666: * @param columnId Column to use, starting from 0.
dvander@666: * @param pInt Pointer to an integer number to set.
dvander@666: * @return A DBResult return code.
dvander@666: */
dvander@666: virtual DBResult GetInt(unsigned int columnId, int *pInt) =0;
dvander@666:
dvander@666: /**
dvander@666: * @brief Returns whether or not a field is NULL.
dvander@666: *
dvander@666: * @param columnId Column to use, starting from 0.
dvander@858: * @return True if field is NULL, false otherwise.
dvander@666: */
dvander@858: virtual bool IsNull(unsigned int columnId) =0;
dvander@666:
dvander@666: /**
dvander@858: * @brief Returns the size of a field (text/raw/blob) in bytes.
dvander@858: * For strings, this returned size will not include the null
dvander@858: * terminator.
dvander@858: *
dvander@858: * When used on fields that are not of variable length,
dvander@858: * the size returned will be the number of bytes required
dvander@858: * to store the internal data. Note that the data size
dvander@858: * will correspond to the ACTUAL data type, not the
dvander@858: * COLUMN type.
dvander@666: *
dvander@666: * @param columnId Column to use, starting from 0.
dvander@858: * @return Number of bytes required to store
dvander@858: * the data, or 0 on failure.
dvander@858: */
dvander@858: virtual size_t GetDataSize(unsigned int columnId) =0;
dvander@858:
dvander@858: /**
dvander@858: * @brief Retrieves field data as a raw bitstream. The pointer returned
dvander@858: * will become invalid after advancing to the next row.
dvander@858: *
dvander@858: * @param columnId Column to use, starting from 0.
dvander@858: * @param pData Pointer to store the raw bit stream. If the
dvander@858: * data is NULL, a NULL pointer will be returned.
dvander@666: * @param length Pointer to store the data length.
dvander@666: * @return A DBResult return code.
dvander@666: */
dvander@858: virtual DBResult GetBlob(unsigned int columnId, const void **pData, size_t *length) =0;
dvander@858:
dvander@858: /**
dvander@858: * @brief Copies field data as a raw bitstream.
dvander@858: *
dvander@858: * @param columnId Column to use, starting from 0.
dvander@858: * @param buffer Pointer to copy the data to. If the data is
dvander@858: * NULL, no data will be copied.
dvander@858: * @param maxlength Maximum length of the buffer.
dvander@858: * @param written Optional pointer to store the number of bytes
dvander@858: * written.
dvander@858: * @return A DBResult return code.
dvander@858: */
dvander@858: virtual DBResult CopyBlob(unsigned int columnId, void *buffer, size_t maxlength, size_t *written) =0;
dvander@666: };
dvander@666:
dvander@666: /**
dvander@666: * @brief Describes a set of database results.
dvander@666: */
dvander@666: class IResultSet
dvander@666: {
dvander@666: public:
dvander@666: /**
dvander@666: * @brief Returns the number of rows in the set.
dvander@666: *
dvander@666: * @return Number of rows in the set.
dvander@666: */
dvander@666: virtual unsigned int GetRowCount() =0;
dvander@666:
dvander@666: /**
dvander@666: * @brief Returns the number of fields in the set.
dvander@666: *
dvander@666: * @return Number of fields in the set.
dvander@666: */
dvander@666: virtual unsigned int GetFieldCount() =0;
dvander@666:
dvander@666: /**
dvander@666: * @brief Converts a column number to a column name.
dvander@666: *
dvander@666: * @param columnId Column to use, starting from 0.
dvander@666: * @return Pointer to column name, or NULL if not found.
dvander@666: */
dvander@858: virtual const char *FieldNumToName(unsigned int columnId) =0;
dvander@666:
dvander@666: /**
dvander@666: * @brief Converts a column name to a column id.
dvander@666: *
dvander@666: * @param name Column name (case sensitive).
dvander@666: * @param columnId Pointer to store the column id. If the
dvander@666: * name is not found, the value will be
dvander@666: * undefined.
dvander@666: * @return True on success, false if not found.
dvander@666: */
dvander@858: virtual bool FieldNameToNum(const char *name, unsigned int *columnId) =0;
dvander@666:
dvander@666: /**
dvander@666: * @brief Returns if there is still data in the result set.
dvander@666: *
dvander@666: * @return False if there is more data to be read,
dvander@666: * true, otherwise.
dvander@666: */
dvander@858: virtual bool MoreRows() =0;
dvander@666:
dvander@666: /**
dvander@666: * @brief Returns a pointer to the current row and advances
dvander@666: * the internal row pointer/counter to the next row available.
dvander@666: *
dvander@666: * @return IResultRow pointer to the current row,
dvander@666: * or NULL if there is no more data.
dvander@666: */
dvander@666: virtual IResultRow *FetchRow() =0;
dvander@666:
dvander@666: /**
dvander@862: * @brief Returns a pointer to the current row.
dvander@862: *
dvander@862: * @return IResultRow pointer to the current row,
dvander@862: * or NULL if the current row is invalid.
dvander@862: */
dvander@862: virtual IResultRow *CurrentRow() =0;
dvander@862:
dvander@862: /**
dvander@666: * @brief Rewinds back to the beginning of the row iteration.
dvander@666: *
dvander@666: * @return True on success, false otherwise.
dvander@666: */
dvander@666: virtual bool Rewind() =0;
dvander@858:
dvander@858: /**
dvander@858: * @brief Returns a field's type as it should be interpreted
dvander@858: * by the user.
dvander@858: *
dvander@858: * @param field Field number (starting from 0).
dvander@858: * @return A DBType value.
dvander@858: */
dvander@858: virtual DBType GetFieldType(unsigned int field) =0;
dvander@858:
dvander@858: /**
dvander@858: * @brief Returns a field's type as it will be interpreted
dvander@858: * by the GetDataSize() function. For example, MySQL
dvander@858: * for non-prepared queries will store all results as
dvander@858: * strings internally.
dvander@858: *
dvander@858: * @param field Field number (starting from 0).
dvander@858: * @return A DBType value.
dvander@858: */
dvander@858: virtual DBType GetFieldDataType(unsigned int field) =0;
dvander@666: };
dvander@666:
dvander@858: class IDBDriver;
dvander@666:
dvander@666: class IQuery
dvander@666: {
dvander@666: public:
dvander@666: /**
dvander@858: * @brief Returns a pointer to the current result set, if any.
dvander@858: *
dvander@858: * @return An IResultSet pointer on success,
dvander@858: * NULL if no result set exists.
dvander@858: */
dvander@858: virtual IResultSet *GetResultSet() =0;
dvander@858:
dvander@858: /**
dvander@858: * @brief Advances to the next result set if one exists. This
dvander@858: * is for checking for MORE result sets, and should not be used
dvander@858: * on the first result set.
dvander@858: *
dvander@858: * Multiple results only happen in certain cases, such as CALLing
dvander@858: * stored procedure that have a SELECTs, where MySQL will return
dvander@858: * both the CALL status and one or more SELECT result sets. If
dvander@858: * you do not process these results, they will be automatically
dvander@858: * processed for you. However, the behaviour of creating a new
dvander@858: * query from the same connection while results are left
dvander@858: * unprocessed is undefined, and may result in a dropped
dvander@858: * connection. Therefore, process all extra results or destroy the
dvander@858: * IQuery pointer before starting a new query.
dvander@858: *
dvander@858: * Again, this only happens in very specific cases, so there is
dvander@858: * no need to call this for normal queries.
dvander@858: *
dvander@858: * After calling this function, GetResultSet() must be called
dvander@858: * again to return the result set. The previous result set
dvander@858: * is automatically destroyed and will be unusable.
dvander@858: *
dvander@858: * @return True if another result set is
dvander@858: * available, false otherwise.
dvander@858: */
dvander@858: virtual bool FetchMoreResults() =0;
dvander@858:
dvander@858: /**
dvander@858: * @brief Frees resources created by this query.
dvander@858: */
dvander@858: virtual void Destroy() =0;
dvander@858: };
dvander@858:
dvander@858: class IPreparedQuery : public IQuery
dvander@858: {
dvander@858: public:
dvander@858: /**
dvander@858: * @brief Binds an integer parameter.
dvander@858: *
dvander@858: * @param param Parameter index, starting from 0.
dvander@858: * @param num Number to bind as a value.
dvander@858: * @param signd True to write as signed, false to write as
dvander@858: * unsigned.
dvander@858: * @return True on success, false otherwise.
dvander@858: */
dvander@858: virtual bool BindParamInt(unsigned int param, int num, bool signd=true) =0;
dvander@858:
dvander@858: /**
dvander@858: * @brief Binds a float parameter.
dvander@858: *
dvander@858: * @param param Parameter index, starting from 0.
dvander@858: * @param f Float to bind as a value.
dvander@858: * @return True on success, false otherwise.
dvander@858: */
dvander@858: virtual bool BindParamFloat(unsigned int param, float f) =0;
dvander@858:
dvander@858: /**
dvander@858: * @brief Binds an SQL NULL type as a parameter.
dvander@858: *
dvander@858: * @param param Parameter index, starting from 0.
dvander@858: * @return True on success, false otherwise.
dvander@858: */
dvander@858: virtual bool BindParamNull(unsigned int param) =0;
dvander@858:
dvander@858: /**
dvander@858: * @brief Binds a string as a parameter.
dvander@858: *
dvander@858: * @param param Parameter index, starting from 0.
dvander@858: * @param text Pointer to a null-terminated string.
dvander@858: * @param copy If true, the pointer is assumed to be
dvander@858: * volatile and a temporary copy may be
dvander@858: * made for safety.
dvander@858: * @return True on success, false otherwise.
dvander@858: */
dvander@858: virtual bool BindParamString(unsigned int param, const char *text, bool copy) =0;
dvander@858:
dvander@858: /**
dvander@858: * @brief Binds a blob of raw data as a parameter.
dvander@858: *
dvander@858: * @param param Parameter index, starting from 0.
dvander@858: * @param data Pointer to a blob of memory.
dvander@858: * @param length Number of bytes to copy.
dvander@858: * @param copy If true, the pointer is assumed to be
dvander@858: * volatile and a temporary copy may be
dvander@858: * made for safety.
dvander@858: * @return True on success, false otherwise.
dvander@858: */
dvander@858: virtual bool BindParamBlob(unsigned int param,
dvander@858: const void *data,
dvander@858: size_t length,
dvander@858: bool copy) =0;
dvander@858:
dvander@858: /**
dvander@858: * @brief Executes the query with the currently bound parameters.
dvander@858:
dvander@858: * @return True on success, false otherwise.
dvander@858: */
dvander@858: virtual bool Execute() =0;
dvander@858:
dvander@858: /**
dvander@858: * @brief Returns the last error message from this statement.
dvander@858: *
dvander@858: * @param errCode Optional pointer to store the driver-specific
dvander@858: * error code.
dvander@858: * @return Error message string.
dvander@858: */
dvander@858: virtual const char *GetError(int *errCode=NULL) =0;
dvander@858:
dvander@858: /**
dvander@666: * @brief Number of rows affected by the last execute.
dvander@666: *
dvander@666: * @return Number of rows affected by the last execute.
dvander@666: */
dvander@666: virtual unsigned int GetAffectedRows() =0;
dvander@666:
dvander@666: /**
dvander@858: * @brief Retrieves the last insert ID on this database connection.
dvander@666: *
dvander@666: * @return Row insertion ID of the last execute, if any.
dvander@666: */
dvander@666: virtual unsigned int GetInsertID() =0;
dvander@666: };
dvander@666:
dvander@1095: class IDBDriver;
dvander@1095:
dvander@666: /**
dvander@666: * @brief Encapsulates a database connection.
dvander@666: */
dvander@666: class IDatabase
dvander@666: {
dvander@666: public:
dvander@666: /**
dvander@666: * @brief Disconnects the database and frees its associated memory.
dvander@858: * Note that the actual object will not be freed until all open
dvander@858: * references have been closed.
dvander@858: *
dvander@858: * It is guaranteed that an IDatabase pointer won't be destroyed until
dvander@858: * all open IQuery or IPreparedQuery pointers are closed.
dvander@1158: *
dvander@1158: * This function is thread safe.
dvander@875: *
dvander@858: * @return True if object was destroyed, false if
dvander@858: * references are remaining.
dvander@666: */
dvander@875: virtual bool Close() =0;
dvander@666:
dvander@666: /**
dvander@666: * @brief Error code and string returned by the last operation on this
dvander@666: * connection.
dvander@666: *
dvander@1158: * This function is not thread safe and must be included in any locks.
dvander@1158: *
dvander@666: * @param errorCode Optional pointer to retrieve an error code.
dvander@666: * @return Error string pointer (empty if none).
dvander@666: */
dvander@858: virtual const char *GetError(int *errorCode=NULL) =0;
dvander@858:
dvander@858: /**
dvander@858: * @brief Prepares and executes a query in one step, and discards
dvander@858: * any return data.
dvander@858: *
dvander@1158: * This function is not thread safe and must be included in any locks.
dvander@1158: *
dvander@858: * @param query Query string.
dvander@858: * @return True on success, false otherwise.
dvander@858: */
dvander@858: virtual bool DoSimpleQuery(const char *query) =0;
dvander@666:
dvander@666: /**
dvander@666: * @brief Prepares and executes a query in one step, and returns
dvander@858: * the resultant data set.
dvander@858: *
dvander@858: * Note: If a query contains more than one result set, each
dvander@858: * result set must be processed before a new query is started.
dvander@666: *
dvander@1158: * This function is not thread safe and must be included in any locks.
dvander@1158: *
dvander@858: * @param query Query string.
dvander@858: * @return IQuery pointer on success, NULL otherwise.
dvander@666: */
dvander@858: virtual IQuery *DoQuery(const char *query) =0;
dvander@858:
dvander@858: /**
dvander@858: * @brief Prepares a query statement for multiple executions and/or
dvander@858: * binding marked parameters (? in MySQL/sqLite, $n in PostgreSQL).
dvander@858: *
dvander@1158: * This function is not thread safe and must be included in any locks.
dvander@1158: *
dvander@858: * @param query Query string.
dvander@858: * @param error Error buffer.
dvander@858: * @param maxlength Maximum length of the error buffer.
dvander@858: * @param errCode Optional pointer to store a driver-specific error code.
dvander@858: * @return IPreparedQuery pointer on success, NULL
dvander@858: * otherwise.
dvander@858: */
dvander@858: virtual IPreparedQuery *PrepareQuery(const char *query, char *error, size_t maxlength, int *errCode=NULL) =0;
dvander@666:
dvander@666: /**
dvander@666: * Quotes a string for insertion into a query.
dvander@666: *
dvander@666: * @param str Source string.
dvander@666: * @param buffer Buffer to store new string (should not overlap source string).
dvander@666: * @param maxlen Maximum length of the output buffer.
dvander@666: * @param newSize Pointer to store the output size.
dvander@666: * @return True on success, false if the output buffer is not big enough.
dvander@666: * If not big enough, the required buffer size is passed through
dvander@666: * newSize.
dvander@666: */
dvander@666: virtual bool QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newSize) =0;
dvander@666:
dvander@666: /**
dvander@858: * @brief Number of rows affected by the last execute.
dvander@858: *
dvander@1158: * This function is not thread safe and must be included in any locks.
dvander@1158: *
dvander@858: * @return Number of rows affected by the last execute.
dvander@858: */
dvander@858: virtual unsigned int GetAffectedRows() =0;
dvander@858:
dvander@858: /**
dvander@858: * @brief Retrieves the last insert ID on this database connection.
dvander@666: *
dvander@1158: * This function is not thread safe and must be included in any locks.
dvander@1158: *
dvander@858: * @return Row insertion ID of the last execute, if any.
dvander@666: */
dvander@858: virtual unsigned int GetInsertID() =0;
dvander@1095:
dvander@1095: /**
dvander@1095: * @brief Locks the database for an atomic query+retrieval operation.
dvander@1095: *
dvander@1095: * @return True on success, false if not supported.
dvander@1095: */
dvander@1095: virtual bool LockForFullAtomicOperation() =0;
dvander@1095:
dvander@1095: /**
dvander@1095: * @brief Unlocks a locked atomic fetch.
dvander@1095: */
dvander@1095: virtual void UnlockFromFullAtomicOperation() =0;
dvander@1095:
dvander@1095: /**
dvander@1095: * @brief Increases the reference count on the database.
dvander@1158: *
dvander@1158: * This function is thread safe.
dvander@1095: */
dvander@1095: virtual void IncReferenceCount() =0;
dvander@1095:
dvander@1095: /**
dvander@1095: * @brief Returns the parent driver.
dvander@1158: *
dvander@1158: * This function is thread safe.
dvander@1095: */
dvander@1095: virtual IDBDriver *GetDriver() =0;
dvander@1912:
dvander@1912: /**
dvander@1912: * @brief Prepares and executes a binary query in one step, and discards
dvander@1912: * any return data.
dvander@1912: *
dvander@1912: * This function is not thread safe and must be included in any locks.
dvander@1912: *
dvander@1912: * @param query Query string.
dvander@1912: * @param length Length of query string.
dvander@1912: * @return True on success, false otherwise.
dvander@1912: */
dvander@1912: virtual bool DoSimpleQueryEx(const char *query, size_t len) =0;
dvander@1912:
dvander@1912: /**
dvander@1912: * @brief Prepares and executes a binary query in one step, and returns
dvander@1912: * the resultant data set.
dvander@1912: *
dvander@1912: * Note: If a query contains more than one result set, each
dvander@1912: * result set must be processed before a new query is started.
dvander@1912: *
dvander@1912: * This function is not thread safe and must be included in any locks.
dvander@1912: *
dvander@1912: * @param query Query string.
dvander@1912: * @return IQuery pointer on success, NULL otherwise.
dvander@1912: */
dvander@1912: virtual IQuery *DoQueryEx(const char *query, size_t len) =0;
dvander@666: };
dvander@666:
dvander@666: /**
dvander@666: * @brief Describes database connection info.
dvander@666: */
dvander@666: struct DatabaseInfo
dvander@666: {
dvander@666: DatabaseInfo()
dvander@666: {
dvander@666: dbiVersion = SMINTERFACE_DBI_VERSION;
dvander@666: port = 0;
dvander@666: maxTimeout = 0;
dvander@666: }
dvander@666: unsigned int dbiVersion; /**< DBI Version for backwards compatibility */
dvander@666: const char *host; /**< Host string */
dvander@666: const char *database; /**< Database name string */
dvander@666: const char *user; /**< User to authenticate as */
dvander@666: const char *pass; /**< Password to authenticate with */
dvander@666: const char *driver; /**< Driver to use */
dvander@666: unsigned int port; /**< Port to use, 0=default */
dvander@666: unsigned int maxTimeout; /**< Maximum timeout, 0=default */
dvander@666: };
dvander@666:
dvander@666: /**
dvander@666: * @brief Describes an SQL driver.
dvander@666: */
dvander@666: class IDBDriver
dvander@666: {
dvander@666: public:
dvander@666: virtual unsigned int GetDBIVersion()
dvander@666: {
dvander@666: return SMINTERFACE_DBI_VERSION;
dvander@666: }
dvander@666: public:
dvander@666: /**
dvander@666: * @brief Initiates a database connection.
dvander@1158: *
dvander@1158: * Note: Persistent connections should never be created from a thread.
dvander@666: *
dvander@666: * @param info Database connection info pointer.
dvander@858: * @param persistent If true, a previous persistent connection will
dvander@858: * be re-used if possible.
dvander@858: * @param error Buffer to store error message.
dvander@858: * @param maxlength Maximum size of the error buffer.
dvander@666: * @return A new IDatabase pointer, or NULL on failure.
dvander@666: */
dvander@858: virtual IDatabase *Connect(const DatabaseInfo *info, bool persistent, char *error, size_t maxlength) =0;
dvander@666:
dvander@666: /**
dvander@666: * @brief Returns a case insensitive database identifier string.
dvander@858: *
dvander@858: * @return String containing an identifier.
dvander@666: */
dvander@666: virtual const char *GetIdentifier() =0;
dvander@666:
dvander@666: /**
dvander@666: * @brief Returns a case sensitive implementation name.
dvander@858: *
dvander@858: * @return String containing an implementation name.
dvander@666: */
dvander@666: virtual const char *GetProductName() =0;
dvander@666:
dvander@666: /**
dvander@858: * @brief Retrieves a Handle_t handle of the IDBDriver type.
dvander@858: *
dvander@858: * @return A Handle_t handle.
dvander@858: */
dvander@858: virtual Handle_t GetHandle() =0;
dvander@858:
dvander@858: /**
dvander@868: * @brief Returns the driver's controlling identity (must be the same
dvander@868: * as from IExtension::GetIdentity).
dvander@666: *
dvander@858: * @return An IdentityToken_t identity.
dvander@666: */
dvander@858: virtual IdentityToken_t *GetIdentity() =0;
dvander@1095:
dvander@1095: /**
dvander@1095: * @brief Returns whether the driver is thread safe.
dvander@1095: *
dvander@1095: * @return True if thread safe, false otherwise.
dvander@1095: */
dvander@1095: virtual bool IsThreadSafe() =0;
dvander@1095:
dvander@1095: /**
dvander@1095: * @brief Initializes thread safety for the calling thread.
dvander@1095: *
dvander@1095: * @return True on success, false otherwise.
dvander@1095: */
dvander@1095: virtual bool InitializeThreadSafety() =0;
dvander@1095:
dvander@1095: /**
dvander@1095: * @brief Shuts down thread safety for the calling thread.
dvander@1095: */
dvander@1095: virtual void ShutdownThreadSafety() =0;
dvander@858: };
dvander@858:
dvander@858: /**
dvander@1158: * @brief Priority queue level.
dvander@1158: */
dvander@1158: enum PrioQueueLevel
dvander@1158: {
dvander@1158: PrioQueue_High, /**< High priority */
dvander@1158: PrioQueue_Normal, /**< Normal priority */
dvander@1158: PrioQueue_Low /**< Low priority */
dvander@1158: };
dvander@1158:
dvander@1158: /**
dvander@1158: * Specification for a threaded database operation.
dvander@1158: */
dvander@1158: class IDBThreadOperation
dvander@1158: {
dvander@1158: public:
dvander@1158: /**
dvander@1158: * @brief Must return the driver this operation is using, or
dvander@1158: * NULL if not using any driver. This is not never inside
dvander@1158: * the thread.
dvander@1158: *
dvander@1158: * @return IDBDriver pointer.
dvander@1158: */
dvander@1158: virtual IDBDriver *GetDriver() =0;
dvander@1158:
dvander@1158: /**
dvander@1158: * @brief Must return the object owning this threaded operation.
dvander@1158: * This is never called inside the thread.
dvander@1158: *
dvander@1158: * @return IdentityToken_t pointer.
dvander@1158: */
dvander@1158: virtual IdentityToken_t *GetOwner() =0;
dvander@1158:
dvander@1158: /**
dvander@1158: * @brief Called inside the thread; this is where any blocking
dvander@1158: * or threaded operations must occur.
dvander@1158: */
dvander@1158: virtual void RunThreadPart() =0;
dvander@1158:
dvander@1158: /**
dvander@1158: * @brief Called in a server frame after the thread operation
dvander@1158: * has completed. This is the non-threaded completion callback,
dvander@1158: * which although optional, is useful for pumping results back
dvander@1158: * to normal game API.
dvander@1158: */
dvander@1158: virtual void RunThinkPart() =0;
dvander@1158:
dvander@1158: /**
dvander@1158: * @brief If RunThinkPart() is not called, this will be called
dvander@1158: * instead. Note that RunThreadPart() is ALWAYS called regardless,
dvander@1158: * and this is only called when Core requests that the operation
dvander@1158: * be scrapped (for example, the database driver might be unloading).
dvander@1158: */
dvander@1158: virtual void CancelThinkPart() =0;
dvander@1158:
dvander@1158: /**
dvander@1158: * @brief Called when the operation is finalized and any resources
dvander@1158: * can be released.
dvander@1158: */
dvander@1158: virtual void Destroy() =0;
dvander@1158: };
dvander@1158:
dvander@1158: /**
dvander@858: * @brief Database-related Handle types.
dvander@858: */
dvander@858: enum DBHandleType
dvander@858: {
dvander@858: DBHandle_Driver = 0, /**< Driver Handle */
dvander@858: DBHandle_Database = 1, /**< Database Handle */
dvander@666: };
dvander@666:
dvander@666: /**
dvander@666: * @brief Describes the DBI manager.
dvander@666: */
dvander@666: class IDBManager : public SMInterface
dvander@666: {
dvander@666: public:
dvander@666: virtual const char *GetInterfaceName() =0;
dvander@666: virtual unsigned int GetInterfaceVersion() =0;
dvander@666: public:
dvander@666: /**
dvander@1095: * @brief Adds a driver to the DBI system. Not thread safe.
dvander@666: *
dvander@666: * @param pDriver Database driver.
dvander@666: */
dvander@858: virtual void AddDriver(IDBDriver *pDriver) =0;
dvander@666:
dvander@666: /**
dvander@1095: * @brief Removes a driver from the DBI system. Not thread safe.
dvander@666: *
dvander@666: * @param pDriver Database driver.
dvander@666: */
dvander@666: virtual void RemoveDriver(IDBDriver *pDriver) =0;
dvander@666:
dvander@666: /**
dvander@868: * @brief Searches for database info by name. Both the return pointer
dvander@868: * and all pointers contained therein should be considered volatile.
dvander@666: *
dvander@666: * @param name Named database info.
dvander@666: * @return DatabaseInfo pointer.
dvander@666: */
dvander@666: virtual const DatabaseInfo *FindDatabaseConf(const char *name) =0;
dvander@666:
dvander@666: /**
dvander@1095: * @brief Tries to connect to a named database. Not thread safe.
dvander@666: *
dvander@666: * @param name Named database info.
dvander@666: * @param pdr Pointer to store the IDBDriver pointer in.
dvander@666: * If driver is not found, NULL will be stored.
dvander@666: * @param pdb Pointer to store the IDatabase pointer in.
dvander@666: * If connection fails, NULL will be stored.
dvander@666: * @param persistent If true, the dbmanager will attempt to PConnect
dvander@666: * instead of connect.
dvander@858: * @param error Error buffer to store a driver's error message.
dvander@858: * @param maxlength Maximum length of the error buffer.
dvander@666: * @return True on success, false otherwise.
dvander@666: */
dvander@858: virtual bool Connect(const char *name,
dvander@858: IDBDriver **pdr,
dvander@858: IDatabase **pdb,
dvander@858: bool persistent,
dvander@858: char *error,
dvander@858: size_t maxlength) =0;
dvander@666:
dvander@666: /**
dvander@1095: * @brief Returns the number of drivers loaded. Not thread safe.
dvander@666: *
dvander@666: * @return Number of drivers loaded.
dvander@666: */
dvander@666: virtual unsigned int GetDriverCount() =0;
dvander@666:
dvander@666: /**
dvander@1095: * @brief Returns a driver by index. Not thread safe.
dvander@666: *
dvander@666: * @param index Driver index, starting from 0.
dvander@666: * @return IDBDriver pointer for the given index.
dvander@666: */
dvander@858: virtual IDBDriver *GetDriver(unsigned int index) =0;
dvander@858:
dvander@858: /**
dvander@1095: * @brief Creates a Handle_t of the IDBDriver type. Not thread safe.
dvander@858: *
dvander@858: * @param type A DBHandleType value.
dvander@868: * @param ptr A pointer corrresponding to a DBHandleType
dvander@868: * object.
dvander@1678: * @param pToken Identity pointer of the owning identity.
dvander@858: * @return A new Handle_t handle, or 0 on failure.
dvander@858: */
dvander@858: virtual Handle_t CreateHandle(DBHandleType type, void *ptr, IdentityToken_t *pToken) =0;
dvander@858:
dvander@858: /**
dvander@1095: * @brief Reads an IDBDriver pointer from an IDBDriver handle. Not
dvander@1095: * thread safe.
dvander@858: *
dvander@858: * @param hndl Handle_t handle to read.
dvander@858: * @param type A DBHandleType value.
dvander@858: * @param ptr Pointer to store the object pointer.
dvander@858: * @return HandleError value.
dvander@858: */
dvander@858: virtual HandleError ReadHandle(Handle_t hndl, DBHandleType type, void **ptr) =0;
dvander@858:
dvander@858: /**
dvander@858: * @brief Releases an IDBDriver handle.
dvander@858: *
dvander@858: * @param hndl Handle_t handle to release.
dvander@858: * @param type A DBHandleType value.
dvander@858: * @param token Identity pointer of the owning identity.
dvander@858: * @return HandleError value.
dvander@858: */
dvander@858: virtual HandleError ReleaseHandle(Handle_t hndl, DBHandleType type, IdentityToken_t *token) =0;
dvander@868:
dvander@868: /**
dvander@868: * @brief Given a driver name, attempts to find it. If it is not found, SourceMod
dvander@1095: * will attempt to load it. This function is not thread safe.
dvander@868: *
dvander@1678: * @param driver Driver identifier name.
dvander@868: * @return IDBDriver pointer on success, NULL otherwise.
dvander@868: */
dvander@868: virtual IDBDriver *FindOrLoadDriver(const char *driver) =0;
dvander@868:
dvander@868: /**
dvander@1095: * @brief Returns the default driver, or NULL if none is set. This
dvander@1095: * function is not thread safe.
dvander@868: *
dvander@868: * @return IDBDriver pointer on success, NULL otherwise.
dvander@868: */
dvander@868: virtual IDBDriver *GetDefaultDriver() =0;
dvander@1158:
dvander@1158: /**
dvander@1158: * @brief Adds a threaded database operation to the priority queue.
dvander@1158: * This function is not thread safe.
dvander@1158: *
dvander@1158: * @param op Instance of an IDBThreadOperation.
dvander@1158: * @param prio Priority level to run at.
dvander@1158: * @return True on success, false on failure.
dvander@1158: */
dvander@1158: virtual bool AddToThreadQueue(IDBThreadOperation *op, PrioQueueLevel prio) =0;
dvander@2134:
dvander@2134: /**
dvander@2134: * @brief Adds a dependency from one extension to the owner of a driver.
dvander@2134: *
dvander@2134: * @param myself Extension that is using the IDBDriver.
dvander@2134: * @param driver Driver that is being used.
dvander@2134: */
dvander@2134: virtual void AddDependency(IExtension *myself, IDBDriver *driver) =0;
dvander@666: };
dvander@666: }
dvander@666:
dvander@666: #endif //_INCLUDE_SOURCEMOD_INTERFACE_DBDRIVER_H_
dvander@2134: