sourcemod/extensions/mysql/mysql/MyDatabase.cpp
David Anderson d4c602f022 updated license headers for most extensions
updated sdk bases for most extensions

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401232
2007-08-01 01:54:53 +00:00

289 lines
6.0 KiB
C++

/**
* vim: set ts=4 :
* ================================================================
* SourceMod MySQL 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,
* 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 "MyDatabase.h"
#include "smsdk_ext.h"
#include "MyBasicResults.h"
#include "MyStatement.h"
DBType GetOurType(enum_field_types type)
{
switch (type)
{
case MYSQL_TYPE_DOUBLE:
case MYSQL_TYPE_FLOAT:
{
return DBType_Float;
}
case MYSQL_TYPE_TINY:
case MYSQL_TYPE_SHORT:
case MYSQL_TYPE_LONG:
case MYSQL_TYPE_INT24:
case MYSQL_TYPE_YEAR:
case MYSQL_TYPE_BIT:
{
return DBType_Integer;
}
case MYSQL_TYPE_LONGLONG:
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_TIME:
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_NEWDATE:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_VARCHAR:
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_NEWDECIMAL:
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_ENUM:
case MYSQL_TYPE_SET:
{
return DBType_String;
}
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_GEOMETRY:
{
return DBType_Blob;
}
default:
{
return DBType_String;
}
}
return DBType_Unknown;
}
MyDatabase::MyDatabase(MYSQL *mysql, const DatabaseInfo *info, bool persistent)
: m_mysql(mysql), m_refcount(1), m_pFullLock(NULL), m_bPersistent(persistent)
{
m_Host.assign(info->host);
m_Database.assign(info->database);
m_User.assign(info->user);
m_Pass.assign(info->pass);
m_Info.database = m_Database.c_str();
m_Info.host = m_Host.c_str();
m_Info.user = m_User.c_str();
m_Info.pass = m_Pass.c_str();
m_Info.driver = NULL;
m_Info.maxTimeout = info->maxTimeout;
m_Info.port = info->port;
m_pRefLock = threader->MakeMutex();
}
MyDatabase::~MyDatabase()
{
mysql_close(m_mysql);
m_mysql = NULL;
m_pRefLock->DestroyThis();
if (m_pFullLock)
{
m_pFullLock->DestroyThis();
}
}
void MyDatabase::IncReferenceCount()
{
m_pRefLock->Lock();
m_refcount++;
m_pRefLock->Unlock();
}
bool MyDatabase::Close()
{
m_pRefLock->Lock();
if (m_refcount > 1)
{
m_refcount--;
m_pRefLock->Unlock();
return false;
}
m_pRefLock->Unlock();
/* Remove us from the search list */
if (m_bPersistent)
{
g_MyDriver.RemoveFromList(this, true);
}
/* Finally, free our resource(s) */
delete this;
return true;
}
const DatabaseInfo &MyDatabase::GetInfo()
{
return m_Info;
}
unsigned int MyDatabase::GetInsertID()
{
return (unsigned int)mysql_insert_id(m_mysql);
}
unsigned int MyDatabase::GetAffectedRows()
{
return (unsigned int)mysql_affected_rows(m_mysql);
}
const char *MyDatabase::GetError(int *errCode)
{
if (errCode)
{
*errCode = mysql_errno(m_mysql);
}
return mysql_error(m_mysql);
}
bool MyDatabase::QuoteString(const char *str, char buffer[], size_t maxlength, size_t *newSize)
{
unsigned long size = static_cast<unsigned long>(strlen(str));
unsigned long needed = size * 2 + 1;
if (maxlength < needed)
{
if (newSize)
{
*newSize = (size_t)needed;
}
return false;
}
needed = mysql_real_escape_string(m_mysql, buffer, str, size);
if (newSize)
{
*newSize = (size_t)needed;
}
return true;
}
bool MyDatabase::DoSimpleQuery(const char *query)
{
IQuery *pQuery = DoQuery(query);
if (!pQuery)
{
return false;
}
pQuery->Destroy();
return true;
}
IQuery *MyDatabase::DoQuery(const char *query)
{
if (mysql_real_query(m_mysql, query, strlen(query)) != 0)
{
return NULL;
}
MYSQL_RES *res = NULL;
if (mysql_field_count(m_mysql))
{
res = mysql_store_result(m_mysql);
if (!res)
{
return NULL;
}
}
return new MyQuery(this, res);
}
IPreparedQuery *MyDatabase::PrepareQuery(const char *query, char *error, size_t maxlength, int *errCode)
{
MYSQL_STMT *stmt = mysql_stmt_init(m_mysql);
if (!stmt)
{
if (error)
{
strncopy(error, GetError(errCode), maxlength);
} else if (errCode) {
*errCode = mysql_errno(m_mysql);
}
return NULL;
}
if (mysql_stmt_prepare(stmt, query, strlen(query)) != 0)
{
if (error)
{
strncopy(error, mysql_stmt_error(stmt), maxlength);
}
if (errCode)
{
*errCode = mysql_stmt_errno(stmt);
}
mysql_stmt_close(stmt);
return NULL;
}
return new MyStatement(this, stmt);
}
bool MyDatabase::LockForFullAtomicOperation()
{
if (!m_pFullLock)
{
m_pFullLock = threader->MakeMutex();
if (!m_pFullLock)
{
return false;
}
}
m_pFullLock->Lock();
return true;
}
void MyDatabase::UnlockFromFullAtomicOperation()
{
if (m_pFullLock)
{
m_pFullLock->Unlock();
}
}
IDBDriver *MyDatabase::GetDriver()
{
return &g_MyDriver;
}