dvander@868: #include "sm_globals.h" dvander@868: #include "HandleSys.h" dvander@868: #include "Database.h" dvander@868: #include "ExtensionSys.h" dvander@868: #include "PluginSys.h" dvander@868: dvander@868: HandleType_t hQueryType; dvander@868: HandleType_t hStmtType; dvander@868: dvander@868: class DatabaseHelpers : dvander@868: public SMGlobalClass, dvander@868: public IHandleTypeDispatch dvander@868: { dvander@868: public: dvander@868: virtual void OnSourceModAllInitialized() dvander@868: { dvander@868: HandleAccess acc; dvander@868: dvander@868: /* Disable cloning */ dvander@868: g_HandleSys.InitAccessDefaults(NULL, &acc); dvander@868: acc.access[HandleAccess_Clone] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY; dvander@868: dvander@868: TypeAccess tacc; dvander@868: dvander@868: g_HandleSys.InitAccessDefaults(&tacc, NULL); dvander@868: tacc.ident = g_pCoreIdent; dvander@868: dvander@868: hQueryType = g_HandleSys.CreateType("IQuery", this, 0, &tacc, &acc, g_pCoreIdent, NULL); dvander@869: hStmtType = g_HandleSys.CreateType("IPreparedQuery", this, hQueryType, &tacc, &acc, g_pCoreIdent, NULL); dvander@868: } dvander@868: dvander@868: virtual void OnSourceModShutdown() dvander@868: { dvander@868: g_HandleSys.RemoveType(hStmtType, g_pCoreIdent); dvander@868: g_HandleSys.RemoveType(hQueryType, g_pCoreIdent); dvander@868: } dvander@868: dvander@868: virtual void OnHandleDestroy(HandleType_t type, void *object) dvander@868: { dvander@868: if (type == hQueryType) dvander@868: { dvander@868: IQuery *query = (IQuery *)object; dvander@868: query->Destroy(); dvander@868: } else if (type == hStmtType) { dvander@868: IPreparedQuery *query = (IPreparedQuery *)object; dvander@868: query->Destroy(); dvander@868: } dvander@868: } dvander@868: } s_DatabaseNativeHelpers; dvander@868: dvander@868: //is this safe for stmt handles? i think since it's single inheritance, it always will be. dvander@868: inline HandleError ReadQueryHndl(Handle_t hndl, IPluginContext *pContext, IQuery **query) dvander@868: { dvander@868: HandleSecurity sec; dvander@868: sec.pOwner = pContext->GetIdentity(); dvander@868: sec.pIdentity = g_pCoreIdent; dvander@868: dvander@868: return g_HandleSys.ReadHandle(hndl, hQueryType, &sec, (void **)query); dvander@868: } dvander@868: dvander@868: inline HandleError ReadStmtHndl(Handle_t hndl, IPluginContext *pContext, IPreparedQuery **query) dvander@868: { dvander@868: HandleSecurity sec; dvander@868: sec.pOwner = pContext->GetIdentity(); dvander@868: sec.pIdentity = g_pCoreIdent; dvander@868: dvander@868: return g_HandleSys.ReadHandle(hndl, hStmtType, &sec, (void **)query); dvander@868: } dvander@868: dvander@868: inline HandleError ReadDbOrStmtHndl(Handle_t hndl, IPluginContext *pContext, IDatabase **db, IPreparedQuery **query) dvander@868: { dvander@868: HandleError err; dvander@868: if ((err = g_DBMan.ReadHandle(hndl, DBHandle_Database, (void **)db)) == HandleError_Type) dvander@868: { dvander@868: *db = NULL; dvander@868: return ReadStmtHndl(hndl, pContext, query); dvander@868: } dvander@868: return err; dvander@868: } dvander@868: dvander@868: static cell_t SQL_Connect(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: char *conf, *err; dvander@868: dvander@868: size_t maxlength = (size_t)params[4]; dvander@868: bool persistent = params[2] ? true : false; dvander@868: pContext->LocalToString(params[1], &conf); dvander@868: pContext->LocalToString(params[3], &err); dvander@868: dvander@868: IDBDriver *driver; dvander@868: IDatabase *db; dvander@868: if (!g_DBMan.Connect(conf, &driver, &db, persistent, err, maxlength)) dvander@868: { dvander@868: return BAD_HANDLE; dvander@868: } dvander@868: dvander@875: Handle_t hndl = g_DBMan.CreateHandle(DBHandle_Database, db, pContext->GetIdentity()); dvander@875: if (!hndl) dvander@875: { dvander@875: db->Close(); dvander@875: return BAD_HANDLE; dvander@875: } dvander@875: dvander@868: /* HACK! Add us to the dependency list */ dvander@868: CExtension *pExt = g_Extensions.GetExtensionFromIdent(driver->GetIdentity()); dvander@868: if (pExt) dvander@868: { dvander@868: g_Extensions.BindChildPlugin(pExt, g_PluginSys.FindPluginByContext(pContext->GetContext())); dvander@868: } dvander@868: dvander@875: return hndl; dvander@868: } dvander@868: dvander@868: static cell_t SQL_ConnectEx(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IDBDriver *driver; dvander@868: if (params[1] == BAD_HANDLE) dvander@868: { dvander@868: if ((driver = g_DBMan.GetDefaultDriver()) == NULL) dvander@868: { dvander@868: return pContext->ThrowNativeError("Could not find any default driver"); dvander@868: } dvander@868: } else { dvander@868: HandleError err; dvander@868: if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Driver, (void **)&driver)) dvander@868: != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid driver Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: } dvander@868: dvander@868: char *host, *user, *pass, *database, *error; dvander@868: size_t maxlength = (size_t)params[7]; dvander@868: bool persistent = params[8] ? true : false; dvander@868: unsigned int port = params[9]; dvander@868: unsigned int maxTimeout = params[10]; dvander@868: pContext->LocalToString(params[2], &host); dvander@868: pContext->LocalToString(params[3], &user); dvander@868: pContext->LocalToString(params[4], &pass); dvander@868: pContext->LocalToString(params[5], &database); dvander@868: pContext->LocalToString(params[6], &error); dvander@868: dvander@868: DatabaseInfo info; dvander@868: info.database = database; dvander@868: info.driver = driver->GetIdentifier(); dvander@868: info.host = host; dvander@868: info.maxTimeout = maxTimeout; dvander@868: info.pass = pass; dvander@868: info.port = port; dvander@868: info.user = user; dvander@868: dvander@868: IDatabase *db = driver->Connect(&info, persistent, error, maxlength); dvander@868: dvander@868: if (db) dvander@868: { dvander@875: Handle_t hndl = g_DBMan.CreateHandle(DBHandle_Database, db, pContext->GetIdentity()); dvander@875: if (!hndl) dvander@875: { dvander@875: db->Close(); dvander@875: return BAD_HANDLE; dvander@875: } dvander@875: dvander@868: /* HACK! Add us to the dependency list */ dvander@868: CExtension *pExt = g_Extensions.GetExtensionFromIdent(driver->GetIdentity()); dvander@868: if (pExt) dvander@868: { dvander@868: g_Extensions.BindChildPlugin(pExt, g_PluginSys.FindPluginByContext(pContext->GetContext())); dvander@868: } dvander@868: dvander@875: return hndl; dvander@868: } dvander@868: dvander@868: return BAD_HANDLE; dvander@868: } dvander@868: dvander@868: static cell_t SQL_GetDriverIdent(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IDBDriver *driver; dvander@868: if (params[1] == BAD_HANDLE) dvander@868: { dvander@868: if ((driver = g_DBMan.GetDefaultDriver()) == NULL) dvander@868: { dvander@868: return pContext->ThrowNativeError("Could not find any default driver"); dvander@868: } dvander@868: } else { dvander@868: HandleError err; dvander@868: if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Driver, (void **)&driver)) dvander@868: != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid driver Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: } dvander@868: dvander@868: pContext->StringToLocalUTF8(params[2], params[3], driver->GetIdentifier(), NULL); dvander@868: dvander@868: return 1; dvander@868: } dvander@868: dvander@868: static cell_t SQL_GetDriver(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: char *name; dvander@868: pContext->LocalToString(params[1], &name); dvander@868: dvander@868: IDBDriver *driver = NULL; dvander@868: if (name[0] == '\0') dvander@868: { dvander@868: driver = g_DBMan.GetDefaultDriver(); dvander@868: } else { dvander@868: driver = g_DBMan.FindOrLoadDriver(name); dvander@868: } dvander@868: dvander@868: return (driver != NULL) ? driver->GetHandle() : BAD_HANDLE; dvander@868: } dvander@868: dvander@868: static cell_t SQL_GetDriverProduct(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IDBDriver *driver; dvander@868: if (params[1] == BAD_HANDLE) dvander@868: { dvander@868: if ((driver = g_DBMan.GetDefaultDriver()) == NULL) dvander@868: { dvander@868: return pContext->ThrowNativeError("Could not find any default driver"); dvander@868: } dvander@868: } else { dvander@868: HandleError err; dvander@868: if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Driver, (void **)&driver)) dvander@868: != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid driver Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: } dvander@868: dvander@868: pContext->StringToLocalUTF8(params[2], params[3], driver->GetProductName(), NULL); dvander@868: dvander@868: return 1; dvander@868: } dvander@868: dvander@868: static cell_t SQL_GetAffectedRows(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IDatabase *db = NULL; dvander@868: IPreparedQuery *stmt = NULL; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = ReadDbOrStmtHndl(params[1], pContext, &db, &stmt)) != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid statement or db Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: if (db) dvander@868: { dvander@868: return db->GetAffectedRows(); dvander@868: } else if (stmt) { dvander@868: return stmt->GetAffectedRows(); dvander@868: } dvander@868: dvander@868: return pContext->ThrowNativeError("Unknown error reading db/stmt handles"); dvander@868: } dvander@868: dvander@868: static cell_t SQL_GetInsertId(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IDatabase *db = NULL; dvander@868: IPreparedQuery *stmt = NULL; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = ReadDbOrStmtHndl(params[1], pContext, &db, &stmt)) != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid statement or db Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: if (db) dvander@868: { dvander@868: return db->GetInsertID(); dvander@868: } else if (stmt) { dvander@868: return stmt->GetInsertID(); dvander@868: } dvander@868: dvander@868: return pContext->ThrowNativeError("Unknown error reading db/stmt handles"); dvander@868: } dvander@868: dvander@868: static cell_t SQL_GetError(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IDatabase *db = NULL; dvander@868: IPreparedQuery *stmt = NULL; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = ReadDbOrStmtHndl(params[1], pContext, &db, &stmt)) != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid statement or db Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: const char *error = ""; dvander@868: if (db) dvander@868: { dvander@868: error = db->GetError(); dvander@868: } else if (stmt) { dvander@868: error = stmt->GetError(); dvander@868: } dvander@868: dvander@868: if (error[0] == '\0') dvander@868: { dvander@868: return false; dvander@868: } dvander@868: dvander@868: pContext->StringToLocalUTF8(params[2], params[3], error, NULL); dvander@868: dvander@868: return 1; dvander@868: } dvander@868: dvander@868: static cell_t SQL_QuoteString(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IDatabase *db = NULL; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db)) dvander@868: != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: char *input, *output; dvander@868: size_t maxlength = (size_t)params[4]; dvander@868: pContext->LocalToString(params[2], &input); dvander@868: pContext->LocalToString(params[3], &output); dvander@868: dvander@868: size_t written; dvander@868: bool s = db->QuoteString(input, output, maxlength, &written); dvander@868: dvander@868: cell_t *addr; dvander@868: pContext->LocalToPhysAddr(params[5], &addr); dvander@868: *addr = (cell_t)written; dvander@868: dvander@868: return s ? 1 : 0; dvander@868: } dvander@868: dvander@868: static cell_t SQL_FastQuery(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IDatabase *db = NULL; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db)) dvander@868: != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: char *query; dvander@868: pContext->LocalToString(params[2], &query); dvander@868: dvander@868: return db->DoSimpleQuery(query) ? 1 : 0; dvander@868: } dvander@868: dvander@868: static cell_t SQL_Query(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IDatabase *db = NULL; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db)) dvander@868: != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: char *query; dvander@868: pContext->LocalToString(params[2], &query); dvander@868: dvander@868: IQuery *qr = db->DoQuery(query); dvander@868: dvander@868: if (!qr) dvander@868: { dvander@868: return BAD_HANDLE; dvander@868: } dvander@868: dvander@868: Handle_t hndl = g_HandleSys.CreateHandle(hQueryType, qr, pContext->GetIdentity(), g_pCoreIdent, NULL); dvander@868: if (hndl == BAD_HANDLE) dvander@868: { dvander@868: qr->Destroy(); dvander@868: return BAD_HANDLE; dvander@868: } dvander@868: dvander@868: return hndl; dvander@868: } dvander@868: dvander@868: static cell_t SQL_PrepareQuery(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IDatabase *db = NULL; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db)) dvander@868: != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: char *query, *error; dvander@868: size_t maxlength = (size_t)params[4]; dvander@868: pContext->LocalToString(params[2], &query); dvander@868: pContext->LocalToString(params[3], &error); dvander@868: dvander@868: IPreparedQuery *qr = db->PrepareQuery(query, error, maxlength); dvander@868: dvander@868: if (!qr) dvander@868: { dvander@868: return BAD_HANDLE; dvander@868: } dvander@868: dvander@868: Handle_t hndl = g_HandleSys.CreateHandle(hStmtType, qr, pContext->GetIdentity(), g_pCoreIdent, NULL); dvander@868: if (hndl == BAD_HANDLE) dvander@868: { dvander@868: qr->Destroy(); dvander@868: return BAD_HANDLE; dvander@868: } dvander@868: dvander@868: return hndl; dvander@868: } dvander@868: dvander@868: static cell_t SQL_FetchMoreResults(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IQuery *query; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: return query->FetchMoreResults() ? 1 : 0; dvander@868: } dvander@868: dvander@868: static cell_t SQL_HasResultSet(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IQuery *query; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: return query->GetResultSet() != NULL ? true : false; dvander@868: } dvander@868: dvander@868: static cell_t SQL_GetRowCount(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IQuery *query; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: IResultSet *rs = query->GetResultSet(); dvander@868: if (!rs) dvander@868: { dvander@868: return 0; dvander@868: } dvander@868: dvander@868: return rs->GetRowCount(); dvander@868: } dvander@868: dvander@868: static cell_t SQL_GetFieldCount(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IQuery *query; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: IResultSet *rs = query->GetResultSet(); dvander@868: if (!rs) dvander@868: { dvander@868: return 0; dvander@868: } dvander@868: dvander@868: return rs->GetFieldCount(); dvander@868: } dvander@868: dvander@868: static cell_t SQL_FieldNumToName(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IQuery *query; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: IResultSet *rs = query->GetResultSet(); dvander@868: if (!rs) dvander@868: { dvander@868: return pContext->ThrowNativeError("No current result set"); dvander@868: } dvander@868: dvander@868: unsigned int field = params[2]; dvander@868: dvander@868: const char *fldname; dvander@868: if ((fldname = rs->FieldNumToName(field)) == NULL) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid field index %d", field); dvander@868: } dvander@868: dvander@868: pContext->StringToLocalUTF8(params[3], params[4], fldname, NULL); dvander@868: dvander@868: return 1; dvander@868: } dvander@868: dvander@868: static cell_t SQL_FieldNameToNum(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IQuery *query; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: IResultSet *rs = query->GetResultSet(); dvander@868: if (!rs) dvander@868: { dvander@868: return pContext->ThrowNativeError("No current result set"); dvander@868: } dvander@868: dvander@868: char *field; dvander@868: pContext->LocalToString(params[2], &field); dvander@868: dvander@868: cell_t *num; dvander@868: pContext->LocalToPhysAddr(params[3], &num); dvander@868: dvander@868: return rs->FieldNameToNum(field, (unsigned int *)num) ? 1 : 0; dvander@868: } dvander@868: dvander@868: static cell_t SQL_FetchRow(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IQuery *query; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: IResultSet *rs = query->GetResultSet(); dvander@868: if (!rs) dvander@868: { dvander@868: return pContext->ThrowNativeError("No current result set"); dvander@868: } dvander@868: dvander@868: return (rs->FetchRow() != NULL) ? true : false; dvander@868: } dvander@868: dvander@868: static cell_t SQL_MoreRows(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IQuery *query; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: IResultSet *rs = query->GetResultSet(); dvander@868: if (!rs) dvander@868: { dvander@868: return pContext->ThrowNativeError("No current result set"); dvander@868: } dvander@868: dvander@868: return rs->MoreRows() ? 1 : 0; dvander@868: } dvander@868: dvander@868: static cell_t SQL_Rewind(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IQuery *query; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: IResultSet *rs = query->GetResultSet(); dvander@868: if (!rs) dvander@868: { dvander@868: return pContext->ThrowNativeError("No current result set"); dvander@868: } dvander@868: dvander@868: return rs->Rewind() ? 1 : 0; dvander@868: } dvander@868: dvander@868: static cell_t SQL_FetchString(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IQuery *query; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: IResultSet *rs = query->GetResultSet(); dvander@868: if (!rs) dvander@868: { dvander@868: return pContext->ThrowNativeError("No current result set"); dvander@868: } dvander@868: dvander@868: IResultRow *row = rs->CurrentRow(); dvander@868: if (!row) dvander@868: { dvander@868: return pContext->ThrowNativeError("Current result set has no fetched rows"); dvander@868: } dvander@868: dvander@868: const char *str; dvander@868: size_t length; dvander@868: DBResult res = row->GetString(params[2], &str, &length); dvander@868: dvander@868: if (res == DBVal_Error) dvander@868: { dvander@868: return pContext->ThrowNativeError("Error fetching data from field %d", params[2]); dvander@868: } else if (res == DBVal_TypeMismatch) { dvander@868: return pContext->ThrowNativeError("Could not fetch data in field %d as a string", params[2]); dvander@868: } dvander@868: dvander@868: pContext->StringToLocalUTF8(params[3], params[4], str, &length); dvander@868: dvander@868: cell_t *addr; dvander@868: pContext->LocalToPhysAddr(params[5], &addr); dvander@868: *addr = (cell_t)res; dvander@868: dvander@868: return (cell_t)length; dvander@868: } dvander@868: dvander@868: static cell_t SQL_FetchFloat(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IQuery *query; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: IResultSet *rs = query->GetResultSet(); dvander@868: if (!rs) dvander@868: { dvander@868: return pContext->ThrowNativeError("No current result set"); dvander@868: } dvander@868: dvander@868: IResultRow *row = rs->CurrentRow(); dvander@868: if (!row) dvander@868: { dvander@868: return pContext->ThrowNativeError("Current result set has no fetched rows"); dvander@868: } dvander@868: dvander@868: float f; dvander@868: DBResult res = row->GetFloat(params[2], &f); dvander@868: dvander@868: if (res == DBVal_Error) dvander@868: { dvander@868: return pContext->ThrowNativeError("Error fetching data from field %d", params[2]); dvander@868: } else if (res == DBVal_TypeMismatch) { dvander@868: return pContext->ThrowNativeError("Could not fetch data in field %d as a float", params[2]); dvander@868: } dvander@868: dvander@868: cell_t *addr; dvander@868: pContext->LocalToPhysAddr(params[5], &addr); dvander@868: *addr = (cell_t)res; dvander@868: dvander@868: return sp_ftoc(f); dvander@868: } dvander@868: dvander@868: static cell_t SQL_FetchInt(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IQuery *query; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: IResultSet *rs = query->GetResultSet(); dvander@868: if (!rs) dvander@868: { dvander@868: return pContext->ThrowNativeError("No current result set"); dvander@868: } dvander@868: dvander@868: IResultRow *row = rs->CurrentRow(); dvander@868: if (!row) dvander@868: { dvander@868: return pContext->ThrowNativeError("Current result set has no fetched rows"); dvander@868: } dvander@868: dvander@868: int iv; dvander@868: DBResult res = row->GetInt(params[2], &iv); dvander@868: dvander@868: if (res == DBVal_Error) dvander@868: { dvander@868: return pContext->ThrowNativeError("Error fetching data from field %d", params[2]); dvander@868: } else if (res == DBVal_TypeMismatch) { dvander@868: return pContext->ThrowNativeError("Could not fetch data in field %d as an integer", params[2]); dvander@868: } dvander@868: dvander@868: cell_t *addr; dvander@868: pContext->LocalToPhysAddr(params[5], &addr); dvander@868: *addr = (cell_t)res; dvander@868: dvander@868: return iv; dvander@868: } dvander@868: dvander@868: static cell_t SQL_IsFieldNull(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IQuery *query; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: IResultSet *rs = query->GetResultSet(); dvander@868: if (!rs) dvander@868: { dvander@868: return pContext->ThrowNativeError("No current result set"); dvander@868: } dvander@868: dvander@868: IResultRow *row = rs->CurrentRow(); dvander@868: if (!row) dvander@868: { dvander@868: return pContext->ThrowNativeError("Current result set has no fetched rows"); dvander@868: } dvander@868: dvander@868: if ((unsigned)params[2] >= rs->GetFieldCount()) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid field index %d", params[2]); dvander@868: } dvander@868: dvander@868: return row->IsNull(params[2]) ? 1 : 0; dvander@868: } dvander@868: dvander@868: static cell_t SQL_FetchSize(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IQuery *query; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: IResultSet *rs = query->GetResultSet(); dvander@868: if (!rs) dvander@868: { dvander@868: return pContext->ThrowNativeError("No current result set"); dvander@868: } dvander@868: dvander@868: IResultRow *row = rs->CurrentRow(); dvander@868: if (!row) dvander@868: { dvander@868: return pContext->ThrowNativeError("Current result set has no fetched rows"); dvander@868: } dvander@868: dvander@868: if ((unsigned)params[2] >= rs->GetFieldCount()) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid field index %d", params[2]); dvander@868: } dvander@868: dvander@868: return row->GetDataSize(params[2]); dvander@868: } dvander@868: dvander@868: static cell_t SQL_BindParamInt(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IPreparedQuery *stmt; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = ReadStmtHndl(params[1], pContext, &stmt)) != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid statement Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: if (!stmt->BindParamInt(params[2], params[3], params[4] ? true : false)) dvander@868: { dvander@868: return pContext->ThrowNativeError("Could not bind parameter %d as an integer", params[2]); dvander@868: } dvander@868: dvander@868: return 1; dvander@868: } dvander@868: dvander@868: static cell_t SQL_BindParamFloat(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IPreparedQuery *stmt; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = ReadStmtHndl(params[1], pContext, &stmt)) != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid statement Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: if (!stmt->BindParamFloat(params[2], sp_ctof(params[3]))) dvander@868: { dvander@868: return pContext->ThrowNativeError("Could not bind parameter %d as a float", params[2]); dvander@868: } dvander@868: dvander@868: return 1; dvander@868: } dvander@868: dvander@868: static cell_t SQL_BindParamString(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IPreparedQuery *stmt; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = ReadStmtHndl(params[1], pContext, &stmt)) != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid statement Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: char *str; dvander@868: pContext->LocalToString(params[3], &str); dvander@868: dvander@868: if (!stmt->BindParamString(params[2], str, params[4] ? true : false)) dvander@868: { dvander@868: return pContext->ThrowNativeError("Could not bind parameter %d as a string", params[2]); dvander@868: } dvander@868: dvander@868: return 1; dvander@868: } dvander@868: dvander@868: static cell_t SQL_Execute(IPluginContext *pContext, const cell_t *params) dvander@868: { dvander@868: IPreparedQuery *stmt; dvander@868: HandleError err; dvander@868: dvander@868: if ((err = ReadStmtHndl(params[1], pContext, &stmt)) != HandleError_None) dvander@868: { dvander@868: return pContext->ThrowNativeError("Invalid statement Handle %x (error: %d)", params[1], err); dvander@868: } dvander@868: dvander@868: return stmt->Execute() ? 1 : 0; dvander@868: } dvander@868: dvander@868: REGISTER_NATIVES(dbNatives) dvander@868: { dvander@868: {"SQL_BindParamInt", SQL_BindParamInt}, dvander@868: {"SQL_BindParamFloat", SQL_BindParamFloat}, dvander@868: {"SQL_BindParamString", SQL_BindParamString}, dvander@868: {"SQL_Connect", SQL_Connect}, dvander@868: {"SQL_ConnectEx", SQL_ConnectEx}, dvander@868: {"SQL_Execute", SQL_Execute}, dvander@868: {"SQL_FastQuery", SQL_FastQuery}, dvander@868: {"SQL_FetchFloat", SQL_FetchFloat}, dvander@868: {"SQL_FetchInt", SQL_FetchInt}, dvander@868: {"SQL_FetchMoreResults", SQL_FetchMoreResults}, dvander@868: {"SQL_FetchRow", SQL_FetchRow}, dvander@868: {"SQL_FetchSize", SQL_FetchSize}, dvander@868: {"SQL_FetchString", SQL_FetchString}, dvander@868: {"SQL_FieldNameToNum", SQL_FieldNameToNum}, dvander@868: {"SQL_FieldNumToName", SQL_FieldNumToName}, dvander@868: {"SQL_GetAffectedRows", SQL_GetAffectedRows}, dvander@868: {"SQL_GetDriver", SQL_GetDriver}, dvander@868: {"SQL_GetDriverIdent", SQL_GetDriverIdent}, dvander@868: {"SQL_GetDriverProduct", SQL_GetDriverProduct}, dvander@868: {"SQL_GetError", SQL_GetError}, dvander@868: {"SQL_GetFieldCount", SQL_GetFieldCount}, dvander@868: {"SQL_GetInsertId", SQL_GetInsertId}, dvander@868: {"SQL_GetRowCount", SQL_GetRowCount}, dvander@868: {"SQL_HasResultSet", SQL_HasResultSet}, dvander@868: {"SQL_IsFieldNull", SQL_IsFieldNull}, dvander@868: {"SQL_MoreRows", SQL_MoreRows}, dvander@868: {"SQL_Query", SQL_Query}, dvander@868: {"SQL_QuoteString", SQL_QuoteString}, dvander@868: {"SQL_PrepareQuery", SQL_PrepareQuery}, dvander@868: {"SQL_Rewind", SQL_Rewind}, dvander@868: {NULL, NULL}, dvander@868: };