initial import of sqlite extension
--HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401209
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* ===============================================================
|
||||
* SourceMod SQLite Driver Extension
|
||||
* Copyright (C) 2004-2007 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
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "extension.h"
|
||||
#include "SqDatabase.h"
|
||||
#include "SqQuery.h"
|
||||
|
||||
SqDatabase::SqDatabase(sqlite3 *sq3, bool persistent) :
|
||||
m_sq3(sq3), m_refcount(1), m_pFullLock(NULL), m_Persistent(persistent)
|
||||
{
|
||||
m_pRefLock = threader->MakeMutex();
|
||||
}
|
||||
|
||||
SqDatabase::~SqDatabase()
|
||||
{
|
||||
m_pRefLock->DestroyThis();
|
||||
if (m_pFullLock)
|
||||
{
|
||||
m_pFullLock->DestroyThis();
|
||||
}
|
||||
sqlite3_close(m_sq3);
|
||||
}
|
||||
|
||||
void SqDatabase::IncReferenceCount()
|
||||
{
|
||||
m_pRefLock->Lock();
|
||||
m_refcount++;
|
||||
m_pRefLock->Unlock();
|
||||
}
|
||||
|
||||
bool SqDatabase::Close()
|
||||
{
|
||||
m_pRefLock->Lock();
|
||||
if (m_refcount > 1)
|
||||
{
|
||||
m_refcount--;
|
||||
m_pRefLock->Unlock();
|
||||
return false;
|
||||
}
|
||||
m_pRefLock->Unlock();
|
||||
|
||||
if (m_Persistent)
|
||||
{
|
||||
g_SqDriver.RemovePersistent(this);
|
||||
}
|
||||
|
||||
delete this;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *SqDatabase::GetError(int *errorCode/* =NULL */)
|
||||
{
|
||||
return sqlite3_errmsg(m_sq3);
|
||||
}
|
||||
|
||||
bool SqDatabase::LockForFullAtomicOperation()
|
||||
{
|
||||
if (!m_pFullLock)
|
||||
{
|
||||
m_pFullLock = threader->MakeMutex();
|
||||
if (!m_pFullLock)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_pFullLock->Lock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SqDatabase::UnlockFromFullAtomicOperation()
|
||||
{
|
||||
if (m_pFullLock)
|
||||
{
|
||||
m_pFullLock->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
IDBDriver *SqDatabase::GetDriver()
|
||||
{
|
||||
return &g_SqDriver;
|
||||
}
|
||||
|
||||
bool SqDatabase::QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newSize)
|
||||
{
|
||||
char *res = sqlite3_snprintf(static_cast<int>(maxlen), buffer, "%q", str);
|
||||
|
||||
if (res != NULL && newSize != NULL)
|
||||
{
|
||||
*newSize = strlen(buffer);
|
||||
}
|
||||
|
||||
return (res != NULL);
|
||||
}
|
||||
|
||||
unsigned int SqDatabase::GetInsertID()
|
||||
{
|
||||
return (unsigned int)sqlite3_last_insert_rowid(m_sq3);
|
||||
}
|
||||
|
||||
unsigned int SqDatabase::GetAffectedRows()
|
||||
{
|
||||
return (unsigned int)sqlite3_changes(m_sq3);
|
||||
}
|
||||
|
||||
bool SqDatabase::DoSimpleQuery(const char *query)
|
||||
{
|
||||
IQuery *pQuery = DoQuery(query);
|
||||
if (!pQuery)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
pQuery->Destroy();
|
||||
return true;
|
||||
}
|
||||
|
||||
/* this sounds like daiquiri.. i'm tired. */
|
||||
IQuery *SqDatabase::DoQuery(const char *query)
|
||||
{
|
||||
IPreparedQuery *pQuery = PrepareQuery(query, NULL, 0, NULL);
|
||||
if (!pQuery)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (!pQuery->Execute())
|
||||
{
|
||||
pQuery->Destroy();
|
||||
return NULL;
|
||||
}
|
||||
return pQuery;
|
||||
}
|
||||
|
||||
IPreparedQuery *SqDatabase::PrepareQuery(const char *query, char *error, size_t maxlength, int *errCode/* =NULL */)
|
||||
{
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
if ((m_LastErrorCode = sqlite3_prepare_v2(m_sq3, query, -1, &stmt, NULL)) != SQLITE_OK
|
||||
|| !stmt)
|
||||
{
|
||||
const char *msg;
|
||||
if (m_LastErrorCode != SQLITE_OK)
|
||||
{
|
||||
msg = sqlite3_errmsg(m_sq3);
|
||||
} else {
|
||||
msg = "Invalid query string";
|
||||
m_LastErrorCode = SQLITE_MISUSE;
|
||||
}
|
||||
if (error)
|
||||
{
|
||||
strncopy(error, msg, maxlength);
|
||||
}
|
||||
m_LastError.assign(msg);
|
||||
if (stmt)
|
||||
{
|
||||
sqlite3_finalize(stmt);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
return new SqQuery(this, stmt);
|
||||
}
|
||||
|
||||
sqlite3 *SqDatabase::GetDb()
|
||||
{
|
||||
return m_sq3;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* ===============================================================
|
||||
* SourceMod SQLite Driver Extension
|
||||
* Copyright (C) 2004-2007 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
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SQLITE_SOURCEMOD_DATABASE_H_
|
||||
#define _INCLUDE_SQLITE_SOURCEMOD_DATABASE_H_
|
||||
|
||||
#include <IThreader.h>
|
||||
#include "SqDriver.h"
|
||||
|
||||
class SqDatabase : public IDatabase
|
||||
{
|
||||
public:
|
||||
SqDatabase(sqlite3 *sq3, bool persistent);
|
||||
~SqDatabase();
|
||||
public:
|
||||
bool Close();
|
||||
const char *GetError(int *errorCode=NULL);
|
||||
bool DoSimpleQuery(const char *query);
|
||||
IQuery *DoQuery(const char *query);
|
||||
IPreparedQuery *PrepareQuery(const char *query, char *error, size_t maxlength, int *errCode=NULL);
|
||||
bool QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newSize);
|
||||
unsigned int GetAffectedRows();
|
||||
unsigned int GetInsertID();
|
||||
bool LockForFullAtomicOperation();
|
||||
void UnlockFromFullAtomicOperation();
|
||||
void IncReferenceCount();
|
||||
IDBDriver *GetDriver();
|
||||
public:
|
||||
sqlite3 *GetDb();
|
||||
private:
|
||||
sqlite3 *m_sq3;
|
||||
unsigned int m_refcount;
|
||||
IMutex *m_pFullLock;
|
||||
IMutex *m_pRefLock;
|
||||
bool m_Persistent;
|
||||
String m_LastError;
|
||||
int m_LastErrorCode;
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SQLITE_SOURCEMOD_DATABASE_H_
|
||||
@@ -0,0 +1,244 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* ===============================================================
|
||||
* SourceMod SQLite Driver Extension
|
||||
* Copyright (C) 2004-2007 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
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <sm_platform.h>
|
||||
#include "extension.h"
|
||||
#include "SqDriver.h"
|
||||
#include "SqDatabase.h"
|
||||
|
||||
SqDriver g_SqDriver;
|
||||
|
||||
unsigned int strncopy(char *dest, const char *src, size_t count)
|
||||
{
|
||||
if (!count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *start = dest;
|
||||
while ((*src) && (--count))
|
||||
{
|
||||
*dest++ = *src++;
|
||||
}
|
||||
*dest = '\0';
|
||||
|
||||
return (dest - start);
|
||||
}
|
||||
|
||||
SqDriver::SqDriver()
|
||||
{
|
||||
m_Handle = BAD_HANDLE;
|
||||
m_pOpenLock = NULL;
|
||||
}
|
||||
|
||||
void SqDriver::Initialize()
|
||||
{
|
||||
m_pOpenLock = threader->MakeMutex();
|
||||
}
|
||||
|
||||
void SqDriver::Shutdown()
|
||||
{
|
||||
if (m_pOpenLock)
|
||||
{
|
||||
m_pOpenLock->DestroyThis();
|
||||
}
|
||||
}
|
||||
|
||||
bool SqDriver::IsThreadSafe()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SqDriver::InitializeThreadSafety()
|
||||
{
|
||||
/* sqlite should be thread safe if the locks are done right.
|
||||
* we don't enable the "shared cache" because it can corrupt
|
||||
* open databases!
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
void SqDriver::ShutdownThreadSafety()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IdentityToken_t *SqDriver::GetIdentity()
|
||||
{
|
||||
return myself->GetIdentity();
|
||||
}
|
||||
|
||||
const char *SqDriver::GetProductName()
|
||||
{
|
||||
return "SQLite";
|
||||
}
|
||||
|
||||
const char *SqDriver::GetIdentifier()
|
||||
{
|
||||
return "sqlite";
|
||||
}
|
||||
|
||||
Handle_t SqDriver::GetHandle()
|
||||
{
|
||||
if (m_Handle == BAD_HANDLE)
|
||||
{
|
||||
m_Handle = dbi->CreateHandle(DBHandle_Driver, this, myself->GetIdentity());
|
||||
}
|
||||
|
||||
return m_Handle;
|
||||
}
|
||||
|
||||
inline bool IsPathSepChar(char c)
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
return (c == '\\' || c == '/');
|
||||
#elif defined PLATFORM_LINUX
|
||||
return (c == '/');
|
||||
#endif
|
||||
}
|
||||
|
||||
IDatabase *SqDriver::Connect(const DatabaseInfo *info, bool persistent, char *error, size_t maxlength)
|
||||
{
|
||||
/* We wrap most of the open process in a mutex just to be safe */
|
||||
m_pOpenLock->Lock();
|
||||
|
||||
/* Format our path */
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
size_t len = libsys->PathFormat(path, sizeof(path), "sqlite/%s", info->database);
|
||||
|
||||
/* Chop any filename off */
|
||||
for (size_t i = len-1;
|
||||
i >= 0 && i <= len-1;
|
||||
i--)
|
||||
{
|
||||
if (IsPathSepChar(path[i]))
|
||||
{
|
||||
path[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Test the full path */
|
||||
char fullpath[PLATFORM_MAX_PATH];
|
||||
g_pSM->BuildPath(Path_SM, fullpath, sizeof(fullpath), "data/%s", path);
|
||||
if (!libsys->IsPathDirectory(fullpath))
|
||||
{
|
||||
/* Make sure the data folder exists */
|
||||
len = g_pSM->BuildPath(Path_SM, fullpath, sizeof(fullpath), "data");
|
||||
if (!libsys->IsPathDirectory(fullpath))
|
||||
{
|
||||
if (!libsys->CreateFolder(fullpath))
|
||||
{
|
||||
strncopy(error, "Could not create or open \"data\" folder\"", maxlength);
|
||||
m_pOpenLock->Unlock();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* The data folder exists - create each subdir as needed! */
|
||||
char *cur_ptr = path;
|
||||
|
||||
do
|
||||
{
|
||||
/* Find the next suitable path */
|
||||
char *next_ptr = cur_ptr;
|
||||
while (*next_ptr != '\0')
|
||||
{
|
||||
if (IsPathSepChar(*next_ptr))
|
||||
{
|
||||
*next_ptr = '\0';
|
||||
next_ptr++;
|
||||
break;
|
||||
}
|
||||
next_ptr++;
|
||||
}
|
||||
if (*next_ptr == '\0')
|
||||
{
|
||||
next_ptr = NULL;
|
||||
}
|
||||
len += libsys->PathFormat(&fullpath[len], sizeof(fullpath)-len, "/%s", cur_ptr);
|
||||
if (!libsys->IsPathDirectory(fullpath) && !libsys->CreateFolder(fullpath))
|
||||
{
|
||||
break;
|
||||
}
|
||||
cur_ptr = next_ptr;
|
||||
} while (cur_ptr);
|
||||
}
|
||||
|
||||
/* Build the FINAL path. */
|
||||
g_pSM->BuildPath(Path_SM, fullpath, sizeof(fullpath), "data/sqlite/%s.sq3", info->database);
|
||||
|
||||
/* If we're requesting a persistent connection, see if something is already open */
|
||||
if (persistent)
|
||||
{
|
||||
/* See if anything in the cache matches */
|
||||
List<SqDbInfo>::iterator iter;
|
||||
for (iter = m_Cache.begin(); iter != m_Cache.end(); iter++)
|
||||
{
|
||||
if ((*iter).path.compare(fullpath) == 0)
|
||||
{
|
||||
(*iter).db->IncReferenceCount();
|
||||
m_pOpenLock->Unlock();
|
||||
return (*iter).db;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to open a new connection */
|
||||
sqlite3 *sql;
|
||||
int err = sqlite3_open(fullpath, &sql);
|
||||
if (err != SQLITE_OK)
|
||||
{
|
||||
strncopy(error, sqlite3_errmsg(sql), maxlength);
|
||||
sqlite3_close(sql);
|
||||
m_pOpenLock->Unlock();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SqDatabase *pdb = new SqDatabase(sql, persistent);
|
||||
|
||||
if (persistent)
|
||||
{
|
||||
SqDbInfo pinfo;
|
||||
pinfo.path = fullpath;
|
||||
pinfo.db = pdb;
|
||||
m_Cache.push_back(pinfo);
|
||||
}
|
||||
|
||||
m_pOpenLock->Unlock();
|
||||
|
||||
return pdb;
|
||||
}
|
||||
|
||||
void SqDriver::RemovePersistent(IDatabase *pdb)
|
||||
{
|
||||
List<SqDbInfo>::iterator iter;
|
||||
for (iter = m_Cache.begin(); iter != m_Cache.end(); iter++)
|
||||
{
|
||||
if ((*iter).db == pdb)
|
||||
{
|
||||
iter = m_Cache.erase(iter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* ===============================================================
|
||||
* SourceMod SQLite Driver Extension
|
||||
* Copyright (C) 2004-2007 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
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SQLITE_SOURCEMOD_DRIVER_H_
|
||||
#define _INCLUDE_SQLITE_SOURCEMOD_DRIVER_H_
|
||||
|
||||
#include <IDBDriver.h>
|
||||
#include <IThreader.h>
|
||||
#include <sh_list.h>
|
||||
#include <sh_string.h>
|
||||
#include "sqlite-source/sqlite3.h"
|
||||
|
||||
using namespace SourceMod;
|
||||
using namespace SourceHook;
|
||||
|
||||
struct SqDbInfo
|
||||
{
|
||||
String path;
|
||||
IDatabase *db;
|
||||
};
|
||||
|
||||
/**
|
||||
* Tee-hee.. sounds like "screw driver," except maybe if
|
||||
* Elmer Fudd was saying it.
|
||||
*/
|
||||
class SqDriver : public IDBDriver
|
||||
{
|
||||
public:
|
||||
SqDriver();
|
||||
void Initialize();
|
||||
void Shutdown();
|
||||
public:
|
||||
IDatabase *Connect(const DatabaseInfo *info, bool persistent, char *error, size_t maxlength);
|
||||
const char *GetIdentifier();
|
||||
const char *GetProductName();
|
||||
Handle_t GetHandle();
|
||||
IdentityToken_t *GetIdentity();
|
||||
bool IsThreadSafe();
|
||||
bool InitializeThreadSafety();
|
||||
void ShutdownThreadSafety();
|
||||
public:
|
||||
void RemovePersistent(IDatabase *pdb);
|
||||
private:
|
||||
Handle_t m_Handle;
|
||||
IMutex *m_pOpenLock;
|
||||
List<SqDbInfo> m_Cache;
|
||||
};
|
||||
|
||||
extern SqDriver g_SqDriver;
|
||||
|
||||
unsigned int strncopy(char *dest, const char *src, size_t count);
|
||||
|
||||
#endif //_INCLUDE_SQLITE_SOURCEMOD_DRIVER_H_
|
||||
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* ===============================================================
|
||||
* SourceMod SQLite Driver Extension
|
||||
* Copyright (C) 2004-2007 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
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "SqQuery.h"
|
||||
|
||||
SqQuery::SqQuery(SqDatabase *parent, sqlite3_stmt *stmt) :
|
||||
m_pParent(parent), m_pStmt(stmt), m_pResults(NULL), m_AffectedRows(0), m_InsertID(0)
|
||||
{
|
||||
m_ParamCount = sqlite3_bind_parameter_count(m_pStmt);
|
||||
m_pParent->IncReferenceCount();
|
||||
}
|
||||
|
||||
SqQuery::~SqQuery()
|
||||
{
|
||||
delete m_pResults;
|
||||
sqlite3_finalize(m_pStmt);
|
||||
m_pParent->Close();
|
||||
}
|
||||
|
||||
IResultSet *SqQuery::GetResultSet()
|
||||
{
|
||||
return m_pResults;
|
||||
}
|
||||
|
||||
bool SqQuery::FetchMoreResults()
|
||||
{
|
||||
/* We never have multiple result sets */
|
||||
return false;
|
||||
}
|
||||
|
||||
void SqQuery::Destroy()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
bool SqQuery::BindParamFloat(unsigned int param, float f)
|
||||
{
|
||||
/* SQLite is 1 indexed */
|
||||
param++;
|
||||
|
||||
if (param > m_ParamCount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (sqlite3_bind_double(m_pStmt, param, (double)f) == SQLITE_OK);
|
||||
}
|
||||
|
||||
bool SqQuery::BindParamNull(unsigned int param)
|
||||
{
|
||||
/* SQLite is 1 indexed */
|
||||
param++;
|
||||
|
||||
if (param > m_ParamCount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (sqlite3_bind_null(m_pStmt, param) == SQLITE_OK);
|
||||
}
|
||||
|
||||
bool SqQuery::BindParamString(unsigned int param, const char *text, bool copy)
|
||||
{
|
||||
/* SQLite is 1 indexed */
|
||||
param++;
|
||||
|
||||
if (param > m_ParamCount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (sqlite3_bind_text(m_pStmt, param, text, -1, copy ? SQLITE_TRANSIENT : SQLITE_STATIC) == SQLITE_OK);
|
||||
}
|
||||
|
||||
bool SqQuery::BindParamInt(unsigned int param, int num, bool signd/* =true */)
|
||||
{
|
||||
/* SQLite is 1 indexed */
|
||||
param++;
|
||||
|
||||
if (param > m_ParamCount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (sqlite3_bind_int(m_pStmt, param, num) == SQLITE_OK);
|
||||
}
|
||||
|
||||
bool SqQuery::BindParamBlob(unsigned int param, const void *data, size_t length, bool copy)
|
||||
{
|
||||
/* SQLite is 1 indexed */
|
||||
param++;
|
||||
|
||||
if (param > m_ParamCount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (sqlite3_bind_blob(m_pStmt, param, data, length, copy ? SQLITE_TRANSIENT : SQLITE_STATIC) == SQLITE_OK);
|
||||
}
|
||||
|
||||
sqlite3_stmt *SqQuery::GetStmt()
|
||||
{
|
||||
return m_pStmt;
|
||||
}
|
||||
|
||||
bool SqQuery::Execute()
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* If we've got results, throw them away */
|
||||
if (m_pResults)
|
||||
{
|
||||
m_pResults->ResetResultCount();
|
||||
}
|
||||
|
||||
while ((rc = sqlite3_step(m_pStmt)) == SQLITE_ROW)
|
||||
{
|
||||
/* Delay creation as long as possible... */
|
||||
if (!m_pResults)
|
||||
{
|
||||
m_pResults = new SqResults(this);
|
||||
}
|
||||
m_pResults->PushResult();
|
||||
}
|
||||
|
||||
sqlite3 *db = m_pParent->GetDb();
|
||||
if (rc != SQLITE_OK && rc != SQLITE_DONE && rc == sqlite3_errcode(db))
|
||||
{
|
||||
/* Something happened... */
|
||||
m_LastErrorCode = rc;
|
||||
m_LastError.assign(sqlite3_errmsg(db));
|
||||
m_AffectedRows = 0;
|
||||
m_InsertID = 0;
|
||||
} else {
|
||||
m_LastErrorCode = SQLITE_OK;
|
||||
m_AffectedRows = (unsigned int)sqlite3_changes(db);
|
||||
m_InsertID = (unsigned int)sqlite3_last_insert_rowid(db);
|
||||
}
|
||||
|
||||
/* Reset everything for the next execute */
|
||||
sqlite3_reset(m_pStmt);
|
||||
sqlite3_clear_bindings(m_pStmt);
|
||||
|
||||
return (m_LastErrorCode == SQLITE_OK);
|
||||
}
|
||||
|
||||
const char *SqQuery::GetError(int *errCode/* =NULL */)
|
||||
{
|
||||
if (errCode)
|
||||
{
|
||||
*errCode = m_LastErrorCode;
|
||||
}
|
||||
return m_LastError.c_str();
|
||||
}
|
||||
|
||||
unsigned int SqQuery::GetAffectedRows()
|
||||
{
|
||||
return m_AffectedRows;
|
||||
}
|
||||
|
||||
unsigned int SqQuery::GetInsertID()
|
||||
{
|
||||
return m_InsertID;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* ===============================================================
|
||||
* SourceMod SQLite Driver Extension
|
||||
* Copyright (C) 2004-2007 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
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SQLITE_SOURCEMOD_QUERY_H_
|
||||
#define _INCLUDE_SQLITE_SOURCEMOD_QUERY_H_
|
||||
|
||||
#include "SqDatabase.h"
|
||||
#include "SqResults.h"
|
||||
|
||||
class SqQuery :
|
||||
public IPreparedQuery
|
||||
{
|
||||
public:
|
||||
SqQuery(SqDatabase *parent, sqlite3_stmt *stmt);
|
||||
~SqQuery();
|
||||
public: //IQuery
|
||||
IResultSet *GetResultSet();
|
||||
bool FetchMoreResults();
|
||||
void Destroy();
|
||||
public: //IPreparedQuery
|
||||
bool BindParamInt(unsigned int param, int num, bool signd=true);
|
||||
bool BindParamFloat(unsigned int param, float f);
|
||||
bool BindParamNull(unsigned int param);
|
||||
bool BindParamString(unsigned int param, const char *text, bool copy);
|
||||
bool BindParamBlob(unsigned int param, const void *data, size_t length, bool copy);
|
||||
bool Execute();
|
||||
const char *GetError(int *errCode=NULL);
|
||||
unsigned int GetAffectedRows();
|
||||
unsigned int GetInsertID();
|
||||
public: //IResultSet
|
||||
unsigned int GetRowCount();
|
||||
unsigned int GetFieldCount();
|
||||
const char *FieldNumToName(unsigned int columnId);
|
||||
bool FieldNameToNum(const char *name, unsigned int *columnId);
|
||||
bool MoreRows();
|
||||
IResultRow *FetchRow();
|
||||
IResultRow *CurrentRow();
|
||||
bool Rewind();
|
||||
DBType GetFieldType(unsigned int field);
|
||||
DBType GetFieldDataType(unsigned int field);
|
||||
public: //IResultRow
|
||||
DBResult GetString(unsigned int columnId, const char **pString, size_t *length);
|
||||
DBResult CopyString(unsigned int columnId,
|
||||
char *buffer,
|
||||
size_t maxlength,
|
||||
size_t *written);
|
||||
DBResult GetFloat(unsigned int columnId, float *pFloat);
|
||||
DBResult GetInt(unsigned int columnId, int *pInt);
|
||||
bool IsNull(unsigned int columnId);
|
||||
size_t GetDataSize(unsigned int columnId);
|
||||
DBResult GetBlob(unsigned int columnId, const void **pData, size_t *length);
|
||||
DBResult CopyBlob(unsigned int columnId, void *buffer, size_t maxlength, size_t *written);
|
||||
public:
|
||||
sqlite3_stmt *GetStmt();
|
||||
private:
|
||||
SqDatabase *m_pParent;
|
||||
sqlite3_stmt *m_pStmt;
|
||||
SqResults *m_pResults;
|
||||
unsigned int m_ParamCount;
|
||||
String m_LastError;
|
||||
int m_LastErrorCode;
|
||||
unsigned int m_AffectedRows;
|
||||
unsigned int m_InsertID;
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SQLITE_SOURCEMOD_QUERY_H_
|
||||
@@ -0,0 +1,474 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* ===============================================================
|
||||
* SourceMod SQLite Driver Extension
|
||||
* Copyright (C) 2004-2007 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
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#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; i++)
|
||||
{
|
||||
m_ColNames[i].assign(sqlite3_column_name(m_pStmt, i));
|
||||
}
|
||||
} else {
|
||||
m_ColNames = NULL;
|
||||
}
|
||||
|
||||
m_pMemory = m_Strings.GetMemTable();
|
||||
}
|
||||
|
||||
SqResults::~SqResults()
|
||||
{
|
||||
delete [] m_ColNames;
|
||||
free(m_Rows);
|
||||
}
|
||||
|
||||
unsigned int SqResults::GetRowCount()
|
||||
{
|
||||
return m_RowCount;
|
||||
}
|
||||
|
||||
unsigned int SqResults::GetFieldCount()
|
||||
{
|
||||
return m_ColCount;
|
||||
}
|
||||
|
||||
const char *SqResults::FieldNumToName(unsigned int columnId)
|
||||
{
|
||||
if (columnId >= m_ColCount)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_ColNames[columnId].c_str();
|
||||
}
|
||||
|
||||
bool SqResults::FieldNameToNum(const char *name, unsigned int *columnId)
|
||||
{
|
||||
for (unsigned int i=0; i<m_ColCount; i++)
|
||||
{
|
||||
if (m_ColNames[i].compare(name) == 0)
|
||||
{
|
||||
if (columnId)
|
||||
{
|
||||
*columnId = i;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SqResults::ResetResultCount()
|
||||
{
|
||||
m_RowCount = 0;
|
||||
m_CurRow = 0;
|
||||
m_NextRow = 0;
|
||||
m_pMemory->Reset();
|
||||
}
|
||||
|
||||
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; i<m_ColCount; i++)
|
||||
{
|
||||
row[i].type = sqlite3_column_type(m_pStmt, i);
|
||||
if (row[i].type == SQLITE_INTEGER)
|
||||
{
|
||||
row[i].u.idx = sqlite3_column_int(m_pStmt, i);
|
||||
row[i].size = sizeof(int);
|
||||
} else if (row[i].type == SQLITE_FLOAT) {
|
||||
row[i].u.f = (float)sqlite3_column_double(m_pStmt, i);
|
||||
row[i].size = sizeof(float);
|
||||
} else if (row[i].type == SQLITE_BLOB) {
|
||||
int bytes = sqlite3_column_bytes(m_pStmt, i);
|
||||
const void *pOrig;
|
||||
if ((pOrig = sqlite3_column_blob(m_pStmt, i)) != NULL)
|
||||
{
|
||||
void *pAddr;
|
||||
row[i].u.idx = m_pMemory->CreateMem(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;
|
||||
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);
|
||||
}
|
||||
|
||||
unsigned int 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;
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* ===============================================================
|
||||
* SourceMod SQLite Driver Extension
|
||||
* Copyright (C) 2004-2007 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
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SQLITE_SOURCEMOD_RESULT_SET_H_
|
||||
#define _INCLUDE_SQLITE_SOURCEMOD_RESULT_SET_H_
|
||||
|
||||
#include "SqDriver.h"
|
||||
#include "sm_memtable.h"
|
||||
|
||||
class SqQuery;
|
||||
|
||||
struct SqField
|
||||
{
|
||||
int type;
|
||||
union
|
||||
{
|
||||
int idx;
|
||||
float f;
|
||||
} u;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
class SqResults :
|
||||
public IResultSet,
|
||||
public IResultRow
|
||||
{
|
||||
friend class SqQuery;
|
||||
public:
|
||||
SqResults(SqQuery *query);
|
||||
~SqResults();
|
||||
public: //IResultSet
|
||||
unsigned int GetRowCount();
|
||||
unsigned int GetFieldCount();
|
||||
const char *FieldNumToName(unsigned int columnId);
|
||||
bool FieldNameToNum(const char *name, unsigned int *columnId);
|
||||
bool MoreRows();
|
||||
IResultRow *FetchRow();
|
||||
IResultRow *CurrentRow();
|
||||
bool Rewind();
|
||||
DBType GetFieldType(unsigned int field);
|
||||
DBType GetFieldDataType(unsigned int field);
|
||||
public: //IResultRow
|
||||
DBResult GetString(unsigned int columnId, const char **pString, size_t *length);
|
||||
DBResult CopyString(unsigned int columnId,
|
||||
char *buffer,
|
||||
size_t maxlength,
|
||||
size_t *written);
|
||||
DBResult GetFloat(unsigned int columnId, float *pFloat);
|
||||
DBResult GetInt(unsigned int columnId, int *pInt);
|
||||
bool IsNull(unsigned int columnId);
|
||||
size_t GetDataSize(unsigned int columnId);
|
||||
DBResult GetBlob(unsigned int columnId, const void **pData, size_t *length);
|
||||
DBResult CopyBlob(unsigned int columnId, void *buffer, size_t maxlength, size_t *written);
|
||||
public:
|
||||
void ResetResultCount();
|
||||
void PushResult();
|
||||
private:
|
||||
SqField *GetField(unsigned int col);
|
||||
private:
|
||||
sqlite3_stmt *m_pStmt; /** DOES NOT CHANGE */
|
||||
String *m_ColNames; /** DOES NOT CHANGE */
|
||||
unsigned int m_ColCount; /** DOES NOT CHANGE */
|
||||
unsigned int m_RowCount;
|
||||
unsigned int m_MaxRows;
|
||||
BaseMemTable *m_pMemory; /** DOES NOT CHANGE */
|
||||
BaseStringTable m_Strings; /** DOES NOT CHANGE */
|
||||
SqField *m_Rows;
|
||||
unsigned int m_CurRow;
|
||||
unsigned int m_NextRow;
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SQLITE_SOURCEMOD_RESULT_SET_H_
|
||||
Reference in New Issue
Block a user