core/logic/smn_database.cpp
author Ruben Gonzalez <drifter01620@gmail.com>
Thu May 15 21:22:24 2014 -0400 (2014-05-15)
changeset 4362 8a15e967d983
parent 4138 da768ad428cf
permissions -rw-r--r--
Update gamedata for CS:S update.
dvander@1141
     1
/**
dvander@1141
     2
 * vim: set ts=4 :
ds@1330
     3
 * =============================================================================
dvander@1231
     4
 * SourceMod
ds@1947
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
ds@1330
     6
 * =============================================================================
dvander@1141
     7
 *
ds@1330
     8
 * This program is free software; you can redistribute it and/or modify it under
ds@1330
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330
    10
 * Free Software Foundation.
dvander@1231
    11
 * 
ds@1330
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
ds@1330
    15
 * details.
dvander@1231
    16
 *
ds@1330
    17
 * You should have received a copy of the GNU General Public License along with
ds@1330
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1231
    19
 *
ds@1330
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
ds@1330
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
ds@1330
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
ds@1330
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330
    27
 * or <http://www.sourcemod.net/license.php>.
dvander@1141
    28
 *
dvander@1141
    29
 * Version: $Id$
dvander@1141
    30
 */
dvander@1141
    31
skamonkey@4138
    32
#include "common_logic.h"
dvander@868
    33
#include "Database.h"
skamonkey@4138
    34
#include "ExtensionSys.h"
skamonkey@4138
    35
#include "stringutil.h"
skamonkey@4138
    36
#include "ISourceMod.h"
dvander@868
    37
dvander@868
    38
HandleType_t hStmtType;
dvander@868
    39
john@3271
    40
HandleType_t hCombinedQueryType;
john@3271
    41
typedef struct
john@3271
    42
{
john@3271
    43
	IQuery *query;
john@3271
    44
	IDatabase *db;
john@3271
    45
} CombinedQuery;
john@3271
    46
dvander@868
    47
class DatabaseHelpers : 
dvander@868
    48
	public SMGlobalClass,
dvander@868
    49
	public IHandleTypeDispatch
dvander@868
    50
{
dvander@868
    51
public:
dvander@868
    52
	virtual void OnSourceModAllInitialized()
dvander@868
    53
	{
dvander@868
    54
		HandleAccess acc;
dvander@868
    55
dvander@868
    56
		/* Disable cloning */
dvander@3872
    57
		handlesys->InitAccessDefaults(NULL, &acc);
dvander@868
    58
		acc.access[HandleAccess_Clone] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY;
dvander@868
    59
dvander@868
    60
		TypeAccess tacc;
dvander@868
    61
dvander@3872
    62
		handlesys->InitAccessDefaults(&tacc, NULL);
dvander@868
    63
		tacc.ident = g_pCoreIdent;
dvander@868
    64
dvander@3872
    65
		hCombinedQueryType = handlesys->CreateType("IQuery", this, 0, &tacc, &acc, g_pCoreIdent, NULL);
dvander@3872
    66
		hStmtType = handlesys->CreateType("IPreparedQuery", this, 0, &tacc, &acc, g_pCoreIdent, NULL);
dvander@868
    67
	}
dvander@868
    68
dvander@868
    69
	virtual void OnSourceModShutdown()
dvander@868
    70
	{
dvander@3872
    71
		handlesys->RemoveType(hStmtType, g_pCoreIdent);
dvander@3872
    72
		handlesys->RemoveType(hCombinedQueryType, g_pCoreIdent);
dvander@868
    73
	}
dvander@868
    74
dvander@868
    75
	virtual void OnHandleDestroy(HandleType_t type, void *object)
dvander@868
    76
	{
john@3271
    77
		if (type == hCombinedQueryType)
dvander@868
    78
		{
john@3271
    79
			CombinedQuery *combined = (CombinedQuery *)object;
john@3271
    80
			combined->query->Destroy();
john@3271
    81
			delete combined;
dvander@868
    82
		} else if (type == hStmtType) {
dvander@868
    83
			IPreparedQuery *query = (IPreparedQuery *)object;
dvander@868
    84
			query->Destroy();
dvander@868
    85
		}
dvander@868
    86
	}
dvander@868
    87
} s_DatabaseNativeHelpers;
dvander@868
    88
dvander@868
    89
//is this safe for stmt handles? i think since it's single inheritance, it always will be.
dvander@868
    90
inline HandleError ReadQueryHndl(Handle_t hndl, IPluginContext *pContext, IQuery **query)
dvander@868
    91
{
dvander@868
    92
	HandleSecurity sec;
john@3271
    93
	CombinedQuery *c;
dvander@868
    94
	sec.pOwner = pContext->GetIdentity();
dvander@868
    95
	sec.pIdentity = g_pCoreIdent;
dvander@868
    96
john@3271
    97
	HandleError ret;
john@3271
    98
	
dvander@3872
    99
	if ((ret = handlesys->ReadHandle(hndl, hStmtType, &sec, (void **)query)) != HandleError_None)
john@3271
   100
	{
dvander@3872
   101
		ret = handlesys->ReadHandle(hndl, hCombinedQueryType, &sec, (void **)&c);
john@3271
   102
		if (ret == HandleError_None)
john@3271
   103
		{
john@3271
   104
			*query = c->query;
john@3271
   105
		}
john@3271
   106
	}
john@3271
   107
	return ret;
john@3271
   108
}
john@3271
   109
john@3271
   110
inline HandleError ReadQueryAndDbHndl(Handle_t hndl, IPluginContext *pContext, IQuery **query, IDatabase **db)
john@3271
   111
{
john@3271
   112
	HandleSecurity sec;
john@3271
   113
	CombinedQuery *c;
john@3271
   114
	sec.pOwner = pContext->GetIdentity();
john@3271
   115
	sec.pIdentity = g_pCoreIdent;
john@3271
   116
dvander@3872
   117
	HandleError ret = handlesys->ReadHandle(hndl, hCombinedQueryType, &sec, (void **)&c);
john@3271
   118
	if (ret == HandleError_None)
john@3271
   119
	{
john@3271
   120
		*query = c->query;
john@3271
   121
		*db = c->db;
john@3271
   122
	}
john@3271
   123
	return ret;
dvander@868
   124
}
dvander@868
   125
dvander@868
   126
inline HandleError ReadStmtHndl(Handle_t hndl, IPluginContext *pContext, IPreparedQuery **query)
dvander@868
   127
{
dvander@868
   128
	HandleSecurity sec;
dvander@868
   129
	sec.pOwner = pContext->GetIdentity();
dvander@868
   130
	sec.pIdentity = g_pCoreIdent;
dvander@868
   131
dvander@3872
   132
	return handlesys->ReadHandle(hndl, hStmtType, &sec, (void **)query);
dvander@868
   133
}
dvander@868
   134
dvander@868
   135
inline HandleError ReadDbOrStmtHndl(Handle_t hndl, IPluginContext *pContext, IDatabase **db, IPreparedQuery **query)
dvander@868
   136
{
dvander@868
   137
	HandleError err;
dvander@868
   138
	if ((err = g_DBMan.ReadHandle(hndl, DBHandle_Database, (void **)db)) == HandleError_Type)
dvander@868
   139
	{
dvander@868
   140
		*db = NULL;
dvander@868
   141
		return ReadStmtHndl(hndl, pContext, query);
dvander@868
   142
	}
dvander@868
   143
	return err;
dvander@868
   144
}
dvander@868
   145
dvander@1096
   146
