/** * vim: set ts=4 : * ============================================================================= * SourceMod SQLite Extension * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License, version 3.0, as published by the * Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . * * As a special exception, AlliedModders LLC gives you permission to link the * code of this program (as well as its derivative works) to "Half-Life 2," the * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software * by the Valve Corporation. You must obey the GNU General Public License in * all respects for all other code used. Additionally, AlliedModders LLC grants * this exception to all derivative works. AlliedModders LLC defines further * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), * or . * * Version: $Id$ */ #include #include "extension.h" #include "SqResults.h" #include "SqQuery.h" SqResults::SqResults(SqQuery *query) : m_pStmt(query->GetStmt()), m_Strings(1024), m_RowCount(0), m_MaxRows(0), m_Rows(NULL), m_CurRow(0), m_NextRow(0) { m_ColCount = sqlite3_column_count(m_pStmt); if (m_ColCount) { m_ColNames = new String[m_ColCount]; for (unsigned int i=0; i= m_ColCount) { return NULL; } return m_ColNames[columnId].c_str(); } bool SqResults::FieldNameToNum(const char *name, unsigned int *columnId) { for (unsigned int i=0; iReset(); } void SqResults::PushResult() { /* First make sure we can fit one more row */ if (m_RowCount + 1 > m_MaxRows) { /* Create a new array */ if (!m_Rows) { m_MaxRows = 8; m_Rows = (SqField *)malloc(sizeof(SqField) * m_ColCount * m_MaxRows); } else { m_MaxRows *= 2; m_Rows = (SqField *)realloc(m_Rows, sizeof(SqField) * m_ColCount * m_MaxRows); } } SqField *row = &m_Rows[m_RowCount * m_ColCount]; for (unsigned int i=0; iCreateMem(bytes, &pAddr); memcpy(pAddr, pOrig, bytes); } else { row[i].u.idx = -1; } row[i].size = sqlite3_column_bytes(m_pStmt, i); } else if (row[i].type == SQLITE_TEXT) { const char *str = (const char *)sqlite3_column_text(m_pStmt, i); if (str) { row[i].u.idx = m_Strings.AddString(str); } else { row[i].u.idx = -1; } row[i].size = sqlite3_column_bytes(m_pStmt, i); } else { row[i].size = 0; } } /* Finally, increase the row count */ m_RowCount++; } bool SqResults::MoreRows() { return (m_CurRow < m_RowCount); } IResultRow *SqResults::FetchRow() { m_CurRow = m_NextRow; if (m_CurRow >= m_RowCount) { return NULL; } m_NextRow++; return this; } IResultRow *SqResults::CurrentRow() { if (!m_RowCount || m_CurRow >= m_RowCount) { return NULL; } return this; } bool SqResults::Rewind() { m_CurRow = 0; m_NextRow = 0; return true; } SqField *SqResults::GetField(unsigned int col) { if (m_CurRow >= m_RowCount || col >= m_ColCount) { return NULL; } return &m_Rows[(m_CurRow * m_ColCount) + col]; } DBType SqResults::GetFieldType(unsigned int field) { /* Leaving unimplemented... */ return DBType_Unknown; } DBType SqResults::GetFieldDataType(unsigned int field) { /* Leaving unimplemented... */ return DBType_Unknown; } DBResult SqResults::GetString(unsigned int columnId, const char **pString, size_t *_length) { SqField *field = GetField(columnId); if (!field) { return DBVal_Error; } DBResult res = DBVal_Data; const char *ptr = NULL; size_t length = 0; if (field->type == SQLITE_TEXT || field->type == SQLITE_BLOB) { ptr = m_Strings.GetString(field->u.idx); length = field->size; } else if (field->type == SQLITE_INTEGER) { char number[24]; field->size = UTIL_Format(number, sizeof(number), "%d", field->u.idx); field->type = SQLITE_TEXT; field->u.idx = m_Strings.AddString(number); ptr = m_Strings.GetString(field->u.idx); length = field->size; } else if (field->type == SQLITE_FLOAT) { char number[24]; field->size = UTIL_Format(number, sizeof(number), "%f", field->u.f); field->type = SQLITE_TEXT; field->u.idx = m_Strings.AddString(number); ptr = m_Strings.GetString(field->u.idx); length = field->size; } else if (field->type == SQLITE_NULL) { res = DBVal_Null; } if (!ptr) { ptr = ""; } if (pString) { *pString = ptr; } if (_length) { *_length = length; } return res; } DBResult SqResults::CopyString(unsigned int columnId, char *buffer, size_t maxlength, size_t *written) { SqField *field = GetField(columnId); if (!field) { return DBVal_Error; } DBResult res = DBVal_Data; if (field->type == SQLITE_TEXT || field->type == SQLITE_BLOB) { const char *ptr = m_Strings.GetString(field->u.idx); if (!ptr) { ptr = ""; field->type = SQLITE_TEXT; res = DBVal_Null; } size_t wr = 0; if (field->type == SQLITE_TEXT) { wr = strncopy(buffer, ptr, maxlength); } else if (field->type == SQLITE_BLOB) { wr = (maxlength < field->size) ? maxlength : field->size; memcpy(buffer, ptr, wr); } if (written) { *written = wr; } return res; } else if (field->type == SQLITE_INTEGER) { size_t wr = 0; if (buffer) { wr = UTIL_Format(buffer, maxlength, "%d", field->u.idx); } if (written) { *written = wr; } return DBVal_Data; } else if (field->type == SQLITE_FLOAT) { size_t wr = 0; if (buffer) { wr = UTIL_Format(buffer, maxlength, "%f", field->u.f); } if (written) { *written = wr; } return DBVal_Data; } if (buffer) { strncopy(buffer, "", maxlength); } if (written) { *written = 0; } return DBVal_Null; } bool SqResults::IsNull(unsigned int columnId) { SqField *field = GetField(columnId); if (!field) { return true; } return (field->type == SQLITE_NULL); } size_t SqResults::GetDataSize(unsigned int columnId) { SqField *field = GetField(columnId); if (!field) { return 0; } return field->size; } DBResult SqResults::GetFloat(unsigned int columnId, float *pFloat) { SqField *field = GetField(columnId); if (!field) { return DBVal_Error; } else if (field->type == SQLITE_BLOB) { return DBVal_Error; } float fVal = 0.0f; if (field->type == SQLITE_FLOAT) { fVal = field->u.f; } else if (field->type == SQLITE_TEXT) { const char *ptr = m_Strings.GetString(field->u.idx); if (ptr) { fVal = (float)atof(ptr); } } else if (field->type == SQLITE_INTEGER) { fVal = (float)field->u.idx; } if (pFloat) { *pFloat = fVal; } return (field->type == SQLITE_NULL) ? DBVal_Null : DBVal_Data; } DBResult SqResults::GetInt(unsigned int columnId, int *pInt) { SqField *field = GetField(columnId); if (!field) { return DBVal_Error; } else if (field->type == SQLITE_BLOB) { return DBVal_Error; } int val = 0; if (field->type == SQLITE_INTEGER) { val = field->u.idx; } else if (field->type == SQLITE_TEXT) { const char *ptr = m_Strings.GetString(field->u.idx); if (ptr) { val = atoi(ptr); } } else if (field->type == SQLITE_FLOAT) { val = (int)field->u.f; } if (pInt) { *pInt = val; } return (field->type == SQLITE_NULL) ? DBVal_Null : DBVal_Data; } DBResult SqResults::GetBlob(unsigned int columnId, const void **pData, size_t *length) { SqField *field = GetField(columnId); if (!field) { return DBVal_Error; } void *addr = NULL; if (field->type == SQLITE_TEXT || field->type == SQLITE_BLOB) { addr = m_pMemory->GetAddress(field->u.idx); } else if (field->type == SQLITE_FLOAT || field->type == SQLITE_INTEGER) { addr = &(field->u); } if (pData) { *pData = addr; } if (length) { *length = field->size; } return (field->type == SQLITE_NULL) ? DBVal_Null : DBVal_Data; } DBResult SqResults::CopyBlob(unsigned int columnId, void *buffer, size_t maxlength, size_t *written) { SqField *field = GetField(columnId); if (!field) { return DBVal_Error; } void *addr = NULL; if (field->type == SQLITE_TEXT || field->type == SQLITE_BLOB) { addr = m_pMemory->GetAddress(field->u.idx); } else if (field->type == SQLITE_FLOAT || field->type == SQLITE_INTEGER) { addr = &(field->u); } size_t toCopy = field->size > maxlength ? maxlength : field->size; if (buffer && addr && toCopy) { memcpy(buffer, addr, toCopy); } else { toCopy = 0; } if (written) { *written = toCopy; } return (field->type == SQLITE_NULL) ? DBVal_Null : DBVal_Data; }