extensions/sqlite/driver/SqResults.cpp
author David Anderson <dvander@alliedmods.net>
Sun Aug 30 01:54:45 2009 -0700 (2009-08-30)
changeset 2790 6dd851ba15fd
parent 2471 194be299b700
permissions -rw-r--r--
Fixed extension version reporting.
dvander@1203
     1
/**
dvander@1203
     2
 * vim: set ts=4 :
ds@1330
     3
 * =============================================================================
dvander@1226
     4
 * SourceMod SQLite Extension
ds@1947
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
ds@1330
     6
 * =============================================================================
dvander@1203
     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@1226
    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@1226
    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@1226
    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@1203
    28
 *
dvander@1203
    29
 * Version: $Id$
dvander@1203
    30
 */
dvander@1203
    31
dvander@1203
    32
#include <stdlib.h>
dvander@1203
    33
#include "extension.h"
dvander@1203
    34
#include "SqResults.h"
dvander@1203
    35
#include "SqQuery.h"
dvander@1203
    36
dvander@1203
    37
SqResults::SqResults(SqQuery *query) : 
dvander@1203
    38
	m_pStmt(query->GetStmt()), m_Strings(1024),
dvander@1203
    39
	m_RowCount(0), m_MaxRows(0), m_Rows(NULL),
dvander@1203
    40
	m_CurRow(0), m_NextRow(0)
dvander@1203
    41
{
dvander@1203
    42
	m_ColCount = sqlite3_column_count(m_pStmt);
dvander@1203
    43
	if (m_ColCount)
dvander@1203
    44
	{
dvander@1203
    45
		m_ColNames = new String[m_ColCount];
dvander@1203
    46
		for (unsigned int i=0; i<m_ColCount; i++)
dvander@1203
    47
		{
dvander@1203
    48
			m_ColNames[i].assign(sqlite3_column_name(m_pStmt, i));
dvander@1203
    49
		}
dvander@1203
    50
	} else {
dvander@1203
    51
		m_ColNames = NULL;
dvander@1203
    52
	}
dvander@1203
    53
dvander@1203
    54
	m_pMemory = m_Strings.GetMemTable();
dvander@1203
    55
}
dvander@1203
    56
dvander@1203
    57
SqResults::~SqResults()
dvander@1203
    58
{
dvander@1203
    59
	delete [] m_ColNames;
dvander@1203
    60
	free(m_Rows);
dvander@1203
    61
}
dvander@1203
    62
dvander@1203
    63
unsigned int SqResults::GetRowCount()
dvander@1203
    64
{
dvander@1203
    65
	return m_RowCount;
dvander@1203
    66
}
dvander@1203
    67
dvander@1203
    68
unsigned int SqResults::GetFieldCount()
dvander@1203
    69
{
dvander@1203
    70
	return m_ColCount;
dvander@1203
    71
}
dvander@1203
    72
dvander@1203
    73
const char *SqResults::FieldNumToName(unsigned int columnId)
dvander@1203
    74
{
dvander@1203
    75
	if (columnId >= m_ColCount)
dvander@1203
    76
	{
dvander@1203
    77
		return NULL;
dvander@1203
    78
	}
dvander@1203
    79
dvander@1203
    80
	return m_ColNames[columnId].c_str();
dvander@1203
    81
}
dvander@1203
    82
dvander@1203
    83
bool SqResults::FieldNameToNum(const char *name, unsigned int *columnId)
dvander@1203
    84
{
dvander@1203
    85
	for (unsigned int i=0; i<m_ColCount; i++)
dvander@1203
    86
	{
dvander@1203
    87
		if (m_ColNames[i].compare(name) == 0)
dvander@1203
    88
		{
dvander@1203
    89
			if (columnId)
dvander@1203
    90
			{
dvander@1203
    91
				*columnId = i;
dvander@1203
    92
			}
dvander@1203
    93
			return true;
dvander@1203
    94
		}
dvander@1203
    95
	}
dvander@1203
    96
	return false;
dvander@1203
    97
}
dvander@1203
    98
