3 * ===============================================================
4 * SourceMod, Copyright (C) 2004-2007 AlliedModders LLC.
6 * ===============================================================
8 * This file is part of the SourceMod/SourcePawn SDK. This file may only be
9 * used or modified under the Terms and Conditions of its License Agreement,
10 * which is found in public/licenses/LICENSE.txt. As of this notice, derivative
11 * works must be licensed under the GNU General Public License (version 2 or
12 * greater). A copy of the GPL is included under public/licenses/GPL.txt.
14 * To view the latest information, see: http://www.sourcemod.net/license.php
19 #ifndef _INCLUDE_SOURCEMOD_INTERFACE_DBDRIVER_H_
20 #define _INCLUDE_SOURCEMOD_INTERFACE_DBDRIVER_H_
22 #include <IShareSys.h>
23 #include <IHandleSys.h>
26 #define SMINTERFACE_DBI_NAME "IDBI"
27 #define SMINTERFACE_DBI_VERSION 5
32 * @brief Describes a database field value.
36 DBVal_Error = 0, /**< Column number/field is invalid */
37 DBVal_TypeMismatch = 1, /**< You cannot retrieve this data with this type */
38 DBVal_Null = 2, /**< Field has no data (NULL) */
39 DBVal_Data = 3, /**< Field has data */
43 * @brief Describes a primitive database type.
47 DBType_Unknown = 0, /**< Type could not be inferred */
48 DBType_String, /**< NULL-terminated string (variable length) */
49 DBType_Blob, /**< Raw binary data (variable length) */
50 DBType_Integer, /**< 4-byte signed integer */
51 DBType_Float, /**< 4-byte floating point */
55 * @brief Represents a one database result row.
57 * Note that type mismatches will only occur when type safety is being
58 * enforced. So far this is only the case for prepared statements in
61 * Also, it is worth noting that retrieving as raw data will never cause a
68 * @brief Retrieves a database field result as a string.
70 * For NULL values, the resulting string pointer will be non-NULL but
71 * empty. The pointer returned will become invalid after advancing to
74 * @param columnId Column to use, starting from 0.
75 * @param pString Pointer to store a pointer to the string.
76 * @param length Optional pointer to store the string length.
77 * @return A DBResult return code.
79 virtual DBResult GetString(unsigned int columnId, const char **pString, size_t *length) =0;
82 * @brief Retrieves a database field result as a string, using a
83 * user-supplied buffer. If the field is NULL, an empty string
86 * @param columnId Column to use, starting from 0.
87 * @param buffer Buffer to store string in.
88 * @param maxlength Maximum length of the buffer.
89 * @param written Optional pointer to store the number of bytes
90 * written, excluding the null terminator.
91 * @return A DBResult return code.
93 virtual DBResult CopyString(unsigned int columnId,
99 * @brief Retrieves a database field result as a float.
101 * For NULL entries, the returned float value will be 0.0.
103 * @param columnId Column to use, starting from 0.
104 * @param pFloat Pointer to a floating point number to set.
105 * @return A DBResult return code.
107 virtual DBResult GetFloat(unsigned int columnId, float *pFloat) =0;
110 * @brief Retrieves a database field result as an integer.
112 * For NULL entries, the returned integer value will be 0.
114 * @param columnId Column to use, starting from 0.
115 * @param pInt Pointer to an integer number to set.
116 * @return A DBResult return code.
118 virtual DBResult GetInt(unsigned int columnId, int *pInt) =0;
121 * @brief Returns whether or not a field is NULL.
123 * @param columnId Column to use, starting from 0.
124 * @return True if field is NULL, false otherwise.
126 virtual bool IsNull(unsigned int columnId) =0;
129 * @brief Returns the size of a field (text/raw/blob) in bytes.
130 * For strings, this returned size will not include the null
133 * When used on fields that are not of variable length,
134 * the size returned will be the number of bytes required
135 * to store the internal data. Note that the data size
136 * will correspond to the ACTUAL data type, not the
139 * @param columnId Column to use, starting from 0.
140 * @return Number of bytes required to store
141 * the data, or 0 on failure.
143 virtual size_t GetDataSize(unsigned int columnId) =0;
146 * @brief Retrieves field data as a raw bitstream. The pointer returned
147 * will become invalid after advancing to the next row.
149 * @param columnId Column to use, starting from 0.
150 * @param pData Pointer to store the raw bit stream. If the
151 * data is NULL, a NULL pointer will be returned.
152 * @param length Pointer to store the data length.
153 * @return A DBResult return code.
155 virtual DBResult GetBlob(unsigned int columnId, const void **pData, size_t *length) =0;
158 * @brief Copies field data as a raw bitstream.
160 * @param columnId Column to use, starting from 0.
161 * @param buffer Pointer to copy the data to. If the data is
162 * NULL, no data will be copied.
163 * @param maxlength Maximum length of the buffer.
164 * @param written Optional pointer to store the number of bytes
166 * @return A DBResult return code.
168 virtual DBResult CopyBlob(unsigned int columnId, void *buffer, size_t maxlength, size_t *written) =0;
172 * @brief Describes a set of database results.
178 * @brief Returns the number of rows in the set.
180 * @return Number of rows in the set.
182 virtual unsigned int GetRowCount() =0;
185 * @brief Returns the number of fields in the set.
187 * @return Number of fields in the set.
189 virtual unsigned int GetFieldCount() =0;
192 * @brief Converts a column number to a column name.
194 * @param columnId Column to use, starting from 0.
195 * @return Pointer to column name, or NULL if not found.
197 virtual const char *FieldNumToName(unsigned int columnId) =0;
200 * @brief Converts a column name to a column id.
202 * @param name Column name (case sensitive).
203 * @param columnId Pointer to store the column id. If the
204 * name is not found, the value will be
206 * @return True on success, false if not found.
208 virtual bool FieldNameToNum(const char *name, unsigned int *columnId) =0;
211 * @brief Returns if there is still data in the result set.
213 * @return False if there is more data to be read,
216 virtual bool MoreRows() =0;
219 * @brief Returns a pointer to the current row and advances
220 * the internal row pointer/counter to the next row available.
222 * @return IResultRow pointer to the current row,
223 * or NULL if there is no more data.
225 virtual IResultRow *FetchRow() =0;
228 * @brief Returns a pointer to the current row.
230 * @return IResultRow pointer to the current row,
231 * or NULL if the current row is invalid.
233 virtual IResultRow *CurrentRow() =0;
236 * @brief Rewinds back to the beginning of the row iteration.
238 * @return True on success, false otherwise.
240 virtual bool Rewind() =0;
243 * @brief Returns a field's type as it should be interpreted
246 * @param field Field number (starting from 0).
247 * @return A DBType value.
249 virtual DBType GetFieldType(unsigned int field) =0;
252 * @brief Returns a field's type as it will be interpreted
253 * by the GetDataSize() function. For example, MySQL
254 * for non-prepared queries will store all results as
255 * strings internally.
257 * @param field Field number (starting from 0).
258 * @return A DBType value.
260 virtual DBType GetFieldDataType(unsigned int field) =0;
269 * @brief Returns a pointer to the current result set, if any.
271 * @return An IResultSet pointer on success,
272 * NULL if no result set exists.
274 virtual IResultSet *GetResultSet() =0;
277 * @brief Advances to the next result set if one exists. This
278 * is for checking for MORE result sets, and should not be used
279 * on the first result set.
281 * Multiple results only happen in certain cases, such as CALLing
282 * stored procedure that have a SELECTs, where MySQL will return
283 * both the CALL status and one or more SELECT result sets. If
284 * you do not process these results, they will be automatically
285 * processed for you. However, the behaviour of creating a new
286 * query from the same connection while results are left
287 * unprocessed is undefined, and may result in a dropped
288 * connection. Therefore, process all extra results or destroy the
289 * IQuery pointer before starting a new query.
291 * Again, this only happens in very specific cases, so there is
292 * no need to call this for normal queries.
294 * After calling this function, GetResultSet() must be called
295 * again to return the result set. The previous result set
296 * is automatically destroyed and will be unusable.
298 * @return True if another result set is
299 * available, false otherwise.
301 virtual bool FetchMoreResults() =0;
304 * @brief Frees resources created by this query.
306 virtual void Destroy() =0;
309 class IPreparedQuery : public IQuery
313 * @brief Binds an integer parameter.
315 * @param param Parameter index, starting from 0.
316 * @param num Number to bind as a value.
317 * @param signd True to write as signed, false to write as
319 * @return True on success, false otherwise.
321 virtual bool BindParamInt(unsigned int param, int num, bool signd=true) =0;
324 * @brief Binds a float parameter.
326 * @param param Parameter index, starting from 0.
327 * @param f Float to bind as a value.
328 * @return True on success, false otherwise.
330 virtual bool BindParamFloat(unsigned int param, float f) =0;
333 * @brief Binds an SQL NULL type as a parameter.
335 * @param param Parameter index, starting from 0.
336 * @return True on success, false otherwise.
338 virtual bool BindParamNull(unsigned int param) =0;
341 * @brief Binds a string as a parameter.
343 * @param param Parameter index, starting from 0.
344 * @param text Pointer to a null-terminated string.
345 * @param copy If true, the pointer is assumed to be
346 * volatile and a temporary copy may be
348 * @return True on success, false otherwise.
350 virtual bool BindParamString(unsigned int param, const char *text, bool copy) =0;
353 * @brief Binds a blob of raw data as a parameter.
355 * @param param Parameter index, starting from 0.
356 * @param data Pointer to a blob of memory.
357 * @param length Number of bytes to copy.
358 * @param copy If true, the pointer is assumed to be
359 * volatile and a temporary copy may be
361 * @return True on success, false otherwise.
363 virtual bool BindParamBlob(unsigned int param,
369 * @brief Executes the query with the currently bound parameters.
371 * @return True on success, false otherwise.
373 virtual bool Execute() =0;
376 * @brief Returns the last error message from this statement.
378 * @param errCode Optional pointer to store the driver-specific
380 * @return Error message string.
382 virtual const char *GetError(int *errCode=NULL) =0;
385 * @brief Number of rows affected by the last execute.
387 * @return Number of rows affected by the last execute.
389 virtual unsigned int GetAffectedRows() =0;
392 * @brief Retrieves the last insert ID on this database connection.
394 * @return Row insertion ID of the last execute, if any.
396 virtual unsigned int GetInsertID() =0;
402 * @brief Encapsulates a database connection.
408 * @brief Disconnects the database and frees its associated memory.
409 * Note that the actual object will not be freed until all open
410 * references have been closed.
412 * It is guaranteed that an IDatabase pointer won't be destroyed until
413 * all open IQuery or IPreparedQuery pointers are closed.
415 * This function is thread safe.
417 * @return True if object was destroyed, false if
418 * references are remaining.
420 virtual bool Close() =0;
423 * @brief Error code and string returned by the last operation on this
426 * This function is not thread safe and must be included in any locks.
428 * @param errorCode Optional pointer to retrieve an error code.
429 * @return Error string pointer (empty if none).
431 virtual const char *GetError(int *errorCode=NULL) =0;
434 * @brief Prepares and executes a query in one step, and discards
437 * This function is not thread safe and must be included in any locks.
439 * @param query Query string.
440 * @return True on success, false otherwise.
442 virtual bool DoSimpleQuery(const char *query) =0;
445 * @brief Prepares and executes a query in one step, and returns
446 * the resultant data set.
448 * Note: If a query contains more than one result set, each
449 * result set must be processed before a new query is started.
451 * This function is not thread safe and must be included in any locks.
453 * @param query Query string.
454 * @return IQuery pointer on success, NULL otherwise.
456 virtual IQuery *DoQuery(const char *query) =0;
459 * @brief Prepares a query statement for multiple executions and/or
460 * binding marked parameters (? in MySQL/sqLite, $n in PostgreSQL).
462 * This function is not thread safe and must be included in any locks.
464 * @param query Query string.
465 * @param error Error buffer.
466 * @param maxlength Maximum length of the error buffer.
467 * @param errCode Optional pointer to store a driver-specific error code.
468 * @return IPreparedQuery pointer on success, NULL
471 virtual IPreparedQuery *PrepareQuery(const char *query, char *error, size_t maxlength, int *errCode=NULL) =0;
474 * Quotes a string for insertion into a query.
476 * @param str Source string.
477 * @param buffer Buffer to store new string (should not overlap source string).
478 * @param maxlen Maximum length of the output buffer.
479 * @param newSize Pointer to store the output size.
480 * @return True on success, false if the output buffer is not big enough.
481 * If not big enough, the required buffer size is passed through
484 virtual bool QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newSize) =0;
487 * @brief Number of rows affected by the last execute.
489 * This function is not thread safe and must be included in any locks.
491 * @return Number of rows affected by the last execute.
493 virtual unsigned int GetAffectedRows() =0;
496 * @brief Retrieves the last insert ID on this database connection.
498 * This function is not thread safe and must be included in any locks.
500 * @return Row insertion ID of the last execute, if any.
502 virtual unsigned int GetInsertID() =0;
505 * @brief Locks the database for an atomic query+retrieval operation.
507 * @return True on success, false if not supported.
509 virtual bool LockForFullAtomicOperation() =0;
512 * @brief Unlocks a locked atomic fetch.
514 virtual void UnlockFromFullAtomicOperation() =0;
517 * @brief Increases the reference count on the database.
519 * This function is thread safe.
521 virtual void IncReferenceCount() =0;
524 * @brief Returns the parent driver.
526 * This function is thread safe.
528 virtual IDBDriver *GetDriver() =0;
532 * @brief Describes database connection info.
538 dbiVersion = SMINTERFACE_DBI_VERSION;
542 unsigned int dbiVersion; /**< DBI Version for backwards compatibility */
543 const char *host; /**< Host string */
544 const char *database; /**< Database name string */
545 const char *user; /**< User to authenticate as */
546 const char *pass; /**< Password to authenticate with */
547 const char *driver; /**< Driver to use */
548 unsigned int port; /**< Port to use, 0=default */
549 unsigned int maxTimeout; /**< Maximum timeout, 0=default */
553 * @brief Describes an SQL driver.
558 virtual unsigned int GetDBIVersion()
560 return SMINTERFACE_DBI_VERSION;
564 * @brief Initiates a database connection.
566 * Note: Persistent connections should never be created from a thread.
568 * @param info Database connection info pointer.
569 * @param persistent If true, a previous persistent connection will
570 * be re-used if possible.
571 * @param error Buffer to store error message.
572 * @param maxlength Maximum size of the error buffer.
573 * @return A new IDatabase pointer, or NULL on failure.
575 virtual IDatabase *Connect(const DatabaseInfo *info, bool persistent, char *error, size_t maxlength) =0;
578 * @brief Returns a case insensitive database identifier string.
580 * @return String containing an identifier.
582 virtual const char *GetIdentifier() =0;
585 * @brief Returns a case sensitive implementation name.
587 * @return String containing an implementation name.
589 virtual const char *GetProductName() =0;
592 * @brief Retrieves a Handle_t handle of the IDBDriver type.
594 * @return A Handle_t handle.
596 virtual Handle_t GetHandle() =0;
599 * @brief Returns the driver's controlling identity (must be the same
600 * as from IExtension::GetIdentity).
602 * @return An IdentityToken_t identity.
604 virtual IdentityToken_t *GetIdentity() =0;
607 * @brief Returns whether the driver is thread safe.
609 * @return True if thread safe, false otherwise.
611 virtual bool IsThreadSafe() =0;
614 * @brief Initializes thread safety for the calling thread.
616 * @return True on success, false otherwise.
618 virtual bool InitializeThreadSafety() =0;
621 * @brief Shuts down thread safety for the calling thread.
623 virtual void ShutdownThreadSafety() =0;
627 * @brief Priority queue level.
631 PrioQueue_High, /**< High priority */
632 PrioQueue_Normal, /**< Normal priority */
633 PrioQueue_Low /**< Low priority */
637 * Specification for a threaded database operation.
639 class IDBThreadOperation
643 * @brief Must return the driver this operation is using, or
644 * NULL if not using any driver. This is not never inside
647 * @return IDBDriver pointer.
649 virtual IDBDriver *GetDriver() =0;
652 * @brief Must return the object owning this threaded operation.
653 * This is never called inside the thread.
655 * @return IdentityToken_t pointer.
657 virtual IdentityToken_t *GetOwner() =0;
660 * @brief Called inside the thread; this is where any blocking
661 * or threaded operations must occur.
663 virtual void RunThreadPart() =0;
666 * @brief Called in a server frame after the thread operation
667 * has completed. This is the non-threaded completion callback,
668 * which although optional, is useful for pumping results back
669 * to normal game API.
671 virtual void RunThinkPart() =0;
674 * @brief If RunThinkPart() is not called, this will be called
675 * instead. Note that RunThreadPart() is ALWAYS called regardless,
676 * and this is only called when Core requests that the operation
677 * be scrapped (for example, the database driver might be unloading).
679 virtual void CancelThinkPart() =0;
682 * @brief Called when the operation is finalized and any resources
685 virtual void Destroy() =0;
689 * @brief Database-related Handle types.
693 DBHandle_Driver = 0, /**< Driver Handle */
694 DBHandle_Database = 1, /**< Database Handle */
698 * @brief Describes the DBI manager.
700 class IDBManager : public SMInterface
703 virtual const char *GetInterfaceName() =0;
704 virtual unsigned int GetInterfaceVersion() =0;
707 * @brief Adds a driver to the DBI system. Not thread safe.
709 * @param pDriver Database driver.
711 virtual void AddDriver(IDBDriver *pDriver) =0;
714 * @brief Removes a driver from the DBI system. Not thread safe.
716 * @param pDriver Database driver.
718 virtual void RemoveDriver(IDBDriver *pDriver) =0;
721 * @brief Searches for database info by name. Both the return pointer
722 * and all pointers contained therein should be considered volatile.
724 * @param name Named database info.
725 * @return DatabaseInfo pointer.
727 virtual const DatabaseInfo *FindDatabaseConf(const char *name) =0;
730 * @brief Tries to connect to a named database. Not thread safe.
732 * @param name Named database info.
733 * @param pdr Pointer to store the IDBDriver pointer in.
734 * If driver is not found, NULL will be stored.
735 * @param pdb Pointer to store the IDatabase pointer in.
736 * If connection fails, NULL will be stored.
737 * @param persistent If true, the dbmanager will attempt to PConnect
738 * instead of connect.
739 * @param error Error buffer to store a driver's error message.
740 * @param maxlength Maximum length of the error buffer.
741 * @return True on success, false otherwise.
743 virtual bool Connect(const char *name,
748 size_t maxlength) =0;
751 * @brief Returns the number of drivers loaded. Not thread safe.
753 * @return Number of drivers loaded.
755 virtual unsigned int GetDriverCount() =0;
758 * @brief Returns a driver by index. Not thread safe.
760 * @param index Driver index, starting from 0.
761 * @return IDBDriver pointer for the given index.
763 virtual IDBDriver *GetDriver(unsigned int index) =0;
766 * @brief Creates a Handle_t of the IDBDriver type. Not thread safe.
768 * @param type A DBHandleType value.
769 * @param ptr A pointer corrresponding to a DBHandleType
771 * @param token Identity pointer of the owning identity.
772 * @return A new Handle_t handle, or 0 on failure.
774 virtual Handle_t CreateHandle(DBHandleType type, void *ptr, IdentityToken_t *pToken) =0;
777 * @brief Reads an IDBDriver pointer from an IDBDriver handle. Not
780 * @param hndl Handle_t handle to read.
781 * @param type A DBHandleType value.
782 * @param ptr Pointer to store the object pointer.
783 * @return HandleError value.
785 virtual HandleError ReadHandle(Handle_t hndl, DBHandleType type, void **ptr) =0;
788 * @brief Releases an IDBDriver handle.
790 * @param hndl Handle_t handle to release.
791 * @param type A DBHandleType value.
792 * @param token Identity pointer of the owning identity.
793 * @return HandleError value.
795 virtual HandleError ReleaseHandle(Handle_t hndl, DBHandleType type, IdentityToken_t *token) =0;
798 * @brief Given a driver name, attempts to find it. If it is not found, SourceMod
799 * will attempt to load it. This function is not thread safe.
801 * @param name Driver identifier name.
802 * @return IDBDriver pointer on success, NULL otherwise.
804 virtual IDBDriver *FindOrLoadDriver(const char *driver) =0;
807 * @brief Returns the default driver, or NULL if none is set. This
808 * function is not thread safe.
810 * @return IDBDriver pointer on success, NULL otherwise.
812 virtual IDBDriver *GetDefaultDriver() =0;
815 * @brief Adds a threaded database operation to the priority queue.
816 * This function is not thread safe.
818 * @param op Instance of an IDBThreadOperation.
819 * @param prio Priority level to run at.
820 * @return True on success, false on failure.
822 virtual bool AddToThreadQueue(IDBThreadOperation *op, PrioQueueLevel prio) =0;
826 #endif //_INCLUDE_SOURCEMOD_INTERFACE_DBDRIVER_H_