class TQueryOp : public IDBThreadOperation
dvander@1096
   147
{
dvander@1096
   148
public:
dvander@1096
   149
	TQueryOp(IDatabase *db, IPluginFunction *pf, const char *query, cell_t data) : 
dvander@1096
   150
	  m_pDatabase(db), m_pFunction(pf), m_Query(query), m_Data(data),
dvander@3872
   151
	  me(scripts->FindPluginByContext(pf->GetParentContext()->GetContext())),
dvander@1096
   152
	  m_pQuery(NULL)
dvander@1096
   153
	{
dvander@1096
   154
		/* We always increase the reference count because this is potentially
dvander@1096
   155
		 * asynchronous.  Otherwise the original handle could be closed while 
dvander@1096
   156
		 * we're still latched onto it.
dvander@1096
   157
		 */
dvander@1096
   158
		m_pDatabase->IncReferenceCount();
dvander@1096
   159
dvander@1096
   160
		/* Now create our own Handle such that it can only be closed by us.
dvander@1096
   161
		 * We allow cloning just in case someone wants to hold onto it.
dvander@1096
   162
		 */
dvander@1096
   163
		HandleSecurity sec(me->GetIdentity(), g_pCoreIdent);
dvander@1096
   164
		HandleAccess access;
dvander@3872
   165
		handlesys->InitAccessDefaults(NULL, &access);
dvander@1096
   166
		access.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY|HANDLE_RESTRICT_OWNER;
dvander@3872
   167
		m_MyHandle = handlesys->CreateHandleEx(g_DBMan.GetDatabaseType(),
dvander@1096
   168
			db,
dvander@1096
   169
			&sec,
dvander@1096
   170
			&access,
dvander@1096
   171
			NULL);
dvander@1096
   172
	}
dvander@1096
   173
	~TQueryOp()
dvander@1096
   174
	{
dvander@1096
   175
		if (m_pQuery)
dvander@1096
   176
		{
dvander@1096
   177
			m_pQuery->Destroy();
dvander@1096
   178
		}
dvander@1096
   179
dvander@1096
   180
		/* Close our Handle if it's valid. */
dvander@1096
   181
		if (m_MyHandle != BAD_HANDLE)
dvander@1096
   182
		{
dvander@1096
   183
			HandleSecurity sec(me->GetIdentity(), g_pCoreIdent);
dvander@3872
   184
			handlesys->FreeHandle(m_MyHandle, &sec);
dvander@1096
   185
		} else {
dvander@1096
   186
			/* Otherwise, there is an open ref to the db */
dvander@1096
   187
			m_pDatabase->Close();
dvander@1096
   188
		}
dvander@1096
   189
	}
dvander@1157
   190
	IdentityToken_t *GetOwner()
dvander@1096
   191
	{
dvander@1157
   192
		return me->GetIdentity();
dvander@1096
   193
	}
dvander@1096
   194
	IDBDriver *GetDriver()
dvander@1096
   195
	{
dvander@1096
   196
		return m_pDatabase->GetDriver();
dvander@1096
   197
	}
dvander@1096
   198
	void RunThreadPart()
dvander@1096
   199
	{
dvander@1096
   200
		m_pDatabase->LockForFullAtomicOperation();
dvander@1096
   201
		m_pQuery = m_pDatabase->DoQuery(m_Query.c_str());
dvander@1096
   202
		if (!m_pQuery)
dvander@1096
   203
		{
skamonkey@4138
   204
			g_pSM->Format(error, sizeof(error), "%s", m_pDatabase->GetError());
dvander@1096
   205
		}
dvander@1096
   206
		m_pDatabase->UnlockFromFullAtomicOperation();
dvander@1096
   207
	}
dvander@1096
   208
	void CancelThinkPart()
dvander@1096
   209
	{
dvander@1096
   210
		m_pFunction->PushCell(BAD_HANDLE);
dvander@1096
   211
		m_pFunction->PushCell(BAD_HANDLE);
dvander@1096
   212
		m_pFunction->PushString("Driver is unloading");
dvander@1096
   213
		m_pFunction->PushCell(m_Data);
dvander@1096
   214
		m_pFunction->Execute(NULL);
dvander@1096
   215
	}
dvander@1096
   216
	void RunThinkPart()
dvander@1096
   217
	{
dvander@1096
   218
		/* Create a Handle for our query */
dvander@1096
   219
		HandleSecurity sec(me->GetIdentity(), g_pCoreIdent);
dvander@1096
   220
		HandleAccess access;
dvander@3872
   221
		handlesys->InitAccessDefaults(NULL, &access);
dvander@1096
   222
		access.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY|HANDLE_RESTRICT_OWNER;
dvander@1096
   223
dvander@1096
   224
		Handle_t qh = BAD_HANDLE;
dvander@1096
   225
		
dvander@1096
   226
		if (m_pQuery)
dvander@1096
   227
		{
john@3271
   228
			CombinedQuery *c = new CombinedQuery;
john@3271
   229
			c->query = m_pQuery;
john@3271
   230
			c->db = m_pDatabase;
john@3271
   231
			
dvander@3872
   232
			qh = handlesys->CreateHandle(hCombinedQueryType, c, me->GetIdentity(), g_pCoreIdent, NULL);
dvander@1096
   233
			if (qh != BAD_HANDLE)
dvander@1096
   234
			{
dvander@1096
   235
				m_pQuery = NULL;
dvander@1096
   236
			} else {
skamonkey@4138
   237
				g_pSM->Format(error, sizeof(error), "Could not alloc handle");
john@3271
   238
				delete c;
dvander@1096
   239
			}
dvander@1096
   240
		}
dvander@1096
   241
dvander@1096
   242
		m_pFunction->PushCell(m_MyHandle);
dvander@1096
   243
		m_pFunction->PushCell(qh);
dvander@1096
   244
		m_pFunction->PushString(qh == BAD_HANDLE ? error : "");
dvander@1096
   245
		m_pFunction->PushCell(m_Data);
dvander@1096
   246
		m_pFunction->Execute(NULL);
dvander@1096
   247
dvander@1096
   248
		if (qh != BAD_HANDLE)
dvander@1096
   249
		{
dvander@3872
   250
			handlesys->FreeHandle(qh, &sec);
dvander@1096
   251
		}
dvander@1157
   252
	}
dvander@1157
   253
	void Destroy()
dvander@1157
   254
	{
dvander@1096
   255
		delete this;
dvander@1096
   256
	}
dvander@1096
   257
private:
dvander@1096
   258
	IDatabase *m_pDatabase;
dvander@1096
   259
	IPluginFunction *m_pFunction;
dvander@1096
   260
	String m_Query;
dvander@1096
   261
	cell_t m_Data;
dvander@3872
   262
	IPlugin *me;
dvander@1096
   263
	IQuery *m_pQuery;
dvander@1096
   264
	char error[255];
dvander@1096
   265
	Handle_t m_MyHandle;
dvander@1096
   266
};
dvander@1096
   267
dvander@1096
   268
class TConnectOp : public IDBThreadOperation
dvander@1096
   269
{
dvander@1096
   270
public:
dvander@1317
   271
	TConnectOp(IPluginFunction *func, IDBDriver *driver, const char *_dbname, cell_t data)
dvander@1096
   272
	{
dvander@1096
   273
		m_pFunction = func;
dvander@1096
   274
		m_pDriver = driver;
dvander@1096
   275
		m_pDatabase = NULL;
dvander@1317
   276
		m_Data = data;
dvander@1096
   277
		error[0] = '\0';
dvander@1096
   278
		strncopy(dbname, _dbname, sizeof(dbname));
dvander@3872
   279
		me = scripts->FindPluginByContext(m_pFunction->GetParentContext()->GetContext());
dvander@1096
   280
	}
dvander@1157
   281
	IdentityToken_t *GetOwner()
dvander@1096
   282
	{
dvander@1157
   283
		return me->GetIdentity();
dvander@1096
   284
	}
dvander@1096
   285
	IDBDriver *GetDriver()
dvander@1096
   286
	{
dvander@1096
   287
		return m_pDriver;
dvander@1096
   288
	}
dvander@1096
   289
	void RunThreadPart()
dvander@1096
   290
	{
dvander@1096
   291
		g_DBMan.LockConfig();
dvander@1096
   292
		const DatabaseInfo *pInfo = g_DBMan.FindDatabaseConf(dbname);
dvander@1096
   293
		if (!pInfo)
dvander@1096
   294
		{
skamonkey@4138
   295
			g_pSM->Format(error, sizeof(error), "Could not find database config \"%s\"", dbname);
dvander@1096
   296
		} else {
dvander@1096
   297
			m_pDatabase = m_pDriver->Connect(pInfo, false, error, sizeof(error));
dvander@1096
   298
		}
dvander@1096
   299
		g_DBMan.UnlockConfig();
dvander@1096
   300
	}
dvander@1096
   301
	void CancelThinkPart()
dvander@1096
   302
	{
dvander@1096
   303
		if (m_pDatabase)
dvander@1096
   304
		{
dvander@1096
   305
			m_pDatabase->Close();
dvander@1096
   306
		}
dvander@1096
   307
		m_pFunction->PushCell(BAD_HANDLE);
dvander@1096
   308
		m_pFunction->PushCell(BAD_HANDLE);
dvander@1096
   309
		m_pFunction->PushString("Driver is unloading");
dvander@1317
   310
		m_pFunction->PushCell(m_Data);
dvander@1096
   311
		m_pFunction->Execute(NULL);
dvander@1096
   312
	}
dvander@1096
   313
	void RunThinkPart()
dvander@1096
   314
	{
dvander@1096
   315
		Handle_t hndl = BAD_HANDLE;
dvander@1096
   316
		
dvander@1096
   317
		if (m_pDatabase)
dvander@1096
   318
		{
dvander@1096
   319
			if ((hndl = g_DBMan.CreateHandle(DBHandle_Database, m_pDatabase, me->GetIdentity()))
dvander@1096
   320
				== BAD_HANDLE)
dvander@1096
   321
			{
dvander@1096
   322
				m_pDatabase->Close();
skamonkey@4138
   323
				g_pSM->Format(error, sizeof(error), "Unable to allocate Handle");
dvander@1096
   324
			}
dvander@1096
   325
		}
dvander@1096
   326
dvander@1096
   327
		m_pFunction->PushCell(m_pDriver->GetHandle());
dvander@1096
   328
		m_pFunction->PushCell(hndl);
dvander@1100
   329
		m_pFunction->PushString(hndl == BAD_HANDLE ? error : "");
dvander@1317
   330
		m_pFunction->PushCell(m_Data);
dvander@1096
   331
		m_pFunction->Execute(NULL);
dvander@1157
   332
	}
dvander@1157
   333
	void Destroy()
dvander@1157
   334
	{
dvander@1096
   335
		delete this;
dvander@1096
   336
	}
dvander@1096
   337
private:
dvander@3872
   338
	IPlugin *me;
dvander@1096
   339
	IPluginFunction *m_pFunction;
dvander@1096
   340
	IDBDriver *m_pDriver;
dvander@1096
   341
	IDatabase *m_pDatabase;
dvander@1096
   342
	char dbname[64];
dvander@1096
   343
	char error[255];
dvander@1317
   344
	cell_t m_Data;
dvander@1096
   345
};
dvander@1096
   346
dvander@868
   347
