core/smn_database.cpp
author David Anderson <dvander@alliedmods.net>
Fri Jun 01 04:22:53 2007 +0000 (2007-06-01)
changeset 869 caa5587e708a
parent 868 bdbf922e246f
child 875 4a1451bf0925
permissions -rw-r--r--
fixed various bugs in the sql natives and manager
added a basic test plugin
dvander@868
     1
#include "sm_globals.h"
dvander@868
     2
#include "HandleSys.h"
dvander@868
     3
#include "Database.h"
dvander@868
     4
#include "ExtensionSys.h"
dvander@868
     5
#include "PluginSys.h"
dvander@868
     6
dvander@868
     7
HandleType_t hQueryType;
dvander@868
     8
HandleType_t hStmtType;
dvander@868
     9
dvander@868
    10
class DatabaseHelpers : 
dvander@868
    11
	public SMGlobalClass,
dvander@868
    12
	public IHandleTypeDispatch
dvander@868
    13
{
dvander@868
    14
public:
dvander@868
    15
	virtual void OnSourceModAllInitialized()
dvander@868
    16
	{
dvander@868
    17
		HandleAccess acc;
dvander@868
    18
dvander@868
    19
		/* Disable cloning */
dvander@868
    20
		g_HandleSys.InitAccessDefaults(NULL, &acc);
dvander@868
    21
		acc.access[HandleAccess_Clone] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY;
dvander@868
    22
dvander@868
    23
		TypeAccess tacc;
dvander@868
    24
dvander@868
    25
		g_HandleSys.InitAccessDefaults(&tacc, NULL);
dvander@868
    26
		tacc.ident = g_pCoreIdent;
dvander@868
    27
dvander@868
    28
		hQueryType = g_HandleSys.CreateType("IQuery", this, 0, &tacc, &acc, g_pCoreIdent, NULL);
dvander@869
    29
		hStmtType = g_HandleSys.CreateType("IPreparedQuery", this, hQueryType, &tacc, &acc, g_pCoreIdent, NULL);
dvander@868
    30
	}
dvander@868
    31
dvander@868
    32
	virtual void OnSourceModShutdown()
dvander@868
    33
	{
dvander@868
    34
		g_HandleSys.RemoveType(hStmtType, g_pCoreIdent);
dvander@868
    35
		g_HandleSys.RemoveType(hQueryType, g_pCoreIdent);
dvander@868
    36
	}
dvander@868
    37
dvander@868
    38
	virtual void OnHandleDestroy(HandleType_t type, void *object)
dvander@868
    39
	{
dvander@868
    40
		if (type == hQueryType)
dvander@868
    41
		{
dvander@868
    42
			IQuery *query = (IQuery *)object;
dvander@868
    43
			query->Destroy();
dvander@868
    44
		} else if (type == hStmtType) {
dvander@868
    45
			IPreparedQuery *query = (IPreparedQuery *)object;
dvander@868
    46
			query->Destroy();
dvander@868
    47
		}
dvander@868
    48
	}
dvander@868
    49
} s_DatabaseNativeHelpers;
dvander@868
    50
dvander@868
    51
//is this safe for stmt handles? i think since it's single inheritance, it always will be.
dvander@868
    52
inline HandleError ReadQueryHndl(Handle_t hndl, IPluginContext *pContext, IQuery **query)
dvander@868
    53
{
dvander@868
    54
	HandleSecurity sec;
dvander@868
    55
	sec.pOwner = pContext->GetIdentity();
dvander@868
    56
	sec.pIdentity = g_pCoreIdent;
dvander@868
    57
dvander@868
    58
	return g_HandleSys.ReadHandle(hndl, hQueryType, &sec, (void **)query);
dvander@868
    59
}
dvander@868
    60
dvander@868
    61
inline HandleError ReadStmtHndl(Handle_t hndl, IPluginContext *pContext, IPreparedQuery **query)
dvander@868
    62
{
dvander@868
    63
	HandleSecurity sec;
dvander@868
    64
	sec.pOwner = pContext->GetIdentity();
dvander@868
    65
	sec.pIdentity = g_pCoreIdent;
dvander@868
    66
dvander@868
    67
	return g_HandleSys.ReadHandle(hndl, hStmtType, &sec, (void **)query);
dvander@868
    68
}
dvander@868
    69
dvander@868
    70
inline HandleError ReadDbOrStmtHndl(Handle_t hndl, IPluginContext *pContext, IDatabase **db, IPreparedQuery **query)
dvander@868
    71
{
dvander@868
    72
	HandleError err;
dvander@868
    73
	if ((err = g_DBMan.ReadHandle(hndl, DBHandle_Database, (void **)db)) == HandleError_Type)
dvander@868
    74
	{
dvander@868
    75
		*db = NULL;
dvander@868
    76
		return ReadStmtHndl(hndl, pContext, query);
dvander@868
    77
	}
dvander@868
    78
	return err;
dvander@868
    79
}
dvander@868
    80
dvander@868
    81