dvander@1203
    99
void SqResults::ResetResultCount()
dvander@1203
   100
{
dvander@1203
   101
	m_RowCount = 0;
dvander@1203
   102
	m_CurRow = 0;
dvander@1203
   103
	m_NextRow = 0;
dvander@1203
   104
	m_pMemory->Reset();
dvander@1203
   105
}
dvander@1203
   106
dvander@1203
   107
void SqResults::PushResult()
dvander@1203
   108
{
dvander@1203
   109
	/* First make sure we can fit one more row */
dvander@1203
   110
	if (m_RowCount + 1 > m_MaxRows)
dvander@1203
   111
	{
dvander@1203
   112
		/* Create a new array */
dvander@1203
   113
		if (!m_Rows)
dvander@1203
   114
		{
dvander@1203
   115
			m_MaxRows = 8;
dvander@1203
   116
			m_Rows = (SqField *)malloc(sizeof(SqField) * m_ColCount * m_MaxRows);
dvander@1203
   117
		} else {
dvander@1203
   118
			m_MaxRows *= 2;
dvander@1203
   119
			m_Rows = (SqField *)realloc(m_Rows, sizeof(SqField) * m_ColCount * m_MaxRows);
dvander@1203
   120
		}
dvander@1203
   121
	}
dvander@1203
   122
dvander@1203
   123
	SqField *row = &m_Rows[m_RowCount * m_ColCount];
dvander@1203
   124
	for (unsigned int i=0; i<m_ColCount; i++)
dvander@1203
   125
	{
dvander@1203
   126
		row[i].type = sqlite3_column_type(m_pStmt, i);
dvander@1203
   127
		if (row[i].type == SQLITE_INTEGER)
dvander@1203
   128
		{
dvander@1203
   129
			row[i].u.idx = sqlite3_column_int(m_pStmt, i);
dvander@1203
   130
			row[i].size = sizeof(int);
dvander@1203
   131
		} else if (row[i].type == SQLITE_FLOAT) {
dvander@1203
   132
			row[i].u.f = (float)sqlite3_column_double(m_pStmt, i);
dvander@1203
   133
			row[i].size = sizeof(float);
dvander@1203
   134
		} else if (row[i].type == SQLITE_BLOB) {
dvander@1203
   135
			int bytes = sqlite3_column_bytes(m_pStmt, i);
dvander@1203
   136
			const void *pOrig;
dvander@1203
   137
			if ((pOrig = sqlite3_column_blob(m_pStmt, i)) != NULL)
dvander@1203
   138
			{
dvander@1203
   139
				void *pAddr;
dvander@1203
   140
				row[i].u.idx = m_pMemory->CreateMem(bytes, &pAddr);
dvander@1203
   141
				memcpy(pAddr, pOrig, bytes);
dvander@1203
   142
			} else {
dvander@1203
   143
				row[i].u.idx = -1;
dvander@1203
   144
			}
dvander@1203
   145
			row[i].size = sqlite3_column_bytes(m_pStmt, i);
dvander@1203
   146
		} else if (row[i].type == SQLITE_TEXT) {
dvander@1203
   147
			const char *str = (const char *)sqlite3_column_text(m_pStmt, i);
dvander@1203
   148
			if (str)
dvander@1203
   149
			{
dvander@1203
   150
				row[i].u.idx = m_Strings.AddString(str);
dvander@1203
   151
			} else {
dvander@1203
   152
				row[i].u.idx = -1;
dvander@1203
   153
			}
dvander@1203
   154
			row[i].size = sqlite3_column_bytes(m_pStmt, i);
dvander@1203
   155
		} else {
dvander@1203
   156
			row[i].size = 0;
dvander@1203
   157
		}
dvander@1203
   158
	}
dvander@1203
   159
dvander@1203
   160
	/* Finally, increase the row count */
dvander@1203
   161
	m_RowCount++;
dvander@1203
   162
}
dvander@1203
   163