static cell_t SQL_Connect(IPluginContext *pContext, const cell_t *params)
dvander@868
   348
{
dvander@868
   349
	char *conf, *err;
dvander@868
   350
dvander@868
   351
	size_t maxlength = (size_t)params[4];
dvander@868
   352
	bool persistent = params[2] ? true : false;
dvander@868
   353
	pContext->LocalToString(params[1], &conf);
dvander@868
   354
	pContext->LocalToString(params[3], &err);
dvander@868
   355
	
dvander@868
   356
	IDBDriver *driver;
dvander@868
   357
	IDatabase *db;
dvander@868
   358
	if (!g_DBMan.Connect(conf, &driver, &db, persistent, err, maxlength))
dvander@868
   359
	{
dvander@868
   360
		return BAD_HANDLE;
dvander@868
   361
	}
dvander@868
   362
dvander@875
   363
	Handle_t hndl = g_DBMan.CreateHandle(DBHandle_Database, db, pContext->GetIdentity());
dvander@875
   364
	if (!hndl)
dvander@875
   365
	{
dvander@875
   366
		db->Close();
dvander@875
   367
		return BAD_HANDLE;
dvander@875
   368
	}
dvander@875
   369
dvander@868
   370
	/* HACK! Add us to the dependency list */
skamonkey@4138
   371
	IExtension *pExt = g_Extensions.GetExtensionFromIdent(driver->GetIdentity());
dvander@868
   372
	if (pExt)
dvander@868
   373
	{
skamonkey@4138
   374
		g_Extensions.BindChildPlugin(pExt, scripts->FindPluginByContext(pContext->GetContext()));
dvander@868
   375
	}
dvander@868
   376
dvander@875
   377
	return hndl;
dvander@868
   378
}
dvander@868
   379
dvander@1096
   380
static cell_t SQL_TConnect(IPluginContext *pContext, const cell_t *params)
dvander@1096
   381
{
dvander@1096
   382
	IPluginFunction *pf = pContext->GetFunctionById(params[1]);
dvander@1096
   383
	if (!pf)
dvander@1096
   384
	{
dvander@1096
   385
		return pContext->ThrowNativeError("Function id %x is invalid", params[1]);
dvander@1096
   386
	}
dvander@1096
   387
dvander@1096
   388
	char *conf;
dvander@1096
   389
	pContext->LocalToString(params[2], &conf);
dvander@1096
   390
dvander@1096
   391
	IDBDriver *driver = NULL;
dvander@1096
   392
	const DatabaseInfo *pInfo = g_DBMan.FindDatabaseConf(conf);
dvander@1096
   393
	char error[255];
dvander@1096
   394
	if (pInfo != NULL)
dvander@1096
   395
	{
dvander@1096
   396
		if (pInfo->driver[0] == '\0')
dvander@1096
   397
		{
dvander@1096
   398
			driver = g_DBMan.GetDefaultDriver();
dvander@1096
   399
		} else {
dvander@1096
   400
			driver = g_DBMan.FindOrLoadDriver(pInfo->driver);
dvander@1096
   401
		}
dvander@1096
   402
		if (!driver)
dvander@1096
   403
		{
skamonkey@4138
   404
			g_pSM->Format(error, 
dvander@1096
   405
				sizeof(error), 
dvander@1096
   406
				"Could not find driver \"%s\"", 
dvander@1096
   407
				pInfo->driver[0] == '\0' ? g_DBMan.GetDefaultDriverName() : pInfo->driver);
dvander@1096
   408
		} else if (!driver->IsThreadSafe()) {
skamonkey@4138
   409
			g_pSM->Format(error,
dvander@1096
   410
				sizeof(error),
dvander@1096
   411
				"Driver \"%s\" is not thread safe!",
dvander@1096
   412
				driver->GetIdentifier());
dvander@1096
   413
		}
dvander@1096
   414
	} else {
skamonkey@4138
   415
		g_pSM->Format(error, sizeof(error), "Could not find database conf \"%s\"", conf);
dvander@1096
   416
	}
dvander@1096
   417
dvander@1096
   418
	if (!pInfo || !driver)
dvander@1096
   419
	{
dvander@1096
   420
		pf->PushCell(BAD_HANDLE);
dvander@1096
   421
		pf->PushCell(BAD_HANDLE);
dvander@1096
   422
		pf->PushString(error);
dvander@1096
   423
		pf->PushCell(0);
dvander@1096
   424
		pf->Execute(NULL);
dvander@1096
   425
		return 0;
dvander@1096
   426
	}
dvander@1096
   427
dvander@1096
   428
	/* HACK! Add us to the dependency list */
skamonkey@4138
   429
	IExtension *pExt = g_Extensions.GetExtensionFromIdent(driver->GetIdentity());
dvander@1096
   430
	if (pExt)
dvander@1096
   431
	{
skamonkey@4138
   432
		g_Extensions.BindChildPlugin(pExt, scripts->FindPluginByContext(pContext->GetContext()));
dvander@1096
   433
	}
dvander@1096
   434
dvander@1096
   435
	/* Finally, add to the thread if we can */
dvander@1317
   436
	TConnectOp *op = new TConnectOp(pf, driver, conf, params[3]);
dvander@3872
   437
	IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
dvander@1096
   438
	if (pPlugin->GetProperty("DisallowDBThreads", NULL)
dvander@1096
   439
		|| !g_DBMan.AddToThreadQueue(op, PrioQueue_High))
dvander@1096
   440
	{
dvander@1096
   441
		/* Do everything right now */
dvander@1096
   442
		op->RunThreadPart();
dvander@1096
   443
		op->RunThinkPart();
dvander@1157
   444
		op->Destroy();
dvander@1096
   445
	}
dvander@1096
   446
dvander@1096
   447
	return 1;
dvander@1096
   448
}
dvander@1096
   449
dvander@868
   450
static cell_t SQL_ConnectEx(IPluginContext *pContext, const cell_t *params)
dvander@868
   451
{
dvander@868
   452
	IDBDriver *driver;
dvander@868
   453
	if (params[1] == BAD_HANDLE)
dvander@868
   454
	{
dvander@868
   455
		if ((driver = g_DBMan.GetDefaultDriver()) == NULL)
dvander@868
   456
		{
dvander@868
   457
			return pContext->ThrowNativeError("Could not find any default driver");
dvander@868
   458
		}
dvander@868
   459
	} else {
dvander@868
   460
		HandleError err;
dvander@868
   461
		if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Driver, (void **)&driver))
dvander@868
   462
			!= HandleError_None)
dvander@868
   463
		{
dvander@868
   464
			return pContext->ThrowNativeError("Invalid driver Handle %x (error: %d)", params[1], err);
dvander@868
   465
		}
dvander@868
   466
	}
dvander@868
   467
 
dvander@868
   468
	char *host, *user, *pass, *database, *error;
dvander@868
   469
	size_t maxlength = (size_t)params[7];
dvander@868
   470
	bool persistent = params[8] ? true : false;
dvander@868
   471
	unsigned int port = params[9];
dvander@868
   472
	unsigned int maxTimeout = params[10];
dvander@868
   473
	pContext->LocalToString(params[2], &host);
dvander@868
   474
	pContext->LocalToString(params[3], &user);
dvander@868
   475
	pContext->LocalToString(params[4], &pass);
dvander@868
   476
	pContext->LocalToString(params[5], &database);
dvander@868
   477
	pContext->LocalToString(params[6], &error);
dvander@868
   478
dvander@868
   479
	DatabaseInfo info;
dvander@868
   480
	info.database = database;
dvander@868
   481
	info.driver = driver->GetIdentifier();
dvander@868
   482
	info.host = host;
dvander@868
   483
	info.maxTimeout = maxTimeout;
dvander@868
   484
	info.pass = pass;
dvander@868
   485
	info.port = port;
dvander@868
   486
	info.user = user;
dvander@868
   487
	
dvander@868
   488
	IDatabase *db = driver->Connect(&info, persistent, error, maxlength);
dvander@868
   489
dvander@868
   490
	if (db)
dvander@868
   491
	{
dvander@875
   492
		Handle_t hndl = g_DBMan.CreateHandle(DBHandle_Database, db, pContext->GetIdentity());
dvander@875
   493
		if (!hndl)
dvander@875
   494
		{
dvander@875
   495
			db->Close();
dvander@875
   496
			return BAD_HANDLE;
dvander@875
   497
		}
dvander@875
   498
dvander@868
   499
		/* HACK! Add us to the dependency list */
skamonkey@4138
   500
		IExtension *pExt = g_Extensions.GetExtensionFromIdent(driver->GetIdentity());
dvander@868
   501
		if (pExt)
dvander@868
   502
		{
skamonkey@4138
   503
			g_Extensions.BindChildPlugin(pExt, scripts->FindPluginByContext(pContext->GetContext()));
dvander@868
   504
		}
dvander@868
   505
dvander@875
   506
		return hndl;
dvander@868
   507
	}
dvander@868
   508
	
dvander@868
   509
	return BAD_HANDLE;
dvander@868
   510
}
dvander@868
   511
dvander@868
   512
static cell_t SQL_GetDriverIdent(IPluginContext *pContext, const cell_t *params)
dvander@868
   513
{
dvander@868
   514
	IDBDriver *driver;
dvander@868
   515
	if (params[1] == BAD_HANDLE)
dvander@868
   516
	{
dvander@868
   517
		if ((driver = g_DBMan.GetDefaultDriver()) == NULL)
dvander@868
   518
		{
dvander@868
   519
			return pContext->ThrowNativeError("Could not find any default driver");
dvander@868
   520
		}
dvander@868
   521
	} else {
dvander@868
   522
		HandleError err;
dvander@868
   523
		if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Driver, (void **)&driver))