static cell_t SQL_Connect(IPluginContext *pContext, const cell_t *params)
dvander@868
    82
{
dvander@868
    83
	char *conf, *err;
dvander@868
    84
dvander@868
    85
	size_t maxlength = (size_t)params[4];
dvander@868
    86
	bool persistent = params[2] ? true : false;
dvander@868
    87
	pContext->LocalToString(params[1], &conf);
dvander@868
    88
	pContext->LocalToString(params[3], &err);
dvander@868
    89
	
dvander@868
    90
	IDBDriver *driver;
dvander@868
    91
	IDatabase *db;
dvander@868
    92
	if (!g_DBMan.Connect(conf, &driver, &db, persistent, err, maxlength))
dvander@868
    93
	{
dvander@868
    94
		return BAD_HANDLE;
dvander@868
    95
	}
dvander@868
    96
dvander@868
    97
	/* HACK! Add us to the dependency list */
dvander@868
    98
	CExtension *pExt = g_Extensions.GetExtensionFromIdent(driver->GetIdentity());
dvander@868
    99
	if (pExt)
dvander@868
   100
	{
dvander@868
   101
		g_Extensions.BindChildPlugin(pExt, g_PluginSys.FindPluginByContext(pContext->GetContext()));
dvander@868
   102
	}
dvander@868
   103
dvander@868
   104
	return db->GetHandle();
dvander@868
   105
}
dvander@868
   106
dvander@868
   107
static cell_t SQL_ConnectEx(IPluginContext *pContext, const cell_t *params)
dvander@868
   108
{
dvander@868
   109
	IDBDriver *driver;
dvander@868
   110
	if (params[1] == BAD_HANDLE)
dvander@868
   111
	{
dvander@868
   112
		if ((driver = g_DBMan.GetDefaultDriver()) == NULL)
dvander@868
   113
		{
dvander@868
   114
			return pContext->ThrowNativeError("Could not find any default driver");
dvander@868
   115
		}
dvander@868
   116
	} else {
dvander@868
   117
		HandleError err;
dvander@868
   118
		if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Driver, (void **)&driver))
dvander@868
   119
			!= HandleError_None)
dvander@868
   120
		{
dvander@868
   121
			return pContext->ThrowNativeError("Invalid driver Handle %x (error: %d)", params[1], err);
dvander@868
   122
		}
dvander@868
   123
	}
dvander@868
   124
 
dvander@868
   125
	char *host, *user, *pass, *database, *error;
dvander@868
   126
	size_t maxlength = (size_t)params[7];
dvander@868
   127
	bool persistent = params[8] ? true : false;
dvander@868
   128
	unsigned int port = params[9];
dvander@868
   129
	unsigned int maxTimeout = params[10];
dvander@868
   130
	pContext->LocalToString(params[2], &host);
dvander@868
   131
	pContext->LocalToString(params[3], &user);
dvander@868
   132
	pContext->LocalToString(params[4], &pass);
dvander@868
   133
	pContext->LocalToString(params[5], &database);
dvander@868
   134
	pContext->LocalToString(params[6], &error);
dvander@868
   135
dvander@868
   136
	DatabaseInfo info;
dvander@868
   137
	info.database = database;
dvander@868
   138
	info.driver = driver->GetIdentifier();
dvander@868
   139
	info.host = host;
dvander@868
   140
	info.maxTimeout = maxTimeout;
dvander@868
   141
	info.pass = pass;
dvander@868
   142
	info.port = port;
dvander@868
   143
	info.user = user;
dvander@868
   144
	
dvander@868
   145
	IDatabase *db = driver->Connect(&info, persistent, error, maxlength);
dvander@868
   146
dvander@868
   147
	if (db)
dvander@868
   148
	{
dvander@868
   149
		/* HACK! Add us to the dependency list */
dvander@868
   150
		CExtension *pExt = g_Extensions.GetExtensionFromIdent(driver->GetIdentity());
dvander@868
   151
		if (pExt)
dvander@868
   152
		{
dvander@868
   153
			g_Extensions.BindChildPlugin(pExt, g_PluginSys.FindPluginByContext(pContext->GetContext()));
dvander@868
   154
		}
dvander@868
   155
dvander@868
   156
		return db->GetHandle();
dvander@868
   157
	}
dvander@868
   158
	
dvander@868
   159
	return BAD_HANDLE;
dvander@868
   160
}
dvander@868
   161
dvander@868
   162
static cell_t SQL_GetDriverIdent(IPluginContext *pContext, const cell_t *params)
dvander@868
   163
{
dvander@868
   164
	IDBDriver *driver;
dvander@868
   165
	if (params[1] == BAD_HANDLE)
dvander@868
   166
	{
dvander@868
   167
		if ((driver = g_DBMan.GetDefaultDriver()) == NULL)
dvander@868
   168
		{
dvander@868
   169
			return pContext->ThrowNativeError("Could not find any default driver");
dvander@868
   170
		}
dvander@868
   171
	} else {
dvander@868
   172
		HandleError err;
dvander@868
   173
		if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Driver, (void **)&driver))
dvander@868
   174
			!= HandleError_None)
dvander@868
   175
		{
dvander@868
   176
			return pContext->ThrowNativeError("Invalid driver Handle %x (error: %d)", params[1], err);
dvander@868
   177
		}
dvander@868
   178
	}
dvander@868
   179
dvander@868
   180
	pContext->StringToLocalUTF8(params[2], params[3], driver->GetIdentifier(), NULL);
dvander@868
   181
dvander@868
   182
	return 1;
dvander@868
   183
}
dvander@868
   184
dvander@868
   185
