extensions/sqlite/driver/SqDatabase.cpp
author Scott Ehlert <ds@alliedmods.net>
Sun Sep 14 03:01:05 2008 -0500 (2008-09-14)
changeset 2289 44045ead61cd
parent 1952 b7aa2b626807
parent 1947 e73a1e51833b
child 3271 acc921bc57ef
permissions -rw-r--r--
Eliminated head: da55a80522cf, a remnant of sourcemod-1.1.0 branch
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod SQLite Extension
     5  * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     8  * This program is free software; you can redistribute it and/or modify it under
     9  * the terms of the GNU General Public License, version 3.0, as published by the
    10  * Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful, but WITHOUT
    13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    15  * details.
    16  *
    17  * You should have received a copy of the GNU General Public License along with
    18  * this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to link the
    21  * code of this program (as well as its derivative works) to "Half-Life 2," the
    22  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    23  * by the Valve Corporation.  You must obey the GNU General Public License in
    24  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    25  * this exception to all derivative works.  AlliedModders LLC defines further
    26  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    27  * or <http://www.sourcemod.net/license.php>.
    28  *
    29  * Version: $Id$
    30  */
    31 
    32 #include "extension.h"
    33 #include "SqDatabase.h"
    34 #include "SqQuery.h"
    35 
    36 SqDatabase::SqDatabase(sqlite3 *sq3, bool persistent) : 
    37 	m_sq3(sq3), m_refcount(1), m_pFullLock(NULL), m_Persistent(persistent)
    38 {
    39 	m_pRefLock = threader->MakeMutex();
    40 }
    41 
    42 SqDatabase::~SqDatabase()
    43 {
    44 	m_pRefLock->DestroyThis();
    45 	if (m_pFullLock)
    46 	{
    47 		m_pFullLock->DestroyThis();
    48 	}
    49 	sqlite3_close(m_sq3);
    50 }
    51 
    52 void SqDatabase::IncReferenceCount()
    53 {
    54 	m_pRefLock->Lock();
    55 	m_refcount++;
    56 	m_pRefLock->Unlock();
    57 }
    58 
    59 bool SqDatabase::Close()
    60 {
    61 	m_pRefLock->Lock();
    62 	if (m_refcount > 1)
    63 	{
    64 		m_refcount--;
    65 		m_pRefLock->Unlock();
    66 		return false;
    67 	}
    68 	m_pRefLock->Unlock();
    69 
    70 	if (m_Persistent)
    71 	{
    72 		g_SqDriver.RemovePersistent(this);
    73 	}
    74 
    75 	delete this;
    76 
    77 	return true;
    78 }
    79 
    80 const char *SqDatabase::GetError(int *errorCode/* =NULL */)
    81 {
    82 	return sqlite3_errmsg(m_sq3);
    83 }
    84 
    85 bool SqDatabase::LockForFullAtomicOperation()
    86 {
    87 	if (!m_pFullLock)
    88 	{
    89 		m_pFullLock = threader->MakeMutex();
    90 		if (!m_pFullLock)
    91 		{
    92 			return false;
    93 		}
    94 	}
    95 
    96 	m_pFullLock->Lock();
    97 
    98 	return true;
    99 }
   100 
   101 void SqDatabase::UnlockFromFullAtomicOperation()
   102 {
   103 	if (m_pFullLock)
   104 	{
   105 		m_pFullLock->Unlock();
   106 	}
   107 }
   108 
   109 IDBDriver *SqDatabase::GetDriver()
   110 {
   111 	return &g_SqDriver;
   112 }
   113 
   114 bool SqDatabase::QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newSize)
   115 {
   116 	char *res = sqlite3_snprintf(static_cast<int>(maxlen), buffer, "%q", str);
   117 
   118 	if (res != NULL && newSize != NULL)
   119 	{
   120 		*newSize = strlen(buffer);
   121 	}
   122 
   123 	return (res != NULL);
   124 }
   125 
   126 unsigned int SqDatabase::GetInsertID()
   127 {
   128 	return (unsigned int)sqlite3_last_insert_rowid(m_sq3);
   129 }
   130 
   131 unsigned int SqDatabase::GetAffectedRows()
   132 {
   133 	return (unsigned int)sqlite3_changes(m_sq3);
   134 }
   135 
   136 bool SqDatabase::DoSimpleQuery(const char *query)
   137 {
   138 	IQuery *pQuery = DoQuery(query);
   139 	if (!pQuery)
   140 	{
   141 		return false;
   142 	}
   143 	pQuery->Destroy();
   144 	return true;
   145 }
   146 
   147 /* this sounds like daiquiri.. i'm tired. */
   148 IQuery *SqDatabase::DoQuery(const char *query)
   149 {
   150 	IPreparedQuery *pQuery = PrepareQuery(query, NULL, 0, NULL);
   151 	if (!pQuery)
   152 	{
   153 		return NULL;
   154 	}
   155 	if (!pQuery->Execute())
   156 	{
   157 		pQuery->Destroy();
   158 		return NULL;
   159 	}
   160 	return pQuery;
   161 }
   162 
   163 bool SqDatabase::DoSimpleQueryEx(const char *query, size_t len)
   164 {
   165 	IQuery *pQuery = DoQueryEx(query, len);
   166 	if (!pQuery)
   167 	{
   168 		return false;
   169 	}
   170 	pQuery->Destroy();
   171 	return true;
   172 }
   173 
   174 IQuery *SqDatabase::DoQueryEx(const char *query, size_t len)
   175 {
   176 	IPreparedQuery *pQuery = PrepareQueryEx(query, len, NULL, 0, NULL);
   177 	if (!pQuery)
   178 	{
   179 		return NULL;
   180 	}
   181 	if (!pQuery->Execute())
   182 	{
   183 		pQuery->Destroy();
   184 		return NULL;
   185 	}
   186 	return pQuery;
   187 }
   188 
   189 IPreparedQuery *SqDatabase::PrepareQuery(const char *query, 
   190 										 char *error, 
   191 										 size_t maxlength, 
   192 										 int *errCode/* =NULL */)
   193 {
   194 	sqlite3_stmt *stmt = NULL;
   195 	if ((m_LastErrorCode = sqlite3_prepare_v2(m_sq3, query, -1, &stmt, NULL)) != SQLITE_OK
   196 		|| !stmt)
   197 	{
   198 		const char *msg;
   199 		if (m_LastErrorCode != SQLITE_OK)
   200 		{
   201 			msg = sqlite3_errmsg(m_sq3);
   202 		} else {
   203 			msg = "Invalid query string";
   204 			m_LastErrorCode = SQLITE_ERROR;
   205 		}
   206 		if (error)
   207 		{
   208 			strncopy(error, msg, maxlength);
   209 		}
   210 		m_LastError.assign(msg);
   211 		return NULL;
   212 	}
   213 	return new SqQuery(this, stmt);
   214 }
   215 
   216 IPreparedQuery *SqDatabase::PrepareQueryEx(const char *query, 
   217 										   size_t len, 
   218 										   char *error, 
   219 										   size_t maxlength, 
   220 										   int *errCode/* =NULL */)
   221 {
   222 	sqlite3_stmt *stmt = NULL;
   223 	if ((m_LastErrorCode = sqlite3_prepare_v2(m_sq3, query, len, &stmt, NULL)) != SQLITE_OK
   224 		|| !stmt)
   225 	{
   226 		const char *msg;
   227 		if (m_LastErrorCode != SQLITE_OK)
   228 		{
   229 			msg = sqlite3_errmsg(m_sq3);
   230 		} else {
   231 			msg = "Invalid query string";
   232 			m_LastErrorCode = SQLITE_ERROR;
   233 		}
   234 		if (error)
   235 		{
   236 			strncopy(error, msg, maxlength);
   237 		}
   238 		m_LastError.assign(msg);
   239 		return NULL;
   240 	}
   241 	return new SqQuery(this, stmt);
   242 }
   243 
   244 sqlite3 *SqDatabase::GetDb()
   245 {
   246 	return m_sq3;
   247 }