dvander@868
   524
			!= HandleError_None)
dvander@868
   525
		{
dvander@868
   526
			return pContext->ThrowNativeError("Invalid driver Handle %x (error: %d)", params[1], err);
dvander@868
   527
		}
dvander@868
   528
	}
dvander@868
   529
dvander@868
   530
	pContext->StringToLocalUTF8(params[2], params[3], driver->GetIdentifier(), NULL);
dvander@868
   531
dvander@868
   532
	return 1;
dvander@868
   533
}
dvander@868
   534
dvander@868
   535
static cell_t SQL_GetDriver(IPluginContext *pContext, const cell_t *params)
dvander@868
   536
{
dvander@868
   537
	char *name;
dvander@868
   538
	pContext->LocalToString(params[1], &name);
dvander@868
   539
dvander@868
   540
	IDBDriver *driver = NULL;
dvander@868
   541
	if (name[0] == '\0')
dvander@868
   542
	{
dvander@868
   543
		driver = g_DBMan.GetDefaultDriver();
dvander@868
   544
	} else {
dvander@868
   545
		driver = g_DBMan.FindOrLoadDriver(name);
dvander@868
   546
	}
dvander@868
   547
dvander@868
   548
	return (driver != NULL) ? driver->GetHandle() : BAD_HANDLE;
dvander@868
   549
}
dvander@868
   550
dvander@868
   551
static cell_t SQL_GetDriverProduct(IPluginContext *pContext, const cell_t *params)
dvander@868
   552
{
dvander@868
   553
	IDBDriver *driver;
dvander@868
   554
	if (params[1] == BAD_HANDLE)
dvander@868
   555
	{
dvander@868
   556
		if ((driver = g_DBMan.GetDefaultDriver()) == NULL)
dvander@868
   557
		{
dvander@868
   558
			return pContext->ThrowNativeError("Could not find any default driver");
dvander@868
   559
		}
dvander@868
   560
	} else {
dvander@868
   561
		HandleError err;
dvander@868
   562
		if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Driver, (void **)&driver))
dvander@868
   563
			!= HandleError_None)
dvander@868
   564
		{
dvander@868
   565
			return pContext->ThrowNativeError("Invalid driver Handle %x (error: %d)", params[1], err);
dvander@868
   566
		}
dvander@868
   567
	}
dvander@868
   568
dvander@868
   569
	pContext->StringToLocalUTF8(params[2], params[3], driver->GetProductName(), NULL);
dvander@868
   570
dvander@868
   571
	return 1;
dvander@868
   572
}
dvander@868
   573
dvander@868
   574
static cell_t SQL_GetAffectedRows(IPluginContext *pContext, const cell_t *params)
dvander@868
   575
{
dvander@868
   576
	IDatabase *db = NULL;
dvander@868
   577
	IPreparedQuery *stmt = NULL;
john@3271
   578
	IQuery *query = NULL;
dvander@868
   579
	HandleError err;
dvander@868
   580
john@3271
   581
	if (((err = ReadDbOrStmtHndl(params[1], pContext, &db, &stmt)) != HandleError_None)
john@3271
   582
		&& ((err = ReadQueryAndDbHndl(params[1], pContext, &query, &db)) != HandleError_None))
dvander@868
   583
	{
john@3271
   584
		return pContext->ThrowNativeError("Invalid statement, db, or query Handle %x (error: %d)", params[1], err);
dvander@868
   585
	}
dvander@868
   586
john@3271
   587
john@3271
   588
	if (stmt)
john@3271
   589
	{
john@3271
   590
		return stmt->GetAffectedRows();
john@3271
   591
	}
john@3271
   592
	else if (query)
john@3271
   593
	{
john@3271
   594
		return db->GetAffectedRowsForQuery(query);
john@3271
   595
	}
john@3271
   596
	else if (db)
dvander@868
   597
	{
dvander@868
   598
		return db->GetAffectedRows();
dvander@868
   599
	}
dvander@868
   600
john@3271
   601
	return pContext->ThrowNativeError("Unknown error reading db/stmt/query handles");
dvander@868
   602
}
dvander@868
   603
dvander@868
   604
static cell_t SQL_GetInsertId(IPluginContext *pContext, const cell_t *params)
dvander@868
   605
{
dvander@868
   606
	IDatabase *db = NULL;
john@3271
   607
	IQuery *query = NULL;
dvander@868
   608
	IPreparedQuery *stmt = NULL;
dvander@868
   609
	HandleError err;
dvander@868
   610
john@3271
   611
	if (((err = ReadDbOrStmtHndl(params[1], pContext, &db, &stmt)) != HandleError_None)
john@3271
   612
		&& ((err = ReadQueryAndDbHndl(params[1], pContext, &query, &db)) != HandleError_None))
dvander@868
   613
	{
john@3271
   614
		return pContext->ThrowNativeError("Invalid statement, db, or query Handle %x (error: %d)", params[1], err);
dvander@868
   615
	}
dvander@868
   616
john@3271
   617
	if (query)
john@3271
   618
	{
john@3271
   619
		return db->GetInsertIDForQuery(query);
john@3271
   620
	}
john@3271
   621
	else if (db)
dvander@868
   622
	{
dvander@868
   623
		return db->GetInsertID();
john@3271
   624
	}
john@3271
   625
	else if (stmt)
john@3271
   626
	{
dvander@868
   627
		return stmt->GetInsertID();
dvander@868
   628
	}
dvander@868
   629
john@3271
   630
	return pContext->ThrowNativeError("Unknown error reading db/stmt/query handles");
dvander@868
   631
}
dvander@868
   632
dvander@868
   633
static cell_t SQL_GetError(IPluginContext *pContext, const cell_t *params)
dvander@868
   634
{
dvander@868
   635
	IDatabase *db = NULL;
dvander@868
   636
	IPreparedQuery *stmt = NULL;
dvander@868
   637
	HandleError err;
dvander@868
   638
dvander@868
   639
	if ((err = ReadDbOrStmtHndl(params[1], pContext, &db, &stmt)) != HandleError_None)
dvander@868
   640
	{
dvander@868
   641
		return pContext->ThrowNativeError("Invalid statement or db Handle %x (error: %d)", params[1], err);
dvander@868
   642
	}
dvander@868
   643
dvander@868
   644
	const char *error = "";
dvander@868
   645
	if (db)
dvander@868
   646
	{
dvander@868
   647
		error = db->GetError();
dvander@868
   648
	} else if (stmt) {
dvander@868
   649
		error = stmt->GetError();
dvander@868
   650
	}
dvander@868
   651
dvander@868
   652
	if (error[0] == '\0')
dvander@868
   653
	{
dvander@868
   654
		return false;
dvander@868
   655
	}
dvander@868
   656
dvander@868
   657
	pContext->StringToLocalUTF8(params[2], params[3], error, NULL);
dvander@868
   658
dvander@868
   659
	return 1;
dvander@868
   660
}
dvander@868
   661
dvander@868
   662
static cell_t SQL_QuoteString(IPluginContext *pContext, const cell_t *params)
dvander@868
   663
{
fyrenmoo@3376
   664
	IDatabase *db = NULL;
fyrenmoo@3376
   665
	HandleError err;
dvander@868
   666
fyrenmoo@3376
   667
	if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
dvander@868
   668
		!= HandleError_None)
dvander@868
   669
	{
dvander@868
   670
		return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
dvander@868
   671
	}
dvander@868
   672
dvander@868
   673
	char *input, *output;
fyrenmoo@3376
   674
	size_t maxlength = (size_t)params[4];
dvander@868
   675
	pContext->LocalToString(params[2], &input);
dvander@868
   676
	pContext->LocalToString(params[3], &output);
dvander@868
   677
dvander@868
   678
	size_t written;
fyrenmoo@3376
   679
	bool s = db->QuoteString(input, output, maxlength, &written);
dvander@868
   680
dvander@868
   681
	cell_t *addr;
dvander@868
   682
	pContext->LocalToPhysAddr(params[5], &addr);
dvander@868
   683
	*addr = (cell_t)written;
dvander@868
   684
dvander@868
   685
	return s ? 1 : 0;
dvander@868
   686
}
dvander@868
   687
dvander@868
   688
static cell_t SQL_FastQuery(IPluginContext *pContext, const cell_t *params)
dvander@868
   689
{
dvander@868
   690
	IDatabase *db = NULL;
dvander@868
   691
	HandleError err;
dvander@868
   692
dvander@868
   693
	if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
dvander@868
   694
		!= HandleError_None)
dvander@868
   695
	{
dvander@868
   696
		return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
dvander@868
   697
	}
dvander@868
   698
dvander@868
   699
	char *query;
dvander@868
   700
	pContext->LocalToString(params[2], &query);
dvander@868
   701
dvander@1912
   702
	if (params[0] >= 3 && params[3] != -1)
dvander@1912
   703
	{
dvander@1912
   704
		return db->DoSimpleQueryEx(query, params[3]) ? 1 : 0;
dvander@1912
   705
	}
dvander@1912
   706
dvander@868
   707
	return db->DoSimpleQuery(query) ? 1 : 0;
