#include "pch.h" #include "l2c_utils.h" #include "l2c_db.h" MysqlQuery::MysqlQuery() { q = NULL; result = NULL; num_rows = num_fields = 0; strcpy( NULL_RET, "NULL" ); } MysqlQuery::MysqlQuery( const wchar_t *_Format, ... ) { q = NULL; result = NULL; num_rows = num_fields = 0; strcpy( NULL_RET, "NULL" ); if( _Format ) { va_list arglist; va_start( arglist, _Format ); int n = _vscwprintf( _Format, arglist ); if( n >= 1 ) { q = (wchar_t *)malloc( 2*n + 16 ); if( q ) { va_start( arglist, _Format ); vswprintf( q, n+2, _Format, arglist ); } } } } MysqlQuery::~MysqlQuery() { clear(); } void MysqlQuery::clear() { if( q ) free( q ); q = NULL; if( result ) mysql_free_result( result ); result = NULL; num_rows = num_fields = 0; row = NULL; } int MysqlQuery::getNumRows() const { return num_rows; } int MysqlQuery::getNumFields() const { return num_fields; } void MysqlQuery::create( const wchar_t *_Format, ... ) { clear(); va_list _ArgList; va_start( _ArgList, _Format ); int l = _vscwprintf( _Format, _ArgList ); // number of chars will be printed if( l <= 1 ) return; q = (wchar_t *)malloc( l*2 + 2 ); // number of bytes needed if( !q ) return; va_start( _ArgList, _Format ); vswprintf( q, l+1, _Format, _ArgList ); } bool MysqlQuery::getNextRow() { if( !result ) return false; row = mysql_fetch_row( result ); if( row ) return true; return false; } char *MysqlQuery::getFieldStr( int idx ) { if( !row || !result ) return NULL_RET; char *ret = NULL; if( idx>=0 && idx<=(num_fields-1) ) ret = row[idx]; if( !ret ) return NULL_RET; // row[idx] can still be NULL if MySQL table specs ALLOW NULL return ret; } char *MysqlQuery::getFieldStr( const wchar_t *field_name ) { if( !field_name ) return NULL_RET; size_t flen = wcslen( field_name ); char *aname = (char *)malloc( flen+1 ); if( !aname ) return NULL_RET; l2c_unicode_to_ansi( field_name, aname, flen ); char *ret = getFieldStr( aname ); free( aname ); aname = NULL; return ret; } char *MysqlQuery::getFieldStr( const char *field_name ) { if( !field_name ) return NULL_RET; if( !result || !row ) return NULL_RET; if( num_fields < 1 ) return NULL_RET; MYSQL_FIELD *fields = mysql_fetch_fields( result ); if( !fields ) return NULL_RET; int i; int idx = -1; for( i=0; i" ); if( aerr ) l2c_ansi_to_unicode( aerr, m_errstr, 255 ); return (const wchar_t *)m_errstr; } bool MysqlConnection::isConnected() { if( m_connected ) { int ret = mysql_ping( &m_mysql ); if( ret != 0 ) { close(); return false; } return true; } return false; } bool MysqlConnection::executeQuery( MysqlQuery& q ) { if( !m_connected ) return false; if( !q.q ) return false; size_t qlen = wcslen( q.q ); char *a_query = (char *)malloc( qlen + 1 ); if( !a_query ) return false; l2c_unicode_to_ansi( q.q, a_query, qlen+1 ); int q_res = mysql_query( &m_mysql, a_query ); free( a_query ); a_query = NULL; if( q_res == 0 ) { // no error q.result = mysql_store_result( &m_mysql ); if( q.result ) { q.num_fields = (int)mysql_num_fields( q.result ); q.num_rows = (int)mysql_num_rows( q.result ); } else { q.num_fields = mysql_field_count( &m_mysql ); // query was not a SELECT if( q.num_fields == 0 ) q.num_rows = (int)mysql_affected_rows( &m_mysql ); } // no error return true; } // error return false; } // memory for static variable bool MysqlConnectionManager::m_wasLibraryInit = false; MysqlConnectionManager::MysqlConnectionManager() { m_initialized = false; m_server[0] = m_user[0] = m_pass[0] = m_db[0] = 0; m_maxConnections = m_numActiveConnections = 0; m_connections = NULL; } MysqlConnectionManager::~MysqlConnectionManager() { closeAllConnections(); } bool MysqlConnectionManager::initialize( int maxConnections, const wchar_t *server, const wchar_t *user, const wchar_t *pass, const wchar_t *db ) { if( m_initialized ) return true; // init lock InitializeCriticalSectionAndSpinCount( &m_lock, 10 ); Lock(); // init mysql library? if( !MysqlConnectionManager::m_wasLibraryInit ) { mysql_server_init( 0, NULL, NULL ); MysqlConnectionManager::m_wasLibraryInit = true; } // try allocate m_connections = (MysqlConnection **)malloc( maxConnections * sizeof(MysqlConnection *) ); if( !m_connections ) { Unlock(); return false; } m_connbusy = (bool *)malloc( maxConnections * sizeof(bool) ); if( !m_connbusy ) { free( m_connections ); m_connections = NULL; Unlock(); return false; } // init nulls int i; for( i=0; iclose(); delete m_connections[i]; m_connections[i] = NULL; m_connbusy[i] = false; } } free( m_connections ); m_connections = NULL; free( m_connbusy ); m_connbusy = NULL; m_initialized = false; Unlock(); DeleteCriticalSection( &m_lock ); } MysqlConnection *MysqlConnectionManager::getConnection() { MysqlConnection *ret = NULL; int i = 0; Lock(); for( i=0; iconnect( m_server, m_user, m_pass, m_db ); m_connbusy[i] = true; ret = m_connections[i]; m_numActiveConnections++; break; } if( m_connections[i] && !m_connbusy[i] ) { if( !m_connections[i]->isConnected() ) m_connections[i]->connect( m_server, m_user, m_pass, m_db ); m_connbusy[i] = true; ret = m_connections[i]; m_numActiveConnections++; break; } } Unlock(); return ret; } bool MysqlConnectionManager::releaseConnection( MysqlConnection *con ) { if( !con ) return false; int i = 0; bool ret = false; Lock(); for( i=0; i 0 if( i > 0 ) m_connections[i]->close(); // at least 1 conn with idx 0 will be active all the time m_numActiveConnections--; ret = true; break; } } Unlock(); return ret; } int MysqlConnectionManager::getCountActiveConnections() const { return m_numActiveConnections; } int MysqlConnectionManager::getCountMaxConnections() const { return m_maxConnections; } void MysqlConnectionManager::Lock() { EnterCriticalSection( &m_lock ); } void MysqlConnectionManager::Unlock() { LeaveCriticalSection( &m_lock ); }