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