dvander@868
   708
}
dvander@868
   709
dvander@868
   710
static cell_t SQL_Query(IPluginContext *pContext, const cell_t *params)
dvander@868
   711
{
dvander@868
   712
	IDatabase *db = NULL;
dvander@868
   713
	HandleError err;
dvander@868
   714
dvander@868
   715
	if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
dvander@868
   716
		!= HandleError_None)
dvander@868
   717
	{
dvander@868
   718
		return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
dvander@868
   719
	}
dvander@868
   720
dvander@868
   721
	char *query;
dvander@868
   722
	pContext->LocalToString(params[2], &query);
dvander@868
   723
dvander@1912
   724
	IQuery *qr;
dvander@1912
   725
	
dvander@1912
   726
	if (params[0] >= 3 && params[3] != -1)
dvander@1912
   727
	{
dvander@1912
   728
		qr = db->DoQueryEx(query, params[3]);
dvander@1912
   729
	}
dvander@1912
   730
	else
dvander@1912
   731
	{
dvander@1912
   732
		qr = db->DoQuery(query);
dvander@1912
   733
	}
dvander@868
   734
dvander@868
   735
	if (!qr)
dvander@868
   736
	{
dvander@868
   737
		return BAD_HANDLE;
dvander@868
   738
	}
dvander@868
   739
john@3271
   740
	CombinedQuery *c = new CombinedQuery;
john@3271
   741
	c->query = qr;
john@3271
   742
	c->db = db;
dvander@3872
   743
	Handle_t hndl = handlesys->CreateHandle(hCombinedQueryType, c, pContext->GetIdentity(), g_pCoreIdent, NULL);
dvander@868
   744
	if (hndl == BAD_HANDLE)
dvander@868
   745
	{
dvander@868
   746
		qr->Destroy();
john@3271
   747
		delete c;
dvander@868
   748
		return BAD_HANDLE;
dvander@868
   749
	}
dvander@868
   750
dvander@868
   751
	return hndl;
dvander@868
   752
}
dvander@868
   753
dvander@1096
   754
static cell_t SQL_TQuery(IPluginContext *pContext, const cell_t *params)
dvander@1096
   755
{
dvander@1096
   756
	IDatabase *db = NULL;
dvander@1096
   757
	HandleError err;
dvander@1096
   758
dvander@1096
   759
	if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
dvander@1096
   760
		!= HandleError_None)
dvander@1096
   761
	{
dvander@1096
   762
		return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
dvander@1096
   763
	}
dvander@1096
   764
dvander@1101
   765
	if (!db->GetDriver()->IsThreadSafe())
dvander@1101
   766
	{
dvander@1101
   767
		return pContext->ThrowNativeError("Driver \"%s\" is not thread safe!", db->GetDriver()->GetIdentifier());
dvander@1101
   768
	}
dvander@1101
   769
dvander@1096
   770
	IPluginFunction *pf = pContext->GetFunctionById(params[2]);
dvander@1096
   771
	if (!pf)
dvander@1096
   772
	{
dvander@1096
   773
		return pContext->ThrowNativeError("Function id %x is invalid", params[2]);
dvander@1096
   774
	}
dvander@1096
   775
dvander@1096
   776
	char *query;
dvander@1096
   777
	pContext->LocalToString(params[3], &query);
dvander@1096
   778
dvander@1096
   779
	cell_t data = params[4];
dvander@1096
   780
	PrioQueueLevel level = PrioQueue_Normal;
dvander@1096
   781
	if (params[5] == (cell_t)PrioQueue_High)
dvander@1096
   782
	{
dvander@1096
   783
		level = PrioQueue_High;
dvander@1096
   784
	} else if (params[5] == (cell_t)PrioQueue_Low) {
dvander@1096
   785
		level = PrioQueue_Low;
dvander@1096
   786
	}
dvander@1096
   787
dvander@3872
   788
	IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
dvander@1096
   789
dvander@1096
   790
	TQueryOp *op = new TQueryOp(db, pf, query, data);
dvander@1096
   791
	if (pPlugin->GetProperty("DisallowDBThreads", NULL)
dvander@1096
   792
		|| !g_DBMan.AddToThreadQueue(op, level))
dvander@1096
   793
	{
dvander@1096
   794
		/* Do everything right now */
dvander@1096
   795
		op->RunThreadPart();
dvander@1096
   796
		op->RunThinkPart();
dvander@1157
   797
		op->Destroy();
dvander@1096
   798
	}
dvander@1096
   799
dvander@1096
   800
	return 1;
dvander@1096
   801
}
dvander@1096
   802
dvander@1096
   803
static cell_t SQL_LockDatabase(IPluginContext *pContext, const cell_t *params)
dvander@1096
   804
{
dvander@1096
   805
	IDatabase *db = NULL;
dvander@1096
   806
	HandleError err;
dvander@1096
   807
dvander@1096
   808
	if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
dvander@1096
   809
		!= HandleError_None)
dvander@1096
   810
	{
dvander@1096
   811
		return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
dvander@1096
   812
	}
dvander@1096
   813
dvander@1096
   814
	db->LockForFullAtomicOperation();
dvander@1096
   815
dvander@1096
   816
	return 1;
dvander@1096
   817
}
dvander@1096
   818
dvander@1096
   819
static cell_t SQL_UnlockDatabase(IPluginContext *pContext, const cell_t *params)
dvander@1096
   820
{
dvander@1096
   821
	IDatabase *db = NULL;
dvander@1096
   822
	HandleError err;
dvander@1096
   823
dvander@1096
   824
	if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
dvander@1096
   825
		!= HandleError_None)
dvander@1096
   826
	{
dvander@1096
   827
		return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
dvander@1096
   828
	}
dvander@1096
   829
dvander@1096
   830
	db->UnlockFromFullAtomicOperation();
dvander@1096
   831
dvander@1096
   832
	return 1;
dvander@1096
   833
}
dvander@1096
   834
dvander@868
   835
static cell_t SQL_PrepareQuery(IPluginContext *pContext, const cell_t *params)
dvander@868
   836
{
dvander@868
   837
	IDatabase *db = NULL;
dvander@868
   838
	HandleError err;
dvander@868
   839
dvander@868
   840
	if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
dvander@868
   841
		!= HandleError_None)
dvander@868
   842
	{
dvander@868
   843
		return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
dvander@868
   844
	}
dvander@868
   845
dvander@868
   846
	char *query, *error;
dvander@868
   847
	size_t maxlength = (size_t)params[4];
dvander@868
   848
	pContext->LocalToString(params[2], &query);
dvander@868
   849
	pContext->LocalToString(params[3], &error);
dvander@868
   850
dvander@868
   851
	IPreparedQuery *qr = db->PrepareQuery(query, error, maxlength);
dvander@868
   852
dvander@868
   853
	if (!qr)
dvander@868
   854
	{
dvander@868
   855
		return BAD_HANDLE;
dvander@868
   856
	}
dvander@868
   857
dvander@3872
   858
	Handle_t hndl = handlesys->CreateHandle(hStmtType, qr, pContext->GetIdentity(), g_pCoreIdent, NULL);
dvander@868
   859
	if (hndl == BAD_HANDLE)
dvander@868
   860
	{
dvander@868
   861
		qr->Destroy();
dvander@868
   862
		return BAD_HANDLE;
dvander@868
   863
	}
dvander@868
   864
dvander@868
   865
	return hndl;
dvander@868
   866
}
dvander@868
   867
dvander@868
   868
static cell_t SQL_FetchMoreResults(IPluginContext *pContext, const cell_t *params)
dvander@868
   869
{
dvander@868
   870
	IQuery *query;
dvander@868
   871
	HandleError err;
dvander@868
   872
dvander@868
   873
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
   874
	{
dvander@868
   875
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
   876
	}
dvander@868
   877
dvander@868
   878
	return query->FetchMoreResults() ? 1 : 0;
dvander@868
   879
}
dvander@868
   880
dvander@868
   881
static cell_t SQL_HasResultSet(IPluginContext *pContext, const cell_t *params)
dvander@868
   882
{
dvander@868
   883
	IQuery *query;
dvander@868
   884
	HandleError err;
dvander@868
   885
dvander@868
   886
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
   887
	{
dvander@868
   888
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
   889
	}
dvander@868
   890
dvander@868
   891
	return query->GetResultSet() != NULL ? true : false;
dvander@868
   892
}
dvander@868
   893
dvander@868
   894
static cell_t SQL_GetRowCount(IPluginContext *pContext, const cell_t *params)
dvander@868
   895
{
dvander@868
   896
	IQuery *query;
dvander@868
   897
	HandleError err;
dvander@868
   898
dvander@868
   899
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
   900
	{
dvander@868
   901
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
   902
	}
dvander@868
   903
dvander@868
   904
	IResultSet *rs = query->GetResultSet();
dvander@868
   905
	if (!rs)
dvander@868
   906
	{
dvander@868
   907
		return 0;
dvander@868
   908
	}
dvander@868
   909
dvander@868
   910
	return rs->GetRowCount();
dvander@868
   911
}
dvander@868
   912
dvander@868
   913
