1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/extensions/sqlite/driver/SqDatabase.cpp Sun Mar 30 07:00:22 2008 +0000
1.3 @@ -0,0 +1,247 @@
1.4 +/**
1.5 + * vim: set ts=4 :
1.6 + * =============================================================================
1.7 + * SourceMod SQLite Extension
1.8 + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
1.9 + * =============================================================================
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify it under
1.12 + * the terms of the GNU General Public License, version 3.0, as published by the
1.13 + * Free Software Foundation.
1.14 + *
1.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 + * details.
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License along with
1.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 + *
1.23 + * As a special exception, AlliedModders LLC gives you permission to link the
1.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 + * by the Valve Corporation. You must obey the GNU General Public License in
1.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 + * this exception to all derivative works. AlliedModders LLC defines further
1.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 + * or <http://www.sourcemod.net/license.php>.
1.31 + *
1.32 + * Version: $Id$
1.33 + */
1.34 +
1.35 +#include "extension.h"
1.36 +#include "SqDatabase.h"
1.37 +#include "SqQuery.h"
1.38 +
1.39 +SqDatabase::SqDatabase(sqlite3 *sq3, bool persistent) :
1.40 + m_sq3(sq3), m_refcount(1), m_pFullLock(NULL), m_Persistent(persistent)
1.41 +{
1.42 + m_pRefLock = threader->MakeMutex();
1.43 +}
1.44 +
1.45 +SqDatabase::~SqDatabase()
1.46 +{
1.47 + m_pRefLock->DestroyThis();
1.48 + if (m_pFullLock)
1.49 + {
1.50 + m_pFullLock->DestroyThis();
1.51 + }
1.52 + sqlite3_close(m_sq3);
1.53 +}
1.54 +
1.55 +void SqDatabase::IncReferenceCount()
1.56 +{
1.57 + m_pRefLock->Lock();
1.58 + m_refcount++;
1.59 + m_pRefLock->Unlock();
1.60 +}
1.61 +
1.62 +bool SqDatabase::Close()
1.63 +{
1.64 + m_pRefLock->Lock();
1.65 + if (m_refcount > 1)
1.66 + {
1.67 + m_refcount--;
1.68 + m_pRefLock->Unlock();
1.69 + return false;
1.70 + }
1.71 + m_pRefLock->Unlock();
1.72 +
1.73 + if (m_Persistent)
1.74 + {
1.75 + g_SqDriver.RemovePersistent(this);
1.76 + }
1.77 +
1.78 + delete this;
1.79 +
1.80 + return true;
1.81 +}
1.82 +
1.83 +const char *SqDatabase::GetError(int *errorCode/* =NULL */)
1.84 +{
1.85 + return sqlite3_errmsg(m_sq3);
1.86 +}
1.87 +
1.88 +bool SqDatabase::LockForFullAtomicOperation()
1.89 +{
1.90 + if (!m_pFullLock)
1.91 + {
1.92 + m_pFullLock = threader->MakeMutex();
1.93 + if (!m_pFullLock)
1.94 + {
1.95 + return false;
1.96 + }
1.97 + }
1.98 +
1.99 + m_pFullLock->Lock();
1.100 +
1.101 + return true;
1.102 +}
1.103 +
1.104 +void SqDatabase::UnlockFromFullAtomicOperation()
1.105 +{
1.106 + if (m_pFullLock)
1.107 + {
1.108 + m_pFullLock->Unlock();
1.109 + }
1.110 +}
1.111 +
1.112 +IDBDriver *SqDatabase::GetDriver()
1.113 +{
1.114 + return &g_SqDriver;
1.115 +}
1.116 +
1.117 +bool SqDatabase::QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newSize)
1.118 +{
1.119 + char *res = sqlite3_snprintf(static_cast<int>(maxlen), buffer, "%q", str);
1.120 +
1.121 + if (res != NULL && newSize != NULL)
1.122 + {
1.123 + *newSize = strlen(buffer);
1.124 + }
1.125 +
1.126 + return (res != NULL);
1.127 +}
1.128 +
1.129 +unsigned int SqDatabase::GetInsertID()
1.130 +{
1.131 + return (unsigned int)sqlite3_last_insert_rowid(m_sq3);
1.132 +}
1.133 +
1.134 +unsigned int SqDatabase::GetAffectedRows()
1.135 +{
1.136 + return (unsigned int)sqlite3_changes(m_sq3);
1.137 +}
1.138 +
1.139 +bool SqDatabase::DoSimpleQuery(const char *query)
1.140 +{
1.141 + IQuery *pQuery = DoQuery(query);
1.142 + if (!pQuery)
1.143 + {
1.144 + return false;
1.145 + }
1.146 + pQuery->Destroy();
1.147 + return true;
1.148 +}
1.149 +
1.150 +/* this sounds like daiquiri.. i'm tired. */
1.151 +IQuery *SqDatabase::DoQuery(const char *query)
1.152 +{
1.153 + IPreparedQuery *pQuery = PrepareQuery(query, NULL, 0, NULL);
1.154 + if (!pQuery)
1.155 + {
1.156 + return NULL;
1.157 + }
1.158 + if (!pQuery->Execute())
1.159 + {
1.160 + pQuery->Destroy();
1.161 + return NULL;
1.162 + }
1.163 + return pQuery;
1.164 +}
1.165 +
1.166 +bool SqDatabase::DoSimpleQueryEx(const char *query, size_t len)
1.167 +{
1.168 + IQuery *pQuery = DoQueryEx(query, len);
1.169 + if (!pQuery)
1.170 + {
1.171 + return false;
1.172 + }
1.173 + pQuery->Destroy();
1.174 + return true;
1.175 +}
1.176 +
1.177 +IQuery *SqDatabase::DoQueryEx(const char *query, size_t len)
1.178 +{
1.179 + IPreparedQuery *pQuery = PrepareQueryEx(query, len, NULL, 0, NULL);
1.180 + if (!pQuery)
1.181 + {
1.182 + return NULL;
1.183 + }
1.184 + if (!pQuery->Execute())
1.185 + {
1.186 + pQuery->Destroy();
1.187 + return NULL;
1.188 + }
1.189 + return pQuery;
1.190 +}
1.191 +
1.192 +IPreparedQuery *SqDatabase::PrepareQuery(const char *query,
1.193 + char *error,
1.194 + size_t maxlength,
1.195 + int *errCode/* =NULL */)
1.196 +{
1.197 + sqlite3_stmt *stmt = NULL;
1.198 + if ((m_LastErrorCode = sqlite3_prepare_v2(m_sq3, query, -1, &stmt, NULL)) != SQLITE_OK
1.199 + || !stmt)
1.200 + {
1.201 + const char *msg;
1.202 + if (m_LastErrorCode != SQLITE_OK)
1.203 + {
1.204 + msg = sqlite3_errmsg(m_sq3);
1.205 + } else {
1.206 + msg = "Invalid query string";
1.207 + m_LastErrorCode = SQLITE_ERROR;
1.208 + }
1.209 + if (error)
1.210 + {
1.211 + strncopy(error, msg, maxlength);
1.212 + }
1.213 + m_LastError.assign(msg);
1.214 + return NULL;
1.215 + }
1.216 + return new SqQuery(this, stmt);
1.217 +}
1.218 +
1.219 +IPreparedQuery *SqDatabase::PrepareQueryEx(const char *query,
1.220 + size_t len,
1.221 + char *error,
1.222 + size_t maxlength,
1.223 + int *errCode/* =NULL */)
1.224 +{
1.225 + sqlite3_stmt *stmt = NULL;
1.226 + if ((m_LastErrorCode = sqlite3_prepare_v2(m_sq3, query, len, &stmt, NULL)) != SQLITE_OK
1.227 + || !stmt)
1.228 + {
1.229 + const char *msg;
1.230 + if (m_LastErrorCode != SQLITE_OK)
1.231 + {
1.232 + msg = sqlite3_errmsg(m_sq3);
1.233 + } else {
1.234 + msg = "Invalid query string";
1.235 + m_LastErrorCode = SQLITE_ERROR;
1.236 + }
1.237 + if (error)
1.238 + {
1.239 + strncopy(error, msg, maxlength);
1.240 + }
1.241 + m_LastError.assign(msg);
1.242 + return NULL;
1.243 + }
1.244 + return new SqQuery(this, stmt);
1.245 +}
1.246 +
1.247 +sqlite3 *SqDatabase::GetDb()
1.248 +{
1.249 + return m_sq3;
1.250 +}