summaryrefslogtreecommitdiff
path: root/utils/sqlwrapper
diff options
context:
space:
mode:
Diffstat (limited to 'utils/sqlwrapper')
-rw-r--r--utils/sqlwrapper/sqlhelpers.cpp543
-rw-r--r--utils/sqlwrapper/sqlhelpers.h162
-rw-r--r--utils/sqlwrapper/sqlwrapper.cpp453
-rw-r--r--utils/sqlwrapper/sqlwrapper.vcproj200
4 files changed, 1358 insertions, 0 deletions
diff --git a/utils/sqlwrapper/sqlhelpers.cpp b/utils/sqlwrapper/sqlhelpers.cpp
new file mode 100644
index 0000000..878c13c
--- /dev/null
+++ b/utils/sqlwrapper/sqlhelpers.cpp
@@ -0,0 +1,543 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================
+
+//#include "misc.h"
+#include "isqlwrapper.h"
+#include "time.h"
+#include "sqlhelpers.h"
+
+#include "tier0/memdbgon.h"
+
+#pragma warning( disable : 4706 ) // Warning C4706: assignment within conditional expression
+
+//-----------------------------------------------------------------------------
+// Purpose: converts between a MySQL field type and our column types
+//-----------------------------------------------------------------------------
+EColumnType GetEColumnTypeFromESQLFieldType( ESQLFieldType eSQLFieldType )
+{
+ switch( eSQLFieldType )
+ {
+ case FIELD_TYPE_DECIMAL:
+ case FIELD_TYPE_TINY:
+ case FIELD_TYPE_SHORT:
+ case FIELD_TYPE_LONG:
+ return SQL_INT;
+ break;
+ case FIELD_TYPE_FLOAT:
+ case FIELD_TYPE_DOUBLE:
+ return SQL_FLOAT;
+ break;
+ case FIELD_TYPE_LONGLONG:
+ return SQL_UINT64;
+ break;
+ case FIELD_TYPE_NULL:
+ case FIELD_TYPE_INT24:
+ return SQL_NONE;
+ break;
+ case FIELD_TYPE_DATE:
+ case FIELD_TYPE_TIMESTAMP:
+ case FIELD_TYPE_TIME:
+ case FIELD_TYPE_DATETIME:
+ case FIELD_TYPE_YEAR:
+ case FIELD_TYPE_NEWDATE:
+ return SQL_TIME;
+ break;
+ case FIELD_TYPE_ENUM:
+ case FIELD_TYPE_SET:
+ case FIELD_TYPE_TINY_BLOB:
+ case FIELD_TYPE_MEDIUM_BLOB:
+ case FIELD_TYPE_LONG_BLOB:
+ case FIELD_TYPE_BLOB:
+ return SQL_NONE;
+ break;
+ case FIELD_TYPE_VAR_STRING:
+ case FIELD_TYPE_STRING:
+ return SQL_STRING;
+ break;
+ }
+ return SQL_NONE;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor.
+//-----------------------------------------------------------------------------
+CSQLColumn::CSQLColumn( const char *pchName, ESQLFieldType eSQLFieldType )
+{
+ Assert( pchName );
+ Q_strncpy( m_rgchName, pchName, sizeof( m_rgchName ) );
+ m_ESQLFieldType = eSQLFieldType;
+ m_EColumnType = GetEColumnTypeFromESQLFieldType( m_ESQLFieldType );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CSQLTable::CSQLTable( const char *pchName )
+{
+ Assert( pchName );
+ Q_strncpy( m_rgchName, pchName, sizeof( m_rgchName ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: copy constructor (used by CUtlVector)
+//-----------------------------------------------------------------------------
+CSQLTable::CSQLTable( CSQLTable const &sqlTable )
+{
+ Q_strncpy( m_rgchName, sqlTable.m_rgchName, sizeof( m_rgchName ) );
+ for ( int iSQLColumn = 0; iSQLColumn < sqlTable.m_VecSQLColumn.Count(); iSQLColumn++ )
+ {
+ m_VecSQLColumn.AddToTail( CSQLColumn( sqlTable.m_VecSQLColumn[iSQLColumn].PchColumnName(),
+ sqlTable.m_VecSQLColumn[iSQLColumn].GetESQLFieldType() ) );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: add a new column to this data description
+//-----------------------------------------------------------------------------
+void CSQLTable::AddColumn( const char *pchName, ESQLFieldType eSQLFieldType )
+{
+ m_VecSQLColumn.AddToTail( CSQLColumn( pchName, eSQLFieldType ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Ensure that all of our internal structures are consistent, and
+// account for all memory that we've allocated.
+// Input: validator - Our global validator object
+// pchName - Our name (typically a member var in our container)
+//-----------------------------------------------------------------------------
+#ifdef DBGFLAG_VALIDATE
+void CSQLTable::Validate( CValidator &validator, char *pchName )
+{
+ validator.Push( "CSQLTable", this, pchName );
+
+ m_VecSQLColumn.Validate( validator, "m_VecSQLColumn" );
+
+ validator.Pop();
+}
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Create the table descriptions from a data base
+//-----------------------------------------------------------------------------
+bool CSQLTableSet::Init( ISQLHelper *pSQLHelper )
+{
+ m_VecSQLTable.RemoveAll();
+
+ MYSQL_RES *pMySQLRes = NULL;
+ bool bRet = pSQLHelper->BInternalQuery( "show tables", &pMySQLRes );
+ if ( !bRet || !pMySQLRes )
+ {
+ return false;
+ }
+
+ MYSQL_ROW row;
+ while ( ( row = mysql_fetch_row( pMySQLRes ) ) )
+ {
+ CSQLTable sqlTable( row[0] );
+ m_VecSQLTable.AddToTail( sqlTable );
+ }
+ mysql_free_result( pMySQLRes );
+
+ for ( int i = 0; i < m_VecSQLTable.Count(); i++ )
+ {
+ CSQLTable &sqlTable = m_VecSQLTable[i];
+
+ char szQuery[512];
+ Q_snprintf( szQuery, sizeof(szQuery), "select * from %s limit 1", sqlTable.PchName() );
+ MYSQL_RES *pMySQLRes = NULL;
+ bool bRet = pSQLHelper->BInternalQuery( szQuery, &pMySQLRes );
+ if ( !bRet || !pMySQLRes )
+ {
+ m_VecSQLTable.RemoveAll();
+ return false;
+ }
+
+ uint nFields = mysql_num_fields( pMySQLRes );
+ Assert( nFields > 0 );
+ MYSQL_FIELD *pFields = mysql_fetch_fields( pMySQLRes );
+ for( uint i = 0; i < nFields; i++)
+ {
+ sqlTable.AddColumn( pFields[i].name, pFields[i].type );
+ }
+
+ mysql_free_result( pMySQLRes );
+ }
+
+ m_bInit = true;
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: returns a pointer to each table in the db
+//-----------------------------------------------------------------------------
+const ISQLTable *CSQLTableSet::PSQLTable( int iSQLTable ) const
+{
+ return &m_VecSQLTable[iSQLTable];
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Ensure that all of our internal structures are consistent, and
+// account for all memory that we've allocated.
+// Input: validator - Our global validator object
+// pchName - Our name (typically a member var in our container)
+//-----------------------------------------------------------------------------
+#ifdef DBGFLAG_VALIDATE
+void CSQLTableSet::Validate( CValidator &validator, char *pchName )
+{
+ validator.Push( "CSQLTableSet", this, pchName );
+
+ m_VecSQLTable.Validate( validator, "m_VecSQLTable" );
+ for ( int i = 0; i < m_VecSQLTable.Count(); i++ )
+ {
+ m_VecSQLTable[i].Validate( validator, "m_VecSQLTable[i]" );
+ }
+
+ validator.Pop();
+}
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Purpose: constructor
+//-----------------------------------------------------------------------------
+CSQLRow::CSQLRow( MYSQL_ROW *pMySQLRow, const ISQLTable *pSQLTableDescription, int cRowData )
+{
+ Assert( pMySQLRow && pSQLTableDescription );
+ for ( int iRowData = 0; iRowData < cRowData; iRowData++ )
+ {
+ struct SQLRowData_s sqlRowData;
+ sqlRowData.eColumnType = pSQLTableDescription->GetEColumnType( iRowData );
+ const CSQLTable *tableDesc = static_cast<const CSQLTable *>(pSQLTableDescription);
+ switch ( tableDesc->GetESQLFieldType( iRowData ) )
+ {
+ case FIELD_TYPE_TINY:
+ case FIELD_TYPE_DECIMAL:
+ case FIELD_TYPE_SHORT:
+ case FIELD_TYPE_LONG:
+ sqlRowData.data.nData = atoi( ( *pMySQLRow ) [iRowData] );
+ break;
+
+ case FIELD_TYPE_FLOAT:
+ case FIELD_TYPE_DOUBLE:
+ sqlRowData.data.flData = atof( ( *pMySQLRow ) [iRowData] );
+ break;
+
+ case FIELD_TYPE_NULL:
+ case FIELD_TYPE_INT24:
+ memset( &sqlRowData.data, 0x0, sizeof( sqlRowData.data ) );
+ break;
+
+ case FIELD_TYPE_LONGLONG:
+ sqlRowData.data.nData = atoi( ( *pMySQLRow ) [iRowData] );
+ break;
+
+ case FIELD_TYPE_TIMESTAMP:
+ case FIELD_TYPE_DATETIME:
+ {
+ struct tm tm;
+ char num[5];
+ char szValue[64];
+ Q_memset( &tm, 0x0, sizeof( tm ) );
+ Q_strncpy( szValue, ( *pMySQLRow )[iRowData], sizeof( szValue ) );
+ const char *str= szValue;
+ num[0] =*str++; num[1] =*str++; num[2] =*str++; num[3] =*str++; num[4] = 0;
+ tm.tm_year = strtol( num, 0, 10 ) - 1900;
+ if (*str == '-') str++;
+ num[0] = *str++; num[1] = *str++; num[2] = 0;
+ tm.tm_mon = strtol( num, 0, 10 ) - 1;
+ if (*str == '-') str++;
+ num[0] = *str++; num[1] = *str++; num[2] = 0;
+ tm.tm_mday = strtol( num, 0, 10 );
+ num[0] = *str++; num[1] = *str++; num[2] = 0;
+ tm.tm_hour = strtol( num, 0, 10 );
+ if (*str == ':') str++;
+ num[0] = *str++; num[1] = *str++; num[2] = 0;
+ tm.tm_min = strtol( num, 0, 10 );
+ if (*str == ':') str++;
+ num[0] = *str++; num[1] = *str++; num[2] = 0;
+ tm.tm_sec = strtol( num, 0, 10 );
+
+ sqlRowData.data.ulTime = _mktime64( &tm );
+ }
+ break;
+
+ case FIELD_TYPE_TIME:
+ case FIELD_TYPE_DATE:
+ case FIELD_TYPE_YEAR:
+ case FIELD_TYPE_NEWDATE:
+ sqlRowData.data.ulTime = time( NULL ); // FIXME
+ Assert( !"Not implemented" );
+ break;
+
+ case FIELD_TYPE_ENUM:
+ case FIELD_TYPE_SET:
+ case FIELD_TYPE_TINY_BLOB:
+ case FIELD_TYPE_MEDIUM_BLOB:
+ case FIELD_TYPE_LONG_BLOB:
+ case FIELD_TYPE_BLOB:
+ memset( &sqlRowData.data, 0x0, sizeof( sqlRowData.data ) );
+ Assert( !"Not implemented" );
+ break;
+
+ case FIELD_TYPE_VAR_STRING:
+ case FIELD_TYPE_STRING:
+ {
+ int cchString = Q_strlen( ( char * )( *pMySQLRow )[iRowData] );
+ char *pchNewString = new char[ cchString + 1 ];
+ m_VecPchStoredStrings.AddToTail( pchNewString );
+ Q_strncpy( pchNewString, ( char * )( *pMySQLRow )[iRowData], cchString + 1 );
+ pchNewString[ cchString ] = 0;
+ sqlRowData.data.pchData = pchNewString;
+ }
+ break;
+ }
+ m_VecSQLRowData.AddToTail( sqlRowData );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: destructor
+//-----------------------------------------------------------------------------
+CSQLRow::~CSQLRow()
+{
+ for ( int ipch = 0; ipch < m_VecPchStoredStrings.Count(); ipch++ )
+ {
+ delete m_VecPchStoredStrings[ipch];
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: pointer to the char data
+//-----------------------------------------------------------------------------
+const char *CSQLRow::PchData( int iRowData ) const
+{
+ Assert( m_VecSQLRowData[iRowData].eColumnType == SQL_STRING );
+ return m_VecSQLRowData[iRowData].data.pchData;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the int value of this column
+//-----------------------------------------------------------------------------
+int CSQLRow::NData( int iRowData ) const
+{
+ Assert( m_VecSQLRowData[iRowData].eColumnType == SQL_INT);
+ return m_VecSQLRowData[iRowData].data.nData;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the uint64 value of this column
+//-----------------------------------------------------------------------------
+uint64 CSQLRow::UlData( int iRowData ) const
+{
+ Assert( m_VecSQLRowData[iRowData].eColumnType == SQL_UINT64);
+ return m_VecSQLRowData[iRowData].data.ulData;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the float value of this column
+//-----------------------------------------------------------------------------
+float CSQLRow::FlData( int iRowData ) const
+{
+ Assert( m_VecSQLRowData[iRowData].eColumnType == SQL_FLOAT );
+ return m_VecSQLRowData[iRowData].data.flData;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the time value of this column (time_t equivalent, seconds since midnight (00:00:00), January 1, 1970, coordinated universal time (UTC)
+// ignoring daylight savings
+//-----------------------------------------------------------------------------
+uint64 CSQLRow::UlTime( int iRowData ) const
+{
+ Assert( m_VecSQLRowData[iRowData].eColumnType == SQL_TIME );
+ return m_VecSQLRowData[iRowData].data.ulTime;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the boolean value of this column
+//-----------------------------------------------------------------------------
+bool CSQLRow::BData( int iRowData ) const
+{
+ Assert( m_VecSQLRowData[iRowData].eColumnType == SQL_INT );
+ return (m_VecSQLRowData[iRowData].data.nData == 1);
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the data type contained in this column
+//-----------------------------------------------------------------------------
+EColumnType CSQLRow::GetEColumnType( int iRowData ) const
+{
+ return m_VecSQLRowData[iRowData].eColumnType;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Ensure that all of our internal structures are consistent, and
+// account for all memory that we've allocated.
+// Input: validator - Our global validator object
+// pchName - Our name (typically a member var in our container)
+//-----------------------------------------------------------------------------
+#ifdef DBGFLAG_VALIDATE
+void CSQLRow::Validate( CValidator &validator, char *pchName )
+{
+ validator.Push( "CSQLRow", this, pchName );
+
+ m_VecSQLRowData.Validate( validator, "m_VecSQLRowData" );
+
+ m_VecPchStoredStrings.Validate( validator, "m_VecPchStoredStrings" );
+ for ( int i = 0; i < m_VecPchStoredStrings.Count(); i++ )
+ {
+ validator.ClaimMemory( m_VecPchStoredStrings[i] );
+ }
+
+ validator.Pop();
+}
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Purpose: constructor
+//-----------------------------------------------------------------------------
+CResultSet::CResultSet()
+:m_SQLTableDescription( "Table" )
+{
+ m_pSQLRow = NULL;
+ m_MySQLRes = NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: run a query on the database
+//-----------------------------------------------------------------------------
+bool CResultSet::Query( const char *pchQuery, ISQLHelper *pSQLHelper )
+{
+ m_SQLTableDescription.Reset();
+
+ m_pSQLRow = NULL;
+
+ bool bRet = pSQLHelper->BInternalQuery( pchQuery, &m_MySQLRes );
+ if ( !bRet || !m_MySQLRes )
+ {
+ m_cSQLField = -1;
+ m_cSQLRow = -1;
+ return false;
+ }
+
+ m_cSQLField = mysql_num_fields( m_MySQLRes );
+ m_cSQLRow = mysql_num_rows( m_MySQLRes );
+
+ MYSQL_FIELD *pMySQLField = mysql_fetch_fields( m_MySQLRes );
+ for ( int iMySQLField = 0; iMySQLField < m_cSQLField; iMySQLField++ )
+ {
+ m_SQLTableDescription.AddColumn( pMySQLField[iMySQLField].name, pMySQLField[iMySQLField].type );
+ }
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: destructor
+//-----------------------------------------------------------------------------
+CResultSet::~CResultSet()
+{
+ FreeResult();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: free any outstanding query
+//-----------------------------------------------------------------------------
+void CResultSet::FreeResult()
+{
+ if ( m_MySQLRes )
+ {
+ mysql_free_result( m_MySQLRes );
+ m_MySQLRes = NULL;
+ }
+
+ if ( m_pSQLRow )
+ {
+ delete m_pSQLRow;
+ m_pSQLRow = NULL;
+ }
+
+ m_SQLTableDescription.Reset();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: number of rows in the result set
+//-----------------------------------------------------------------------------
+int CResultSet::GetCSQLRow() const
+{
+ return m_cSQLRow;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: get the new row from the result set
+//-----------------------------------------------------------------------------
+const ISQLRow *CResultSet::PSQLRowNextResult()
+{
+ if ( m_pSQLRow )
+ {
+ delete m_pSQLRow;
+ m_pSQLRow = NULL;
+ }
+
+ MYSQL_ROW mySQLRow;
+ if ( mySQLRow = mysql_fetch_row( m_MySQLRes ) )
+ {
+ m_pSQLRow = new CSQLRow( &mySQLRow, &m_SQLTableDescription, m_cSQLField );
+ }
+ else
+ {
+ FreeResult(); // end of result set
+ }
+
+ return m_pSQLRow;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Ensure that all of our internal structures are consistent, and
+// account for all memory that we've allocated.
+// Input: validator - Our global validator object
+// pchName - Our name (typically a member var in our container)
+//-----------------------------------------------------------------------------
+#ifdef DBGFLAG_VALIDATE
+void CResultSet::Validate( CValidator &validator, char *pchName )
+{
+ validator.Push( "CResultSet", this, pchName );
+
+ validator.ClaimMemory( m_MySQLRes );
+ if ( m_pSQLRow )
+ {
+ validator.ClaimMemory( m_pSQLRow );
+ m_pSQLRow->Validate( validator, "m_pSQLRow" );
+ }
+
+ m_SQLTableDescription.Validate( validator, "m_SQLTableDescription" );
+
+ validator.Pop();
+}
+#endif
+
diff --git a/utils/sqlwrapper/sqlhelpers.h b/utils/sqlwrapper/sqlhelpers.h
new file mode 100644
index 0000000..b2c53f6
--- /dev/null
+++ b/utils/sqlwrapper/sqlhelpers.h
@@ -0,0 +1,162 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================
+#include "utlvector.h"
+
+extern "C"
+{
+ #include <WinSock.H>
+ #include "mysql.h"
+};
+#include "utlvector.h"
+
+typedef enum_field_types ESQLFieldType;
+
+//-----------------------------------------------------------------------------
+// Purpose: helper interface for running queries internal to this dll
+//-----------------------------------------------------------------------------
+class ISQLHelper
+{
+public:
+ // run a sql query on the db
+ virtual bool BInternalQuery( const char *pchQueryString, MYSQL_RES **ppMySQLRes, bool bRecurse = true ) = 0;
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: represents the data about a single SQL column
+//-----------------------------------------------------------------------------
+class CSQLColumn
+{
+public:
+ CSQLColumn() { m_rgchName[0] = 0; }
+ CSQLColumn( const char *pchName, ESQLFieldType eSQLFieldType );
+ virtual const char *PchColumnName() const { return m_rgchName; };
+ virtual EColumnType GetEColumnType() const { return m_EColumnType; };
+ virtual ESQLFieldType GetESQLFieldType() const { return m_ESQLFieldType; };
+
+private:
+ char m_rgchName[64];
+ EColumnType m_EColumnType;
+ ESQLFieldType m_ESQLFieldType;
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: encapsulates a table's description
+//-----------------------------------------------------------------------------
+class CSQLTable : public ISQLTable
+{
+public:
+ CSQLTable( const char *pchName );
+ CSQLTable( CSQLTable const &CSQLTable ); // copy constructor
+ void AddColumn( const char *pchName, ESQLFieldType ESQLFieldType );
+ const char *PchName() const { return m_rgchName; };
+ virtual int GetCSQLColumn() const { return m_VecSQLColumn.Count(); };
+ virtual const char *PchColumnName( int iSQLColumn ) const { return m_VecSQLColumn[iSQLColumn].PchColumnName(); };
+ virtual EColumnType GetEColumnType( int iSQLColumn ) const { return m_VecSQLColumn[iSQLColumn].GetEColumnType(); };
+ virtual ESQLFieldType GetESQLFieldType( int iSQLColumn ) const { return m_VecSQLColumn[iSQLColumn].GetESQLFieldType(); };
+
+ void Reset() { m_VecSQLColumn.RemoveAll(); }
+
+#ifdef DBGFLAG_VALIDATE
+ void Validate( CValidator &validator, char *pchName );
+#endif
+
+private:
+ char m_rgchName[64];
+ CUtlVector<CSQLColumn> m_VecSQLColumn;
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: encapsulates a db's worth of tables
+//-----------------------------------------------------------------------------
+class CSQLTableSet : public ISQLTableSet
+{
+public:
+ CSQLTableSet() { m_bInit = false; }
+ bool Init( ISQLHelper *pISQLHelper );
+ bool BInit() { return m_bInit; }
+ virtual int GetCSQLTable() const { return m_VecSQLTable.Count(); };
+ virtual const ISQLTable *PSQLTable( int iSQLTable ) const;
+
+#ifdef DBGFLAG_VALIDATE
+ void Validate( CValidator &validator, char *pchName );
+#endif
+
+private:
+ static EColumnType EColumnTypeFromPchName( const char *pchName );
+ CUtlVector<CSQLTable> m_VecSQLTable;
+ bool m_bInit;
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: describes a single row in a result set
+//-----------------------------------------------------------------------------
+class CSQLRow : public ISQLRow
+{
+public:
+ CSQLRow( MYSQL_ROW *pMySQLRow, const ISQLTable *pSQLTableDescription, int cSQLRowData );
+ ~CSQLRow();
+ virtual int GetCSQLRowData() const { return m_VecSQLRowData.Count(); };
+ virtual const char *PchData( int iSQLRowData ) const;
+ virtual int NData( int iSQLRowData ) const;
+ virtual uint64 UlData( int iSQLRowData ) const;
+ virtual float FlData( int iSQLRowData ) const;
+ virtual uint64 UlTime( int iSQLRowData ) const;
+ virtual bool BData( int iSQLRowData ) const;
+ virtual EColumnType GetEColumnType( int iSQLRowData ) const;
+
+#ifdef DBGFLAG_VALIDATE
+ void Validate( CValidator &validator, char *pchName );
+#endif
+
+private:
+ struct SQLRowData_s
+ {
+ union
+ {
+ int nData;
+ float flData;
+ const char *pchData;
+ uint64 ulTime;
+ uint64 ulData;
+ } data;
+ EColumnType eColumnType;
+ };
+
+ CUtlVector<struct SQLRowData_s> m_VecSQLRowData;
+ CUtlVector<char *> m_VecPchStoredStrings;
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: encapsulates a result set from a SQL query
+//-----------------------------------------------------------------------------
+class CResultSet : public IResultSet
+{
+public:
+ CResultSet();
+ ~CResultSet();
+ bool Query( const char *pchQuery, ISQLHelper *pISQLHelper );
+ virtual int GetCSQLRow() const;
+ virtual const ISQLRow *PSQLRowNextResult();
+ void FreeResult();
+
+#ifdef DBGFLAG_VALIDATE
+ void Validate( CValidator &validator, char *pchName );
+#endif
+
+private:
+ MYSQL_RES *m_MySQLRes;
+ CSQLRow *m_pSQLRow;
+ CSQLTable m_SQLTableDescription;
+ int m_cSQLField;
+ int m_cSQLRow;
+};
+
diff --git a/utils/sqlwrapper/sqlwrapper.cpp b/utils/sqlwrapper/sqlwrapper.cpp
new file mode 100644
index 0000000..477a066
--- /dev/null
+++ b/utils/sqlwrapper/sqlwrapper.cpp
@@ -0,0 +1,453 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================
+//#include "misc.h"
+//#include "stdafx.h"
+
+#include <windows.h>
+
+////// MySQL API includes
+#include <WinSock.H>
+#include "mysql.h"
+#include "errmsg.h"
+
+
+#include "platform.h"
+#include "isqlwrapper.h"
+#include "sqlhelpers.h"
+#include "interface.h"
+#include "utllinkedlist.h"
+#include "utlvector.h"
+
+#include "tier0/memdbgon.h"
+
+
+///////
+
+//-----------------------------------------------------------------------------
+// Purpose: Main dll entry point
+// Input: hModule - our module handle
+// dwReason - reason we were called
+// lpReserved - bad idea that some Windows developer had some day that
+// we're stuck with
+//-----------------------------------------------------------------------------
+#ifdef _WIN32
+BOOL APIENTRY DllMain( HANDLE hModule,
+ DWORD dwReason,
+ LPVOID lpReserved
+ )
+{
+ switch ( dwReason )
+ {
+ case DLL_PROCESS_ATTACH:
+ break;
+ }
+
+ return TRUE;
+}
+#elif _LINUX
+void __attribute__ ((constructor)) app_init(void);
+void app_init(void)
+{
+}
+#endif
+
+
+class CSQLWrapper : public ISQLWrapper, public ISQLHelper
+{
+public:
+ CSQLWrapper();
+ ~CSQLWrapper ();
+
+ // ISQLWrapper
+ virtual void Init( const char *pchDB, const char *pchHost, const char *pchUsername, const char *pchPassword );
+ virtual bool BInsert( const char *pchQueryString );
+ virtual const ISQLTableSet *PSQLTableSetDescription();
+ virtual IResultSet *PResultSetQuery( const char *pchQueryString );
+ virtual void FreeResult();
+
+ // ISQLHelper
+ virtual bool BInternalQuery( const char *pchQueryString, MYSQL_RES **ppMySQLRes, bool bRecurse /* = true */ );
+
+#ifdef DBGFLAG_VALIDATE
+ void Validate( CValidator &validator, char *pchName ); // Validate our internal structures
+#endif
+
+private:
+ bool BConnect();
+ void Disconnect();
+ bool _Query( const char *pchQueryString, MYSQL_RES **result );
+
+ char *m_pchDB;
+ char *m_pchHost;
+ char *m_pchUsername;
+ char *m_pchPassword;
+ bool m_bConnected;
+
+ MYSQL m_MySQL;
+ CSQLTableSet m_SQLTableSet;
+ CResultSet m_ResultSet;
+ bool m_bInQuery;
+};
+
+
+class CSQLWrapperFactory : public ISQLWrapperFactory
+{
+public:
+ CSQLWrapperFactory() {};
+ ~CSQLWrapperFactory() {};
+
+ virtual ISQLWrapper *Create( const char *pchDB, const char *pchHost, const char *pchUsername, const char *pchPassword );
+ virtual void Free( ISQLWrapper *pWrapper );
+
+#ifdef DBGFLAG_VALIDATE
+ void Validate( CValidator &validator, char *pchName ); // Validate our internal structures
+#endif
+
+private:
+ CUtlFixedLinkedList<CSQLWrapper> m_ListSQLWrapper; // use a fixed in memory data struct so we can return pointers to the interfaces
+};
+
+CSQLWrapperFactory g_SQLWrapperFactory;
+EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CSQLWrapperFactory, ISQLWrapperFactory, INTERFACEVERSION_ISQLWRAPPER, g_SQLWrapperFactory );
+
+#if 0
+//-----------------------------------------------------------------------------
+// Purpose: Ensure that all of our internal structures are consistent, and
+// account for all memory that we've allocated.
+// Input: validator - Our global validator object
+//-----------------------------------------------------------------------------
+class CDLLValidate : public IValidate
+{
+public:
+ virtual void Validate( CValidator & validator )
+ {
+#ifdef DBGFLAG_VALIDATE
+ g_SQLWrapperFactory.Validate( validator, "g_SQLWrapperFactory" );
+#endif
+ }
+};
+CDLLValidate g_DLLValidate;
+EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CDLLValidate, IValidate, INTERFACEVERSION_IVALIDATE, g_DLLValidate );
+#endif
+
+//-----------------------------------------------------------------------------
+// Purpose: Create a SQLWrapper interface to use
+// Input: pchDB - database name to connect to
+// pchHost - host to connect to
+// pchUsername - username to connect as
+// pchPassword - password to use
+// Output: a pointer to a sql wrapper interface
+//-----------------------------------------------------------------------------
+ISQLWrapper *CSQLWrapperFactory::Create( const char *pchDB, const char *pchHost, const char *pchUsername, const char *pchPassword )
+{
+ int iSQLWrapper = m_ListSQLWrapper.AddToTail();
+ CSQLWrapper &sqlWrapper = m_ListSQLWrapper[iSQLWrapper];
+ sqlWrapper.Init( pchDB, pchHost, pchUsername, pchPassword );
+ return &sqlWrapper;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Free a previously allocated sql interface
+// Input: pWrapper - interface that was alloced
+//-----------------------------------------------------------------------------
+void CSQLWrapperFactory::Free( ISQLWrapper *pSQLWrapper )
+{
+ FOR_EACH_LL( m_ListSQLWrapper, iSQLWrapper )
+ {
+ if ( &m_ListSQLWrapper[iSQLWrapper] == ((CSQLWrapper *)pSQLWrapper) )
+ {
+ m_ListSQLWrapper.Remove(iSQLWrapper);
+ break;
+ }
+ }
+
+ Assert( iSQLWrapper != m_ListSQLWrapper.InvalidIndex() );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Ensure that all of our internal structures are consistent, and
+// account for all memory that we've allocated.
+// Input: validator - Our global validator object
+// pchName - Our name (typically a member var in our container)
+//-----------------------------------------------------------------------------
+#ifdef DBGFLAG_VALIDATE
+void CSQLWrapperFactory::Validate( CValidator &validator, char *pchName )
+{
+ validator.Push( "CSQLWrapperFactory", this, pchName );
+
+ m_ListSQLWrapper.Validate( validator, "m_ListSQLWrapper" );
+
+ FOR_EACH_LL( m_ListSQLWrapper, iListSQLWrapper )
+ {
+ m_ListSQLWrapper[ iListSQLWrapper ].Validate( validator, "m_ListSQLWrapper[ iListSQLWrapper ]" );
+ }
+
+ validator.Pop();
+}
+#endif
+
+#define SAFE_DELETE( pointer ) if ( pointer != NULL ) { delete pointer; }
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor.
+//-----------------------------------------------------------------------------
+CSQLWrapper::CSQLWrapper()
+{
+ m_pchDB = NULL;
+ m_pchHost = NULL;
+ m_pchUsername = NULL;
+ m_pchPassword = NULL;
+ m_bConnected = false;
+ m_bInQuery = false;
+
+ mysql_init( &m_MySQL );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Destructor.
+//-----------------------------------------------------------------------------
+CSQLWrapper::~CSQLWrapper()
+{
+ FreeResult();
+ mysql_close( &m_MySQL );
+ m_bConnected = false;
+
+ SAFE_DELETE(m_pchDB);
+ SAFE_DELETE(m_pchHost);
+ SAFE_DELETE(m_pchUsername);
+ SAFE_DELETE(m_pchPassword);
+}
+
+// helper macro to alloc and copy a string to a member var
+// BUGBUG Alfred: Make this a Q_function
+#define COPY_STRING( dst, src ) \
+ dst = new char[Q_strlen(src) + 1]; \
+ Assert( dst ); \
+ Q_strncpy( dst, src, Q_strlen(src) + 1); \
+ dst[ Q_strlen(src) ] = 0;
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Initializer. Sets up connection params but DOESN'T actually do the connection
+// Input: pchDB - database name to connect to
+// pchHost - host to connect to
+// pchUsername - username to connect as
+// pchPassword - password to use
+//-----------------------------------------------------------------------------
+void CSQLWrapper::Init( const char *pchDB, const char *pchHost, const char *pchUsername, const char *pchPassword )
+{
+ COPY_STRING( m_pchDB, pchDB );
+ COPY_STRING( m_pchHost, pchHost );
+ COPY_STRING( m_pchUsername, pchUsername );
+ COPY_STRING( m_pchPassword, pchPassword );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Connects to a MySQL server.
+// Output: true if connect works, false otherwise
+//-----------------------------------------------------------------------------
+bool CSQLWrapper::BConnect()
+{
+ m_bInQuery = false;
+
+ MYSQL *pMYSQL = mysql_real_connect( &m_MySQL, m_pchHost, m_pchUsername, m_pchPassword, m_pchDB, 0, NULL, 0);
+ if ( !pMYSQL || pMYSQL != &m_MySQL ) // on success we get our SQL pointer back
+ {
+ DevMsg( "Failed to connect to DB server (%s)\n", mysql_error(&m_MySQL) );
+ return false;
+ }
+ m_bConnected = true;
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Disconnects from a mysql if you are already connected
+//-----------------------------------------------------------------------------
+void CSQLWrapper::Disconnect()
+{
+ mysql_close( &m_MySQL );
+ mysql_init( &m_MySQL );
+ m_bConnected = false;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: run a query on the db with retries
+// Input: pchQueryString - query string to run
+// ppMySQLRes - mysql result set to set
+// bRecurse - if true allow this function to call itself again (to rety the query)
+// Output: true if query succeeds, false otherwise
+//-----------------------------------------------------------------------------
+bool CSQLWrapper::BInternalQuery( const char *pchQueryString, MYSQL_RES **ppMySQLRes, bool bRecurse )
+{
+ *ppMySQLRes = NULL;
+ if ( !m_pchDB || !m_pchHost || !m_pchUsername || !m_pchPassword || !ppMySQLRes )
+ {
+ return false;
+ }
+
+ if ( !m_bConnected )
+ {
+ BConnect(); // need to reconnect
+ }
+
+ bool bRet = _Query( pchQueryString, ppMySQLRes );
+ if ( !bRet && !m_bConnected && bRecurse ) // hmmm, got hung up when running the query
+ {
+ bRet = BInternalQuery( pchQueryString, ppMySQLRes, false ); // run the query again now we reconnected
+ }
+
+ return bRet;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Actually runs a query on the server
+// Input: pchQueryString - query string to run
+// result - mysql result set to set
+// Output: true if query succeeds, false otherwise, result it set on success
+//-----------------------------------------------------------------------------
+bool CSQLWrapper::_Query( const char *pchQueryString, MYSQL_RES **ppMySQLRes )
+{
+ *ppMySQLRes = NULL;
+ int iResult = mysql_real_query( &m_MySQL, pchQueryString, Q_strlen(pchQueryString) );
+ if ( iResult != 0 )
+ {
+ int iErrNo = mysql_errno(&m_MySQL);
+ if ( iErrNo == CR_COMMANDS_OUT_OF_SYNC ) // I hate this return code, you just need to hang up and try again
+ {
+ Disconnect();
+ return false;
+ }
+ else if ( iErrNo == CR_SERVER_LOST || iErrNo == CR_SERVER_GONE_ERROR )
+ {
+ m_bConnected = false;
+ return false;
+ }
+ else if ( iErrNo != 0 )
+ {
+ DevMsg( "CSQLWrapper::_Query Generic SQL query error: %s\n", mysql_error( &m_MySQL ) );
+ return false;
+ }
+ }
+
+ if ( mysql_field_count( &m_MySQL ) > 0 ) // if there are results clear them from the connection
+ {
+ *ppMySQLRes = mysql_store_result( &m_MySQL );
+ }
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Runs a insert style query on the db (i.e no return set), opens the connection if it isn't currently
+// Input: pchQueryString - query string to run
+// Output: true if query succeeds, false otherwise
+//-----------------------------------------------------------------------------
+bool CSQLWrapper::BInsert( const char *pchQueryString )
+{
+ if ( m_bInQuery )
+ {
+ Assert( !m_bInQuery );
+ return false;
+ }
+
+ m_bInQuery = true;
+ MYSQL_RES *pMySQLRes = NULL;
+ bool bRet = BInternalQuery( pchQueryString, &pMySQLRes, true );
+ if ( bRet && pMySQLRes )
+ {
+ mysql_free_result( pMySQLRes );
+ }
+ m_bInQuery = false;
+ return bRet;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: returns a pointer to the table descriptions for this DB
+// Output: table description pointer
+//-----------------------------------------------------------------------------
+const ISQLTableSet *CSQLWrapper::PSQLTableSetDescription()
+{
+ if ( m_bInQuery )
+ {
+ Assert( !m_bInQuery );
+ return NULL;
+ }
+
+ m_bInQuery = true;
+ if ( !m_SQLTableSet.Init( this ) )
+ {
+ return NULL;
+ }
+
+ m_bInQuery = false;
+ return &m_SQLTableSet;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Runs a select style query on the db (i.e a return set), opens the connection if it isn't currently
+// Input: pchQueryString - query string to run
+// Output: returns a pointer to the result set (NULL on failure)
+//-----------------------------------------------------------------------------
+IResultSet *CSQLWrapper::PResultSetQuery( const char *pchQueryString )
+{
+ if ( m_bInQuery )
+ {
+ Assert( !m_bInQuery );
+ return NULL;
+ }
+
+ bool bRet = m_ResultSet.Query( pchQueryString, this );
+ if ( !bRet )
+ {
+ return NULL;
+ }
+ m_bInQuery = true;
+ return &m_ResultSet;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Free's any currently running result set
+//-----------------------------------------------------------------------------
+void CSQLWrapper::FreeResult()
+{
+ m_bInQuery = false;
+ m_ResultSet.FreeResult();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Ensure that all of our internal structures are consistent, and
+// account for all memory that we've allocated.
+// Input: validator - Our global validator object
+// pchName - Our name (typically a member var in our container)
+//-----------------------------------------------------------------------------
+#ifdef DBGFLAG_VALIDATE
+void CSQLWrapper::Validate( CValidator &validator, char *pchName )
+{
+ validator.Push( "CSQLWrapper", this, pchName );
+
+ validator.ClaimMemory( m_pchDB );
+ validator.ClaimMemory( m_pchHost );
+ validator.ClaimMemory( m_pchUsername );
+ validator.ClaimMemory( m_pchPassword );
+
+ m_SQLTableSet.Validate( validator, "m_SQLTableSet" );
+ m_ResultSet.Validate( validator, "m_ResultSet" );
+
+ validator.Pop();
+}
+#endif
diff --git a/utils/sqlwrapper/sqlwrapper.vcproj b/utils/sqlwrapper/sqlwrapper.vcproj
new file mode 100644
index 0000000..44b9683
--- /dev/null
+++ b/utils/sqlwrapper/sqlwrapper.vcproj
@@ -0,0 +1,200 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="SQLWrapper"
+ ProjectGUID="{D66A7F7E-CD38-45CC-951D-E22E5DED6585}"
+ SccProjectName="Perforce Project"
+ SccAuxPath=""
+ SccLocalPath=".."
+ SccProvider="MSSCCI:Perforce SCM"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\..\bin\$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\common;..\..\public;..\..;..\..\public\tier0;..\..\public\tier1;..\vmpi_private\mysql\include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ RuntimeTypeInfo="TRUE"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ WarnAsError="TRUE"
+ Detect64BitPortabilityProblems="FALSE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"
+ CommandLine="if exist ..\..\..\game\bin\sqlwrapper.dll attrib -r ..\..\..\game\bin\sqlwrapper.dll
+copy &quot;$(TargetDir)&quot;sqlwrapper.dll ..\..\..\game\bin\sqlwrapper.dll
+if exist ..\..\..\game\bin\sqlwrapper.pdb attrib -r ..\..\..\game\bin\sqlwrapper.pdb
+copy &quot;$(TargetDir)&quot;sqlwrapper.pdb ..\..\..\game\bin
+if exist ..\..\..\src\lib\common\sqlwrapper.lib attrib -r ..\..\..\src\lib\common\sqlwrapper.lib
+copy &quot;$(TargetDir)&quot;sqlwrapper.lib ..\..\..\src\lib\common\
+
+"
+ Outputs="..\..\..\game\bin\&quot;$(TargetName)&quot;.dll"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="mswsock.lib winmm.lib ws2_32.lib libmySQL.lib tier0.lib tier1.lib vstdlib.lib"
+ OutputFile="$(OutDir)/sqlwrapper.dll"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="&quot;../../common/$(IntDir)&quot;;../../lib/public;../vmpi_private/mysql/lib/opt"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/sqlwrapper.pdb"
+ SubSystem="0"
+ ImportLibrary="$(OutDir)/sqlwrapper.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="..\..\bin\$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ GlobalOptimizations="TRUE"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="1"
+ OptimizeForProcessor="3"
+ AdditionalIncludeDirectories="..\..\common;..\..\public;..\..;..\..\public\tier0;..\..\public\tier1;..\vmpi_private\mysql\include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ BufferSecurityCheck="FALSE"
+ EnableFunctionLevelLinking="FALSE"
+ EnableEnhancedInstructionSet="1"
+ RuntimeTypeInfo="TRUE"
+ UsePrecompiledHeader="0"
+ WarningLevel="4"
+ WarnAsError="TRUE"
+ Detect64BitPortabilityProblems="FALSE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"
+ CommandLine="if exist ..\..\..\game\bin\sqlwrapper.dll attrib -r ..\..\..\game\bin\sqlwrapper.dll
+copy &quot;$(TargetDir)&quot;sqlwrapper.dll ..\..\..\game\bin\sqlwrapper.dll
+
+if exist ..\..\..\game\bin\sqlwrapper.pdb attrib -r ..\..\..\game\bin\sqlwrapper.pdb
+copy &quot;$(TargetDir)&quot;sqlwrapper.pdb ..\..\..\game\bin\sqlwrapper.pdb
+
+if exist ..\..\..\src\lib\common\sqlwrapper.lib attrib -r ..\..\..\src\lib\common\sqlwrapper.lib
+copy &quot;$(TargetDir)&quot;sqlwrapper.lib ..\..\..\src\lib\common\sqlwrapper.lib
+
+"
+ Outputs="..\..\..\game\bin\&quot;$(TargetName)&quot;.dll"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="mswsock.lib winmm.lib ws2_32.lib libmySQL.lib tier0.lib tier1.lib vstdlib.lib"
+ OutputFile="$(OutDir)/sqlwrapper.dll"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="&quot;../../common/$(IntDir)&quot;;../../lib/public;../vmpi_private/mysql/lib/opt"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/sqlwrapper.pdb"
+ SubSystem="0"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ ImportLibrary="$(OutDir)/sqlwrapper.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath="..\..\tier1\interface.cpp">
+ </File>
+ <File
+ RelativePath="..\..\public\tier0\memoverride.cpp">
+ </File>
+ <File
+ RelativePath=".\sqlhelpers.cpp">
+ </File>
+ <File
+ RelativePath=".\sqlwrapper.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath="..\..\public\tier1\interface.h">
+ </File>
+ <File
+ RelativePath="..\..\public\isqlwrapper.h">
+ </File>
+ <File
+ RelativePath="..\vmpi_private\mysql\include\mysql.h">
+ </File>
+ <File
+ RelativePath=".\sqlhelpers.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>