static cell_t SQL_GetFieldCount(IPluginContext *pContext, const cell_t *params)
dvander@868
   914
{
dvander@868
   915
	IQuery *query;
dvander@868
   916
	HandleError err;
dvander@868
   917
dvander@868
   918
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
   919
	{
dvander@868
   920
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
   921
	}
dvander@868
   922
dvander@868
   923
	IResultSet *rs = query->GetResultSet();
dvander@868
   924
	if (!rs)
dvander@868
   925
	{
dvander@868
   926
		return 0;
dvander@868
   927
	}
dvander@868
   928
dvander@868
   929
	return rs->GetFieldCount();
dvander@868
   930
}
dvander@868
   931
dvander@868
   932
static cell_t SQL_FieldNumToName(IPluginContext *pContext, const cell_t *params)
dvander@868
   933
{
dvander@868
   934
	IQuery *query;
dvander@868
   935
	HandleError err;
dvander@868
   936
dvander@868
   937
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
   938
	{
dvander@868
   939
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
   940
	}
dvander@868
   941
dvander@868
   942
	IResultSet *rs = query->GetResultSet();
dvander@868
   943
	if (!rs)
dvander@868
   944
	{
dvander@868
   945
		return pContext->ThrowNativeError("No current result set");
dvander@868
   946
	}
dvander@868
   947
dvander@868
   948
	unsigned int field = params[2];
dvander@868
   949
dvander@868
   950
	const char *fldname;
dvander@868
   951
	if ((fldname = rs->FieldNumToName(field)) == NULL)
dvander@868
   952
	{
dvander@868
   953
		return pContext->ThrowNativeError("Invalid field index %d", field);
dvander@868
   954
	}
dvander@868
   955
dvander@868
   956
	pContext->StringToLocalUTF8(params[3], params[4], fldname, NULL);
dvander@868
   957
dvander@868
   958
	return 1;
dvander@868
   959
}
dvander@868
   960
dvander@868
   961
static cell_t SQL_FieldNameToNum(IPluginContext *pContext, const cell_t *params)
dvander@868
   962
{
dvander@868
   963
	IQuery *query;
dvander@868
   964
	HandleError err;
dvander@868
   965
dvander@868
   966
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
   967
	{
dvander@868
   968
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
   969
	}
dvander@868
   970
dvander@868
   971
	IResultSet *rs = query->GetResultSet();
dvander@868
   972
	if (!rs)
dvander@868
   973
	{
dvander@868
   974
		return pContext->ThrowNativeError("No current result set");
dvander@868
   975
	}
dvander@868
   976
dvander@868
   977
	char *field;
dvander@868
   978
	pContext->LocalToString(params[2], &field);
dvander@868
   979
dvander@868
   980
	cell_t *num;
dvander@868
   981
	pContext->LocalToPhysAddr(params[3], &num);
dvander@868
   982
dvander@868
   983
	return rs->FieldNameToNum(field, (unsigned int *)num) ? 1 : 0;
dvander@868
   984
}
dvander@868
   985
dvander@868
   986
static cell_t SQL_FetchRow(IPluginContext *pContext, const cell_t *params)
dvander@868
   987
{
dvander@868
   988
	IQuery *query;
dvander@868
   989
	HandleError err;
dvander@868
   990
dvander@868
   991
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
   992
	{
dvander@868
   993
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
   994
	}
dvander@868
   995
dvander@868
   996
	IResultSet *rs = query->GetResultSet();
dvander@868
   997
	if (!rs)
dvander@868
   998
	{
dvander@868
   999
		return pContext->ThrowNativeError("No current result set");
dvander@868
  1000
	}
dvander@868
  1001
dvander@868
  1002
	return (rs->FetchRow() != NULL) ? true : false;
dvander@868
  1003
}
dvander@868
  1004
dvander@868
  1005
static cell_t SQL_MoreRows(IPluginContext *pContext, const cell_t *params)
dvander@868
  1006
{
dvander@868
  1007
	IQuery *query;
dvander@868
  1008
	HandleError err;
dvander@868
  1009
dvander@868
  1010
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
  1011
	{
dvander@868
  1012
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
  1013
	}
dvander@868
  1014
dvander@868
  1015
	IResultSet *rs = query->GetResultSet();
dvander@868
  1016
	if (!rs)
dvander@868
  1017
	{
dvander@868
  1018
		return pContext->ThrowNativeError("No current result set");
dvander@868
  1019
	}
dvander@868
  1020
dvander@868
  1021
	return rs->MoreRows() ? 1 : 0;
dvander@868
  1022
}
dvander@868
  1023
dvander@868
  1024
static cell_t SQL_Rewind(IPluginContext *pContext, const cell_t *params)
dvander@868
  1025
{
dvander@868
  1026
	IQuery *query;
dvander@868
  1027
	HandleError err;
dvander@868
  1028
dvander@868
  1029
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
  1030
	{
dvander@868
  1031
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
  1032
	}
dvander@868
  1033
dvander@868
  1034
	IResultSet *rs = query->GetResultSet();
dvander@868
  1035
	if (!rs)
dvander@868
  1036
	{
dvander@868
  1037
		return pContext->ThrowNativeError("No current result set");
dvander@868
  1038
	}
dvander@868
  1039
dvander@868
  1040
	return rs->Rewind() ? 1 : 0;
dvander@868
  1041
}
dvander@868
  1042
dvander@868
  1043
static cell_t SQL_FetchString(IPluginContext *pContext, const cell_t *params)
dvander@868
  1044
{
dvander@868
  1045
	IQuery *query;
dvander@868
  1046
	HandleError err;
dvander@868
  1047
dvander@868
  1048
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
  1049
	{
dvander@868
  1050
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
  1051
	}
dvander@868
  1052
dvander@868
  1053
	IResultSet *rs = query->GetResultSet();
dvander@868
  1054
	if (!rs)
dvander@868
  1055
	{
dvander@868
  1056
		return pContext->ThrowNativeError("No current result set");
dvander@868
  1057
	}
dvander@868
  1058
dvander@868
  1059
	IResultRow *row = rs->CurrentRow();
dvander@868
  1060
	if (!row)
dvander@868
  1061
	{
dvander@868
  1062
		return pContext->ThrowNativeError("Current result set has no fetched rows");
dvander@868
  1063
	}
dvander@868
  1064
dvander@868
  1065
	const char *str;
dvander@868
  1066
	size_t length;
dvander@868
  1067
	DBResult res = row->GetString(params[2], &str, &length);
dvander@868
  1068
dvander@868
  1069
	if (res == DBVal_Error)
dvander@868
  1070
	{
dvander@868
  1071
		return pContext->ThrowNativeError("Error fetching data from field %d", params[2]);
dvander@868
  1072
	} else if (res == DBVal_TypeMismatch) {
dvander@868
  1073
		return pContext->ThrowNativeError("Could not fetch data in field %d as a string", params[2]);
dvander@868
  1074
	}
dvander@868
  1075
dvander@868
  1076
	pContext->StringToLocalUTF8(params[3], params[4], str, &length);
dvander@868
  1077
dvander@868
  1078
	cell_t *addr;
dvander@868
  1079
	pContext->LocalToPhysAddr(params[5], &addr);
dvander@868
  1080
	*addr = (cell_t)res;
dvander@868
  1081
dvander@868
  1082
	return (cell_t)length;
dvander@868
  1083
}
dvander@868
  1084
dvander@868
  1085
static cell_t SQL_FetchFloat(IPluginContext *pContext, const cell_t *params)
dvander@868
  1086
{
dvander@868
  1087
	IQuery *query;
dvander@868
  1088
	HandleError err;
dvander@868
  1089
dvander@868
  1090
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
  1091
	{
dvander@868
  1092
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
  1093
	}
dvander@868
  1094
dvander@868
  1095
	IResultSet *rs = query->GetResultSet();
dvander@868
  1096
	if (!rs)
dvander@868
  1097
	{
dvander@868
  1098
		return pContext->ThrowNativeError("No current result set");
dvander@868
  1099
	}
dvander@868
  1100
dvander@868
  1101
	IResultRow *row = rs->CurrentRow();
dvander@868
  1102
	if (!row)
dvander@868
  1103
	{
dvander@868
  1104
		return pContext->ThrowNativeError("Current result set has no fetched rows");
dvander@868
  1105
	}
dvander@868
  1106
dvander@868
  1107
	float f;
dvander@868
  1108
	DBResult res = row->GetFloat(params[2], &f);
dvander@868
  1109
dvander@868
  1110
	if (res == DBVal_Error)
dvander@868
  1111
	{
dvander@868
  1112
		return pContext->ThrowNativeError("Error fetching data from field %d", params[2]);
dvander@868
  1113
	} else if (res == DBVal_TypeMismatch) {
dvander@868
  1114
		return pContext->ThrowNativeError("Could not fetch data in field %d as a float", params[2]);
dvander@868
  1115
	}
dvander@868
  1116
dvander@868
  1117
	cell_t *addr;
dvander@1025
  1118
	pContext->LocalToPhysAddr(params[3], &addr);
dvander@868
  1119
	*addr = (cell_t)res;
dvander@868
  1120
dvander@868
  1121
	return sp_ftoc(f);
dvander@868
  1122
}
dvander@868
  1123
dvander@868
  1124
