1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/extensions/sqlite/driver/SqResults.cpp Sun Jul 29 01:15:31 2007 +0000
1.3 @@ -0,0 +1,474 @@
1.4 +/**
1.5 + * vim: set ts=4 :
1.6 + * ===============================================================
1.7 + * SourceMod SQLite Driver Extension
1.8 + * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
1.9 + * ===============================================================
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or
1.12 + * modify it under the terms of the GNU General Public License
1.13 + * as published by the Free Software Foundation; either version 2
1.14 + * of the License, or (at your option) any later version.
1.15 + * This program is distributed in the hope that it will be useful,
1.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.18 + * GNU General Public License for more details.
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License
1.21 + * along with this program; if not, write to the Free Software
1.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1.23 + *
1.24 + * Version: $Id$
1.25 + */
1.26 +
1.27 +#include <stdlib.h>
1.28 +#include "extension.h"
1.29 +#include "SqResults.h"
1.30 +#include "SqQuery.h"
1.31 +
1.32 +SqResults::SqResults(SqQuery *query) :
1.33 + m_pStmt(query->GetStmt()), m_Strings(1024),
1.34 + m_RowCount(0), m_MaxRows(0), m_Rows(NULL),
1.35 + m_CurRow(0), m_NextRow(0)
1.36 +{
1.37 + m_ColCount = sqlite3_column_count(m_pStmt);
1.38 + if (m_ColCount)
1.39 + {
1.40 + m_ColNames = new String[m_ColCount];
1.41 + for (unsigned int i=0; i<m_ColCount; i++)
1.42 + {
1.43 + m_ColNames[i].assign(sqlite3_column_name(m_pStmt, i));
1.44 + }
1.45 + } else {
1.46 + m_ColNames = NULL;
1.47 + }
1.48 +
1.49 + m_pMemory = m_Strings.GetMemTable();
1.50 +}
1.51 +
1.52 +SqResults::~SqResults()
1.53 +{
1.54 + delete [] m_ColNames;
1.55 + free(m_Rows);
1.56 +}
1.57 +
1.58 +unsigned int SqResults::GetRowCount()
1.59 +{
1.60 + return m_RowCount;
1.61 +}
1.62 +
1.63 +unsigned int SqResults::GetFieldCount()
1.64 +{
1.65 + return m_ColCount;
1.66 +}
1.67 +
1.68 +const char *SqResults::FieldNumToName(unsigned int columnId)
1.69 +{
1.70 + if (columnId >= m_ColCount)
1.71 + {
1.72 + return NULL;
1.73 + }
1.74 +
1.75 + return m_ColNames[columnId].c_str();
1.76 +}
1.77 +
1.78 +bool SqResults::FieldNameToNum(const char *name, unsigned int *columnId)
1.79 +{
1.80 + for (unsigned int i=0; i<m_ColCount; i++)
1.81 + {
1.82 + if (m_ColNames[i].compare(name) == 0)
1.83 + {
1.84 + if (columnId)
1.85 + {
1.86 + *columnId = i;
1.87 + }
1.88 + return true;
1.89 + }
1.90 + }
1.91 + return false;
1.92 +}
1.93 +
1.94 +void SqResults::ResetResultCount()
1.95 +{
1.96 + m_RowCount = 0;
1.97 + m_CurRow = 0;
1.98 + m_NextRow = 0;
1.99 + m_pMemory->Reset();
1.100 +}
1.101 +
1.102 +void SqResults::PushResult()
1.103 +{
1.104 + /* First make sure we can fit one more row */
1.105 + if (m_RowCount + 1 > m_MaxRows)
1.106 + {
1.107 + /* Create a new array */
1.108 + if (!m_Rows)
1.109 + {
1.110 + m_MaxRows = 8;
1.111 + m_Rows = (SqField *)malloc(sizeof(SqField) * m_ColCount * m_MaxRows);
1.112 + } else {
1.113 + m_MaxRows *= 2;
1.114 + m_Rows = (SqField *)realloc(m_Rows, sizeof(SqField) * m_ColCount * m_MaxRows);
1.115 + }
1.116 + }
1.117 +
1.118 + SqField *row = &m_Rows[m_RowCount * m_ColCount];
1.119 + for (unsigned int i=0; i<m_ColCount; i++)
1.120 + {
1.121 + row[i].type = sqlite3_column_type(m_pStmt, i);
1.122 + if (row[i].type == SQLITE_INTEGER)
1.123 + {
1.124 + row[i].u.idx = sqlite3_column_int(m_pStmt, i);
1.125 + row[i].size = sizeof(int);
1.126 + } else if (row[i].type == SQLITE_FLOAT) {
1.127 + row[i].u.f = (float)sqlite3_column_double(m_pStmt, i);
1.128 + row[i].size = sizeof(float);
1.129 + } else if (row[i].type == SQLITE_BLOB) {
1.130 + int bytes = sqlite3_column_bytes(m_pStmt, i);
1.131 + const void *pOrig;
1.132 + if ((pOrig = sqlite3_column_blob(m_pStmt, i)) != NULL)
1.133 + {
1.134 + void *pAddr;
1.135 + row[i].u.idx = m_pMemory->CreateMem(bytes, &pAddr);
1.136 + memcpy(pAddr, pOrig, bytes);
1.137 + } else {
1.138 + row[i].u.idx = -1;
1.139 + }
1.140 + row[i].size = sqlite3_column_bytes(m_pStmt, i);
1.141 + } else if (row[i].type == SQLITE_TEXT) {
1.142 + const char *str = (const char *)sqlite3_column_text(m_pStmt, i);
1.143 + if (str)
1.144 + {
1.145 + row[i].u.idx = m_Strings.AddString(str);
1.146 + } else {
1.147 + row[i].u.idx = -1;
1.148 + }
1.149 + row[i].size = sqlite3_column_bytes(m_pStmt, i);
1.150 + } else {
1.151 + row[i].size = 0;
1.152 + }
1.153 + }
1.154 +
1.155 + /* Finally, increase the row count */
1.156 + m_RowCount++;
1.157 +}
1.158 +
1.159 +bool SqResults::MoreRows()
1.160 +{
1.161 + return (m_CurRow < m_RowCount);
1.162 +}
1.163 +
1.164 +IResultRow *SqResults::FetchRow()
1.165 +{
1.166 + m_CurRow = m_NextRow;
1.167 + if (m_CurRow >= m_RowCount)
1.168 + {
1.169 + return NULL;
1.170 + }
1.171 + m_NextRow++;
1.172 + return this;
1.173 +}
1.174 +
1.175 +IResultRow *SqResults::CurrentRow()
1.176 +{
1.177 + if (!m_RowCount || m_CurRow >= m_RowCount)
1.178 + {
1.179 + return NULL;
1.180 + }
1.181 + return this;
1.182 +}
1.183 +
1.184 +bool SqResults::Rewind()
1.185 +{
1.186 + m_CurRow = 0;
1.187 + m_NextRow = 0;
1.188 + return true;
1.189 +}
1.190 +
1.191 +SqField *SqResults::GetField(unsigned int col)
1.192 +{
1.193 + if (m_CurRow >= m_RowCount || col >= m_ColCount)
1.194 + {
1.195 + return NULL;
1.196 + }
1.197 +
1.198 + return &m_Rows[(m_CurRow * m_ColCount) + col];
1.199 +}
1.200 +
1.201 +DBType SqResults::GetFieldType(unsigned int field)
1.202 +{
1.203 + /* Leaving unimplemented... */
1.204 + return DBType_Unknown;
1.205 +}
1.206 +
1.207 +DBType SqResults::GetFieldDataType(unsigned int field)
1.208 +{
1.209 + /* Leaving unimplemented... */
1.210 + return DBType_Unknown;
1.211 +}
1.212 +
1.213 +DBResult SqResults::GetString(unsigned int columnId, const char **pString, size_t *_length)
1.214 +{
1.215 + SqField *field = GetField(columnId);
1.216 + if (!field)
1.217 + {
1.218 + return DBVal_Error;
1.219 + }
1.220 +
1.221 + DBResult res = DBVal_Data;
1.222 + const char *ptr = NULL;
1.223 + size_t length = 0;
1.224 + if (field->type == SQLITE_TEXT || field->type == SQLITE_BLOB)
1.225 + {
1.226 + ptr = m_Strings.GetString(field->u.idx);
1.227 + length = field->size;
1.228 + } else if (field->type == SQLITE_INTEGER) {
1.229 + char number[24];
1.230 + field->size = UTIL_Format(number, sizeof(number), "%d", field->u.idx);
1.231 + field->type = SQLITE_TEXT;
1.232 + field->u.idx = m_Strings.AddString(number);
1.233 + ptr = m_Strings.GetString(field->u.idx);
1.234 + length = field->size;
1.235 + } else if (field->type == SQLITE_FLOAT) {
1.236 + char number[24];
1.237 + field->size = UTIL_Format(number, sizeof(number), "%f", field->u.f);
1.238 + field->type = SQLITE_TEXT;
1.239 + field->u.idx = m_Strings.AddString(number);
1.240 + ptr = m_Strings.GetString(field->u.idx);
1.241 + length = field->size;
1.242 + } else if (field->type == SQLITE_NULL) {
1.243 + res = DBVal_Null;
1.244 + }
1.245 +
1.246 + if (!ptr)
1.247 + {
1.248 + ptr = "";
1.249 + }
1.250 +
1.251 + if (*pString)
1.252 + {
1.253 + *pString = ptr;
1.254 + }
1.255 + if (_length)
1.256 + {
1.257 + *_length = length;
1.258 + }
1.259 +
1.260 + return res;
1.261 +}
1.262 +
1.263 +DBResult SqResults::CopyString(unsigned int columnId, char *buffer, size_t maxlength, size_t *written)
1.264 +{
1.265 + SqField *field = GetField(columnId);
1.266 + if (!field)
1.267 + {
1.268 + return DBVal_Error;
1.269 + }
1.270 +
1.271 + DBResult res = DBVal_Data;
1.272 + if (field->type == SQLITE_TEXT || field->type == SQLITE_BLOB)
1.273 + {
1.274 + const char *ptr = m_Strings.GetString(field->u.idx);
1.275 + if (!ptr)
1.276 + {
1.277 + ptr = "";
1.278 + field->type = SQLITE_TEXT;
1.279 + res = DBVal_Null;
1.280 + }
1.281 + size_t wr;
1.282 + if (field->type == SQLITE_TEXT)
1.283 + {
1.284 + wr = strncopy(buffer, ptr, maxlength);
1.285 + } else if (field->type == SQLITE_BLOB) {
1.286 + wr = (maxlength < field->size) ? maxlength : field->size;
1.287 + memcpy(buffer, ptr, wr);
1.288 + }
1.289 + if (written)
1.290 + {
1.291 + *written = wr;
1.292 + }
1.293 + return res;
1.294 + } else if (field->type == SQLITE_INTEGER) {
1.295 + size_t wr = 0;
1.296 + if (buffer)
1.297 + {
1.298 + wr = UTIL_Format(buffer, maxlength, "%d", field->u.idx);
1.299 + }
1.300 + if (written)
1.301 + {
1.302 + *written = wr;
1.303 + }
1.304 + return DBVal_Data;
1.305 + } else if (field->type == SQLITE_FLOAT) {
1.306 + size_t wr = 0;
1.307 + if (buffer)
1.308 + {
1.309 + wr = UTIL_Format(buffer, maxlength, "%f", field->u.f);
1.310 + }
1.311 + if (written)
1.312 + {
1.313 + *written = wr;
1.314 + }
1.315 + return DBVal_Data;
1.316 + }
1.317 +
1.318 + if (buffer)
1.319 + {
1.320 + strncopy(buffer, "", maxlength);
1.321 + }
1.322 + if (written)
1.323 + {
1.324 + *written = 0;
1.325 + }
1.326 +
1.327 + return DBVal_Null;
1.328 +}
1.329 +
1.330 +bool SqResults::IsNull(unsigned int columnId)
1.331 +{
1.332 + SqField *field = GetField(columnId);
1.333 + if (!field)
1.334 + {
1.335 + return true;
1.336 + }
1.337 +
1.338 + return (field->type == SQLITE_NULL);
1.339 +}
1.340 +
1.341 +unsigned int SqResults::GetDataSize(unsigned int columnId)
1.342 +{
1.343 + SqField *field = GetField(columnId);
1.344 + if (!field)
1.345 + {
1.346 + return 0;
1.347 + }
1.348 +
1.349 + return field->size;
1.350 +}
1.351 +
1.352 +DBResult SqResults::GetFloat(unsigned int columnId, float *pFloat)
1.353 +{
1.354 + SqField *field = GetField(columnId);
1.355 + if (!field)
1.356 + {
1.357 + return DBVal_Error;
1.358 + } else if (field->type == SQLITE_BLOB) {
1.359 + return DBVal_Error;
1.360 + }
1.361 +
1.362 + float fVal = 0.0f;
1.363 + if (field->type == SQLITE_FLOAT)
1.364 + {
1.365 + fVal = field->u.f;
1.366 + } else if (field->type == SQLITE_TEXT) {
1.367 + const char *ptr = m_Strings.GetString(field->u.idx);
1.368 + if (ptr)
1.369 + {
1.370 + fVal = (float)atof(ptr);
1.371 + }
1.372 + } else if (field->type == SQLITE_INTEGER) {
1.373 + fVal = (float)field->u.idx;
1.374 + }
1.375 +
1.376 + if (pFloat)
1.377 + {
1.378 + *pFloat = fVal;
1.379 + }
1.380 +
1.381 + return (field->type == SQLITE_NULL) ? DBVal_Null : DBVal_Data;
1.382 +}
1.383 +
1.384 +DBResult SqResults::GetInt(unsigned int columnId, int *pInt)
1.385 +{
1.386 + SqField *field = GetField(columnId);
1.387 + if (!field)
1.388 + {
1.389 + return DBVal_Error;
1.390 + } else if (field->type == SQLITE_BLOB) {
1.391 + return DBVal_Error;
1.392 + }
1.393 +
1.394 + int val = 0;
1.395 + if (field->type == SQLITE_INTEGER)
1.396 + {
1.397 + val = field->u.idx;
1.398 + } else if (field->type == SQLITE_TEXT) {
1.399 + const char *ptr = m_Strings.GetString(field->u.idx);
1.400 + if (ptr)
1.401 + {
1.402 + val = atoi(ptr);
1.403 + }
1.404 + } else if (field->type == SQLITE_FLOAT) {
1.405 + val = (int)field->u.f;
1.406 + }
1.407 +
1.408 + if (pInt)
1.409 + {
1.410 + *pInt = val;
1.411 + }
1.412 +
1.413 + return (field->type == SQLITE_NULL) ? DBVal_Null : DBVal_Data;
1.414 +}
1.415 +
1.416 +DBResult SqResults::GetBlob(unsigned int columnId, const void **pData, size_t *length)
1.417 +{
1.418 + SqField *field = GetField(columnId);
1.419 + if (!field)
1.420 + {
1.421 + return DBVal_Error;
1.422 + }
1.423 +
1.424 + void *addr = NULL;
1.425 +
1.426 + if (field->type == SQLITE_TEXT || field->type == SQLITE_BLOB)
1.427 + {
1.428 + addr = m_pMemory->GetAddress(field->u.idx);
1.429 + } else if (field->type == SQLITE_FLOAT || field->type == SQLITE_INTEGER) {
1.430 + addr = &(field->u);
1.431 + }
1.432 +
1.433 + if (pData)
1.434 + {
1.435 + *pData = addr;
1.436 + }
1.437 +
1.438 + if (length)
1.439 + {
1.440 + *length = field->size;
1.441 + }
1.442 +
1.443 + return (field->type == SQLITE_NULL) ? DBVal_Null : DBVal_Data;
1.444 +}
1.445 +
1.446 +DBResult SqResults::CopyBlob(unsigned int columnId, void *buffer, size_t maxlength, size_t *written)
1.447 +{
1.448 + SqField *field = GetField(columnId);
1.449 + if (!field)
1.450 + {
1.451 + return DBVal_Error;
1.452 + }
1.453 +
1.454 + void *addr = NULL;
1.455 +
1.456 + if (field->type == SQLITE_TEXT || field->type == SQLITE_BLOB)
1.457 + {
1.458 + addr = m_pMemory->GetAddress(field->u.idx);
1.459 + } else if (field->type == SQLITE_FLOAT || field->type == SQLITE_INTEGER) {
1.460 + addr = &(field->u);
1.461 + }
1.462 +
1.463 + size_t toCopy = field->size > maxlength ? maxlength : field->size;
1.464 + if (buffer && addr && toCopy)
1.465 + {
1.466 + memcpy(buffer, addr, toCopy);
1.467 + } else {
1.468 + toCopy = 0;
1.469 + }
1.470 +
1.471 + if (written)
1.472 + {
1.473 + *written = toCopy;
1.474 + }
1.475 +
1.476 + return (field->type == SQLITE_NULL) ? DBVal_Null : DBVal_Data;
1.477 +}