static cell_t SQL_GetDriver(IPluginContext *pContext, const cell_t *params)
dvander@868
   186
{
dvander@868
   187
	char *name;
dvander@868
   188
	pContext->LocalToString(params[1], &name);
dvander@868
   189
dvander@868
   190
	IDBDriver *driver = NULL;
dvander@868
   191
	if (name[0] == '\0')
dvander@868
   192
	{
dvander@868
   193
		driver = g_DBMan.GetDefaultDriver();
dvander@868
   194
	} else {
dvander@868
   195
		driver = g_DBMan.FindOrLoadDriver(name);
dvander@868
   196
	}
dvander@868
   197
dvander@868
   198
	return (driver != NULL) ? driver->GetHandle() : BAD_HANDLE;
dvander@868
   199
}
dvander@868
   200
dvander@868
   201
static cell_t SQL_GetDriverProduct(IPluginContext *pContext, const cell_t *params)
dvander@868
   202
{
dvander@868
   203
	IDBDriver *driver;
dvander@868
   204
	if (params[1] == BAD_HANDLE)
dvander@868
   205
	{
dvander@868
   206
		if ((driver = g_DBMan.GetDefaultDriver()) == NULL)
dvander@868
   207
		{
dvander@868
   208
			return pContext->ThrowNativeError("Could not find any default driver");
dvander@868
   209
		}
dvander@868
   210
	} else {
dvander@868
   211
		HandleError err;
dvander@868
   212
		if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Driver, (void **)&driver))
dvander@868
   213
			!= HandleError_None)
dvander@868
   214
		{
dvander@868
   215
			return pContext->ThrowNativeError("Invalid driver Handle %x (error: %d)", params[1], err);
dvander@868
   216
		}
dvander@868
   217
	}
dvander@868
   218
dvander@868
   219
	pContext->StringToLocalUTF8(params[2], params[3], driver->GetProductName(), NULL);
dvander@868
   220
dvander@868
   221
	return 1;
dvander@868
   222
}
dvander@868
   223
dvander@868
   224
static cell_t SQL_GetAffectedRows(IPluginContext *pContext, const cell_t *params)
dvander@868
   225
{
dvander@868
   226
	IDatabase *db = NULL;
dvander@868
   227
	IPreparedQuery *stmt = NULL;
dvander@868
   228
	HandleError err;
dvander@868
   229
dvander@868
   230
	if ((err = ReadDbOrStmtHndl(params[1], pContext, &db, &stmt)) != HandleError_None)
dvander@868
   231
	{
dvander@868
   232
		return pContext->ThrowNativeError("Invalid statement or db Handle %x (error: %d)", params[1], err);
dvander@868
   233
	}
dvander@868
   234
dvander@868
   235
	if (db)
dvander@868
   236
	{
dvander@868
   237
		return db->GetAffectedRows();
dvander@868
   238
	} else if (stmt) {
dvander@868
   239
		return stmt->GetAffectedRows();
dvander@868
   240
	}
dvander@868
   241
dvander@868
   242
	return pContext->ThrowNativeError("Unknown error reading db/stmt handles");
dvander@868
   243
}
dvander@868
   244
dvander@868
   245
static cell_t SQL_GetInsertId(IPluginContext *pContext, const cell_t *params)
dvander@868
   246
{
dvander@868
   247
	IDatabase *db = NULL;
dvander@868
   248
	IPreparedQuery *stmt = NULL;
dvander@868
   249
	HandleError err;
dvander@868
   250
dvander@868
   251
	if ((err = ReadDbOrStmtHndl(params[1], pContext, &db, &stmt)) != HandleError_None)
dvander@868
   252
	{
dvander@868
   253
		return pContext->ThrowNativeError("Invalid statement or db Handle %x (error: %d)", params[1], err);
dvander@868
   254
	}
dvander@868
   255
dvander@868
   256
	if (db)
dvander@868
   257
	{
dvander@868
   258
		return db->GetInsertID();
dvander@868
   259
	} else if (stmt) {
dvander@868
   260
		return stmt->GetInsertID();
dvander@868
   261
	}
dvander@868
   262
dvander@868
   263
	return pContext->ThrowNativeError("Unknown error reading db/stmt handles");
dvander@868
   264
}
dvander@868
   265
dvander@868
   266
static cell_t SQL_GetError(IPluginContext *pContext, const cell_t *params)
dvander@868
   267
{
dvander@868
   268
	IDatabase *db = NULL;
dvander@868
   269
	IPreparedQuery *stmt = NULL;
dvander@868
   270
	HandleError err;
dvander@868
   271
dvander@868
   272
	if ((err = ReadDbOrStmtHndl(params[1], pContext, &db, &stmt)) != HandleError_None)
dvander@868
   273
	{
dvander@868
   274
		return pContext->ThrowNativeError("Invalid statement or db Handle %x (error: %d)", params[1], err);
dvander@868
   275
	}
dvander@868
   276
dvander@868
   277
	const char *error = "";
dvander@868
   278
	if (db)
dvander@868
   279
	{
dvander@868
   280
		error = db->GetError();
dvander@868
   281
	} else if (stmt) {
dvander@868
   282
		error = stmt->GetError();
dvander@868
   283
	}
dvander@868
   284
dvander@868
   285
	if (error[0] == '\0')
dvander@868
   286
	{
dvander@868
   287
		return false;
dvander@868
   288
	}
dvander@868
   289
dvander@868
   290
	pContext->StringToLocalUTF8(params[2], params[3], error, NULL);
dvander@868
   291
dvander@868
   292
	return 1;
dvander@868
   293
}
dvander@868
   294
dvander@868
   295