dvander@1203
   164
bool SqResults::MoreRows()
dvander@1203
   165
{
dvander@1203
   166
	return (m_CurRow < m_RowCount);
dvander@1203
   167
}
dvander@1203
   168
dvander@1203
   169
IResultRow *SqResults::FetchRow()
dvander@1203
   170
{
dvander@1203
   171
	m_CurRow = m_NextRow;
dvander@1203
   172
	if (m_CurRow >= m_RowCount)
dvander@1203
   173
	{
dvander@1203
   174
		return NULL;
dvander@1203
   175
	}
dvander@1203
   176
	m_NextRow++;
dvander@1203
   177
	return this;
dvander@1203
   178
}
dvander@1203
   179
dvander@1203
   180
IResultRow *SqResults::CurrentRow()
dvander@1203
   181
{
dvander@1203
   182
	if (!m_RowCount || m_CurRow >= m_RowCount)
dvander@1203
   183
	{
dvander@1203
   184
		return NULL;
dvander@1203
   185
	}
dvander@1203
   186
	return this;
dvander@1203
   187
}
dvander@1203
   188
dvander@1203
   189
bool SqResults::Rewind()
dvander@1203
   190
{
dvander@1203
   191
	m_CurRow = 0;
dvander@1203
   192
	m_NextRow = 0;
dvander@1203
   193
	return true;
dvander@1203
   194
}
dvander@1203
   195
dvander@1203
   196
SqField *SqResults::GetField(unsigned int col)
dvander@1203
   197
{
dvander@1203
   198
	if (m_CurRow >= m_RowCount || col >= m_ColCount)
dvander@1203
   199
	{
dvander@1203
   200
		return NULL;
dvander@1203
   201
	}
dvander@1203
   202
dvander@1203
   203
	return &m_Rows[(m_CurRow * m_ColCount) + col];
dvander@1203
   204
}
dvander@1203
   205
dvander@1203
   206
DBType SqResults::GetFieldType(unsigned int field)
dvander@1203
   207
{
dvander@1203
   208
	/* Leaving unimplemented... */
dvander@1203
   209
	return DBType_Unknown;
dvander@1203
   210
}
dvander@1203
   211
dvander@1203
   212
DBType SqResults::GetFieldDataType(unsigned int field)
dvander@1203
   213
{
dvander@1203
   214
	/* Leaving unimplemented... */
dvander@1203
   215
	return DBType_Unknown;
dvander@1203
   216
}
dvander@1203
   217
dvander@1203
   218
DBResult SqResults::GetString(unsigned int columnId, const char **pString, size_t *_length)
dvander@1203
   219
{
dvander@1203
   220
	SqField *field = GetField(columnId);
dvander@1203
   221
	if (!field)
dvander@1203
   222
	{
dvander@1203
   223
		return DBVal_Error;
dvander@1203
   224
	}
dvander@1203
   225
dvander@1203
   226
	DBResult res = DBVal_Data;
dvander@1203
   227
	const char *ptr = NULL;
dvander@1203
   228
	size_t length = 0;
dvander@1203
   229
	if (field->type == SQLITE_TEXT || field->type == SQLITE_BLOB)
dvander@1203
   230
	{
dvander@1203
   231
		ptr = m_Strings.GetString(field->u.idx);
dvander@1203
   232
		length = field->size;
dvander@1203
   233
	} else if (field->type == SQLITE_INTEGER) {
dvander@1203
   234
		char number[24];
dvander@1203
   235
		field->size = UTIL_Format(number, sizeof(number), "%d", field->u.idx);
dvander@1203
   236
		field->type = SQLITE_TEXT;
dvander@1203
   237
		field->u.idx = m_Strings.AddString(number);
dvander@1203
   238
		ptr = m_Strings.GetString(field->u.idx);
dvander@1203
   239
		length = field->size;
dvander@1203
   240
	} else if (field->type == SQLITE_FLOAT) {
dvander@1203
   241
		char number[24];
dvander@1203
   242
		field->size = UTIL_Format(number, sizeof(number), "%f", field->u.f);
dvander@1203
   243
		field->type = SQLITE_TEXT;
dvander@1203
   244
		field->u.idx = m_Strings.AddString(number);
dvander@1203
   245
		ptr = m_Strings.GetString(field->u.idx);
dvander@1203
   246
		length = field->size;
dvander@1203
   247
	} else if (field->type == SQLITE_NULL) {
dvander@1203
   248
		res = DBVal_Null;
dvander@1203
   249
	}
dvander@1203
   250
dvander@1203
   251
	if (!ptr)
dvander@1203
   252
	{
dvander@1203
   253
		ptr = "";
dvander@1203
   254
	}
dvander@1203
   255
faluco@1224
   256
	if (pString)
dvander@1203
   257
	{
dvander@1203
   258
		*pString = ptr;
dvander@1203
   259
	}
dvander@1203
   260
	if (_length)
dvander@1203
   261
	{
dvander@1203
   262
		*_length = length;
dvander@1203
   263
	}
dvander@1203
   264
dvander@1203
   265
	return res;
dvander@1203
   266
}
dvander@1203
   267
