mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-08 01:39:36 +00:00
1
This commit is contained in:
@@ -0,0 +1,398 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
// mysql_wrapper.cpp : Defines the entry point for the DLL application.
|
||||
//
|
||||
#include "stdafx.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "mysql.h"
|
||||
};
|
||||
|
||||
#include "imysqlwrapper.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
static char* CopyString( const char *pStr )
|
||||
{
|
||||
if ( !pStr )
|
||||
{
|
||||
pStr = "";
|
||||
}
|
||||
|
||||
char *pRet = new char[ strlen( pStr ) + 1 ];
|
||||
strcpy( pRet, pStr );
|
||||
return pRet;
|
||||
}
|
||||
|
||||
|
||||
BOOL APIENTRY DllMain( HANDLE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
class CCopiedRow
|
||||
{
|
||||
public:
|
||||
~CCopiedRow()
|
||||
{
|
||||
m_Columns.PurgeAndDeleteElements();
|
||||
}
|
||||
|
||||
CUtlVector<char*> m_Columns;
|
||||
};
|
||||
|
||||
|
||||
class CMySQLCopiedRowSet : public IMySQLRowSet
|
||||
{
|
||||
public:
|
||||
~CMySQLCopiedRowSet()
|
||||
{
|
||||
m_Rows.PurgeAndDeleteElements();
|
||||
m_ColumnNames.PurgeAndDeleteElements();
|
||||
}
|
||||
|
||||
virtual void Release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual int NumFields()
|
||||
{
|
||||
return m_ColumnNames.Count();
|
||||
}
|
||||
|
||||
virtual const char* GetFieldName( int iColumn )
|
||||
{
|
||||
return m_ColumnNames[iColumn];
|
||||
}
|
||||
|
||||
virtual bool NextRow()
|
||||
{
|
||||
++m_iCurRow;
|
||||
return m_iCurRow < m_Rows.Count();
|
||||
}
|
||||
|
||||
virtual bool SeekToFirstRow()
|
||||
{
|
||||
m_iCurRow = 0;
|
||||
return m_iCurRow < m_Rows.Count();
|
||||
}
|
||||
|
||||
virtual CColumnValue GetColumnValue( int iColumn )
|
||||
{
|
||||
return CColumnValue( this, iColumn );
|
||||
}
|
||||
|
||||
virtual CColumnValue GetColumnValue( const char *pColumnName )
|
||||
{
|
||||
return CColumnValue( this, GetColumnIndex( pColumnName ) );
|
||||
}
|
||||
|
||||
virtual const char* GetColumnValue_String( int iColumn )
|
||||
{
|
||||
if ( iColumn < 0 || iColumn >= m_ColumnNames.Count() )
|
||||
return "<invalid column specified>";
|
||||
else if ( m_iCurRow < 0 || m_iCurRow >= m_Rows.Count() )
|
||||
return "<invalid row specified>";
|
||||
else
|
||||
return m_Rows[m_iCurRow]->m_Columns[iColumn];
|
||||
}
|
||||
|
||||
virtual long GetColumnValue_Int( int iColumn )
|
||||
{
|
||||
return atoi( GetColumnValue_String( iColumn ) );
|
||||
}
|
||||
|
||||
virtual int GetColumnIndex( const char *pColumnName )
|
||||
{
|
||||
for ( int i=0; i < m_ColumnNames.Count(); i++ )
|
||||
{
|
||||
if ( stricmp( m_ColumnNames[i], pColumnName ) == 0 )
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
int m_iCurRow;
|
||||
CUtlVector<CCopiedRow*> m_Rows;
|
||||
CUtlVector<char*> m_ColumnNames;
|
||||
};
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------- //
|
||||
// CMySQL class.
|
||||
// -------------------------------------------------------------------------------------------------------- //
|
||||
|
||||
class CMySQL : public IMySQL
|
||||
{
|
||||
public:
|
||||
CMySQL();
|
||||
virtual ~CMySQL();
|
||||
|
||||
virtual bool InitMySQL( const char *pDBName, const char *pHostName, const char *pUserName, const char *pPassword );
|
||||
virtual void Release();
|
||||
virtual int Execute( const char *pString );
|
||||
virtual IMySQLRowSet* DuplicateRowSet();
|
||||
virtual unsigned long InsertID();
|
||||
virtual int NumFields();
|
||||
virtual const char* GetFieldName( int iColumn );
|
||||
virtual bool NextRow();
|
||||
virtual bool SeekToFirstRow();
|
||||
virtual CColumnValue GetColumnValue( int iColumn );
|
||||
virtual CColumnValue GetColumnValue( const char *pColumnName );
|
||||
virtual const char* GetColumnValue_String( int iColumn );
|
||||
virtual long GetColumnValue_Int( int iColumn );
|
||||
virtual int GetColumnIndex( const char *pColumnName );
|
||||
|
||||
// Cancels the storage of the rows from the latest query.
|
||||
void CancelIteration();
|
||||
|
||||
virtual const char * GetLastError( void );
|
||||
|
||||
|
||||
public:
|
||||
|
||||
MYSQL *m_pSQL;
|
||||
MYSQL_RES *m_pResult;
|
||||
MYSQL_ROW m_Row;
|
||||
CUtlVector<MYSQL_FIELD> m_Fields;
|
||||
|
||||
char m_szLastError[128];
|
||||
};
|
||||
|
||||
|
||||
EXPOSE_INTERFACE( CMySQL, IMySQL, MYSQL_WRAPPER_VERSION_NAME );
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------- //
|
||||
// CMySQL implementation.
|
||||
// -------------------------------------------------------------------------------------------------------- //
|
||||
|
||||
CMySQL::CMySQL()
|
||||
{
|
||||
m_pSQL = NULL;
|
||||
m_pResult = NULL;
|
||||
m_Row = NULL;
|
||||
}
|
||||
|
||||
|
||||
CMySQL::~CMySQL()
|
||||
{
|
||||
CancelIteration();
|
||||
|
||||
if ( m_pSQL )
|
||||
{
|
||||
mysql_close( m_pSQL );
|
||||
m_pSQL = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CMySQL::InitMySQL( const char *pDBName, const char *pHostName, const char *pUserName, const char *pPassword )
|
||||
{
|
||||
MYSQL *pSQL = mysql_init( NULL );
|
||||
if ( !pSQL )
|
||||
return NULL;
|
||||
|
||||
if ( !mysql_real_connect( pSQL, pHostName, pUserName, pPassword, pDBName, 0, NULL, 0 ) )
|
||||
{
|
||||
Q_strncpy( m_szLastError, mysql_error( pSQL ), sizeof(m_szLastError) );
|
||||
|
||||
mysql_close( pSQL );
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pSQL = pSQL;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CMySQL::Release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
|
||||
int CMySQL::Execute( const char *pString )
|
||||
{
|
||||
CancelIteration();
|
||||
|
||||
int result = mysql_query( m_pSQL, pString );
|
||||
if ( result == 0 )
|
||||
{
|
||||
// Is this a query with a result set?
|
||||
m_pResult = mysql_store_result( m_pSQL );
|
||||
if ( m_pResult )
|
||||
{
|
||||
// Store the field information.
|
||||
int count = mysql_field_count( m_pSQL );
|
||||
MYSQL_FIELD *pFields = mysql_fetch_fields( m_pResult );
|
||||
m_Fields.CopyArray( pFields, count );
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No result set. Was a set expected?
|
||||
if ( mysql_field_count( m_pSQL ) != 0 )
|
||||
return 1; // error! The query expected data but didn't get it.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *pError = mysql_error( m_pSQL );
|
||||
pError = pError;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
IMySQLRowSet* CMySQL::DuplicateRowSet()
|
||||
{
|
||||
CMySQLCopiedRowSet *pSet = new CMySQLCopiedRowSet;
|
||||
|
||||
pSet->m_iCurRow = -1;
|
||||
|
||||
pSet->m_ColumnNames.SetSize( m_Fields.Count() );
|
||||
for ( int i=0; i < m_Fields.Count(); i++ )
|
||||
pSet->m_ColumnNames[i] = CopyString( m_Fields[i].name );
|
||||
|
||||
while ( NextRow() )
|
||||
{
|
||||
CCopiedRow *pRow = new CCopiedRow;
|
||||
pSet->m_Rows.AddToTail( pRow );
|
||||
pRow->m_Columns.SetSize( m_Fields.Count() );
|
||||
|
||||
for ( int i=0; i < m_Fields.Count(); i++ )
|
||||
{
|
||||
pRow->m_Columns[i] = CopyString( m_Row[i] );
|
||||
}
|
||||
}
|
||||
|
||||
return pSet;
|
||||
}
|
||||
|
||||
|
||||
unsigned long CMySQL::InsertID()
|
||||
{
|
||||
return mysql_insert_id( m_pSQL );
|
||||
}
|
||||
|
||||
|
||||
int CMySQL::NumFields()
|
||||
{
|
||||
return m_Fields.Count();
|
||||
}
|
||||
|
||||
|
||||
const char* CMySQL::GetFieldName( int iColumn )
|
||||
{
|
||||
return m_Fields[iColumn].name;
|
||||
}
|
||||
|
||||
|
||||
bool CMySQL::NextRow()
|
||||
{
|
||||
if ( !m_pResult )
|
||||
return false;
|
||||
|
||||
m_Row = mysql_fetch_row( m_pResult );
|
||||
if ( m_Row == 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CMySQL::SeekToFirstRow()
|
||||
{
|
||||
if ( !m_pResult )
|
||||
return false;
|
||||
|
||||
mysql_data_seek( m_pResult, 0 );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
CColumnValue CMySQL::GetColumnValue( int iColumn )
|
||||
{
|
||||
return CColumnValue( this, iColumn );
|
||||
}
|
||||
|
||||
|
||||
CColumnValue CMySQL::GetColumnValue( const char *pColumnName )
|
||||
{
|
||||
return CColumnValue( this, GetColumnIndex( pColumnName ) );
|
||||
}
|
||||
|
||||
|
||||
const char* CMySQL::GetColumnValue_String( int iColumn )
|
||||
{
|
||||
if ( m_Row && iColumn >= 0 && iColumn < m_Fields.Count() && m_Row[iColumn] )
|
||||
return m_Row[iColumn];
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
long CMySQL::GetColumnValue_Int( int iColumn )
|
||||
{
|
||||
return atoi( GetColumnValue_String( iColumn ) );
|
||||
}
|
||||
|
||||
|
||||
int CMySQL::GetColumnIndex( const char *pColumnName )
|
||||
{
|
||||
for ( int i=0; i < m_Fields.Count(); i++ )
|
||||
{
|
||||
if ( stricmp( pColumnName, m_Fields[i].name ) == 0 )
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void CMySQL::CancelIteration()
|
||||
{
|
||||
m_Fields.Purge();
|
||||
|
||||
if ( m_pResult )
|
||||
{
|
||||
mysql_free_result( m_pResult );
|
||||
m_pResult = NULL;
|
||||
}
|
||||
|
||||
m_Row = NULL;
|
||||
}
|
||||
|
||||
const char *CMySQL::GetLastError( void )
|
||||
{
|
||||
// Default to the last error if m_pSQL was not successfully initialized
|
||||
const char *pszLastError = m_szLastError;
|
||||
|
||||
if ( m_pSQL )
|
||||
{
|
||||
pszLastError = mysql_error( m_pSQL );
|
||||
}
|
||||
|
||||
return pszLastError;
|
||||
}
|
||||
Reference in New Issue
Block a user