static cell_t SQL_FetchInt(IPluginContext *pContext, const cell_t *params)
dvander@868
  1125
{
dvander@868
  1126
	IQuery *query;
dvander@868
  1127
	HandleError err;
dvander@868
  1128
dvander@868
  1129
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
  1130
	{
dvander@868
  1131
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
  1132
	}
dvander@868
  1133
dvander@868
  1134
	IResultSet *rs = query->GetResultSet();
dvander@868
  1135
	if (!rs)
dvander@868
  1136
	{
dvander@868
  1137
		return pContext->ThrowNativeError("No current result set");
dvander@868
  1138
	}
dvander@868
  1139
dvander@868
  1140
	IResultRow *row = rs->CurrentRow();
dvander@868
  1141
	if (!row)
dvander@868
  1142
	{
dvander@868
  1143
		return pContext->ThrowNativeError("Current result set has no fetched rows");
dvander@868
  1144
	}
dvander@868
  1145
dvander@868
  1146
	int iv;
dvander@868
  1147
	DBResult res = row->GetInt(params[2], &iv);
dvander@868
  1148
dvander@868
  1149
	if (res == DBVal_Error)
dvander@868
  1150
	{
dvander@868
  1151
		return pContext->ThrowNativeError("Error fetching data from field %d", params[2]);
dvander@868
  1152
	} else if (res == DBVal_TypeMismatch) {
dvander@868
  1153
		return pContext->ThrowNativeError("Could not fetch data in field %d as an integer", params[2]);
dvander@868
  1154
	}
dvander@868
  1155
dvander@868
  1156
	cell_t *addr;
dvander@1025
  1157
	pContext->LocalToPhysAddr(params[3], &addr);
dvander@868
  1158
	*addr = (cell_t)res;
dvander@868
  1159
dvander@868
  1160
	return iv;
dvander@868
  1161
}
dvander@868
  1162
dvander@868
  1163
static cell_t SQL_IsFieldNull(IPluginContext *pContext, const cell_t *params)
dvander@868
  1164
{
dvander@868
  1165
	IQuery *query;
dvander@868
  1166
	HandleError err;
dvander@868
  1167
dvander@868
  1168
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
  1169
	{
dvander@868
  1170
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
  1171
	}
dvander@868
  1172
dvander@868
  1173
	IResultSet *rs = query->GetResultSet();
dvander@868
  1174
	if (!rs)
dvander@868
  1175
	{
dvander@868
  1176
		return pContext->ThrowNativeError("No current result set");
dvander@868
  1177
	}
dvander@868
  1178
dvander@868
  1179
	IResultRow *row = rs->CurrentRow();
dvander@868
  1180
	if (!row)
dvander@868
  1181
	{
dvander@868
  1182
		return pContext->ThrowNativeError("Current result set has no fetched rows");
dvander@868
  1183
	}
dvander@868
  1184
dvander@868
  1185
	if ((unsigned)params[2] >= rs->GetFieldCount())
dvander@868
  1186
	{
dvander@868
  1187
		return pContext->ThrowNativeError("Invalid field index %d", params[2]);
dvander@868
  1188
	}
dvander@868
  1189
dvander@868
  1190
	return row->IsNull(params[2]) ? 1 : 0;
dvander@868
  1191
}
dvander@868
  1192
dvander@868
  1193
static cell_t SQL_FetchSize(IPluginContext *pContext, const cell_t *params)
dvander@868
  1194
{
dvander@868
  1195
	IQuery *query;
dvander@868
  1196
	HandleError err;
dvander@868
  1197
dvander@868
  1198
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
  1199
	{
dvander@868
  1200
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
  1201
	}
dvander@868
  1202
dvander@868
  1203
	IResultSet *rs = query->GetResultSet();
dvander@868
  1204
	if (!rs)
dvander@868
  1205
	{
dvander@868
  1206
		return pContext->ThrowNativeError("No current result set");
dvander@868
  1207
	}
dvander@868
  1208
dvander@868
  1209
	IResultRow *row = rs->CurrentRow();
dvander@868
  1210
	if (!row)
dvander@868
  1211
	{
dvander@868
  1212
		return pContext->ThrowNativeError("Current result set has no fetched rows");
dvander@868
  1213
	}
dvander@868
  1214
dvander@868
  1215
	if ((unsigned)params[2] >= rs->GetFieldCount())
dvander@868
  1216
	{
dvander@868
  1217
		return pContext->ThrowNativeError("Invalid field index %d", params[2]);
dvander@868
  1218
	}
dvander@868
  1219
dvander@868
  1220
	return row->GetDataSize(params[2]);
dvander@868
  1221
}
dvander@868
  1222
dvander@868
  1223
static cell_t SQL_BindParamInt(IPluginContext *pContext, const cell_t *params)
dvander@868
  1224
{
dvander@868
  1225
	IPreparedQuery *stmt;
dvander@868
  1226
	HandleError err;
dvander@868
  1227
dvander@868
  1228
	if ((err = ReadStmtHndl(params[1], pContext, &stmt)) != HandleError_None)
dvander@868
  1229
	{
dvander@868
  1230
		return pContext->ThrowNativeError("Invalid statement Handle %x (error: %d)", params[1], err);
dvander@868
  1231
	}
dvander@868
  1232
dvander@868
  1233
	if (!stmt->BindParamInt(params[2], params[3], params[4] ? true : false))
dvander@868
  1234
	{
dvander@868
  1235
		return pContext->ThrowNativeError("Could not bind parameter %d as an integer", params[2]);
dvander@868
  1236
	}
dvander@868
  1237
dvander@868
  1238
	return 1;
dvander@868
  1239
}
dvander@868
  1240
dvander@868
  1241
static cell_t SQL_BindParamFloat(IPluginContext *pContext, const cell_t *params)
dvander@868
  1242
{
dvander@868
  1243
	IPreparedQuery *stmt;
dvander@868
  1244
	HandleError err;
dvander@868
  1245
dvander@868
  1246
	if ((err = ReadStmtHndl(params[1], pContext, &stmt)) != HandleError_None)
dvander@868
  1247
	{
dvander@868
  1248
		return pContext->ThrowNativeError("Invalid statement Handle %x (error: %d)", params[1], err);
dvander@868
  1249
	}
dvander@868
  1250
dvander@868
  1251
	if (!stmt->BindParamFloat(params[2], sp_ctof(params[3])))
dvander@868
  1252
	{
dvander@868
  1253
		return pContext->ThrowNativeError("Could not bind parameter %d as a float", params[2]);
dvander@868
  1254
	}
dvander@868
  1255
dvander@868
  1256
	return 1;
dvander@868
  1257
}
dvander@868
  1258
dvander@868
  1259
static cell_t SQL_BindParamString(IPluginContext *pContext, const cell_t *params)
dvander@868
  1260
{
dvander@868
  1261
	IPreparedQuery *stmt;
dvander@868
  1262
	HandleError err;
dvander@868
  1263
dvander@868
  1264
	if ((err = ReadStmtHndl(params[1], pContext, &stmt)) != HandleError_None)
dvander@868
  1265
	{
dvander@868
  1266
		return pContext->ThrowNativeError("Invalid statement Handle %x (error: %d)", params[1], err);
dvander@868
  1267
	}
dvander@868
  1268
dvander@868
  1269
	char *str;
dvander@868
  1270
	pContext->LocalToString(params[3], &str);
dvander@868
  1271
dvander@868
  1272
	if (!stmt->BindParamString(params[2], str, params[4] ? true : false))
dvander@868
  1273
	{
dvander@868
  1274
		return pContext->ThrowNativeError("Could not bind parameter %d as a string", params[2]);
dvander@868
  1275
	}
dvander@868
  1276
dvander@868
  1277
	return 1;
dvander@868
  1278
}
dvander@868
  1279
dvander@868
  1280
static cell_t SQL_Execute(IPluginContext *pContext, const cell_t *params)
dvander@868
  1281
{
dvander@868
  1282
	IPreparedQuery *stmt;
dvander@868
  1283
	HandleError err;
dvander@868
  1284
dvander@868
  1285
	if ((err = ReadStmtHndl(params[1], pContext, &stmt)) != HandleError_None)
dvander@868
  1286
	{
dvander@868
  1287
		return pContext->ThrowNativeError("Invalid statement Handle %x (error: %d)", params[1], err);
dvander@868
  1288
	}
dvander@868
  1289
dvander@868
  1290
	return stmt->Execute() ? 1 : 0;
dvander@868
  1291
}
dvander@868
  1292
dvander@1096
  1293
static cell_t SQL_IsSameConnection(IPluginContext *pContext, const cell_t *params)
dvander@1096
  1294
{
dvander@1096
  1295
	IDatabase *db1=NULL, *db2=NULL;
dvander@1096
  1296
	HandleError err;
dvander@1096
  1297
dvander@1096
  1298
	if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db1))
dvander@1096
  1299
		!= HandleError_None)
dvander@1096
  1300
	{
dvander@1096
  1301
		return pContext->ThrowNativeError("Invalid database Handle 1/%x (error: %d)", params[1], err);
dvander@1096
  1302
	}
dvander@1096
  1303
dvander@1096
  1304
	if ((err = g_DBMan.ReadHandle(params[2], DBHandle_Database, (void **)&db2))
dvander@1096
  1305
		!= HandleError_None)
dvander@1096
  1306
	{
dvander@1096
  1307
		return pContext->ThrowNativeError("Invalid database Handle 2/%x (error: %d)", params[2], err);
dvander@1096
  1308
	}
dvander@1096
  1309
dvander@1096
  1310
	return (db1 == db2) ? true : false;
dvander@1096
  1311
}
dvander@1096
  1312
dvander@1294
  1313
static cell_t SQL_ReadDriver(IPluginContext *pContext, const cell_t *params)
dvander@1294
  1314
{
dvander@1294
  1315
	IDatabase *db1=NULL;
dvander@1294
  1316
	HandleError err;
dvander@1294
  1317
dvander@1294
  1318
	if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db1))