dvander@1203
   268
DBResult SqResults::CopyString(unsigned int columnId, char *buffer, size_t maxlength, size_t *written)
dvander@1203
   269
{
dvander@1203
   270
	SqField *field = GetField(columnId);
dvander@1203
   271
	if (!field)
dvander@1203
   272
	{
dvander@1203
   273
		return DBVal_Error;
dvander@1203
   274
	}
dvander@1203
   275
dvander@1203
   276
	DBResult res = DBVal_Data;
dvander@1203
   277
	if (field->type == SQLITE_TEXT || field->type == SQLITE_BLOB)
dvander@1203
   278
	{
dvander@1203
   279
		const char *ptr = m_Strings.GetString(field->u.idx);
dvander@1203
   280
		if (!ptr)
dvander@1203
   281
		{
dvander@1203
   282
			ptr = "";
dvander@1203
   283
			field->type = SQLITE_TEXT;
dvander@1203
   284
			res = DBVal_Null;
dvander@1203
   285
		}
dvander@1206
   286
		size_t wr = 0;
dvander@1203
   287
		if (field->type == SQLITE_TEXT)
dvander@1203
   288
		{
dvander@1203
   289
			wr = strncopy(buffer, ptr, maxlength);
dvander@1203
   290
		} else if (field->type == SQLITE_BLOB) {
dvander@1203
   291
			wr = (maxlength < field->size) ? maxlength : field->size;
dvander@1203
   292
			memcpy(buffer, ptr, wr);
dvander@1203
   293
		}
dvander@1203
   294
		if (written)
dvander@1203
   295
		{
dvander@1203
   296
			*written = wr;
dvander@1203
   297
		}
dvander@1203
   298
		return res;
dvander@1203
   299
	} else if (field->type == SQLITE_INTEGER) {
dvander@1203
   300
		size_t wr = 0;
dvander@1203
   301
		if (buffer)
dvander@1203
   302
		{
dvander@1203
   303
			wr = UTIL_Format(buffer, maxlength, "%d", field->u.idx);
dvander@1203
   304
		}
dvander@1203
   305
		if (written)
dvander@1203
   306
		{
dvander@1203
   307
			*written = wr;
dvander@1203
   308
		}
dvander@1203
   309
		return DBVal_Data;
dvander@1203
   310
	} else if (field->type == SQLITE_FLOAT) {
dvander@1203
   311
		size_t wr = 0;
dvander@1203
   312
		if (buffer)
dvander@1203
   313
		{
dvander@1203
   314
			wr = UTIL_Format(buffer, maxlength, "%f", field->u.f);
dvander@1203
   315
		}
dvander@1203
   316
		if (written)
dvander@1203
   317
		{
dvander@1203
   318
			*written = wr;
dvander@1203
   319
		}
dvander@1203
   320
		return DBVal_Data;
dvander@1203
   321
	}
dvander@1203
   322
dvander@1203
   323
	if (buffer)
dvander@1203
   324
	{
dvander@1203
   325
		strncopy(buffer, "", maxlength);
dvander@1203
   326
	}
dvander@1203
   327
	if (written)
dvander@1203
   328
	{
dvander@1203
   329
		*written = 0;
dvander@1203
   330
	}
dvander@1203
   331
dvander@1203
   332
	return DBVal_Null;
dvander@1203
   333
}
dvander@1203
   334
