1 #include "sm_globals.h"
4 #include "ExtensionSys.h"
6 #include "sm_stringutil.h"
8 HandleType_t hQueryType;
9 HandleType_t hStmtType;
11 class DatabaseHelpers :
13 public IHandleTypeDispatch
16 virtual void OnSourceModAllInitialized()
21 g_HandleSys.InitAccessDefaults(NULL, &acc);
22 acc.access[HandleAccess_Clone] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY;
26 g_HandleSys.InitAccessDefaults(&tacc, NULL);
27 tacc.ident = g_pCoreIdent;
29 hQueryType = g_HandleSys.CreateType("IQuery", this, 0, &tacc, &acc, g_pCoreIdent, NULL);
30 hStmtType = g_HandleSys.CreateType("IPreparedQuery", this, hQueryType, &tacc, &acc, g_pCoreIdent, NULL);
33 virtual void OnSourceModShutdown()
35 g_HandleSys.RemoveType(hStmtType, g_pCoreIdent);
36 g_HandleSys.RemoveType(hQueryType, g_pCoreIdent);
39 virtual void OnHandleDestroy(HandleType_t type, void *object)
41 if (type == hQueryType)
43 IQuery *query = (IQuery *)object;
45 } else if (type == hStmtType) {
46 IPreparedQuery *query = (IPreparedQuery *)object;
50 } s_DatabaseNativeHelpers;
52 //is this safe for stmt handles? i think since it's single inheritance, it always will be.
53 inline HandleError ReadQueryHndl(Handle_t hndl, IPluginContext *pContext, IQuery **query)
56 sec.pOwner = pContext->GetIdentity();
57 sec.pIdentity = g_pCoreIdent;
59 return g_HandleSys.ReadHandle(hndl, hQueryType, &sec, (void **)query);
62 inline HandleError ReadStmtHndl(Handle_t hndl, IPluginContext *pContext, IPreparedQuery **query)
65 sec.pOwner = pContext->GetIdentity();
66 sec.pIdentity = g_pCoreIdent;
68 return g_HandleSys.ReadHandle(hndl, hStmtType, &sec, (void **)query);
71 inline HandleError ReadDbOrStmtHndl(Handle_t hndl, IPluginContext *pContext, IDatabase **db, IPreparedQuery **query)
74 if ((err = g_DBMan.ReadHandle(hndl, DBHandle_Database, (void **)db)) == HandleError_Type)
77 return ReadStmtHndl(hndl, pContext, query);
82 class TQueryOp : public IDBThreadOperation
85 TQueryOp(IDatabase *db, IPluginFunction *pf, const char *query, cell_t data) :
86 m_pDatabase(db), m_pFunction(pf), m_Query(query), m_Data(data),
87 me(g_PluginSys.GetPluginByCtx(pf->GetParentContext()->GetContext())),
90 /* We always increase the reference count because this is potentially
91 * asynchronous. Otherwise the original handle could be closed while
92 * we're still latched onto it.
94 m_pDatabase->IncReferenceCount();
96 /* Now create our own Handle such that it can only be closed by us.
97 * We allow cloning just in case someone wants to hold onto it.
99 HandleSecurity sec(me->GetIdentity(), g_pCoreIdent);
101 g_HandleSys.InitAccessDefaults(NULL, &access);
102 access.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY|HANDLE_RESTRICT_OWNER;
103 m_MyHandle = g_HandleSys.CreateHandleEx(g_DBMan.GetDatabaseType(),
116 /* Close our Handle if it's valid. */
117 if (m_MyHandle != BAD_HANDLE)
119 HandleSecurity sec(me->GetIdentity(), g_pCoreIdent);
120 g_HandleSys.FreeHandle(m_MyHandle, &sec);
122 /* Otherwise, there is an open ref to the db */
123 m_pDatabase->Close();
130 IDBDriver *GetDriver()
132 return m_pDatabase->GetDriver();
136 m_pDatabase->LockForFullAtomicOperation();
137 m_pQuery = m_pDatabase->DoQuery(m_Query.c_str());
140 UTIL_Format(error, sizeof(error), "%s", m_pDatabase->GetError());
142 m_pDatabase->UnlockFromFullAtomicOperation();
144 void CancelThinkPart()
146 m_pFunction->PushCell(BAD_HANDLE);
147 m_pFunction->PushCell(BAD_HANDLE);
148 m_pFunction->PushString("Driver is unloading");
149 m_pFunction->PushCell(m_Data);
150 m_pFunction->Execute(NULL);
155 /* Create a Handle for our query */
156 HandleSecurity sec(me->GetIdentity(), g_pCoreIdent);
158 g_HandleSys.InitAccessDefaults(NULL, &access);
159 access.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY|HANDLE_RESTRICT_OWNER;
161 Handle_t qh = BAD_HANDLE;
165 qh = g_HandleSys.CreateHandle(hQueryType, m_pQuery, me->GetIdentity(), g_pCoreIdent, NULL);
166 if (qh != BAD_HANDLE)
170 UTIL_Format(error, sizeof(error), "Could not alloc handle");
174 m_pFunction->PushCell(m_MyHandle);
175 m_pFunction->PushCell(qh);
176 m_pFunction->PushString(qh == BAD_HANDLE ? error : "");
177 m_pFunction->PushCell(m_Data);
178 m_pFunction->Execute(NULL);
180 if (qh != BAD_HANDLE)
182 g_HandleSys.FreeHandle(qh, &sec);
188 IDatabase *m_pDatabase;
189 IPluginFunction *m_pFunction;
198 class TConnectOp : public IDBThreadOperation
201 TConnectOp(IPluginFunction *func, IDBDriver *driver, const char *_dbname)
207 strncopy(dbname, _dbname, sizeof(dbname));
208 me = g_PluginSys.GetPluginByCtx(m_pFunction->GetParentContext()->GetContext());
214 IDBDriver *GetDriver()
220 g_DBMan.LockConfig();
221 const DatabaseInfo *pInfo = g_DBMan.FindDatabaseConf(dbname);
224 UTIL_Format(error, sizeof(error), "Could not find database config \"%s\"", dbname);
226 m_pDatabase = m_pDriver->Connect(pInfo, false, error, sizeof(error));
228 g_DBMan.UnlockConfig();
230 void CancelThinkPart()
234 m_pDatabase->Close();
236 m_pFunction->PushCell(BAD_HANDLE);
237 m_pFunction->PushCell(BAD_HANDLE);
238 m_pFunction->PushString("Driver is unloading");
239 m_pFunction->PushCell(0);
240 m_pFunction->Execute(NULL);
245 Handle_t hndl = BAD_HANDLE;
249 if ((hndl = g_DBMan.CreateHandle(DBHandle_Database, m_pDatabase, me->GetIdentity()))
252 m_pDatabase->Close();
253 UTIL_Format(error, sizeof(error), "Unable to allocate Handle");
257 m_pFunction->PushCell(m_pDriver->GetHandle());
258 m_pFunction->PushCell(hndl);
259 m_pFunction->PushString(hndl == BAD_HANDLE ? error : "");
260 m_pFunction->PushCell(0);
261 m_pFunction->Execute(NULL);
266 IPluginFunction *m_pFunction;
267 IDBDriver *m_pDriver;
268 IDatabase *m_pDatabase;
273 static cell_t SQL_Connect(IPluginContext *pContext, const cell_t *params)
277 size_t maxlength = (size_t)params[4];
278 bool persistent = params[2] ? true : false;
279 pContext->LocalToString(params[1], &conf);
280 pContext->LocalToString(params[3], &err);
284 if (!g_DBMan.Connect(conf, &driver, &db, persistent, err, maxlength))
289 Handle_t hndl = g_DBMan.CreateHandle(DBHandle_Database, db, pContext->GetIdentity());
296 /* HACK! Add us to the dependency list */
297 CExtension *pExt = g_Extensions.GetExtensionFromIdent(driver->GetIdentity());
300 g_Extensions.BindChildPlugin(pExt, g_PluginSys.FindPluginByContext(pContext->GetContext()));
306 static cell_t SQL_TConnect(IPluginContext *pContext, const cell_t *params)
308 IPluginFunction *pf = pContext->GetFunctionById(params[1]);
311 return pContext->ThrowNativeError("Function id %x is invalid", params[1]);
315 pContext->LocalToString(params[2], &conf);
317 IDBDriver *driver = NULL;
318 const DatabaseInfo *pInfo = g_DBMan.FindDatabaseConf(conf);
322 if (pInfo->driver[0] == '\0')
324 driver = g_DBMan.GetDefaultDriver();
326 driver = g_DBMan.FindOrLoadDriver(pInfo->driver);
332 "Could not find driver \"%s\"",
333 pInfo->driver[0] == '\0' ? g_DBMan.GetDefaultDriverName() : pInfo->driver);
334 } else if (!driver->IsThreadSafe()) {
337 "Driver \"%s\" is not thread safe!",
338 driver->GetIdentifier());
341 UTIL_Format(error, sizeof(error), "Could not find database conf \"%s\"", conf);
344 if (!pInfo || !driver)
346 pf->PushCell(BAD_HANDLE);
347 pf->PushCell(BAD_HANDLE);
348 pf->PushString(error);
354 /* HACK! Add us to the dependency list */
355 CExtension *pExt = g_Extensions.GetExtensionFromIdent(driver->GetIdentity());
358 g_Extensions.BindChildPlugin(pExt, g_PluginSys.FindPluginByContext(pContext->GetContext()));
361 /* Finally, add to the thread if we can */
362 TConnectOp *op = new TConnectOp(pf, driver, conf);
363 CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
364 if (pPlugin->GetProperty("DisallowDBThreads", NULL)
365 || !g_DBMan.AddToThreadQueue(op, PrioQueue_High))
367 /* Do everything right now */
375 static cell_t SQL_ConnectEx(IPluginContext *pContext, const cell_t *params)
378 if (params[1] == BAD_HANDLE)
380 if ((driver = g_DBMan.GetDefaultDriver()) == NULL)
382 return pContext->ThrowNativeError("Could not find any default driver");
386 if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Driver, (void **)&driver))
389 return pContext->ThrowNativeError("Invalid driver Handle %x (error: %d)", params[1], err);
393 char *host, *user, *pass, *database, *error;
394 size_t maxlength = (size_t)params[7];
395 bool persistent = params[8] ? true : false;
396 unsigned int port = params[9];
397 unsigned int maxTimeout = params[10];
398 pContext->LocalToString(params[2], &host);
399 pContext->LocalToString(params[3], &user);
400 pContext->LocalToString(params[4], &pass);
401 pContext->LocalToString(params[5], &database);
402 pContext->LocalToString(params[6], &error);
405 info.database = database;
406 info.driver = driver->GetIdentifier();
408 info.maxTimeout = maxTimeout;
413 IDatabase *db = driver->Connect(&info, persistent, error, maxlength);
417 Handle_t hndl = g_DBMan.CreateHandle(DBHandle_Database, db, pContext->GetIdentity());
424 /* HACK! Add us to the dependency list */
425 CExtension *pExt = g_Extensions.GetExtensionFromIdent(driver->GetIdentity());
428 g_Extensions.BindChildPlugin(pExt, g_PluginSys.FindPluginByContext(pContext->GetContext()));
437 static cell_t SQL_GetDriverIdent(IPluginContext *pContext, const cell_t *params)
440 if (params[1] == BAD_HANDLE)
442 if ((driver = g_DBMan.GetDefaultDriver()) == NULL)
444 return pContext->ThrowNativeError("Could not find any default driver");
448 if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Driver, (void **)&driver))
451 return pContext->ThrowNativeError("Invalid driver Handle %x (error: %d)", params[1], err);
455 pContext->StringToLocalUTF8(params[2], params[3], driver->GetIdentifier(), NULL);
460 static cell_t SQL_GetDriver(IPluginContext *pContext, const cell_t *params)
463 pContext->LocalToString(params[1], &name);
465 IDBDriver *driver = NULL;
468 driver = g_DBMan.GetDefaultDriver();
470 driver = g_DBMan.FindOrLoadDriver(name);
473 return (driver != NULL) ? driver->GetHandle() : BAD_HANDLE;
476 static cell_t SQL_GetDriverProduct(IPluginContext *pContext, const cell_t *params)
479 if (params[1] == BAD_HANDLE)
481 if ((driver = g_DBMan.GetDefaultDriver()) == NULL)
483 return pContext->ThrowNativeError("Could not find any default driver");
487 if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Driver, (void **)&driver))
490 return pContext->ThrowNativeError("Invalid driver Handle %x (error: %d)", params[1], err);
494 pContext->StringToLocalUTF8(params[2], params[3], driver->GetProductName(), NULL);
499 static cell_t SQL_GetAffectedRows(IPluginContext *pContext, const cell_t *params)
501 IDatabase *db = NULL;
502 IPreparedQuery *stmt = NULL;
505 if ((err = ReadDbOrStmtHndl(params[1], pContext, &db, &stmt)) != HandleError_None)
507 return pContext->ThrowNativeError("Invalid statement or db Handle %x (error: %d)", params[1], err);
512 return db->GetAffectedRows();
514 return stmt->GetAffectedRows();
517 return pContext->ThrowNativeError("Unknown error reading db/stmt handles");
520 static cell_t SQL_GetInsertId(IPluginContext *pContext, const cell_t *params)
522 IDatabase *db = NULL;
523 IPreparedQuery *stmt = NULL;
526 if ((err = ReadDbOrStmtHndl(params[1], pContext, &db, &stmt)) != HandleError_None)
528 return pContext->ThrowNativeError("Invalid statement or db Handle %x (error: %d)", params[1], err);
533 return db->GetInsertID();
535 return stmt->GetInsertID();
538 return pContext->ThrowNativeError("Unknown error reading db/stmt handles");
541 static cell_t SQL_GetError(IPluginContext *pContext, const cell_t *params)
543 IDatabase *db = NULL;
544 IPreparedQuery *stmt = NULL;
547 if ((err = ReadDbOrStmtHndl(params[1], pContext, &db, &stmt)) != HandleError_None)
549 return pContext->ThrowNativeError("Invalid statement or db Handle %x (error: %d)", params[1], err);
552 const char *error = "";
555 error = db->GetError();
557 error = stmt->GetError();
560 if (error[0] == '\0')
565 pContext->StringToLocalUTF8(params[2], params[3], error, NULL);
570 static cell_t SQL_QuoteString(IPluginContext *pContext, const cell_t *params)
572 IDatabase *db = NULL;
575 if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
578 return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
581 char *input, *output;
582 size_t maxlength = (size_t)params[4];
583 pContext->LocalToString(params[2], &input);
584 pContext->LocalToString(params[3], &output);
587 bool s = db->QuoteString(input, output, maxlength, &written);
590 pContext->LocalToPhysAddr(params[5], &addr);
591 *addr = (cell_t)written;
596 static cell_t SQL_FastQuery(IPluginContext *pContext, const cell_t *params)
598 IDatabase *db = NULL;
601 if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
604 return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
608 pContext->LocalToString(params[2], &query);
610 return db->DoSimpleQuery(query) ? 1 : 0;
613 static cell_t SQL_Query(IPluginContext *pContext, const cell_t *params)
615 IDatabase *db = NULL;
618 if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
621 return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
625 pContext->LocalToString(params[2], &query);
627 IQuery *qr = db->DoQuery(query);
634 Handle_t hndl = g_HandleSys.CreateHandle(hQueryType, qr, pContext->GetIdentity(), g_pCoreIdent, NULL);
635 if (hndl == BAD_HANDLE)
644 static cell_t SQL_TQuery(IPluginContext *pContext, const cell_t *params)
646 IDatabase *db = NULL;
649 if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
652 return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
655 if (!db->GetDriver()->IsThreadSafe())
657 return pContext->ThrowNativeError("Driver \"%s\" is not thread safe!", db->GetDriver()->GetIdentifier());
660 IPluginFunction *pf = pContext->GetFunctionById(params[2]);
663 return pContext->ThrowNativeError("Function id %x is invalid", params[2]);
667 pContext->LocalToString(params[3], &query);
669 cell_t data = params[4];
670 PrioQueueLevel level = PrioQueue_Normal;
671 if (params[5] == (cell_t)PrioQueue_High)
673 level = PrioQueue_High;
674 } else if (params[5] == (cell_t)PrioQueue_Low) {
675 level = PrioQueue_Low;
678 CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
680 TQueryOp *op = new TQueryOp(db, pf, query, data);
681 if (pPlugin->GetProperty("DisallowDBThreads", NULL)
682 || !g_DBMan.AddToThreadQueue(op, level))
684 /* Do everything right now */
692 static cell_t SQL_LockDatabase(IPluginContext *pContext, const cell_t *params)
694 IDatabase *db = NULL;
697 if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
700 return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
703 db->LockForFullAtomicOperation();
708 static cell_t SQL_UnlockDatabase(IPluginContext *pContext, const cell_t *params)
710 IDatabase *db = NULL;
713 if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
716 return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
719 db->UnlockFromFullAtomicOperation();
724 static cell_t SQL_PrepareQuery(IPluginContext *pContext, const cell_t *params)
726 IDatabase *db = NULL;
729 if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
732 return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
736 size_t maxlength = (size_t)params[4];
737 pContext->LocalToString(params[2], &query);
738 pContext->LocalToString(params[3], &error);
740 IPreparedQuery *qr = db->PrepareQuery(query, error, maxlength);
747 Handle_t hndl = g_HandleSys.CreateHandle(hStmtType, qr, pContext->GetIdentity(), g_pCoreIdent, NULL);
748 if (hndl == BAD_HANDLE)
757 static cell_t SQL_FetchMoreResults(IPluginContext *pContext, const cell_t *params)
762 if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
764 return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
767 return query->FetchMoreResults() ? 1 : 0;
770 static cell_t SQL_HasResultSet(IPluginContext *pContext, const cell_t *params)
775 if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
777 return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
780 return query->GetResultSet() != NULL ? true : false;
783 static cell_t SQL_GetRowCount(IPluginContext *pContext, const cell_t *params)
788 if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
790 return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
793 IResultSet *rs = query->GetResultSet();
799 return rs->GetRowCount();
802 static cell_t SQL_GetFieldCount(IPluginContext *pContext, const cell_t *params)
807 if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
809 return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
812 IResultSet *rs = query->GetResultSet();
818 return rs->GetFieldCount();
821 static cell_t SQL_FieldNumToName(IPluginContext *pContext, const cell_t *params)
826 if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
828 return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
831 IResultSet *rs = query->GetResultSet();
834 return pContext->ThrowNativeError("No current result set");
837 unsigned int field = params[2];
840 if ((fldname = rs->FieldNumToName(field)) == NULL)
842 return pContext->ThrowNativeError("Invalid field index %d", field);
845 pContext->StringToLocalUTF8(params[3], params[4], fldname, NULL);
850 static cell_t SQL_FieldNameToNum(IPluginContext *pContext, const cell_t *params)
855 if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
857 return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
860 IResultSet *rs = query->GetResultSet();
863 return pContext->ThrowNativeError("No current result set");
867 pContext->LocalToString(params[2], &field);
870 pContext->LocalToPhysAddr(params[3], &num);
872 return rs->FieldNameToNum(field, (unsigned int *)num) ? 1 : 0;
875 static cell_t SQL_FetchRow(IPluginContext *pContext, const cell_t *params)
880 if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
882 return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
885 IResultSet *rs = query->GetResultSet();
888 return pContext->ThrowNativeError("No current result set");
891 return (rs->FetchRow() != NULL) ? true : false;
894 static cell_t SQL_MoreRows(IPluginContext *pContext, const cell_t *params)
899 if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
901 return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
904 IResultSet *rs = query->GetResultSet();
907 return pContext->ThrowNativeError("No current result set");
910 return rs->MoreRows() ? 1 : 0;
913 static cell_t SQL_Rewind(IPluginContext *pContext, const cell_t *params)
918 if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
920 return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
923 IResultSet *rs = query->GetResultSet();
926 return pContext->ThrowNativeError("No current result set");
929 return rs->Rewind() ? 1 : 0;
932 static cell_t SQL_FetchString(IPluginContext *pContext, const cell_t *params)
937 if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
939 return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
942 IResultSet *rs = query->GetResultSet();
945 return pContext->ThrowNativeError("No current result set");
948 IResultRow *row = rs->CurrentRow();
951 return pContext->ThrowNativeError("Current result set has no fetched rows");
956 DBResult res = row->GetString(params[2], &str, &length);
958 if (res == DBVal_Error)
960 return pContext->ThrowNativeError("Error fetching data from field %d", params[2]);
961 } else if (res == DBVal_TypeMismatch) {
962 return pContext->ThrowNativeError("Could not fetch data in field %d as a string", params[2]);
965 pContext->StringToLocalUTF8(params[3], params[4], str, &length);
968 pContext->LocalToPhysAddr(params[5], &addr);
971 return (cell_t)length;
974 static cell_t SQL_FetchFloat(IPluginContext *pContext, const cell_t *params)
979 if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
981 return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
984 IResultSet *rs = query->GetResultSet();
987 return pContext->ThrowNativeError("No current result set");
990 IResultRow *row = rs->CurrentRow();
993 return pContext->ThrowNativeError("Current result set has no fetched rows");
997 DBResult res = row->GetFloat(params[2], &f);
999 if (res == DBVal_Error)
1001 return pContext->ThrowNativeError("Error fetching data from field %d", params[2]);
1002 } else if (res == DBVal_TypeMismatch) {
1003 return pContext->ThrowNativeError("Could not fetch data in field %d as a float", params[2]);
1007 pContext->LocalToPhysAddr(params[3], &addr);
1008 *addr = (cell_t)res;
1013 static cell_t SQL_FetchInt(IPluginContext *pContext, const cell_t *params)
1018 if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
1020 return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
1023 IResultSet *rs = query->GetResultSet();
1026 return pContext->ThrowNativeError("No current result set");
1029 IResultRow *row = rs->CurrentRow();
1032 return pContext->ThrowNativeError("Current result set has no fetched rows");
1036 DBResult res = row->GetInt(params[2], &iv);
1038 if (res == DBVal_Error)
1040 return pContext->ThrowNativeError("Error fetching data from field %d", params[2]);
1041 } else if (res == DBVal_TypeMismatch) {
1042 return pContext->ThrowNativeError("Could not fetch data in field %d as an integer", params[2]);
1046 pContext->LocalToPhysAddr(params[3], &addr);
1047 *addr = (cell_t)res;
1052 static cell_t SQL_IsFieldNull(IPluginContext *pContext, const cell_t *params)
1057 if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
1059 return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
1062 IResultSet *rs = query->GetResultSet();
1065 return pContext->ThrowNativeError("No current result set");
1068 IResultRow *row = rs->CurrentRow();
1071 return pContext->ThrowNativeError("Current result set has no fetched rows");
1074 if ((unsigned)params[2] >= rs->GetFieldCount())
1076 return pContext->ThrowNativeError("Invalid field index %d", params[2]);
1079 return row->IsNull(params[2]) ? 1 : 0;
1082 static cell_t SQL_FetchSize(IPluginContext *pContext, const cell_t *params)
1087 if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
1089 return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
1092 IResultSet *rs = query->GetResultSet();
1095 return pContext->ThrowNativeError("No current result set");
1098 IResultRow *row = rs->CurrentRow();
1101 return pContext->ThrowNativeError("Current result set has no fetched rows");
1104 if ((unsigned)params[2] >= rs->GetFieldCount())
1106 return pContext->ThrowNativeError("Invalid field index %d", params[2]);
1109 return row->GetDataSize(params[2]);
1112 static cell_t SQL_BindParamInt(IPluginContext *pContext, const cell_t *params)
1114 IPreparedQuery *stmt;
1117 if ((err = ReadStmtHndl(params[1], pContext, &stmt)) != HandleError_None)
1119 return pContext->ThrowNativeError("Invalid statement Handle %x (error: %d)", params[1], err);
1122 if (!stmt->BindParamInt(params[2], params[3], params[4] ? true : false))
1124 return pContext->ThrowNativeError("Could not bind parameter %d as an integer", params[2]);
1130 static cell_t SQL_BindParamFloat(IPluginContext *pContext, const cell_t *params)
1132 IPreparedQuery *stmt;
1135 if ((err = ReadStmtHndl(params[1], pContext, &stmt)) != HandleError_None)
1137 return pContext->ThrowNativeError("Invalid statement Handle %x (error: %d)", params[1], err);
1140 if (!stmt->BindParamFloat(params[2], sp_ctof(params[3])))
1142 return pContext->ThrowNativeError("Could not bind parameter %d as a float", params[2]);
1148 static cell_t SQL_BindParamString(IPluginContext *pContext, const cell_t *params)
1150 IPreparedQuery *stmt;
1153 if ((err = ReadStmtHndl(params[1], pContext, &stmt)) != HandleError_None)
1155 return pContext->ThrowNativeError("Invalid statement Handle %x (error: %d)", params[1], err);
1159 pContext->LocalToString(params[3], &str);
1161 if (!stmt->BindParamString(params[2], str, params[4] ? true : false))
1163 return pContext->ThrowNativeError("Could not bind parameter %d as a string", params[2]);
1169 static cell_t SQL_Execute(IPluginContext *pContext, const cell_t *params)
1171 IPreparedQuery *stmt;
1174 if ((err = ReadStmtHndl(params[1], pContext, &stmt)) != HandleError_None)
1176 return pContext->ThrowNativeError("Invalid statement Handle %x (error: %d)", params[1], err);
1179 return stmt->Execute() ? 1 : 0;
1182 static cell_t SQL_IsSameConnection(IPluginContext *pContext, const cell_t *params)
1184 IDatabase *db1=NULL, *db2=NULL;
1187 if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db1))
1188 != HandleError_None)
1190 return pContext->ThrowNativeError("Invalid database Handle 1/%x (error: %d)", params[1], err);
1193 if ((err = g_DBMan.ReadHandle(params[2], DBHandle_Database, (void **)&db2))
1194 != HandleError_None)
1196 return pContext->ThrowNativeError("Invalid database Handle 2/%x (error: %d)", params[2], err);
1199 return (db1 == db2) ? true : false;
1202 REGISTER_NATIVES(dbNatives)
1204 {"SQL_BindParamInt", SQL_BindParamInt},
1205 {"SQL_BindParamFloat", SQL_BindParamFloat},
1206 {"SQL_BindParamString", SQL_BindParamString},
1207 {"SQL_Connect", SQL_Connect},
1208 {"SQL_ConnectEx", SQL_ConnectEx},
1209 {"SQL_Execute", SQL_Execute},
1210 {"SQL_FastQuery", SQL_FastQuery},
1211 {"SQL_FetchFloat", SQL_FetchFloat},
1212 {"SQL_FetchInt", SQL_FetchInt},
1213 {"SQL_FetchMoreResults", SQL_FetchMoreResults},
1214 {"SQL_FetchRow", SQL_FetchRow},
1215 {"SQL_FetchSize", SQL_FetchSize},
1216 {"SQL_FetchString", SQL_FetchString},
1217 {"SQL_FieldNameToNum", SQL_FieldNameToNum},
1218 {"SQL_FieldNumToName", SQL_FieldNumToName},
1219 {"SQL_GetAffectedRows", SQL_GetAffectedRows},
1220 {"SQL_GetDriver", SQL_GetDriver},
1221 {"SQL_GetDriverIdent", SQL_GetDriverIdent},
1222 {"SQL_GetDriverProduct", SQL_GetDriverProduct},
1223 {"SQL_GetError", SQL_GetError},
1224 {"SQL_GetFieldCount", SQL_GetFieldCount},
1225 {"SQL_GetInsertId", SQL_GetInsertId},
1226 {"SQL_GetRowCount", SQL_GetRowCount},
1227 {"SQL_HasResultSet", SQL_HasResultSet},
1228 {"SQL_IsFieldNull", SQL_IsFieldNull},
1229 {"SQL_IsSameConnection", SQL_IsSameConnection},
1230 {"SQL_LockDatabase", SQL_LockDatabase},
1231 {"SQL_MoreRows", SQL_MoreRows},
1232 {"SQL_PrepareQuery", SQL_PrepareQuery},
1233 {"SQL_Query", SQL_Query},
1234 {"SQL_QuoteString", SQL_QuoteString},
1235 {"SQL_Rewind", SQL_Rewind},
1236 {"SQL_TConnect", SQL_TConnect},
1237 {"SQL_TQuery", SQL_TQuery},
1238 {"SQL_UnlockDatabase", SQL_UnlockDatabase},