static cell_t SQL_QuoteString(IPluginContext *pContext, const cell_t *params)
dvander@868
   296
{
dvander@868
   297
	IDatabase *db = NULL;
dvander@868
   298
	HandleError err;
dvander@868
   299
dvander@868
   300
	if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
dvander@868
   301
		!= HandleError_None)
dvander@868
   302
	{
dvander@868
   303
		return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
dvander@868
   304
	}
dvander@868
   305
dvander@868
   306
	char *input, *output;
dvander@868
   307
	size_t maxlength = (size_t)params[4];
dvander@868
   308
	pContext->LocalToString(params[2], &input);
dvander@868
   309
	pContext->LocalToString(params[3], &output);
dvander@868
   310
dvander@868
   311
	size_t written;
dvander@868
   312
	bool s = db->QuoteString(input, output, maxlength, &written);
dvander@868
   313
dvander@868
   314
	cell_t *addr;
dvander@868
   315
	pContext->LocalToPhysAddr(params[5], &addr);
dvander@868
   316
	*addr = (cell_t)written;
dvander@868
   317
dvander@868
   318
	return s ? 1 : 0;
dvander@868
   319
}
dvander@868
   320
dvander@868
   321
static cell_t SQL_FastQuery(IPluginContext *pContext, const cell_t *params)
dvander@868
   322
{
dvander@868
   323
	IDatabase *db = NULL;
dvander@868
   324
	HandleError err;
dvander@868
   325
dvander@868
   326
	if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
dvander@868
   327
		!= HandleError_None)
dvander@868
   328
	{
dvander@868
   329
		return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
dvander@868
   330
	}
dvander@868
   331
dvander@868
   332
	char *query;
dvander@868
   333
	pContext->LocalToString(params[2], &query);
dvander@868
   334
dvander@868
   335
	return db->DoSimpleQuery(query) ? 1 : 0;
dvander@868
   336
}
dvander@868
   337
dvander@868
   338
static cell_t SQL_Query(IPluginContext *pContext, const cell_t *params)
dvander@868
   339
{
dvander@868
   340
	IDatabase *db = NULL;
dvander@868
   341
	HandleError err;
dvander@868
   342
dvander@868
   343
	if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
dvander@868
   344
		!= HandleError_None)
dvander@868
   345
	{
dvander@868
   346
		return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
dvander@868
   347
	}
dvander@868
   348
dvander@868
   349
	char *query;
dvander@868
   350
	pContext->LocalToString(params[2], &query);
dvander@868
   351
dvander@868
   352
	IQuery *qr = db->DoQuery(query);
dvander@868
   353
dvander@868
   354
	if (!qr)
dvander@868
   355
	{
dvander@868
   356
		return BAD_HANDLE;
dvander@868
   357
	}
dvander@868
   358
dvander@868
   359
	Handle_t hndl = g_HandleSys.CreateHandle(hQueryType, qr, pContext->GetIdentity(), g_pCoreIdent, NULL);
dvander@868
   360
	if (hndl == BAD_HANDLE)
dvander@868
   361
	{
dvander@868
   362
		qr->Destroy();
dvander@868
   363
		return BAD_HANDLE;
dvander@868
   364
	}
dvander@868
   365
dvander@868
   366
	return hndl;
dvander@868
   367
}
dvander@868
   368
dvander@868
   369
static cell_t SQL_PrepareQuery(IPluginContext *pContext, const cell_t *params)
dvander@868
   370
{
dvander@868
   371
	IDatabase *db = NULL;
dvander@868
   372
	HandleError err;
dvander@868
   373
dvander@868
   374
	if ((err = g_DBMan.ReadHandle(params[1], DBHandle_Database, (void **)&db))
dvander@868
   375
		!= HandleError_None)
dvander@868
   376
	{
dvander@868
   377
		return pContext->ThrowNativeError("Invalid database Handle %x (error: %d)", params[1], err);
dvander@868
   378
	}
dvander@868
   379
dvander@868
   380
	char *query, *error;
dvander@868
   381
	size_t maxlength = (size_t)params[4];
dvander@868
   382
	pContext->LocalToString(params[2], &query);
dvander@868
   383
	pContext->LocalToString(params[3], &error);
dvander@868
   384
dvander@868
   385
	IPreparedQuery *qr = db->PrepareQuery(query, error, maxlength);
dvander@868
   386
dvander@868
   387
	if (!qr)
dvander@868
   388
	{
dvander@868
   389
		return BAD_HANDLE;
dvander@868
   390
	}
dvander@868
   391
dvander@868
   392
	Handle_t hndl = g_HandleSys.CreateHandle(hStmtType, qr, pContext->GetIdentity(), g_pCoreIdent, NULL);
dvander@868
   393
	if (hndl == BAD_HANDLE)
dvander@868
   394
	{
dvander@868
   395
		qr->Destroy();
dvander@868
   396
		return BAD_HANDLE;
dvander@868
   397
	}
dvander@868
   398
dvander@868
   399
	return hndl;
dvander@868
   400
}
dvander@868
   401
dvander@868
   402
static cell_t SQL_FetchMoreResults(IPluginContext *pContext, const cell_t *params)
dvander@868
   403
{
dvander@868
   404
	IQuery *query;
dvander@868
   405
	HandleError err;
dvander@868
   406
dvander@868
   407
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
   408
	{
dvander@868
   409
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
   410
	}
dvander@868
   411
dvander@868
   412
	return query->FetchMoreResults() ? 1 : 0;
dvander@868
   413
}
dvander@868
   414