dvander@1203
   335
bool SqResults::IsNull(unsigned int columnId)
dvander@1203
   336
{
dvander@1203
   337
	SqField *field = GetField(columnId);
dvander@1203
   338
	if (!field)
dvander@1203
   339
	{
dvander@1203
   340
		return true;
dvander@1203
   341
	}
dvander@1203
   342
dvander@1203
   343
	return (field->type == SQLITE_NULL);
dvander@1203
   344
}
dvander@1203
   345
dvander@2471
   346
size_t SqResults::GetDataSize(unsigned int columnId)
dvander@1203
   347
{
dvander@1203
   348
	SqField *field = GetField(columnId);
dvander@1203
   349
	if (!field)
dvander@1203
   350
	{
dvander@1203
   351
		return 0;
dvander@1203
   352
	}
dvander@1203
   353
dvander@1203
   354
	return field->size;
dvander@1203
   355
}
dvander@1203
   356
dvander@1203
   357
DBResult SqResults::GetFloat(unsigned int columnId, float *pFloat)
dvander@1203
   358
{
dvander@1203
   359
	SqField *field = GetField(columnId);
dvander@1203
   360
	if (!field)
dvander@1203
   361
	{
dvander@1203
   362
		return DBVal_Error;
dvander@1203
   363
	} else if (field->type == SQLITE_BLOB) {
dvander@1203
   364
		return DBVal_Error;
dvander@1203
   365
	}
dvander@1203
   366
dvander@1203
   367
	float fVal = 0.0f;
dvander@1203
   368
	if (field->type == SQLITE_FLOAT)
dvander@1203
   369
	{
dvander@1203
   370
		fVal = field->u.f;
dvander@1203
   371
	} else if (field->type == SQLITE_TEXT) {
dvander@1203
   372
		const char *ptr = m_Strings.GetString(field->u.idx);
dvander@1203
   373
		if (ptr)
dvander@1203
   374
		{
dvander@1203
   375
			fVal = (float)atof(ptr);
dvander@1203
   376
		}
dvander@1203
   377
	} else if (field->type == SQLITE_INTEGER) {
dvander@1203
   378
		fVal = (float)field->u.idx;
dvander@1203
   379
	}
dvander@1203
   380
dvander@1203
   381
	if (pFloat)
dvander@1203
   382
	{
dvander@1203
   383
		*pFloat = fVal;
dvander@1203
   384
	}
dvander@1203
   385
dvander@1203
   386
	return (field->type == SQLITE_NULL) ? DBVal_Null : DBVal_Data;
dvander@1203
   387
}
dvander@1203
   388
dvander@1203
   389
DBResult SqResults::GetInt(unsigned int columnId, int *pInt)
dvander@1203
   390
{
dvander@1203
   391
	SqField *field = GetField(columnId);
dvander@1203
   392
	if (!field)
dvander@1203
   393
	{
dvander@1203
   394
		return DBVal_Error;
dvander@1203
   395
	} else if (field->type == SQLITE_BLOB) {
dvander@1203
   396
		return DBVal_Error;
dvander@1203
   397
	}
dvander@1203
   398
dvander@1203
   399
	int val = 0;
dvander@1203
   400
	if (field->type == SQLITE_INTEGER)
dvander@1203
   401
	{
dvander@1203
   402
		val = field->u.idx;
dvander@1203
   403
	} else if (field->type == SQLITE_TEXT) {
dvander@1203
   404
		const char *ptr = m_Strings.GetString(field->u.idx);
dvander@1203
   405
		if (ptr)
dvander@1203
   406
		{
dvander@1203
   407
			val = atoi(ptr);
dvander@1203
   408
		}
dvander@1203
   409
	} else if (field->type == SQLITE_FLOAT) {
dvander@1203
   410
		val = (int)field->u.f;
dvander@1203
   411
	}
dvander@1203
   412
dvander@1203
   413
	if (pInt)
dvander@1203
   414
	{
dvander@1203
   415
		*pInt = val;
dvander@1203
   416
	}
dvander@1203
   417
dvander@1203
   418
	return (field->type == SQLITE_NULL) ? DBVal_Null : DBVal_Data;
dvander@1203
   419
}
dvander@1203
   420
