dvander@1203: /**
dvander@4040: * vim: set ts=4 sw=4 tw=99 noet :
ds@1330: * =============================================================================
dvander@1226: * SourceMod SQLite Extension
ds@1947: * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
ds@1330: * =============================================================================
dvander@1203: *
ds@1330: * This program is free software; you can redistribute it and/or modify it under
ds@1330: * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330: * Free Software Foundation.
dvander@1226: *
ds@1330: * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
ds@1330: * details.
dvander@1226: *
ds@1330: * You should have received a copy of the GNU General Public License along with
ds@1330: * this program. If not, see .
dvander@1226: *
ds@1330: * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330: * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330: * by the Valve Corporation. You must obey the GNU General Public License in
ds@1330: * all respects for all other code used. Additionally, AlliedModders LLC grants
ds@1330: * this exception to all derivative works. AlliedModders LLC defines further
ds@1330: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330: * or .
dvander@1203: *
dvander@1203: * Version: $Id$
dvander@1203: */
dvander@1203:
dvander@1203: #include "extension.h"
dvander@1203: #include "SqDatabase.h"
dvander@1203: #include "SqQuery.h"
dvander@1203:
dvander@1203: SqDatabase::SqDatabase(sqlite3 *sq3, bool persistent) :
dvander@4040: m_sq3(sq3), m_Persistent(persistent)
dvander@1203: {
dvander@1203: }
dvander@1203:
dvander@1203: SqDatabase::~SqDatabase()
dvander@1203: {
dvander@4040: if (m_Persistent)
dvander@4040: g_SqDriver.RemovePersistent(this);
dvander@1203: sqlite3_close(m_sq3);
dvander@1203: }
dvander@1203:
dvander@1203: void SqDatabase::IncReferenceCount()
dvander@1203: {
dvander@4040: AddRef();
dvander@1203: }
dvander@1203:
dvander@1203: bool SqDatabase::Close()
dvander@1203: {
dvander@4040: return !Release();
dvander@1203: }
dvander@1203:
dvander@1203: const char *SqDatabase::GetError(int *errorCode/* =NULL */)
dvander@1203: {
dvander@1203: return sqlite3_errmsg(m_sq3);
dvander@1203: }
dvander@1203:
dvander@1203: bool SqDatabase::LockForFullAtomicOperation()
dvander@1203: {
dvander@4040: if (!m_FullLock)
dvander@4040: m_FullLock = new ke::Mutex();
dvander@1203:
dvander@4040: m_FullLock->Lock();
dvander@1203: return true;
dvander@1203: }
dvander@1203:
dvander@1203: void SqDatabase::UnlockFromFullAtomicOperation()
dvander@1203: {
dvander@4040: if (m_FullLock)
dvander@4040: m_FullLock->Unlock();
dvander@1203: }
dvander@1203:
dvander@1203: IDBDriver *SqDatabase::GetDriver()
dvander@1203: {
dvander@1203: return &g_SqDriver;
dvander@1203: }
dvander@1203:
dvander@1203: bool SqDatabase::QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newSize)
dvander@1203: {
dvander@1203: char *res = sqlite3_snprintf(static_cast(maxlen), buffer, "%q", str);
dvander@1203:
dvander@1203: if (res != NULL && newSize != NULL)
dvander@1203: {
dvander@1203: *newSize = strlen(buffer);
dvander@1203: }
dvander@1203:
dvander@1203: return (res != NULL);
dvander@1203: }
dvander@1203:
dvander@1203: unsigned int SqDatabase::GetInsertID()
dvander@1203: {
dvander@1203: return (unsigned int)sqlite3_last_insert_rowid(m_sq3);
dvander@1203: }
dvander@1203:
dvander@1203: unsigned int SqDatabase::GetAffectedRows()
dvander@1203: {
dvander@1203: return (unsigned int)sqlite3_changes(m_sq3);
dvander@1203: }
dvander@1203:
dvander@1203: bool SqDatabase::DoSimpleQuery(const char *query)
dvander@1203: {
dvander@1203: IQuery *pQuery = DoQuery(query);
dvander@1203: if (!pQuery)
dvander@1203: {
dvander@1203: return false;
dvander@1203: }
dvander@1203: pQuery->Destroy();
dvander@1203: return true;
dvander@1203: }
dvander@1203:
dvander@1203: /* this sounds like daiquiri.. i'm tired. */
dvander@1203: IQuery *SqDatabase::DoQuery(const char *query)
dvander@1203: {
dvander@1203: IPreparedQuery *pQuery = PrepareQuery(query, NULL, 0, NULL);
dvander@1203: if (!pQuery)
dvander@1203: {
dvander@1203: return NULL;
dvander@1203: }
dvander@1203: if (!pQuery->Execute())
dvander@1203: {
dvander@1203: pQuery->Destroy();
dvander@1203: return NULL;
dvander@1203: }
dvander@1203: return pQuery;
dvander@1203: }
dvander@1203:
dvander@1912: bool SqDatabase::DoSimpleQueryEx(const char *query, size_t len)
dvander@1912: {
dvander@1912: IQuery *pQuery = DoQueryEx(query, len);
dvander@1912: if (!pQuery)
dvander@1912: {
dvander@1912: return false;
dvander@1912: }
dvander@1912: pQuery->Destroy();
dvander@1912: return true;
dvander@1912: }
dvander@1912:
dvander@1912: IQuery *SqDatabase::DoQueryEx(const char *query, size_t len)
dvander@1912: {
dvander@1912: IPreparedQuery *pQuery = PrepareQueryEx(query, len, NULL, 0, NULL);
dvander@1912: if (!pQuery)
dvander@1912: {
dvander@1912: return NULL;
dvander@1912: }
dvander@1912: if (!pQuery->Execute())
dvander@1912: {
dvander@1912: pQuery->Destroy();
dvander@1912: return NULL;
dvander@1912: }
dvander@1912: return pQuery;
dvander@1912: }
dvander@1912:
john@3271: unsigned int SqDatabase::GetAffectedRowsForQuery(IQuery *query)
john@3271: {
john@3271: return static_cast(query)->GetAffectedRows();
john@3271: }
john@3271: unsigned int SqDatabase::GetInsertIDForQuery(IQuery *query)
john@3271: {
john@3271: return static_cast(query)->GetInsertID();
john@3271: }
john@3271:
dvander@1912: IPreparedQuery *SqDatabase::PrepareQuery(const char *query,
dvander@1912: char *error,
dvander@1912: size_t maxlength,
dvander@1912: int *errCode/* =NULL */)
dvander@1203: {
dvander@1203: sqlite3_stmt *stmt = NULL;
dvander@1203: if ((m_LastErrorCode = sqlite3_prepare_v2(m_sq3, query, -1, &stmt, NULL)) != SQLITE_OK
dvander@1203: || !stmt)
dvander@1203: {
dvander@1203: const char *msg;
dvander@1203: if (m_LastErrorCode != SQLITE_OK)
dvander@1203: {
dvander@1203: msg = sqlite3_errmsg(m_sq3);
dvander@1203: } else {
dvander@1203: msg = "Invalid query string";
dvander@1448: m_LastErrorCode = SQLITE_ERROR;
dvander@1203: }
dvander@1203: if (error)
dvander@1203: {
dvander@1203: strncopy(error, msg, maxlength);
dvander@1203: }
dvander@1203: m_LastError.assign(msg);
dvander@1912: return NULL;
dvander@1912: }
dvander@1912: return new SqQuery(this, stmt);
dvander@1912: }
dvander@1912:
dvander@1912: IPreparedQuery *SqDatabase::PrepareQueryEx(const char *query,
dvander@1912: size_t len,
dvander@1912: char *error,
dvander@1912: size_t maxlength,
dvander@1912: int *errCode/* =NULL */)
dvander@1912: {
dvander@1912: sqlite3_stmt *stmt = NULL;
dvander@1912: if ((m_LastErrorCode = sqlite3_prepare_v2(m_sq3, query, len, &stmt, NULL)) != SQLITE_OK
dvander@1912: || !stmt)
dvander@1912: {
dvander@1912: const char *msg;
dvander@1912: if (m_LastErrorCode != SQLITE_OK)
dvander@1203: {
dvander@1912: msg = sqlite3_errmsg(m_sq3);
dvander@1912: } else {
dvander@1912: msg = "Invalid query string";
dvander@1912: m_LastErrorCode = SQLITE_ERROR;
dvander@1203: }
dvander@1912: if (error)
dvander@1912: {
dvander@1912: strncopy(error, msg, maxlength);
dvander@1912: }
dvander@1912: m_LastError.assign(msg);
dvander@1203: return NULL;
dvander@1203: }
dvander@1203: return new SqQuery(this, stmt);
dvander@1203: }
dvander@1203:
dvander@1203: sqlite3 *SqDatabase::GetDb()
dvander@1203: {
dvander@1203: return m_sq3;
dvander@1203: }
januk@3947:
januk@3947: bool SqDatabase::SetCharacterSet(const char *characterset)
januk@3947: {
januk@3947: // sqlite only supports utf8 and utf16 - by the time the database is created. It's too late here.
januk@3947: return false;
dvander@4040: }