dvander@868
   415
static cell_t SQL_HasResultSet(IPluginContext *pContext, const cell_t *params)
dvander@868
   416
{
dvander@868
   417
	IQuery *query;
dvander@868
   418
	HandleError err;
dvander@868
   419
dvander@868
   420
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
   421
	{
dvander@868
   422
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
   423
	}
dvander@868
   424
dvander@868
   425
	return query->GetResultSet() != NULL ? true : false;
dvander@868
   426
}
dvander@868
   427
dvander@868
   428
static cell_t SQL_GetRowCount(IPluginContext *pContext, const cell_t *params)
dvander@868
   429
{
dvander@868
   430
	IQuery *query;
dvander@868
   431
	HandleError err;
dvander@868
   432
dvander@868
   433
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
   434
	{
dvander@868
   435
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
   436
	}
dvander@868
   437
dvander@868
   438
	IResultSet *rs = query->GetResultSet();
dvander@868
   439
	if (!rs)
dvander@868
   440
	{
dvander@868
   441
		return 0;
dvander@868
   442
	}
dvander@868
   443
dvander@868
   444
	return rs->GetRowCount();
dvander@868
   445
}
dvander@868
   446
dvander@868
   447
static cell_t SQL_GetFieldCount(IPluginContext *pContext, const cell_t *params)
dvander@868
   448
{
dvander@868
   449
	IQuery *query;
dvander@868
   450
	HandleError err;
dvander@868
   451
dvander@868
   452
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
   453
	{
dvander@868
   454
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
   455
	}
dvander@868
   456
dvander@868
   457
	IResultSet *rs = query->GetResultSet();
dvander@868
   458
	if (!rs)
dvander@868
   459
	{
dvander@868
   460
		return 0;
dvander@868
   461
	}
dvander@868
   462
dvander@868
   463
	return rs->GetFieldCount();
dvander@868
   464
}
dvander@868
   465
dvander@868
   466
static cell_t SQL_FieldNumToName(IPluginContext *pContext, const cell_t *params)
dvander@868
   467
{
dvander@868
   468
	IQuery *query;
dvander@868
   469
	HandleError err;
dvander@868
   470
dvander@868
   471
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
   472
	{
dvander@868
   473
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
   474
	}
dvander@868
   475
dvander@868
   476
	IResultSet *rs = query->GetResultSet();
dvander@868
   477
	if (!rs)
dvander@868
   478
	{
dvander@868
   479
		return pContext->ThrowNativeError("No current result set");
dvander@868
   480
	}
dvander@868
   481
dvander@868
   482
	unsigned int field = params[2];
dvander@868
   483
dvander@868
   484
	const char *fldname;
dvander@868
   485
	if ((fldname = rs->FieldNumToName(field)) == NULL)
dvander@868
   486
	{
dvander@868
   487
		return pContext->ThrowNativeError("Invalid field index %d", field);
dvander@868
   488
	}
dvander@868
   489
dvander@868
   490
	pContext->StringToLocalUTF8(params[3], params[4], fldname, NULL);
dvander@868
   491
dvander@868
   492
	return 1;
dvander@868
   493
}
dvander@868
   494
dvander@868
   495
static cell_t SQL_FieldNameToNum(IPluginContext *pContext, const cell_t *params)
dvander@868
   496
{
dvander@868
   497
	IQuery *query;
dvander@868
   498
	HandleError err;
dvander@868
   499
dvander@868
   500
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
   501
	{
dvander@868
   502
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
   503
	}
dvander@868
   504
dvander@868
   505
	IResultSet *rs = query->GetResultSet();
dvander@868
   506
	if (!rs)
dvander@868
   507
	{
dvander@868
   508
		return pContext->ThrowNativeError("No current result set");
dvander@868
   509
	}
dvander@868
   510
dvander@868
   511
	char *field;
dvander@868
   512
	pContext->LocalToString(params[2], &field);
dvander@868
   513
dvander@868
   514
	cell_t *num;
dvander@868
   515
	pContext->LocalToPhysAddr(params[3], &num);
dvander@868
   516
dvander@868
   517
	return rs->FieldNameToNum(field, (unsigned int *)num) ? 1 : 0;
dvander@868
   518
}
dvander@868
   519
dvander@868
   520
static cell_t SQL_FetchRow(IPluginContext *pContext, const cell_t *params)
dvander@868
   521
{
dvander@868
   522
	IQuery *query;
dvander@868
   523
	HandleError err;
dvander@868
   524
dvander@868
   525
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
   526
	{
dvander@868
   527
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
   528
	}
dvander@868
   529
dvander@868
   530
	IResultSet *rs = query->GetResultSet();
dvander@868
   531
	if (!rs)
dvander@868
   532
	{
dvander@868
   533
		return pContext->ThrowNativeError("No current result set");
dvander@868
   534
	}
dvander@868
   535
dvander@868
   536
	return (rs->FetchRow() != NULL) ? true : false;
dvander@868
   537
}
dvander@868
   538
dvander@868
   539
