[Release]DBInstance. :)

07/29/2013 11:24 Wanetrain#1
Bla, da ich n abgang schieb, geb ich euch noch paar dinge, davon ist eins die DBInstance wo von mir überarbeitet worden ist, sollte euren DB Server noch etwas ankurbeln, sofern ihr wisst wie man es einsetzt. ;)

DBInstance.cpp:

Code:
#include "StdAfx.h"
#include "DBInstance.h"

CDBInstance::CDBInstance()
{
	m_hStmt	= NULL;
	m_hDbc	= NULL;
	m_hEnv	= NULL;

	for( byte i = 0; i < MAXCOL; i++ )
	{
		m_szCol[i] = new char[4192];
		memset( m_szCol[i], 0, 4192);
	}
}

CDBInstance::~CDBInstance()
{
	Disconnect();

	for( byte i = 0; i < MAXCOL; i++ )
		delete [] ( m_szCol[i] );
}

void CDBInstance::Disconnect()
{
	Clear();
	SQLFreeHandle(SQL_HANDLE_STMT, m_hStmt );

	SQLDisconnect( m_hDbc );
	SQLFreeHandle(SQL_HANDLE_DBC, m_hDbc );
	SQLFreeHandle(SQL_HANDLE_ENV, m_hEnv );
}

void CDBInstance::Clear()
{
	SQLCloseCursor( m_hStmt );
	SQLFreeStmt( m_hStmt, SQL_UNBIND );
}