dvander@1203
   421
DBResult SqResults::GetBlob(unsigned int columnId, const void **pData, size_t *length)
dvander@1203
   422
{
dvander@1203
   423
	SqField *field = GetField(columnId);
dvander@1203
   424
	if (!field)
dvander@1203
   425
	{
dvander@1203
   426
		return DBVal_Error;
dvander@1203
   427
	} 
dvander@1203
   428
dvander@1203
   429
	void *addr = NULL;
dvander@1203
   430
dvander@1203
   431
	if (field->type == SQLITE_TEXT || field->type == SQLITE_BLOB)
dvander@1203
   432
	{
dvander@1203
   433
		addr = m_pMemory->GetAddress(field->u.idx);
dvander@1203
   434
	} else if (field->type == SQLITE_FLOAT || field->type == SQLITE_INTEGER) {
dvander@1203
   435
		addr = &(field->u);
dvander@1203
   436
	}
dvander@1203
   437
dvander@1203
   438
	if (pData)
dvander@1203
   439
	{
dvander@1203
   440
		*pData = addr;
dvander@1203
   441
	}
dvander@1203
   442
dvander@1203
   443
	if (length)
dvander@1203
   444
	{
dvander@1203
   445
		*length = field->size;
dvander@1203
   446
	}
dvander@1203
   447
dvander@1203
   448
	return (field->type == SQLITE_NULL) ? DBVal_Null : DBVal_Data;
dvander@1203
   449
}
dvander@1203
   450
dvander@1203
   451
DBResult SqResults::CopyBlob(unsigned int columnId, void *buffer, size_t maxlength, size_t *written)
dvander@1203
   452
{
dvander@1203
   453
	SqField *field = GetField(columnId);
dvander@1203
   454
	if (!field)
dvander@1203
   455
	{
dvander@1203
   456
		return DBVal_Error;
dvander@1203
   457
	} 
dvander@1203
   458
dvander@1203
   459
	void *addr = NULL;
dvander@1203
   460
dvander@1203
   461
	if (field->type == SQLITE_TEXT || field->type == SQLITE_BLOB)
dvander@1203
   462
	{
dvander@1203
   463
		addr = m_pMemory->GetAddress(field->u.idx);
dvander@1203
   464
	} else if (field->type == SQLITE_FLOAT || field->type == SQLITE_INTEGER) {
dvander@1203
   465
		addr = &(field->u);
dvander@1203
   466
	}
dvander@1203
   467
dvander@1203
   468
	size_t toCopy = field->size > maxlength ? maxlength : field->size;
dvander@1203
   469
	if (buffer && addr && toCopy)
dvander@1203
   470
	{
dvander@1203
   471
		memcpy(buffer, addr, toCopy);
dvander@1203
   472
	} else {
dvander@1203
   473
		toCopy = 0;
dvander@1203
   474
	}
dvander@1203
   475
dvander@1203
   476
	if (written)
dvander@1203
   477
	{
dvander@1203
   478
		*written = toCopy;
dvander@1203
   479
	}
dvander@1203
   480
dvander@1203
   481
	return (field->type == SQLITE_NULL) ? DBVal_Null : DBVal_Data;
dvander@1203
   482
}