static cell_t SQL_MoreRows(IPluginContext *pContext, const cell_t *params)
dvander@868
   540
{
dvander@868
   541
	IQuery *query;
dvander@868
   542
	HandleError err;
dvander@868
   543
dvander@868
   544
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
   545
	{
dvander@868
   546
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
   547
	}
dvander@868
   548
dvander@868
   549
	IResultSet *rs = query->GetResultSet();
dvander@868
   550
	if (!rs)
dvander@868
   551
	{
dvander@868
   552
		return pContext->ThrowNativeError("No current result set");
dvander@868
   553
	}
dvander@868
   554
dvander@868
   555
	return rs->MoreRows() ? 1 : 0;
dvander@868
   556
}
dvander@868
   557
dvander@868
   558
static cell_t SQL_Rewind(IPluginContext *pContext, const cell_t *params)
dvander@868
   559
{
dvander@868
   560
	IQuery *query;
dvander@868
   561
	HandleError err;
dvander@868
   562
dvander@868
   563
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
   564
	{
dvander@868
   565
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
   566
	}
dvander@868
   567
dvander@868
   568
	IResultSet *rs = query->GetResultSet();
dvander@868
   569
	if (!rs)
dvander@868
   570
	{
dvander@868
   571
		return pContext->ThrowNativeError("No current result set");
dvander@868
   572
	}
dvander@868
   573
dvander@868
   574
	return rs->Rewind() ? 1 : 0;
dvander@868
   575
}
dvander@868
   576
dvander@868
   577
static cell_t SQL_FetchString(IPluginContext *pContext, const cell_t *params)
dvander@868
   578
{
dvander@868
   579
	IQuery *query;
dvander@868
   580
	HandleError err;
dvander@868
   581
dvander@868
   582
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
   583
	{
dvander@868
   584
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
   585
	}
dvander@868
   586
dvander@868
   587
	IResultSet *rs = query->GetResultSet();
dvander@868
   588
	if (!rs)
dvander@868
   589
	{
dvander@868
   590
		return pContext->ThrowNativeError("No current result set");
dvander@868
   591
	}
dvander@868
   592
dvander@868
   593
	IResultRow *row = rs->CurrentRow();
dvander@868
   594
	if (!row)
dvander@868
   595
	{
dvander@868
   596
		return pContext->ThrowNativeError("Current result set has no fetched rows");
dvander@868
   597
	}
dvander@868
   598
dvander@868
   599
	const char *str;
dvander@868
   600
	size_t length;
dvander@868
   601
	DBResult res = row->GetString(params[2], &str, &length);
dvander@868
   602
dvander@868
   603
	if (res == DBVal_Error)
dvander@868
   604
	{
dvander@868
   605
		return pContext->ThrowNativeError("Error fetching data from field %d", params[2]);
dvander@868
   606
	} else if (res == DBVal_TypeMismatch) {
dvander@868
   607
		return pContext->ThrowNativeError("Could not fetch data in field %d as a string", params[2]);
dvander@868
   608
	}
dvander@868
   609
dvander@868
   610
	pContext->StringToLocalUTF8(params[3], params[4], str, &length);
dvander@868
   611
dvander@868
   612
	cell_t *addr;
dvander@868
   613
	pContext->LocalToPhysAddr(params[5], &addr);
dvander@868
   614
	*addr = (cell_t)res;
dvander@868
   615
dvander@868
   616
	return (cell_t)length;
dvander@868
   617
}
dvander@868
   618
dvander@868
   619
static cell_t SQL_FetchFloat(IPluginContext *pContext, const cell_t *params)
dvander@868
   620
{
dvander@868
   621
	IQuery *query;
dvander@868
   622
	HandleError err;
dvander@868
   623
dvander@868
   624
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
   625
	{
dvander@868
   626
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
   627
	}
dvander@868
   628
dvander@868
   629
	IResultSet *rs = query->GetResultSet();
dvander@868
   630
	if (!rs)
dvander@868
   631
	{
dvander@868
   632
		return pContext->ThrowNativeError("No current result set");
dvander@868
   633
	}
dvander@868
   634
dvander@868
   635
	IResultRow *row = rs->CurrentRow();
dvander@868
   636
	if (!row)
dvander@868
   637
	{
dvander@868
   638
		return pContext->ThrowNativeError("Current result set has no fetched rows");
dvander@868
   639
	}
dvander@868
   640
dvander@868
   641
	float f;
dvander@868
   642
	DBResult res = row->GetFloat(params[2], &f);
dvander@868
   643
dvander@868
   644
	if (res == DBVal_Error)
dvander@868
   645
	{
dvander@868
   646
		return pContext->ThrowNativeError("Error fetching data from field %d", params[2]);
dvander@868
   647
	} else if (res == DBVal_TypeMismatch) {
dvander@868
   648
		return pContext->ThrowNativeError("Could not fetch data in field %d as a float", params[2]);
dvander@868
   649
	}
dvander@868
   650
dvander@868
   651
	cell_t *addr;
dvander@868
   652
	pContext->LocalToPhysAddr(params[5], &addr);
dvander@868
   653
	*addr = (cell_t)res;
dvander@868
   654
dvander@868
   655
	return sp_ftoc(f);
dvander@868
   656
}
dvander@868
   657
dvander@868
   658
