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