1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/core/smn_database.cpp Fri Jun 01 02:30:29 2007 +0000
1.3 @@ -0,0 +1,860 @@
1.4 +#include "sm_globals.h"
1.5 +#include "HandleSys.h"
1.6 +#include "Database.h"
1.7 +#include "ExtensionSys.h"
1.8 +#include "PluginSys.h"
1.9 +
1.10 +HandleType_t hQueryType;
1.11 +HandleType_t hStmtType;
1.12 +
1.13 +class DatabaseHelpers :
1.14 + public SMGlobalClass,
1.15 + public IHandleTypeDispatch
1.16 +{
1.17 +public:
1.18 + virtual void OnSourceModAllInitialized()
1.19 + {
1.20 + HandleAccess acc;
1.21 +
1.22 + /* Disable cloning */
1.23 + g_HandleSys.InitAccessDefaults(NULL, &acc);
1.24 + acc.access[HandleAccess_Clone] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY;
1.25 +
1.26 + TypeAccess tacc;
1.27 +
1.28 + g_HandleSys.InitAccessDefaults(&tacc, NULL);
1.29 + tacc.ident = g_pCoreIdent;
1.30 +
1.31 + hQueryType = g_HandleSys.CreateType("IQuery", this, 0, &tacc, &acc, g_pCoreIdent, NULL);
1.32 + hStmtType = g_HandleSys.CreateType("IPreparedQuery", this, hQueryType, &tacc, &acc, NULL, NULL);
1.33 + }
1.34 +
1.35 + virtual void OnSourceModShutdown()
1.36 + {
1.37 + g_HandleSys.RemoveType(hStmtType, g_pCoreIdent);
1.38 + g_HandleSys.RemoveType(hQueryType, g_pCoreIdent);
1.39 + }
1.40 +
1.41 + virtual void OnHandleDestroy(HandleType_t type, void *object)
1.42 + {
1.43 + if (type == hQueryType)
1.44 + {
1.45 + IQuery *query = (IQuery *)object;
1.46 + query->Destroy();
1.47 + } else if (type == hStmtType) {
1.48 + IPreparedQuery *query = (IPreparedQuery *)object;
1.49 + query->Destroy();
1.50 + }
1.51 + }
1.52 +} s_DatabaseNativeHelpers;
1.53 +
1.54 +//is this safe for stmt handles? i think since it's single inheritance, it always will be.
1.55 +inline HandleError ReadQueryHndl(Handle_t hndl, IPluginContext *pContext, IQuery **query)
1.56 +{
1.57 + HandleSecurity sec;
1.58 + sec.pOwner = pContext->GetIdentity();
1.59 + sec.pIdentity = g_pCoreIdent;
1.60 +
1.61 + return g_HandleSys.ReadHandle(hndl, hQueryType, &sec, (void **)query);
1.62 +}
1.63 +
1.64 +inline HandleError ReadStmtHndl(Handle_t hndl, IPluginContext *pContext, IPreparedQuery **query)
1.65 +{
1.66 + HandleSecurity sec;
1.67 + sec.pOwner = pContext->GetIdentity();
1.68 + sec.pIdentity = g_pCoreIdent;
1.69 +
1.70 + return g_HandleSys.ReadHandle(hndl, hStmtType, &sec, (void **)query);
1.71 +}
1.72 +
1.73 +inline HandleError ReadDbOrStmtHndl(Handle_t hndl, IPluginContext *pContext, IDatabase **db, IPreparedQuery **query)
1.74 +{
1.75 + HandleError err;
1.76 + if ((err = g_DBMan.ReadHandle(hndl, DBHandle_Database, (void **)db)) == HandleError_Type)
1.77 + {
1.78 + *db = NULL;
1.79 + return ReadStmtHndl(hndl, pContext, query);
1.80 + }
1.81 + return err;
1.82 +}
1.83 +
1.84 +static cell_t SQL_Connect(IPluginContext *pContext, const cell_t *params)
1.85 +{
1.86 + char *conf, *err;
1.87 +
1.88 + size_t maxlength = (size_t)params[4];
1.89 + bool persistent = params[2] ? true : false;
1.90 + pContext->LocalToString(params[1], &conf);
1.91 + pContext->LocalToString(params[3], &err);
1.92 +
1.93 + IDBDriver *driver;
1.94 + IDatabase *db;
1.95 + if (!g_DBMan.Connect(conf, &driver, &db, persistent, err, maxlength))
1.96 + {
1.97 + return BAD_HANDLE;
1.98 + }
1.99 +
1.100 + /* HACK! Add us to the dependency list */
1.101 + CExtension *pExt = g_Extensions.GetExtensionFromIdent(driver->GetIdentity());
1.102 + if (pExt)
1.103 + {
1.104 + g_Extensions.BindChildPlugin(pExt, g_PluginSys.FindPluginByContext(pContext->GetContext()));
1.105 + }
1.106 +
1.107 + return db->GetHandle();
1.108 +}
1.109 +
1.110 +static cell_t SQL_ConnectEx(IPluginContext *pContext, const cell_t *params)
1.111 +{
1.112 + IDBDriver *driver;
1.113 + if (params[1] == BAD_HANDLE)
1.114 + {
1.115 + if ((driver = g_DBMan.GetDefaultDriver()) == NULL)
1.116 + {
1.117 + return pContext->ThrowNativeError("Could not find any default driver");
1.118 + }
1.119 + } else {
1.120 + HandleError err;
1.121 + if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Driver, (void **)&driver))
1.122 + != HandleError_None)
1.123 + {
1.124 + return pContext->ThrowNativeError("Invalid driver Handle %x (error: %d)", params[1], err);
1.125 + }
1.126 + }
1.127 +
1.128 + char *host, *user, *pass, *database, *error;
1.129 + size_t maxlength = (size_t)params[7];
1.130 + bool persistent = params[8] ? true : false;
1.131 + unsigned int port = params[9];
1.132 + unsigned int maxTimeout = params[10];
1.133 + pContext->LocalToString(params[2], &host);
1.134 + pContext->LocalToString(params[3], &user);
1.135 + pContext->LocalToString(params[4], &pass);
1.136 + pContext->LocalToString(params[5], &database);
1.137 + pContext->LocalToString(params[6], &error);
1.138 +
1.139 + DatabaseInfo info;
1.140 + info.database = database;
1.141 + info.driver = driver->GetIdentifier();
1.142 + info.host = host;
1.143 + info.maxTimeout = maxTimeout;
1.144 + info.pass = pass;
1.145 + info.port = port;
1.146 + info.user = user;
1.147 +
1.148 + IDatabase *db = driver->Connect(&info, persistent, error, maxlength);
1.149 +
1.150 + if (db)
1.151 + {
1.152 + /* HACK! Add us to the dependency list */
1.153 + CExtension *pExt = g_Extensions.GetExtensionFromIdent(driver->GetIdentity());
1.154 + if (pExt)
1.155 + {
1.156 + g_Extensions.BindChildPlugin(pExt, g_PluginSys.FindPluginByContext(pContext->GetContext()));
1.157 + }
1.158 +
1.159 + return db->GetHandle();
1.160 + }
1.161 +
1.162 + return BAD_HANDLE;
1.163 +}
1.164 +
1.165 +static cell_t SQL_GetDriverIdent(IPluginContext *pContext, const cell_t *params)
1.166 +{
1.167 + IDBDriver *driver;
1.168 + if (params[1] == BAD_HANDLE)
1.169 + {
1.170 + if ((driver = g_DBMan.GetDefaultDriver()) == NULL)
1.171 + {
1.172 + return pContext->ThrowNativeError("Could not find any default driver");
1.173 + }
1.174 + } else {
1.175 + HandleError err;
1.176 + if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Driver, (void **)&driver))
1.177 + != HandleError_None)
1.178 + {
1.179 + return pContext->ThrowNativeError("Invalid driver Handle %x (error: %d)", params[1], err);
1.180 + }
1.181 + }
1.182 +
1.183 + pContext->StringToLocalUTF8(params[2], params[3], driver->GetIdentifier(), NULL);
1.184 +
1.185 + return 1;
1.186 +}
1.187 +
1.188 +static cell_t SQL_GetDriver(IPluginContext *pContext, const cell_t *params)
1.189 +{
1.190 + char *name;
1.191 + pContext->LocalToString(params[1], &name);
1.192 +
1.193 + IDBDriver *driver = NULL;
1.194 + if (name[0] == '\0')
1.195 + {
1.196 + driver = g_DBMan.GetDefaultDriver();
1.197 + } else {
1.198 + driver = g_DBMan.FindOrLoadDriver(name);
1.199 + }
1.200 +
1.201 + return (driver != NULL) ? driver->GetHandle() : BAD_HANDLE;
1.202 +}
1.203 +
1.204 +static cell_t SQL_GetDriverProduct(IPluginContext *pContext, const cell_t *params)
1.205 +{
1.206 + IDBDriver *driver;
1.207 + if (params[1] == BAD_HANDLE)
1.208 + {
1.209 + if ((driver = g_DBMan.GetDefaultDriver()) == NULL)
1.210 + {
1.211 + return pContext->ThrowNativeError("Could not find any default driver");
1.212 + }
1.213 + } else {
1.214 + HandleError err;
1.215 + if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Driver, (void **)&driver))
1.216 + != HandleError_None)
1.217 + {
1.218 + return pContext->ThrowNativeError("Invalid driver Handle %x (error: %d)", params[1], err);
1.219 + }
1.220 + }
1.221 +
1.222 + pContext->StringToLocalUTF8(params[2], params[3], driver->GetProductName(), NULL);
1.223 +
1.224 + return 1;
1.225 +}
1.226 +
1.227 +static cell_t SQL_GetAffectedRows(IPluginContext *pContext, const cell_t *params)
1.228 +{
1.229 + IDatabase *db = NULL;
1.230 + IPreparedQuery *stmt = NULL;
1.231 + HandleError err;
1.232 +
1.233 + if ((err = ReadDbOrStmtHndl(params[1], pContext, &db, &stmt)) != HandleError_None)
1.234 + {
1.235 + return pContext->ThrowNativeError("Invalid statement or db Handle %x (error: %d)", params[1], err);
1.236 + }
1.237 +
1.238 + if (db)
1.239 + {
1.240 + return db->GetAffectedRows();
1.241 + } else if (stmt) {
1.242 + return stmt->GetAffectedRows();
1.243 + }
1.244 +
1.245 + return pContext->ThrowNativeError("Unknown error reading db/stmt handles");
1.246 +}
1.247 +
1.248 +static cell_t SQL_GetInsertId(IPluginContext *pContext, const cell_t *params)
1.249 +{
1.250 + IDatabase *db = NULL;
1.251 + IPreparedQuery *stmt = NULL;
1.252 + HandleError err;
1.253 +
1.254 + if ((err = ReadDbOrStmtHndl(params[1], pContext, &db, &stmt)) != HandleError_None)
1.255 + {
1.256 + return pContext->ThrowNativeError("Invalid statement or db Handle %x (error: %d)", params[1], err);
1.257 + }
1.258 +
1.259 + if (db)
1.260 + {
1.261 + return db->GetInsertID();
1.262 + } else if (stmt) {
1.263 + return stmt->GetInsertID();
1.264 + }
1.265 +
1.266 + return pContext->ThrowNativeError("Unknown error reading db/stmt handles");
1.267 +}
1.268 +
1.269 +static cell_t SQL_GetError(IPluginContext *pContext, const cell_t *params)
1.270 +{
1.271 + IDatabase *db = NULL;
1.272 + IPreparedQuery *stmt = NULL;
1.273 + HandleError err;
1.274 +
1.275 + if ((err = ReadDbOrStmtHndl(params[1], pContext, &db, &stmt)) != HandleError_None)
1.276 + {
1.277 + return pContext->ThrowNativeError("Invalid statement or db Handle %x (error: %d)", params[1], err);
1.278 + }
1.279 +
1.280 + const char *error = "";
1.281 + if (db)
1.282 + {
1.283 + error = db->GetError();
1.284 + } else if (stmt) {
1.285 + error = stmt->GetError();
1.286 + }
1.287 +
1.288 + if (error[0] == '\0')
1.289 + {
1.290 + return false;
1.291 + }
1.292 +
1.293 + pContext->StringToLocalUTF8(params[2], params[3], error, NULL);
1.294 +
1.295 + return 1;
1.296 +}
1.297 +
1.298 +static cell_t SQL_QuoteString(IPluginContext *pContext, const cell_t *params)
1.299 +{
1.300 + IDatabase *db = NULL;
1.301 + HandleError err;
1.302 +
1.303 + if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
1.304 + != HandleError_None)
1.305 + {
1.306 + return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
1.307 + }
1.308 +
1.309 + char *input, *output;
1.310 + size_t maxlength = (size_t)params[4];
1.311 + pContext->LocalToString(params[2], &input);
1.312 + pContext->LocalToString(params[3], &output);
1.313 +
1.314 + size_t written;
1.315 + bool s = db->QuoteString(input, output, maxlength, &written);
1.316 +
1.317 + cell_t *addr;
1.318 + pContext->LocalToPhysAddr(params[5], &addr);
1.319 + *addr = (cell_t)written;
1.320 +
1.321 + return s ? 1 : 0;
1.322 +}
1.323 +
1.324 +static cell_t SQL_FastQuery(IPluginContext *pContext, const cell_t *params)
1.325 +{
1.326 + IDatabase *db = NULL;
1.327 + HandleError err;
1.328 +
1.329 + if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
1.330 + != HandleError_None)
1.331 + {
1.332 + return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
1.333 + }
1.334 +
1.335 + char *query;
1.336 + pContext->LocalToString(params[2], &query);
1.337 +
1.338 + return db->DoSimpleQuery(query) ? 1 : 0;
1.339 +}
1.340 +
1.341 +static cell_t SQL_Query(IPluginContext *pContext, const cell_t *params)
1.342 +{
1.343 + IDatabase *db = NULL;
1.344 + HandleError err;
1.345 +
1.346 + if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
1.347 + != HandleError_None)
1.348 + {
1.349 + return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
1.350 + }
1.351 +
1.352 + char *query;
1.353 + pContext->LocalToString(params[2], &query);
1.354 +
1.355 + IQuery *qr = db->DoQuery(query);
1.356 +
1.357 + if (!qr)
1.358 + {
1.359 + return BAD_HANDLE;
1.360 + }
1.361 +
1.362 + Handle_t hndl = g_HandleSys.CreateHandle(hQueryType, qr, pContext->GetIdentity(), g_pCoreIdent, NULL);
1.363 + if (hndl == BAD_HANDLE)
1.364 + {
1.365 + qr->Destroy();
1.366 + return BAD_HANDLE;
1.367 + }
1.368 +
1.369 + return hndl;
1.370 +}
1.371 +
1.372 +static cell_t SQL_PrepareQuery(IPluginContext *pContext, const cell_t *params)
1.373 +{
1.374 + IDatabase *db = NULL;
1.375 + HandleError err;
1.376 +
1.377 + if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
1.378 + != HandleError_None)
1.379 + {
1.380 + return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
1.381 + }
1.382 +
1.383 + char *query, *error;
1.384 + size_t maxlength = (size_t)params[4];
1.385 + pContext->LocalToString(params[2], &query);
1.386 + pContext->LocalToString(params[3], &error);
1.387 +
1.388 + IPreparedQuery *qr = db->PrepareQuery(query, error, maxlength);
1.389 +
1.390 + if (!qr)
1.391 + {
1.392 + return BAD_HANDLE;
1.393 + }
1.394 +
1.395 + Handle_t hndl = g_HandleSys.CreateHandle(hStmtType, qr, pContext->GetIdentity(), g_pCoreIdent, NULL);
1.396 + if (hndl == BAD_HANDLE)
1.397 + {
1.398 + qr->Destroy();
1.399 + return BAD_HANDLE;
1.400 + }
1.401 +
1.402 + return hndl;
1.403 +}
1.404 +
1.405 +static cell_t SQL_FetchMoreResults(IPluginContext *pContext, const cell_t *params)
1.406 +{
1.407 + IQuery *query;
1.408 + HandleError err;
1.409 +
1.410 + if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
1.411 + {
1.412 + return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
1.413 + }
1.414 +
1.415 + return query->FetchMoreResults() ? 1 : 0;
1.416 +}
1.417 +
1.418 +static cell_t SQL_HasResultSet(IPluginContext *pContext, const cell_t *params)
1.419 +{
1.420 + IQuery *query;
1.421 + HandleError err;
1.422 +
1.423 + if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
1.424 + {
1.425 + return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
1.426 + }
1.427 +
1.428 + return query->GetResultSet() != NULL ? true : false;
1.429 +}
1.430 +
1.431 +static cell_t SQL_GetRowCount(IPluginContext *pContext, const cell_t *params)
1.432 +{
1.433 + IQuery *query;
1.434 + HandleError err;
1.435 +
1.436 + if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
1.437 + {
1.438 + return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
1.439 + }
1.440 +
1.441 + IResultSet *rs = query->GetResultSet();
1.442 + if (!rs)
1.443 + {
1.444 + return 0;
1.445 + }
1.446 +
1.447 + return rs->GetRowCount();
1.448 +}
1.449 +
1.450 +static cell_t SQL_GetFieldCount(IPluginContext *pContext, const cell_t *params)
1.451 +{
1.452 + IQuery *query;
1.453 + HandleError err;
1.454 +
1.455 + if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
1.456 + {
1.457 + return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
1.458 + }
1.459 +
1.460 + IResultSet *rs = query->GetResultSet();
1.461 + if (!rs)
1.462 + {
1.463 + return 0;
1.464 + }
1.465 +
1.466 + return rs->GetFieldCount();
1.467 +}
1.468 +
1.469 +static cell_t SQL_FieldNumToName(IPluginContext *pContext, const cell_t *params)
1.470 +{
1.471 + IQuery *query;
1.472 + HandleError err;
1.473 +
1.474 + if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
1.475 + {
1.476 + return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
1.477 + }
1.478 +
1.479 + IResultSet *rs = query->GetResultSet();
1.480 + if (!rs)
1.481 + {
1.482 + return pContext->ThrowNativeError("No current result set");
1.483 + }
1.484 +
1.485 + unsigned int field = params[2];
1.486 +
1.487 + const char *fldname;
1.488 + if ((fldname = rs->FieldNumToName(field)) == NULL)
1.489 + {
1.490 + return pContext->ThrowNativeError("Invalid field index %d", field);
1.491 + }
1.492 +
1.493 + pContext->StringToLocalUTF8(params[3], params[4], fldname, NULL);
1.494 +
1.495 + return 1;
1.496 +}
1.497 +
1.498 +static cell_t SQL_FieldNameToNum(IPluginContext *pContext, const cell_t *params)
1.499 +{
1.500 + IQuery *query;
1.501 + HandleError err;
1.502 +
1.503 + if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
1.504 + {
1.505 + return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
1.506 + }
1.507 +
1.508 + IResultSet *rs = query->GetResultSet();
1.509 + if (!rs)
1.510 + {
1.511 + return pContext->ThrowNativeError("No current result set");
1.512 + }
1.513 +
1.514 + char *field;
1.515 + pContext->LocalToString(params[2], &field);
1.516 +
1.517 + cell_t *num;
1.518 + pContext->LocalToPhysAddr(params[3], &num);
1.519 +
1.520 + return rs->FieldNameToNum(field, (unsigned int *)num) ? 1 : 0;
1.521 +}
1.522 +
1.523 +static cell_t SQL_FetchRow(IPluginContext *pContext, const cell_t *params)
1.524 +{
1.525 + IQuery *query;
1.526 + HandleError err;
1.527 +
1.528 + if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
1.529 + {
1.530 + return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
1.531 + }
1.532 +
1.533 + IResultSet *rs = query->GetResultSet();
1.534 + if (!rs)
1.535 + {
1.536 + return pContext->ThrowNativeError("No current result set");
1.537 + }
1.538 +
1.539 + return (rs->FetchRow() != NULL) ? true : false;
1.540 +}
1.541 +
1.542 +static cell_t SQL_MoreRows(IPluginContext *pContext, const cell_t *params)
1.543 +{
1.544 + IQuery *query;
1.545 + HandleError err;
1.546 +
1.547 + if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
1.548 + {
1.549 + return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
1.550 + }
1.551 +
1.552 + IResultSet *rs = query->GetResultSet();
1.553 + if (!rs)
1.554 + {
1.555 + return pContext->ThrowNativeError("No current result set");
1.556 + }
1.557 +
1.558 + return rs->MoreRows() ? 1 : 0;
1.559 +}
1.560 +
1.561 +static cell_t SQL_Rewind(IPluginContext *pContext, const cell_t *params)
1.562 +{
1.563 + IQuery *query;
1.564 + HandleError err;
1.565 +
1.566 + if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
1.567 + {
1.568 + return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
1.569 + }
1.570 +
1.571 + IResultSet *rs = query->GetResultSet();
1.572 + if (!rs)
1.573 + {
1.574 + return pContext->ThrowNativeError("No current result set");
1.575 + }
1.576 +
1.577 + return rs->Rewind() ? 1 : 0;
1.578 +}
1.579 +
1.580 +static cell_t SQL_FetchString(IPluginContext *pContext, const cell_t *params)
1.581 +{
1.582 + IQuery *query;
1.583 + HandleError err;
1.584 +
1.585 + if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
1.586 + {
1.587 + return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
1.588 + }
1.589 +
1.590 + IResultSet *rs = query->GetResultSet();
1.591 + if (!rs)
1.592 + {
1.593 + return pContext->ThrowNativeError("No current result set");
1.594 + }
1.595 +
1.596 + IResultRow *row = rs->CurrentRow();
1.597 + if (!row)
1.598 + {
1.599 + return pContext->ThrowNativeError("Current result set has no fetched rows");
1.600 + }
1.601 +
1.602 + const char *str;
1.603 + size_t length;
1.604 + DBResult res = row->GetString(params[2], &str, &length);
1.605 +
1.606 + if (res == DBVal_Error)
1.607 + {
1.608 + return pContext->ThrowNativeError("Error fetching data from field %d", params[2]);
1.609 + } else if (res == DBVal_TypeMismatch) {
1.610 + return pContext->ThrowNativeError("Could not fetch data in field %d as a string", params[2]);
1.611 + }
1.612 +
1.613 + pContext->StringToLocalUTF8(params[3], params[4], str, &length);
1.614 +
1.615 + cell_t *addr;
1.616 + pContext->LocalToPhysAddr(params[5], &addr);
1.617 + *addr = (cell_t)res;
1.618 +
1.619 + return (cell_t)length;
1.620 +}
1.621 +
1.622 +static cell_t SQL_FetchFloat(IPluginContext *pContext, const cell_t *params)
1.623 +{
1.624 + IQuery *query;
1.625 + HandleError err;
1.626 +
1.627 + if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
1.628 + {
1.629 + return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
1.630 + }
1.631 +
1.632 + IResultSet *rs = query->GetResultSet();
1.633 + if (!rs)
1.634 + {
1.635 + return pContext->ThrowNativeError("No current result set");
1.636 + }
1.637 +
1.638 + IResultRow *row = rs->CurrentRow();
1.639 + if (!row)
1.640 + {
1.641 + return pContext->ThrowNativeError("Current result set has no fetched rows");
1.642 + }
1.643 +
1.644 + float f;
1.645 + DBResult res = row->GetFloat(params[2], &f);
1.646 +
1.647 + if (res == DBVal_Error)
1.648 + {
1.649 + return pContext->ThrowNativeError("Error fetching data from field %d", params[2]);
1.650 + } else if (res == DBVal_TypeMismatch) {
1.651 + return pContext->ThrowNativeError("Could not fetch data in field %d as a float", params[2]);
1.652 + }
1.653 +
1.654 + cell_t *addr;
1.655 + pContext->LocalToPhysAddr(params[5], &addr);
1.656 + *addr = (cell_t)res;
1.657 +
1.658 + return sp_ftoc(f);
1.659 +}
1.660 +
1.661 +static cell_t SQL_FetchInt(IPluginContext *pContext, const cell_t *params)
1.662 +{
1.663 + IQuery *query;
1.664 + HandleError err;
1.665 +
1.666 + if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
1.667 + {
1.668 + return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
1.669 + }
1.670 +
1.671 + IResultSet *rs = query->GetResultSet();
1.672 + if (!rs)
1.673 + {
1.674 + return pContext->ThrowNativeError("No current result set");
1.675 + }
1.676 +
1.677 + IResultRow *row = rs->CurrentRow();
1.678 + if (!row)
1.679 + {
1.680 + return pContext->ThrowNativeError("Current result set has no fetched rows");
1.681 + }
1.682 +
1.683 + int iv;
1.684 + DBResult res = row->GetInt(params[2], &iv);
1.685 +
1.686 + if (res == DBVal_Error)
1.687 + {
1.688 + return pContext->ThrowNativeError("Error fetching data from field %d", params[2]);
1.689 + } else if (res == DBVal_TypeMismatch) {
1.690 + return pContext->ThrowNativeError("Could not fetch data in field %d as an integer", params[2]);
1.691 + }
1.692 +
1.693 + cell_t *addr;
1.694 + pContext->LocalToPhysAddr(params[5], &addr);
1.695 + *addr = (cell_t)res;
1.696 +
1.697 + return iv;
1.698 +}
1.699 +
1.700 +static cell_t SQL_IsFieldNull(IPluginContext *pContext, const cell_t *params)
1.701 +{
1.702 + IQuery *query;
1.703 + HandleError err;
1.704 +
1.705 + if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
1.706 + {
1.707 + return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
1.708 + }
1.709 +
1.710 + IResultSet *rs = query->GetResultSet();
1.711 + if (!rs)
1.712 + {
1.713 + return pContext->ThrowNativeError("No current result set");
1.714 + }
1.715 +
1.716 + IResultRow *row = rs->CurrentRow();
1.717 + if (!row)
1.718 + {
1.719 + return pContext->ThrowNativeError("Current result set has no fetched rows");
1.720 + }
1.721 +
1.722 + if ((unsigned)params[2] >= rs->GetFieldCount())
1.723 + {
1.724 + return pContext->ThrowNativeError("Invalid field index %d", params[2]);
1.725 + }
1.726 +
1.727 + return row->IsNull(params[2]) ? 1 : 0;
1.728 +}
1.729 +
1.730 +static cell_t SQL_FetchSize(IPluginContext *pContext, const cell_t *params)
1.731 +{
1.732 + IQuery *query;
1.733 + HandleError err;
1.734 +
1.735 + if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
1.736 + {
1.737 + return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
1.738 + }
1.739 +
1.740 + IResultSet *rs = query->GetResultSet();
1.741 + if (!rs)
1.742 + {
1.743 + return pContext->ThrowNativeError("No current result set");
1.744 + }
1.745 +
1.746 + IResultRow *row = rs->CurrentRow();
1.747 + if (!row)
1.748 + {
1.749 + return pContext->ThrowNativeError("Current result set has no fetched rows");
1.750 + }
1.751 +
1.752 + if ((unsigned)params[2] >= rs->GetFieldCount())
1.753 + {
1.754 + return pContext->ThrowNativeError("Invalid field index %d", params[2]);
1.755 + }
1.756 +
1.757 + return row->GetDataSize(params[2]);
1.758 +}
1.759 +
1.760 +static cell_t SQL_BindParamInt(IPluginContext *pContext, const cell_t *params)
1.761 +{
1.762 + IPreparedQuery *stmt;
1.763 + HandleError err;
1.764 +
1.765 + if ((err = ReadStmtHndl(params[1], pContext, &stmt)) != HandleError_None)
1.766 + {
1.767 + return pContext->ThrowNativeError("Invalid statement Handle %x (error: %d)", params[1], err);
1.768 + }
1.769 +
1.770 + if (!stmt->BindParamInt(params[2], params[3], params[4] ? true : false))
1.771 + {
1.772 + return pContext->ThrowNativeError("Could not bind parameter %d as an integer", params[2]);
1.773 + }
1.774 +
1.775 + return 1;
1.776 +}
1.777 +
1.778 +static cell_t SQL_BindParamFloat(IPluginContext *pContext, const cell_t *params)
1.779 +{
1.780 + IPreparedQuery *stmt;
1.781 + HandleError err;
1.782 +
1.783 + if ((err = ReadStmtHndl(params[1], pContext, &stmt)) != HandleError_None)
1.784 + {
1.785 + return pContext->ThrowNativeError("Invalid statement Handle %x (error: %d)", params[1], err);
1.786 + }
1.787 +
1.788 + if (!stmt->BindParamFloat(params[2], sp_ctof(params[3])))
1.789 + {
1.790 + return pContext->ThrowNativeError("Could not bind parameter %d as a float", params[2]);
1.791 + }
1.792 +
1.793 + return 1;
1.794 +}
1.795 +
1.796 +static cell_t SQL_BindParamString(IPluginContext *pContext, const cell_t *params)
1.797 +{
1.798 + IPreparedQuery *stmt;
1.799 + HandleError err;
1.800 +
1.801 + if ((err = ReadStmtHndl(params[1], pContext, &stmt)) != HandleError_None)
1.802 + {
1.803 + return pContext->ThrowNativeError("Invalid statement Handle %x (error: %d)", params[1], err);
1.804 + }
1.805 +
1.806 + char *str;
1.807 + pContext->LocalToString(params[3], &str);
1.808 +
1.809 + if (!stmt->BindParamString(params[2], str, params[4] ? true : false))
1.810 + {
1.811 + return pContext->ThrowNativeError("Could not bind parameter %d as a string", params[2]);
1.812 + }
1.813 +
1.814 + return 1;
1.815 +}
1.816 +
1.817 +static cell_t SQL_Execute(IPluginContext *pContext, const cell_t *params)
1.818 +{
1.819 + IPreparedQuery *stmt;
1.820 + HandleError err;
1.821 +
1.822 + if ((err = ReadStmtHndl(params[1], pContext, &stmt)) != HandleError_None)
1.823 + {
1.824 + return pContext->ThrowNativeError("Invalid statement Handle %x (error: %d)", params[1], err);
1.825 + }
1.826 +
1.827 + return stmt->Execute() ? 1 : 0;
1.828 +}
1.829 +
1.830 +REGISTER_NATIVES(dbNatives)
1.831 +{
1.832 + {"SQL_BindParamInt", SQL_BindParamInt},
1.833 + {"SQL_BindParamFloat", SQL_BindParamFloat},
1.834 + {"SQL_BindParamString", SQL_BindParamString},
1.835 + {"SQL_Connect", SQL_Connect},
1.836 + {"SQL_ConnectEx", SQL_ConnectEx},
1.837 + {"SQL_Execute", SQL_Execute},
1.838 + {"SQL_FastQuery", SQL_FastQuery},
1.839 + {"SQL_FetchFloat", SQL_FetchFloat},
1.840 + {"SQL_FetchInt", SQL_FetchInt},
1.841 + {"SQL_FetchMoreResults", SQL_FetchMoreResults},
1.842 + {"SQL_FetchRow", SQL_FetchRow},
1.843 + {"SQL_FetchSize", SQL_FetchSize},
1.844 + {"SQL_FetchString", SQL_FetchString},
1.845 + {"SQL_FieldNameToNum", SQL_FieldNameToNum},
1.846 + {"SQL_FieldNumToName", SQL_FieldNumToName},
1.847 + {"SQL_GetAffectedRows", SQL_GetAffectedRows},
1.848 + {"SQL_GetDriver", SQL_GetDriver},
1.849 + {"SQL_GetDriverIdent", SQL_GetDriverIdent},
1.850 + {"SQL_GetDriverProduct", SQL_GetDriverProduct},
1.851 + {"SQL_GetError", SQL_GetError},
1.852 + {"SQL_GetFieldCount", SQL_GetFieldCount},
1.853 + {"SQL_GetInsertId", SQL_GetInsertId},
1.854 + {"SQL_GetRowCount", SQL_GetRowCount},
1.855 + {"SQL_HasResultSet", SQL_HasResultSet},
1.856 + {"SQL_IsFieldNull", SQL_IsFieldNull},
1.857 + {"SQL_MoreRows", SQL_MoreRows},
1.858 + {"SQL_Query", SQL_Query},
1.859 + {"SQL_QuoteString", SQL_QuoteString},
1.860 + {"SQL_PrepareQuery", SQL_PrepareQuery},
1.861 + {"SQL_Rewind", SQL_Rewind},
1.862 + {NULL, NULL},
1.863 +};