static cell_t SQL_FetchInt(IPluginContext *pContext, const cell_t *params)
dvander@868
   659
{
dvander@868
   660
	IQuery *query;
dvander@868
   661
	HandleError err;
dvander@868
   662
dvander@868
   663
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
   664
	{
dvander@868
   665
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
   666
	}
dvander@868
   667
dvander@868
   668
	IResultSet *rs = query->GetResultSet();
dvander@868
   669
	if (!rs)
dvander@868
   670
	{
dvander@868
   671
		return pContext->ThrowNativeError("No current result set");
dvander@868
   672
	}
dvander@868
   673
dvander@868
   674
	IResultRow *row = rs->CurrentRow();
dvander@868
   675
	if (!row)
dvander@868
   676
	{
dvander@868
   677
		return pContext->ThrowNativeError("Current result set has no fetched rows");
dvander@868
   678
	}
dvander@868
   679
dvander@868
   680
	int iv;
dvander@868
   681
	DBResult res = row->GetInt(params[2], &iv);
dvander@868
   682
dvander@868
   683
	if (res == DBVal_Error)
dvander@868
   684
	{
dvander@868
   685
		return pContext->ThrowNativeError("Error fetching data from field %d", params[2]);
dvander@868
   686
	} else if (res == DBVal_TypeMismatch) {
dvander@868
   687
		return pContext->ThrowNativeError("Could not fetch data in field %d as an integer", params[2]);
dvander@868
   688
	}
dvander@868
   689
dvander@868
   690
	cell_t *addr;
dvander@868
   691
	pContext->LocalToPhysAddr(params[5], &addr);
dvander@868
   692
	*addr = (cell_t)res;
dvander@868
   693
dvander@868
   694
	return iv;
dvander@868
   695
}
dvander@868
   696
dvander@868
   697
static cell_t SQL_IsFieldNull(IPluginContext *pContext, const cell_t *params)
dvander@868
   698
{
dvander@868
   699
	IQuery *query;
dvander@868
   700
	HandleError err;
dvander@868
   701
dvander@868
   702
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
   703
	{
dvander@868
   704
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
   705
	}
dvander@868
   706
dvander@868
   707
	IResultSet *rs = query->GetResultSet();
dvander@868
   708
	if (!rs)
dvander@868
   709
	{
dvander@868
   710
		return pContext->ThrowNativeError("No current result set");
dvander@868
   711
	}
dvander@868
   712
dvander@868
   713
	IResultRow *row = rs->CurrentRow();
dvander@868
   714
	if (!row)
dvander@868
   715
	{
dvander@868
   716
		return pContext->ThrowNativeError("Current result set has no fetched rows");
dvander@868
   717
	}
dvander@868
   718
dvander@868
   719
	if ((unsigned)params[2] >= rs->GetFieldCount())
dvander@868
   720
	{
dvander@868
   721
		return pContext->ThrowNativeError("Invalid field index %d", params[2]);
dvander@868
   722
	}
dvander@868
   723
dvander@868
   724
	return row->IsNull(params[2]) ? 1 : 0;
dvander@868
   725
}
dvander@868
   726
dvander@868
   727
static cell_t SQL_FetchSize(IPluginContext *pContext, const cell_t *params)
dvander@868
   728
{
dvander@868
   729
	IQuery *query;
dvander@868
   730
	HandleError err;
dvander@868
   731
dvander@868
   732
	if ((err = ReadQueryHndl(params[1], pContext, &query)) != HandleError_None)
dvander@868
   733
	{
dvander@868
   734
		return pContext->ThrowNativeError("Invalid query Handle %x (error: %d)", params[1], err);
dvander@868
   735
	}
dvander@868
   736
dvander@868
   737
	IResultSet *rs = query->GetResultSet();
dvander@868
   738
	if (!rs)
dvander@868
   739
	{
dvander@868
   740
		return pContext->ThrowNativeError("No current result set");
dvander@868
   741
	}
dvander@868
   742
dvander@868
   743
	IResultRow *row = rs->CurrentRow();
dvander@868
   744
	if (!row)
dvander@868
   745
	{
dvander@868
   746
		return pContext->ThrowNativeError("Current result set has no fetched rows");
dvander@868
   747
	}
dvander@868
   748
dvander@868
   749
	if ((unsigned)params[2] >= rs->GetFieldCount())
dvander@868
   750
	{
dvander@868
   751
		return pContext->ThrowNativeError("Invalid field index %d", params[2]);
dvander@868
   752
	}
dvander@868
   753
dvander@868
   754
	return row->GetDataSize(params[2]);
dvander@868
   755
}
dvander@868
   756
dvander@868
   757
static cell_t SQL_BindParamInt(IPluginContext *pContext, const cell_t *params)
dvander@868
   758
{
dvander@868
   759
	IPreparedQuery *stmt;
dvander@868
   760
	HandleError err;
dvander@868
   761
dvander@868
   762
	if ((err = ReadStmtHndl(params[1], pContext, &stmt)) != HandleError_None)
dvander@868
   763
	{
dvander@868
   764
		return pContext->ThrowNativeError("Invalid statement Handle %x (error: %d)", params[1], err);
dvander@868
   765
	}
dvander@868
   766
dvander@868
   767
	if (!stmt->BindParamInt(params[2], params[3], params[4] ? true : false))
dvander@868
   768
	{
dvander@868
   769
		return pContext->ThrowNativeError("Could not bind parameter %d as an integer", params[2]);
dvander@868
   770
	}
dvander@868
   771
dvander@868
   772
	return 1;
dvander@868
   773
}
dvander@868
   774
dvander@868
   775