dvander@1294
  1319
		!= HandleError_None)
dvander@1294
  1320
	{
dvander@1294
  1321
		return pContext->ThrowNativeError("Invalid database Handle 1/%x (error: %d)", params[1], err);
dvander@1294
  1322
	}
dvander@1294
  1323
dvander@1294
  1324
	IDBDriver *driver = db1->GetDriver();
dvander@1294
  1325
dvander@1294
  1326
	pContext->StringToLocalUTF8(params[2], params[3], driver->GetIdentifier(), NULL);
dvander@1294
  1327
dvander@1294
  1328
	return driver->GetHandle();
dvander@1294
  1329
}
dvander@1294
  1330
dvander@1324
  1331
static cell_t SQL_CheckConfig(IPluginContext *pContext, const cell_t *params)
dvander@1324
  1332
{
dvander@1324
  1333
	char *name;
dvander@1324
  1334
	pContext->LocalToString(params[1], &name);
dvander@1324
  1335
dvander@1324
  1336
	return (g_DBMan.FindDatabaseConf(name) != NULL) ? 1 : 0;
dvander@1324
  1337
}
dvander@1324
  1338
dvander@2357
  1339
static cell_t SQL_ConnectCustom(IPluginContext *pContext, const cell_t *params)
dvander@2357
  1340
{
dvander@2357
  1341
	KeyValues *kv;
dvander@2357
  1342
	HandleError err;
dvander@2357
  1343
skamonkey@4138
  1344
	kv = g_pSM->ReadKeyValuesHandle(params[1], &err, false);
dvander@2357
  1345
	if (kv == NULL)
dvander@2357
  1346
	{
dvander@2357
  1347
		return pContext->ThrowNativeError("Invalid KeyValues handle %x (error: %d)",
dvander@2357
  1348
										  params[1],
dvander@2357
  1349
										  err);
dvander@2357
  1350
	}
dvander@2357
  1351
skamonkey@4138
  1352
	DatabaseInfo info = smcore.GetDBInfoFromKeyValues(kv);
dvander@2357
  1353
dvander@2357
  1354
	IDBDriver *driver;
dvander@2357
  1355
	if (info.driver[0] == '\0' || strcmp(info.driver, "default") == 0)
dvander@2357
  1356
	{
dvander@2357
  1357
		driver = g_DBMan.GetDefaultDriver();
dvander@2357
  1358
	}
dvander@2357
  1359
	else
dvander@2357
  1360
	{
dvander@2357
  1361
		driver = g_DBMan.FindOrLoadDriver(info.driver);
dvander@2357
  1362
	}
dvander@2357
  1363
dvander@2357
  1364
	if (driver == NULL)
dvander@2357
  1365
	{
dvander@2357
  1366
		char buffer[255];
dvander@2357
  1367
skamonkey@4138
  1368
		g_pSM->Format(buffer, sizeof(buffer), "Could not find driver \"%s\"", info.driver);
dvander@2357
  1369
		pContext->StringToLocalUTF8(params[2], params[3], buffer, NULL);
dvander@2357
  1370
dvander@2357
  1371
		return BAD_HANDLE;
dvander@2357
  1372
	}
dvander@2357
  1373
dvander@2357
  1374
	char *buffer;
dvander@2357
  1375
	IDatabase *db;
dvander@2357
  1376
dvander@2357
  1377
	pContext->LocalToString(params[2], &buffer);
dvander@2357
  1378
	
dvander@2357
  1379
	db = driver->Connect(&info, params[4] ? true : false, buffer, params[3]);
dvander@2357
  1380
	if (db == NULL)
dvander@2357
  1381
	{
dvander@2357
  1382
		return BAD_HANDLE;
dvander@2357
  1383
	}
dvander@2357
  1384
dvander@2357
  1385
	Handle_t hndl = g_DBMan.CreateHandle(DBHandle_Database, db, pContext->GetIdentity());
dvander@2357
  1386
	if (!hndl)
dvander@2357
  1387
	{
dvander@2357
  1388
		db->Close();
dvander@2357
  1389
		return pContext->ThrowNativeError("Out of handles!");
dvander@2357
  1390
	}
dvander@2357
  1391
dvander@2357
  1392
	/* HACK! Add us to the dependency list */
skamonkey@4138
  1393
	IExtension *pExt = g_Extensions.GetExtensionFromIdent(driver->GetIdentity());
dvander@2357
  1394
	if (pExt)
dvander@2357
  1395
	{
skamonkey@4138
  1396
		g_Extensions.BindChildPlugin(pExt, scripts->FindPluginByContext(pContext->GetContext()));
dvander@2357
  1397
	}
dvander@2357
  1398
dvander@2357
  1399
	return hndl;
dvander@2357
  1400
}
dvander@2357
  1401
januk@3947
  1402
static cell_t SQL_SetCharset(IPluginContext *pContext, const cell_t *params)
januk@3947
  1403
{
januk@3947
  1404
	IDatabase *db = NULL;
januk@3947
  1405
	HandleError err;
januk@3947
  1406
januk@3947
  1407
	if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
januk@3947
  1408
		!= HandleError_None)
januk@3947
  1409
	{
januk@3947
  1410
		return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
januk@3947
  1411
	}
januk@3947
  1412
januk@3947
  1413
	char *characterset;
januk@3947
  1414
	pContext->LocalToString(params[2], &characterset);
januk@3947
  1415
januk@3947
  1416
	return db->SetCharacterSet(characterset);
januk@3947
  1417
}
januk@3947
  1418
dvander@868
  1419
REGISTER_NATIVES(dbNatives)
dvander@868
  1420
{
dvander@868
  1421
	{"SQL_BindParamInt",		SQL_BindParamInt},
dvander@868
  1422
	{"SQL_BindParamFloat",		SQL_BindParamFloat},
dvander@1324
  1423
	{"SQL_BindParamString",		SQL_BindParamString},\
dvander@1324
  1424
	{"SQL_CheckConfig",			SQL_CheckConfig},
dvander@868
  1425
	{"SQL_Connect",				SQL_Connect},
dvander@868
  1426
	{"SQL_ConnectEx",			SQL_ConnectEx},
dvander@1874
  1427
	{"SQL_EscapeString",		SQL_QuoteString},
dvander@868
  1428
	{"SQL_Execute",				SQL_Execute},
dvander@868
  1429
	{"SQL_FastQuery",			SQL_FastQuery},
dvander@868
  1430
	{"SQL_FetchFloat",			SQL_FetchFloat},
dvander@868
  1431
	{"SQL_FetchInt",			SQL_FetchInt},
dvander@868
  1432
	{"SQL_FetchMoreResults",	SQL_FetchMoreResults},
dvander@868
  1433
	{"SQL_FetchRow",			SQL_FetchRow},
dvander@868
  1434
	{"SQL_FetchSize",			SQL_FetchSize},
dvander@868
  1435
	{"SQL_FetchString",			SQL_FetchString},
dvander@868
  1436
	{"SQL_FieldNameToNum",		SQL_FieldNameToNum},
dvander@868
  1437
	{"SQL_FieldNumToName",		SQL_FieldNumToName},
dvander@868
  1438
	{"SQL_GetAffectedRows",		SQL_GetAffectedRows},
dvander@868
  1439
	{"SQL_GetDriver",			SQL_GetDriver},
dvander@868
  1440
	{"SQL_GetDriverIdent",		SQL_GetDriverIdent},
dvander@868
  1441
	{"SQL_GetDriverProduct",	SQL_GetDriverProduct},
dvander@868
  1442
	{"SQL_GetError",			SQL_GetError},
dvander@868
  1443
	{"SQL_GetFieldCount",		SQL_GetFieldCount},
dvander@868
  1444
	{"SQL_GetInsertId",			SQL_GetInsertId},
dvander@868
  1445
	{"SQL_GetRowCount",			SQL_GetRowCount},
dvander@868
  1446
	{"SQL_HasResultSet",		SQL_HasResultSet},
dvander@868
  1447
	{"SQL_IsFieldNull",			SQL_IsFieldNull},
dvander@1096
  1448
	{"SQL_IsSameConnection",	SQL_IsSameConnection},
dvander@1096
  1449
	{"SQL_LockDatabase",		SQL_LockDatabase},
dvander@868
  1450
	{"SQL_MoreRows",			SQL_MoreRows},
dvander@1096
  1451
	{"SQL_PrepareQuery",		SQL_PrepareQuery},
dvander@868
  1452
	{"SQL_Query",				SQL_Query},
dvander@868
  1453
	{"SQL_QuoteString",			SQL_QuoteString},
dvander@1294
  1454
	{"SQL_ReadDriver",			SQL_ReadDriver},
dvander@868
  1455
	{"SQL_Rewind",				SQL_Rewind},
dvander@1096
  1456
	{"SQL_TConnect",			SQL_TConnect},
dvander@1096
  1457
	{"SQL_TQuery",				SQL_TQuery},
dvander@1096
  1458
	{"SQL_UnlockDatabase",		SQL_UnlockDatabase},
dvander@2357
  1459
	{"SQL_ConnectCustom",		SQL_ConnectCustom},
januk@3947
  1460
	{"SQL_SetCharset",		SQL_SetCharset},
dvander@868
  1461
	{NULL,						NULL},
dvander@868
  1462
};
dvander@2357
  1463