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