static cell_t SQL_BindParamFloat(IPluginContext *pContext, const cell_t *params)
dvander@868
   776
{
dvander@868
   777
	IPreparedQuery *stmt;
dvander@868
   778
	HandleError err;
dvander@868
   779
dvander@868
   780
	if ((err = ReadStmtHndl(params[1], pContext, &stmt)) != HandleError_None)
dvander@868
   781
	{
dvander@868
   782
		return pContext->ThrowNativeError("Invalid statement Handle %x (error: %d)", params[1], err);
dvander@868
   783
	}
dvander@868
   784
dvander@868
   785
	if (!stmt->BindParamFloat(params[2], sp_ctof(params[3])))
dvander@868
   786
	{
dvander@868
   787
		return pContext->ThrowNativeError("Could not bind parameter %d as a float", params[2]);
dvander@868
   788
	}
dvander@868
   789
dvander@868
   790
	return 1;
dvander@868
   791
}
dvander@868
   792
dvander@868
   793
static cell_t SQL_BindParamString(IPluginContext *pContext, const cell_t *params)
dvander@868
   794
{
dvander@868
   795
	IPreparedQuery *stmt;
dvander@868
   796
	HandleError err;
dvander@868
   797
dvander@868
   798
	if ((err = ReadStmtHndl(params[1], pContext, &stmt)) != HandleError_None)
dvander@868
   799
	{
dvander@868
   800
		return pContext->ThrowNativeError("Invalid statement Handle %x (error: %d)", params[1], err);
dvander@868
   801
	}
dvander@868
   802
dvander@868
   803
	char *str;
dvander@868
   804
	pContext->LocalToString(params[3], &str);
dvander@868
   805
dvander@868
   806
	if (!stmt->BindParamString(params[2], str, params[4] ? true : false))
dvander@868
   807
	{
dvander@868
   808
		return pContext->ThrowNativeError("Could not bind parameter %d as a string", params[2]);
dvander@868
   809
	}
dvander@868
   810
dvander@868
   811
	return 1;
dvander@868
   812
}
dvander@868
   813
dvander@868
   814
static cell_t SQL_Execute(IPluginContext *pContext, const cell_t *params)
dvander@868
   815
{
dvander@868
   816
	IPreparedQuery *stmt;
dvander@868
   817
	HandleError err;
dvander@868
   818
dvander@868
   819
	if ((err = ReadStmtHndl(params[1], pContext, &stmt)) != HandleError_None)
dvander@868
   820
	{
dvander@868
   821
		return pContext->ThrowNativeError("Invalid statement Handle %x (error: %d)", params[1], err);
dvander@868
   822
	}
dvander@868
   823
dvander@868
   824
	return stmt->Execute() ? 1 : 0;
dvander@868
   825
}
dvander@868
   826
dvander@868
   827
REGISTER_NATIVES(dbNatives)
dvander@868
   828
{
dvander@868
   829
	{"SQL_BindParamInt",		SQL_BindParamInt},
dvander@868
   830
	{"SQL_BindParamFloat",		SQL_BindParamFloat},
dvander@868
   831
	{"SQL_BindParamString",		SQL_BindParamString},
dvander@868
   832
	{"SQL_Connect",				SQL_Connect},
dvander@868
   833
	{"SQL_ConnectEx",			SQL_ConnectEx},
dvander@868
   834
	{"SQL_Execute",				SQL_Execute},
dvander@868
   835
	{"SQL_FastQuery",			SQL_FastQuery},
dvander@868
   836
	{"SQL_FetchFloat",			SQL_FetchFloat},
dvander@868
   837
	{"SQL_FetchInt",			SQL_FetchInt},
dvander@868
   838
	{"SQL_FetchMoreResults",	SQL_FetchMoreResults},
dvander@868
   839
	{"SQL_FetchRow",			SQL_FetchRow},
dvander@868
   840
	{"SQL_FetchSize",			SQL_FetchSize},
dvander@868
   841
	{"SQL_FetchString",			SQL_FetchString},
dvander@868
   842
	{"SQL_FieldNameToNum",		SQL_FieldNameToNum},
dvander@868
   843
	{"SQL_FieldNumToName",		SQL_FieldNumToName},
dvander@868
   844
	{"SQL_GetAffectedRows",		SQL_GetAffectedRows},
dvander@868
   845
	{"SQL_GetDriver",			SQL_GetDriver},
dvander@868
   846
	{"SQL_GetDriverIdent",		SQL_GetDriverIdent},
dvander@868
   847
	{"SQL_GetDriverProduct",	SQL_GetDriverProduct},
dvander@868
   848
	{"SQL_GetError",			SQL_GetError},
dvander@868
   849
	{"SQL_GetFieldCount",		SQL_GetFieldCount},
dvander@868
   850
	{"SQL_GetInsertId",			SQL_GetInsertId},
dvander@868
   851
	{"SQL_GetRowCount",			SQL_GetRowCount},
dvander@868
   852
	{"SQL_HasResultSet",		SQL_HasResultSet},
dvander@868
   853
	{"SQL_IsFieldNull",			SQL_IsFieldNull},
dvander@868
   854
	{"SQL_MoreRows",			SQL_MoreRows},
dvander@868
   855
	{"SQL_Query",				SQL_Query},
dvander@868
   856
	{"SQL_QuoteString",			SQL_QuoteString},
dvander@868
   857
	{"SQL_PrepareQuery",		SQL_PrepareQuery},
dvander@868
   858
	{"SQL_Rewind",				SQL_Rewind},
dvander@868
   859
	{NULL,						NULL},
dvander@868
   860
};