dvander@1203: /** dvander@1203: * vim: set ts=4 : dvander@1203: * =============================================================== dvander@1203: * SourceMod SQLite Driver Extension dvander@1203: * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved. dvander@1203: * =============================================================== dvander@1203: * dvander@1203: * This program is free software; you can redistribute it and/or dvander@1203: * modify it under the terms of the GNU General Public License dvander@1203: * as published by the Free Software Foundation; either version 2 dvander@1203: * of the License, or (at your option) any later version. dvander@1203: * This program is distributed in the hope that it will be useful, dvander@1203: * but WITHOUT ANY WARRANTY; without even the implied warranty of dvander@1203: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the dvander@1203: * GNU General Public License for more details. dvander@1203: * dvander@1203: * You should have received a copy of the GNU General Public License dvander@1203: * along with this program; if not, write to the Free Software dvander@1203: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. dvander@1203: * dvander@1203: * Version: $Id$ dvander@1203: */ dvander@1203: dvander@1203: #include dvander@1203: #include "extension.h" dvander@1203: #include "SqResults.h" dvander@1203: #include "SqQuery.h" dvander@1203: dvander@1203: SqResults::SqResults(SqQuery *query) : dvander@1203: m_pStmt(query->GetStmt()), m_Strings(1024), dvander@1203: m_RowCount(0), m_MaxRows(0), m_Rows(NULL), dvander@1203: m_CurRow(0), m_NextRow(0) dvander@1203: { dvander@1203: m_ColCount = sqlite3_column_count(m_pStmt); dvander@1203: if (m_ColCount) dvander@1203: { dvander@1203: m_ColNames = new String[m_ColCount]; dvander@1203: for (unsigned int i=0; i= m_ColCount) dvander@1203: { dvander@1203: return NULL; dvander@1203: } dvander@1203: dvander@1203: return m_ColNames[columnId].c_str(); dvander@1203: } dvander@1203: dvander@1203: bool SqResults::FieldNameToNum(const char *name, unsigned int *columnId) dvander@1203: { dvander@1203: for (unsigned int i=0; iReset(); dvander@1203: } dvander@1203: dvander@1203: void SqResults::PushResult() dvander@1203: { dvander@1203: /* First make sure we can fit one more row */ dvander@1203: if (m_RowCount + 1 > m_MaxRows) dvander@1203: { dvander@1203: /* Create a new array */ dvander@1203: if (!m_Rows) dvander@1203: { dvander@1203: m_MaxRows = 8; dvander@1203: m_Rows = (SqField *)malloc(sizeof(SqField) * m_ColCount * m_MaxRows); dvander@1203: } else { dvander@1203: m_MaxRows *= 2; dvander@1203: m_Rows = (SqField *)realloc(m_Rows, sizeof(SqField) * m_ColCount * m_MaxRows); dvander@1203: } dvander@1203: } dvander@1203: dvander@1203: SqField *row = &m_Rows[m_RowCount * m_ColCount]; dvander@1203: for (unsigned int i=0; iCreateMem(bytes, &pAddr); dvander@1203: memcpy(pAddr, pOrig, bytes); dvander@1203: } else { dvander@1203: row[i].u.idx = -1; dvander@1203: } dvander@1203: row[i].size = sqlite3_column_bytes(m_pStmt, i); dvander@1203: } else if (row[i].type == SQLITE_TEXT) { dvander@1203: const char *str = (const char *)sqlite3_column_text(m_pStmt, i); dvander@1203: if (str) dvander@1203: { dvander@1203: row[i].u.idx = m_Strings.AddString(str); dvander@1203: } else { dvander@1203: row[i].u.idx = -1; dvander@1203: } dvander@1203: row[i].size = sqlite3_column_bytes(m_pStmt, i); dvander@1203: } else { dvander@1203: row[i].size = 0; dvander@1203: } dvander@1203: } dvander@1203: dvander@1203: /* Finally, increase the row count */ dvander@1203: m_RowCount++; dvander@1203: } dvander@1203: dvander@1203: bool SqResults::MoreRows() dvander@1203: { dvander@1203: return (m_CurRow < m_RowCount); dvander@1203: } dvander@1203: dvander@1203: IResultRow *SqResults::FetchRow() dvander@1203: { dvander@1203: m_CurRow = m_NextRow; dvander@1203: if (m_CurRow >= m_RowCount) dvander@1203: { dvander@1203: return NULL; dvander@1203: } dvander@1203: m_NextRow++; dvander@1203: return this; dvander@1203: } dvander@1203: dvander@1203: IResultRow *SqResults::CurrentRow() dvander@1203: { dvander@1203: if (!m_RowCount || m_CurRow >= m_RowCount) dvander@1203: { dvander@1203: return NULL; dvander@1203: } dvander@1203: return this; dvander@1203: } dvander@1203: dvander@1203: bool SqResults::Rewind() dvander@1203: { dvander@1203: m_CurRow = 0; dvander@1203: m_NextRow = 0; dvander@1203: return true; dvander@1203: } dvander@1203: dvander@1203: SqField *SqResults::GetField(unsigned int col) dvander@1203: { dvander@1203: if (m_CurRow >= m_RowCount || col >= m_ColCount) dvander@1203: { dvander@1203: return NULL; dvander@1203: } dvander@1203: dvander@1203: return &m_Rows[(m_CurRow * m_ColCount) + col]; dvander@1203: } dvander@1203: dvander@1203: DBType SqResults::GetFieldType(unsigned int field) dvander@1203: { dvander@1203: /* Leaving unimplemented... */ dvander@1203: return DBType_Unknown; dvander@1203: } dvander@1203: dvander@1203: DBType SqResults::GetFieldDataType(unsigned int field) dvander@1203: { dvander@1203: /* Leaving unimplemented... */ dvander@1203: return DBType_Unknown; dvander@1203: } dvander@1203: dvander@1203: DBResult SqResults::GetString(unsigned int columnId, const char **pString, size_t *_length) dvander@1203: { dvander@1203: SqField *field = GetField(columnId); dvander@1203: if (!field) dvander@1203: { dvander@1203: return DBVal_Error; dvander@1203: } dvander@1203: dvander@1203: DBResult res = DBVal_Data; dvander@1203: const char *ptr = NULL; dvander@1203: size_t length = 0; dvander@1203: if (field->type == SQLITE_TEXT || field->type == SQLITE_BLOB) dvander@1203: { dvander@1203: ptr = m_Strings.GetString(field->u.idx); dvander@1203: length = field->size; dvander@1203: } else if (field->type == SQLITE_INTEGER) { dvander@1203: char number[24]; dvander@1203: field->size = UTIL_Format(number, sizeof(number), "%d", field->u.idx); dvander@1203: field->type = SQLITE_TEXT; dvander@1203: field->u.idx = m_Strings.AddString(number); dvander@1203: ptr = m_Strings.GetString(field->u.idx); dvander@1203: length = field->size; dvander@1203: } else if (field->type == SQLITE_FLOAT) { dvander@1203: char number[24]; dvander@1203: field->size = UTIL_Format(number, sizeof(number), "%f", field->u.f); dvander@1203: field->type = SQLITE_TEXT; dvander@1203: field->u.idx = m_Strings.AddString(number); dvander@1203: ptr = m_Strings.GetString(field->u.idx); dvander@1203: length = field->size; dvander@1203: } else if (field->type == SQLITE_NULL) { dvander@1203: res = DBVal_Null; dvander@1203: } dvander@1203: dvander@1203: if (!ptr) dvander@1203: { dvander@1203: ptr = ""; dvander@1203: } dvander@1203: dvander@1203: if (*pString) dvander@1203: { dvander@1203: *pString = ptr; dvander@1203: } dvander@1203: if (_length) dvander@1203: { dvander@1203: *_length = length; dvander@1203: } dvander@1203: dvander@1203: return res; dvander@1203: } dvander@1203: dvander@1203: DBResult SqResults::CopyString(unsigned int columnId, char *buffer, size_t maxlength, size_t *written) dvander@1203: { dvander@1203: SqField *field = GetField(columnId); dvander@1203: if (!field) dvander@1203: { dvander@1203: return DBVal_Error; dvander@1203: } dvander@1203: dvander@1203: DBResult res = DBVal_Data; dvander@1203: if (field->type == SQLITE_TEXT || field->type == SQLITE_BLOB) dvander@1203: { dvander@1203: const char *ptr = m_Strings.GetString(field->u.idx); dvander@1203: if (!ptr) dvander@1203: { dvander@1203: ptr = ""; dvander@1203: field->type = SQLITE_TEXT; dvander@1203: res = DBVal_Null; dvander@1203: } dvander@1206: size_t wr = 0; dvander@1203: if (field->type == SQLITE_TEXT) dvander@1203: { dvander@1203: wr = strncopy(buffer, ptr, maxlength); dvander@1203: } else if (field->type == SQLITE_BLOB) { dvander@1203: wr = (maxlength < field->size) ? maxlength : field->size; dvander@1203: memcpy(buffer, ptr, wr); dvander@1203: } dvander@1203: if (written) dvander@1203: { dvander@1203: *written = wr; dvander@1203: } dvander@1203: return res; dvander@1203: } else if (field->type == SQLITE_INTEGER) { dvander@1203: size_t wr = 0; dvander@1203: if (buffer) dvander@1203: { dvander@1203: wr = UTIL_Format(buffer, maxlength, "%d", field->u.idx); dvander@1203: } dvander@1203: if (written) dvander@1203: { dvander@1203: *written = wr; dvander@1203: } dvander@1203: return DBVal_Data; dvander@1203: } else if (field->type == SQLITE_FLOAT) { dvander@1203: size_t wr = 0; dvander@1203: if (buffer) dvander@1203: { dvander@1203: wr = UTIL_Format(buffer, maxlength, "%f", field->u.f); dvander@1203: } dvander@1203: if (written) dvander@1203: { dvander@1203: *written = wr; dvander@1203: } dvander@1203: return DBVal_Data; dvander@1203: } dvander@1203: dvander@1203: if (buffer) dvander@1203: { dvander@1203: strncopy(buffer, "", maxlength); dvander@1203: } dvander@1203: if (written) dvander@1203: { dvander@1203: *written = 0; dvander@1203: } dvander@1203: dvander@1203: return DBVal_Null; dvander@1203: } dvander@1203: dvander@1203: bool SqResults::IsNull(unsigned int columnId) dvander@1203: { dvander@1203: SqField *field = GetField(columnId); dvander@1203: if (!field) dvander@1203: { dvander@1203: return true; dvander@1203: } dvander@1203: dvander@1203: return (field->type == SQLITE_NULL); dvander@1203: } dvander@1203: dvander@1203: unsigned int SqResults::GetDataSize(unsigned int columnId) dvander@1203: { dvander@1203: SqField *field = GetField(columnId); dvander@1203: if (!field) dvander@1203: { dvander@1203: return 0; dvander@1203: } dvander@1203: dvander@1203: return field->size; dvander@1203: } dvander@1203: dvander@1203: DBResult SqResults::GetFloat(unsigned int columnId, float *pFloat) dvander@1203: { dvander@1203: SqField *field = GetField(columnId); dvander@1203: if (!field) dvander@1203: { dvander@1203: return DBVal_Error; dvander@1203: } else if (field->type == SQLITE_BLOB) { dvander@1203: return DBVal_Error; dvander@1203: } dvander@1203: dvander@1203: float fVal = 0.0f; dvander@1203: if (field->type == SQLITE_FLOAT) dvander@1203: { dvander@1203: fVal = field->u.f; dvander@1203: } else if (field->type == SQLITE_TEXT) { dvander@1203: const char *ptr = m_Strings.GetString(field->u.idx); dvander@1203: if (ptr) dvander@1203: { dvander@1203: fVal = (float)atof(ptr); dvander@1203: } dvander@1203: } else if (field->type == SQLITE_INTEGER) { dvander@1203: fVal = (float)field->u.idx; dvander@1203: } dvander@1203: dvander@1203: if (pFloat) dvander@1203: { dvander@1203: *pFloat = fVal; dvander@1203: } dvander@1203: dvander@1203: return (field->type == SQLITE_NULL) ? DBVal_Null : DBVal_Data; dvander@1203: } dvander@1203: dvander@1203: DBResult SqResults::GetInt(unsigned int columnId, int *pInt) dvander@1203: { dvander@1203: SqField *field = GetField(columnId); dvander@1203: if (!field) dvander@1203: { dvander@1203: return DBVal_Error; dvander@1203: } else if (field->type == SQLITE_BLOB) { dvander@1203: return DBVal_Error; dvander@1203: } dvander@1203: dvander@1203: int val = 0; dvander@1203: if (field->type == SQLITE_INTEGER) dvander@1203: { dvander@1203: val = field->u.idx; dvander@1203: } else if (field->type == SQLITE_TEXT) { dvander@1203: const char *ptr = m_Strings.GetString(field->u.idx); dvander@1203: if (ptr) dvander@1203: { dvander@1203: val = atoi(ptr); dvander@1203: } dvander@1203: } else if (field->type == SQLITE_FLOAT) { dvander@1203: val = (int)field->u.f; dvander@1203: } dvander@1203: dvander@1203: if (pInt) dvander@1203: { dvander@1203: *pInt = val; dvander@1203: } dvander@1203: dvander@1203: return (field->type == SQLITE_NULL) ? DBVal_Null : DBVal_Data; dvander@1203: } dvander@1203: dvander@1203: DBResult SqResults::GetBlob(unsigned int columnId, const void **pData, size_t *length) dvander@1203: { dvander@1203: SqField *field = GetField(columnId); dvander@1203: if (!field) dvander@1203: { dvander@1203: return DBVal_Error; dvander@1203: } dvander@1203: dvander@1203: void *addr = NULL; dvander@1203: dvander@1203: if (field->type == SQLITE_TEXT || field->type == SQLITE_BLOB) dvander@1203: { dvander@1203: addr = m_pMemory->GetAddress(field->u.idx); dvander@1203: } else if (field->type == SQLITE_FLOAT || field->type == SQLITE_INTEGER) { dvander@1203: addr = &(field->u); dvander@1203: } dvander@1203: dvander@1203: if (pData) dvander@1203: { dvander@1203: *pData = addr; dvander@1203: } dvander@1203: dvander@1203: if (length) dvander@1203: { dvander@1203: *length = field->size; dvander@1203: } dvander@1203: dvander@1203: return (field->type == SQLITE_NULL) ? DBVal_Null : DBVal_Data; dvander@1203: } dvander@1203: dvander@1203: DBResult SqResults::CopyBlob(unsigned int columnId, void *buffer, size_t maxlength, size_t *written) dvander@1203: { dvander@1203: SqField *field = GetField(columnId); dvander@1203: if (!field) dvander@1203: { dvander@1203: return DBVal_Error; dvander@1203: } dvander@1203: dvander@1203: void *addr = NULL; dvander@1203: dvander@1203: if (field->type == SQLITE_TEXT || field->type == SQLITE_BLOB) dvander@1203: { dvander@1203: addr = m_pMemory->GetAddress(field->u.idx); dvander@1203: } else if (field->type == SQLITE_FLOAT || field->type == SQLITE_INTEGER) { dvander@1203: addr = &(field->u); dvander@1203: } dvander@1203: dvander@1203: size_t toCopy = field->size > maxlength ? maxlength : field->size; dvander@1203: if (buffer && addr && toCopy) dvander@1203: { dvander@1203: memcpy(buffer, addr, toCopy); dvander@1203: } else { dvander@1203: toCopy = 0; dvander@1203: } dvander@1203: dvander@1203: if (written) dvander@1203: { dvander@1203: *written = toCopy; dvander@1203: } dvander@1203: dvander@1203: return (field->type == SQLITE_NULL) ? DBVal_Null : DBVal_Data; dvander@1203: }