bool CDBInstance::Connect( _In_ char* szDBName, _In_ char* szLogin, _In_ char* szDBPass )
{
	SQLAllocHandle( SQL_HANDLE_ENV,SQL_NULL_HANDLE, &m_hEnv );
	SQLSetEnvAttr( m_hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3_80, SQL_IS_INTEGER );

	SQLAllocHandle( SQL_HANDLE_DBC, m_hEnv, &m_hDbc );

	SQLSetConnectAttr(m_hDbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
	if(!SQL_SUCCEEDED( SQLConnect( m_hDbc, (SQLCHAR*)szDBName, SQL_NTS, (SQLCHAR*)szLogin, SQL_NTS, (SQLCHAR*)szDBPass, SQL_NTS ) ))
	{
		Error( "(ERROR) %s(%d): Can't connect to Database!! [%s]", __FUNCTION__, __LINE__, szDBName );
		return false;
	}

	SQLAllocHandle( SQL_HANDLE_STMT, m_hDbc, &m_hStmt );
	return true;
}

bool CDBInstance::BindParameter( _In_ SQLUSMALLINT parameterNumber, _In_ SQLSMALLINT inputOutputType, _In_ SQLSMALLINT valueType, _In_ SQLSMALLINT parameterType, _In_ SQLUINTEGER columnSize, _In_ SQLSMALLINT decimalDigits, _In_ SQLPOINTER  parameterValuePtr, _In_ SQLINTEGER bufferLength, _In_ SQLINTEGER *strLen_or_IndPtr )
{
	return SQL_SUCCEEDED( SQLBindParameter( m_hStmt, parameterNumber, inputOutputType, valueType, parameterType, columnSize, decimalDigits, parameterValuePtr, bufferLength, strLen_or_IndPtr ) );
}

void CDBInstance::PrepareFetch()
{
	SQLNumResultCols( m_hStmt, &m_nCol );

	SWORD	nActualLen		= NULL;
	SWORD	m_nSQLType		= NULL;
	UDWORD	m_nPrecision	= NULL;
	SWORD	m_nScale		= NULL;
	SWORD	m_nNullability	= NULL;

	for( short i = 0; i < m_nCol; i++ ) 
	{
		if( !SQL_SUCCEEDED( SQLBindCol( m_hStmt, i+1, SQL_C_CHAR, m_szCol[i], 8192, &m_nColLength[i] ) ) )
			Error( "(ERROR) %s(%d): Bin col failed. [%d]", __FUNCTION__, __LINE__, i );
		if( !SQL_SUCCEEDED( SQLDescribeCol( m_hStmt, i+1, m_szColName[i], 16, &nActualLen, &m_nSQLType, &m_nPrecision, &m_nScale, &m_nNullability ) ) )
			Error( "(ERROR) %s(%d): Bin describe failed. [%d]", __FUNCTION__, __LINE__, i );
	}
}

void CDBInstance::Execute( _In_ char* szFormat, _In_ ... )
{
	char szBuffer[1024] = { NULL };

	va_list arg;
	va_start( arg, szFormat );
	int nLength = vsnprintf_s( szBuffer, 1024, szFormat, arg );
	va_end(arg);

	Clear();

	if( !SQL_SUCCEEDED( SQLExecDirect( m_hStmt, (SQLCHAR*)szBuffer, nLength ) ) )
	{
		Error( "(ERROR) %s(%d): Query execute failed. [%d][ %s ]", __FUNCTION__, __LINE__, nLength, szBuffer );
		return;
	}

	PrepareFetch();
}

short CDBInstance::FindCol( _In_ char* szName )
{
	for( short i = NULL; i < m_nCol; i++ ) 
	{
		if ( strcmp( szName, (char*)m_szColName[i] ) == 0 )
			return i + 1;
	}

	__debugbreak();
	return -1;
}
DBInstance.h:

Code:
#pragma once

#define MAXCOL		128

#include <sql.h>
#include <sqlext.h>

class CDBInstance
{
public:
	CDBInstance();
	virtual ~CDBInstance();
	inline void Clear();

	bool Connect( _In_ char* szDBName, _In_ char* szLogin, _In_ char* szDBPass );
	void Disconnect();

	void Execute( _In_ char* szFormat, _In_ ... );
	bool BindParameter( _In_ SQLUSMALLINT parameterNumber, _In_ SQLSMALLINT inputOutputType, _In_ SQLSMALLINT valueType, _In_ SQLSMALLINT parameterType, _In_ SQLUINTEGER columnSize, _In_ SQLSMALLINT decimalDigits, _In_ SQLPOINTER  parameterValuePtr, _In_ SQLINTEGER bufferLength, _In_ SQLINTEGER *strLen_or_IndPtr );

	inline bool Fetch()		{ return SQL_SUCCEEDED( SQLFetch( m_hStmt ) ); }
private:
	void			PrepareFetch();	
public:
	inline	byte	GetByte( _In_ char* szColumn )		{ return atoi( m_szCol[FindCol(szColumn)-1] ); }
	inline	double	GetDouble( _In_ char* szColumn )	{ return atof( m_szCol[FindCol(szColumn)-1] ); }
	inline	int		GetInt( _In_ char* szColumn )		{ return atoi( m_szCol[FindCol(szColumn)-1] ); }
	inline	__int64	GetInt64( _In_ char* szColumn )		{ return _atoi64( m_szCol[FindCol(szColumn)-1] ); }
	inline	float	GetFloat( _In_ char* szColumn )		{ return (float)atof( m_szCol[FindCol(szColumn)-1] ); }
	inline	char	GetChar( _In_ char* szColumn )		{ return m_szCol[FindCol(szColumn)-1][0]; }
private:
	SQLHENV		m_hEnv;
	SQLHDBC		m_hDbc;
	SQLHSTMT	m_hStmt;

	char*		m_szCol[MAXCOL];
	SQLCHAR		m_szColName[MAXCOL][32];
	SQLINTEGER	m_nColLength[MAXCOL];

	SQLSMALLINT m_nCol;

	short FindCol( _In_ char* szName );
};
Wie gesagt, ihr müsst nur wissen wie ihr es einsetzt, ich werde es euch nicht verraten. :p

Credits: Crasy, Clemi.

Mfg.
07/29/2013 13:14 cletite#2
So und einmal die "richtige" version:

Code:
#include "StdAfx.h"
#include "Query.h"

CQuery::CQuery()
{
	ZeroMemory( this, sizeof( CQuery ) );

	for( byte i = 0; i < MAXCOL; i++ )
	{
		m_szCol[ i ] = new char[8192];
		ZeroMemory( m_szCol, 8192 );
	}
}

CQuery::~CQuery()
{
	Disconnect();

	for( byte i = 0; i < MAXCOL; i++ )
		delete [] m_szCol[ i ];
}

void CQuery::Disconnect()
{
	Clear();
	SQLFreeHandle( SQL_HANDLE_STMT, m_hStmt );

	SQLDisconnect( m_hDbc );
	SQLFreeHandle( SQL_HANDLE_DBC, m_hDbc );
	SQLFreeHandle( SQL_HANDLE_ENV, m_hEnv );
}

void CQuery::Clear()
{
	SQLCloseCursor( m_hStmt );
	SQLFreeStmt( m_hStmt, SQL_UNBIND );
}

bool CQuery::Connect( _In_ const char* szDBName, _In_ const char* szLogin, _In_ const char* szDBPass )
{
	SQLAllocHandle( SQL_HANDLE_ENV,SQL_NULL_HANDLE, &m_hEnv );
	SQLSetEnvAttr( m_hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3_80, SQL_IS_INTEGER );

	SQLAllocHandle( SQL_HANDLE_DBC, m_hEnv, &m_hDbc );

	SQLSetConnectAttr(m_hDbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
	if(!SQL_SUCCEEDED( SQLConnect( m_hDbc, (SQLCHAR*)szDBName, SQL_NTS, (SQLCHAR*)szLogin, SQL_NTS, (SQLCHAR*)szDBPass, SQL_NTS ) ))
	{
		Error( "(ERROR) %s(%d): Can't connect to Database!! [%s]", __FUNCTION__, __LINE__, szDBName );
		return false;
	}

	return SQL_SUCCEEDED( SQLAllocHandle( SQL_HANDLE_STMT, m_hDbc, &m_hStmt ) );
}

void CQuery::Execute( _In_ const char* szBuff )
{
	Clear();

	int nLen = strlen( szBuff );
	if( !SQL_SUCCEEDED( SQLExecDirect( m_hStmt, (SQLCHAR*)szBuff, nLen ) ) )
	{
		Error( "(ERROR) %s(%d): Query execute failed. [%d][ %s ]", __FUNCTION__, __LINE__, nLen, szBuff );
		return;
	}

	PrepareFetch();
}

void CQuery::Execute( _In_ const char* szBuff, _In_ int nLen )
{
	Clear();

	if( !SQL_SUCCEEDED( SQLExecDirect( m_hStmt, (SQLCHAR*)szBuff, nLen ) ) )
	{
		Error( "(ERROR) %s(%d): Query execute failed. [%d][ %s ]", __FUNCTION__, __LINE__, nLen, szBuff );
		return;
	}

	PrepareFetch();
}

void CQuery::Execute( _In_ const char* szFormat, _In_opt_ ... )
{
	char szBuffer[1024] = { NULL };

	va_list arg;
	va_start( arg, szFormat );
	int nLength = vsnprintf_s( szBuffer, 1024, szFormat, arg );
	va_end(arg);

	Clear();

	if( !SQL_SUCCEEDED( SQLExecDirect( m_hStmt, (SQLCHAR*)szBuffer, nLength ) ) )
	{
		Error( "(ERROR) %s(%d): Query execute failed. [%d][ %s ]", __FUNCTION__, __LINE__, nLength, szBuffer );
		return;
	}

	PrepareFetch();
}

void CQuery::PrepareFetch()
{
	SQLNumResultCols( m_hStmt, &m_nCol );

	SWORD	nActualLen		= 0;
	SWORD	m_nSQLType		= 0;
	UDWORD	m_nPrecision	= 0;
	SWORD	m_nScale		= 0;
	SWORD	m_nNullability	= 0;

	for( short i = 0; i < m_nCol; i++ ) 
	{
		if( !SQL_SUCCEEDED( SQLBindCol( m_hStmt, i+1, SQL_C_CHAR, m_szCol[i], 8192, &m_nColLength[i] ) ) ||
			!SQL_SUCCEEDED( SQLDescribeCol( m_hStmt, i+1, m_szColName[i], 16, &nActualLen, &m_nSQLType, &m_nPrecision, &m_nScale, &m_nNullability ) ) )
			Error( "(ERROR) %s(%d): failed. [%d]", __FUNCTION__, __LINE__, i );
	}
}
Code:
#pragma once


#include <sql.h>
#include <sqlext.h>

#define MAXCOL 256

static inline bool EnableConnectionPooling()	{	return SQL_SUCCEEDED( SQLSetEnvAttr( NULL, SQL_ATTR_CONNECTION_POOLING, (SQLPOINTER)SQL_CP_ONE_PER_DRIVER, SQL_IS_INTEGER ) ); 	}

class CQuery
{
public:
	CQuery();
	~CQuery();

private:
	void Clear();
	void Disconnect();
	void PrepareFetch();

public:
	bool Connect( _In_ const char* szDBName, _In_ const char* szLogin, _In_ const char* szDBPass );

	void Execute( _In_ const char* szBuff );
	void Execute( _In_ const char* szBuff, _In_ int nLen );
	void Execute( _In_ const char* szFormat, _In_opt_ ... );

private:
	inline bool		BindParameter( _In_ SQLUSMALLINT iPar, _In_ SQLSMALLINT fParam, _In_ SQLSMALLINT val, _In_ SQLSMALLINT param, _In_ SQLUINTEGER col, _In_ SQLSMALLINT digits, _In_ SQLPOINTER  valPtr, _In_ SQLINTEGER len, _In_ SQLINTEGER* ptr )
	{	return SQL_SUCCEEDED( SQLBindParameter( m_hStmt, iPar, fParam, val, param, col, digits, valPtr, len, ptr ) );	}
	
	inline bool		Fetch()		{ return SQL_SUCCEEDED( SQLFetch( m_hStmt ) ); }
	inline short	FindCol( _In_ const char* szName )
	{
		for( short i = 0; i < m_nCol; i++ ) 
		{
			if( strcmp( szName, (char*)m_szColName[ i ] ) == 0 )
				return i;
		}

		Error( "(ERROR) %s(%d): Cannot find col [%s]", __FUNCTION__, __LINE__, szName );

		__debugbreak();
		return 0;
	}


public:
	inline EXPINTEGER	GetExpInteger( const char* szCol )			{	return GetInt64( szCol ); 	}
	inline SERIALNUMBER	GetSerialNumber( const char* szCol )		{	return GetInt( szCol );		}

	inline	char		GetChar( _In_ const char* szCol )			{	return *m_szCol[ FindCol( szCol ) ];				}
	inline	byte		GetByte( _In_ const char* szCol )			{	return atoi( m_szCol[ FindCol( szCol) ] );			}
	inline	int			GetInt( _In_ const char* szCol )			{	return atoi( m_szCol[ FindCol( szCol ) ] );			}
	inline	__int64		GetInt64( _In_ const char* szCol )			{	return _atoi64( m_szCol[ FindCol( szCol ) ] );		}
	inline	float		GetFloat( _In_ const char* szCol )			{	return (float)atof( m_szCol[ FindCol( szCol ) ] );	}
	inline	double		GetDouble( _In_ const char* szCol )			{	return atof( m_szCol[ FindCol( szCol ) ] );			}


private:
	SQLHENV		m_hEnv;
	SQLHDBC		m_hDbc;
	char*		m_szCol[MAXCOL];

	SQLHSTMT	m_hStmt;
	SQLSMALLINT m_nCol;
	SQLCHAR		m_szColName[MAXCOL][50];
	SQLINTEGER	m_nColLength[MAXCOL];
};
Lg, Clemi
07/29/2013 13:26 DieLachnummer#3
Was muss man damit machen?
07/29/2013 13:46 Uloure#4
Quote:
Originally Posted by Wanetrain View Post
Wie gesagt, ihr müsst nur wissen wie ihr es einsetzt, ich werde es euch nicht verraten.
Lesen dann weißt du das er keinen Support gibt.
07/29/2013 13:49 ©ross#5
:3 Nice - kannte ich ja schon durch Erzählung :D
Wenn man eben weis wie es einzusetzen ist, sehr geil.


Greetz,
Cross


Sent via Tapatalk 2
11/14/2013 09:09 Wanetrain#6
Little Update.

Da mir zu ohren gekommen ist es sei ein Fehler drin hab ich dass ganze nochmal mit einer Privaten "Version" abgeglichen und ja, es ist wirklich ein Fehler bei "GetChar" drin, einfach Replacen mit:

Quote:
inline char* GetChar( _In_ char* szColumn ) { return m_szCol[FindCol(szColumn)]; }
Dann ist euer Fehler auch schon weg. :)
11/14/2013 13:12 Rhyder'#7
what does the purpose of this?
11/14/2013 14:10 Wanetrain#8
Quote:
Originally Posted by Rhyder' View Post
what does the purpose of this?
Still more performance for DB Server.^^
11/14/2013 15:53 FlyCraft.TobiLap#9
Ja, eher nutzlos, da man die meisten server eh kein 500+ user haben und alle die es haben haben auch hardware die stark genug ist.
11/14/2013 22:56 Wanetrain#10
Quote:
Originally Posted by FlyCraft.TobiLap View Post
Ja, eher nutzlos, da man die meisten server eh kein 500+ user haben und alle die es haben haben auch hardware die stark genug ist.
Ich denke du hast relativ wenig Ahnung von dem hier, oder? wenn am nes ordentlich verbaut kann man einfach mal dass Character Speichern anstat alle 15min einfach mal auf min. 5min runter drücken, dass macht dann weniger Schaden bei einem Server absturz, also von dem her. :)

zzgl. schafft man es Deutlich schneller Querys durch zu ballern als davor, somit ist es auch schneller ein ganzen Character zu laden. :)
11/14/2013 23:46 Rhyder'#11
Quote:
Originally Posted by Wanetrain View Post
Still more performance for DB Server.^^
when i add this to my dbserver it gives a lot of errors :O
11/15/2013 05:09 Wanetrain#12
Quote:
Originally Posted by Rhyder' View Post
tutorial to work this? it gives a lot of errors :O
I work on a tutorial for you. :)
11/15/2013 11:38 Sedrika#13
Ich sehe nicht, wieso deine Klasse hier besser sein soll als das was bereits im Source steht?
11/15/2013 12:05 Wanetrain#14
Die klasse ist in sofern besser weil es großteils Inline ist, sehr viele unnütze Abfragen weg lässt und man sie ohne Probleme in Threads einbauen kann, aber hey, verstehst ja hier bei den ePVP leuten am meisten, also erzähl mal was.
11/15/2013 12:23 Sedrika#15
Welche unnötigen Abfragen hast du denn entfernt, wenn du sagst, dass du welche entfernt hast. Zudem ist der einzige vorteil von Inline, dass diese keinen Aufruf mehr braucht. Die 1ms kann man sich sparen.