static cell_t SQL_ExecuteTransaction(IPluginContext *pContext, const cell_t *params) { HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent); IDatabase *db = NULL; HandleError err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db); if (err != HandleError_None) return pContext->ThrowNativeError("Invalid database handle %x (error: %d)", params[1], err); Transaction *txn; if ((err = handlesys->ReadHandle(params[2], hTransactionType, &sec, (void **)&txn)) != HandleError_None) return pContext->ThrowNativeError("Invalid transaction handle %x (error %d)", params[2], err); if (!db->GetDriver()->IsThreadSafe()) return pContext->ThrowNativeError("Driver \"%s\" is not thread safe!", db->GetDriver()->GetIdentifier()); IPluginFunction *onSuccess = NULL; IPluginFunction *onError = NULL; if (params[3] != -1 && ((onSuccess = pContext->GetFunctionById(params[3])) == NULL)) return pContext->ThrowNativeError("Function id %x is invalid", params[3]); if (params[4] != -1 && ((onError = pContext->GetFunctionById(params[4])) == NULL)) return pContext->ThrowNativeError("Function id %x is invalid", params[4]); cell_t data = params[5]; PrioQueueLevel priority = PrioQueue_Normal; if (params[6] == (cell_t)PrioQueue_High) priority = PrioQueue_High; else if (params[6] == (cell_t)PrioQueue_Low) priority = PrioQueue_Low; TTransactOp *op = new TTransactOp(db, txn, params[2], pContext->GetIdentity(), onSuccess, onError, data); // The handle owns the underlying Transaction object, but we want to close // the plugin's view both to ensure reliable access for us and to prevent // further tampering on the main thread. To do this, TTransactOp clones the // transaction handle and automatically closes it. Therefore, it's safe to // close the plugin's handle here. handlesys->FreeHandle(params[2], &sec); IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext()); if (pPlugin->GetProperty("DisallowDBThreads", NULL) || !g_DBMan.AddToThreadQueue(op, priority)) { // Do everything right now. op->RunThreadPart(); op->RunThinkPart(); op->Destroy(); } return 0; }
static cell_t SQL_TQuery(IPluginContext *pContext, const cell_t *params) { IDatabase *db = NULL; HandleError err; if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db)) != HandleError_None) { return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err); } if (!db->GetDriver()->IsThreadSafe()) { return pContext->ThrowNativeError("Driver \"%s\" is not thread safe!", db->GetDriver()->GetIdentifier()); } IPluginFunction *pf = pContext->GetFunctionById(params[2]); if (!pf) { return pContext->ThrowNativeError("Function id %x is invalid", params[2]); } char *query; pContext->LocalToString(params[3], &query); cell_t data = params[4]; PrioQueueLevel level = PrioQueue_Normal; if (params[5] == (cell_t)PrioQueue_High) { level = PrioQueue_High; } else if (params[5] == (cell_t)PrioQueue_Low) { level = PrioQueue_Low; } CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext()); TQueryOp *op = new TQueryOp(db, pf, query, data); if (pPlugin->GetProperty("DisallowDBThreads", NULL) || !g_DBMan.AddToThreadQueue(op, level)) { /* Do everything right now */ op->RunThreadPart(); op->RunThinkPart(); op->Destroy(); } return 1; }