sourcemod/extensions/sqlite/driver/SqDatabase.cpp

262 lines
5.8 KiB
C++
Raw Normal View History

/**
* 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 <http://www.gnu.org/licenses/>.
*
* 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 <http://www.sourcemod.net/license.php>.
*
* 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;
}
bool SqDatabase::DoSimpleQueryEx(const char *query, size_t len)
{
IQuery *pQuery = DoQueryEx(query, len);
if (!pQuery)
{
return false;
}
pQuery->Destroy();
return true;
}
IQuery *SqDatabase::DoQueryEx(const char *query, size_t len)
{
IPreparedQuery *pQuery = PrepareQueryEx(query, len, NULL, 0, NULL);
if (!pQuery)
{
return NULL;
}
if (!pQuery->Execute())
{
pQuery->Destroy();
return NULL;
}
return pQuery;
}
unsigned int SqDatabase::GetAffectedRowsForQuery(IQuery *query)
{
return static_cast<SqQuery*>(query)->GetAffectedRows();
}
unsigned int SqDatabase::GetInsertIDForQuery(IQuery *query)
{
return static_cast<SqQuery*>(query)->GetInsertID();
}
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_ERROR;
}
if (error)
{
strncopy(error, msg, maxlength);
}
m_LastError.assign(msg);
return NULL;
}
return new SqQuery(this, stmt);
}
IPreparedQuery *SqDatabase::PrepareQueryEx(const char *query,
size_t len,
char *error,
size_t maxlength,
int *errCode/* =NULL */)
{
sqlite3_stmt *stmt = NULL;
if ((m_LastErrorCode = sqlite3_prepare_v2(m_sq3, query, len, &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_ERROR;
}
if (error)
{
strncopy(error, msg, maxlength);
}
m_LastError.assign(msg);
return NULL;
}
return new SqQuery(this, stmt);
}
sqlite3 *SqDatabase::GetDb()
{
return m_sq3;
}
bool SqDatabase::SetCharacterSet(const char *characterset)
{
// sqlite only supports utf8 and utf16 - by the time the database is created. It's too late here.
return false;
}