Skip to main content
GameDev.net gamedev.net
🔒 Locked

C++ ODBC Wrapper Classes ( SQLHANDLES ) - part 1

Started by nuclear123 Aug 3, 2012 at 1:52 AM 1 replies 2.4k views
Original Post
nuclear123
nuclear123
In order to further increase my knowledge of ODBC and C++ good design practices i have decided to try my go at creating wrapper classes of the current ODBC C Api located on MSDN. I'm mainly wanting criticism on design problems people might see. Any advice is greatly appreciated ;) cheers


In order to avoid VTABLE overhead i have tried my best to implement simulated dynamic binding/CRTP ( which i believe i have implemented correctly )



template<class TDerived, SQLSMALLINT THandle = SQL_HANDLE_UNKNOWN>
class __declspec(novtable) CHandle
{
public:
SQLHANDLE m_h;
SQLSMALLINT m_hType;
enum { SQL_HANDLE_UNKNOWN = -1 };
public:
CHandle() :
m_h(NULL), m_hType(THandle)
{
_ASSERTE(m_hType != -1);
}

CHandle(SQLHANDLE h) :
m_h(h), m_hType(THandle)
{
_ASSERTE(h != NULL);
_ASSERTE(m_hType != -1);

Attach(h);
}
void Attach(_In_ SQLHANDLE h)
{
_ASSERTE(h != NULL);
_ASSERTE(m_h == NULL);
_ASSERTE(m_hType != -1);

m_h = h;
}
SQLHANDLE Detach()
{
_ASSERTE(m_h != NULL);
_ASSERTE(m_hType != -1);
SQLHANDLE hTemp = m_h;
m_h = NULL;
return hTemp;
}
bool Create()
{
_ASSERTE(m_h == NULL);
_ASSERTE(m_hType != -1);

g_rt = SQLAllocHandle(THandle, NULL, &m_h);
_ASSERTE(SQL_SUCCEEDED(g_rt));
if (SQL_SUCCEEDED(g_rt) == FALSE)
return FALSE;

return TRUE;
}
void Destroy()
{
_ASSERTE(m_h != NULL);
_ASSERTE(m_hType != -1);

g_rt = SQLFreeHandle(THandle, m_h);
_ASSERTE(SQL_SUCCEEDED(g_rt));
m_h = NULL;
m_hType = -1;
}
// TODO : test setting multiple attributes
bool SetAttribute(_In_ SQLINTEGER attribute, _In_ SQLPOINTER value)
{
_ASSERTE(m_h != NULL);
return static_cast<TDerived*>(this)->_SetAttribute(attribute, value);
}
// TODO : test getting multiple attributes
bool GetAttribute(_In_ SQLINTEGER attribute, _Inout_ SQLPOINTER pValue, _Inout_ SQLINTEGER* pcbWritten)
{
_ASSERTE(m_h != NULL);
return static_cast<TDerived*>(this)->_GetAttribute(attribute, pValue, pcbWritten);
}
operator SQLHANDLE()
{
return m_h;
}
};

class __declspec(novtable) CEnviromentHandle :
public CHandle< CEnviromentHandle, SQL_HANDLE_ENV>
{
public:

bool _SetAttribute(_In_ SQLINTEGER attribute, _In_ SQLPOINTER value)
{
_ASSERTE(m_h != NULL);
g_rt = SQLSetEnvAttr(m_h, attribute, value, SQL_NTS);
_ASSERTE(SQL_SUCCEEDED(g_rt));
if (SQL_SUCCEEDED(g_rt) == FALSE)
return FALSE;

return TRUE;
}
// TODO : i might need last parameter. For now ignoreing
bool _GetAttribute(_In_ SQLINTEGER attribute, _Inout_ SQLPOINTER pValue, _Inout_ SQLINTEGER* pcbWritten)
{
_ASSERTE(m_h != NULL);
g_rt = SQLGetEnvAttr(m_h, attribute, pValue, SQL_IS_UINTEGER, pcbWritten);
_ASSERTE(SQL_SUCCEEDED(g_rt));
if (SQL_SUCCEEDED(g_rt) == FALSE)
return FALSE;

return TRUE;
}
};
class __declspec(novtable) CConnectionHandle :
public CHandle< CConnectionHandle, SQL_HANDLE_DBC>
{
public:
bool _SetAttribute(_In_ SQLINTEGER attribute, _In_ SQLPOINTER value)
{
_ASSERTE(m_h != NULL);
g_rt = SQLSetConnectAttr(m_h, attribute, value, SQL_NTS);
_ASSERTE(SQL_SUCCEEDED(g_rt));
if (SQL_SUCCEEDED(g_rt) == FALSE)
return FALSE;

return TRUE;
}
// TODO : i might need last parameter. For now ignoreing
bool _GetAttribute(_In_ SQLINTEGER attribute, _Inout_ SQLPOINTER pValue, _Inout_ SQLINTEGER* pcbWritten)
{
_ASSERTE(m_h != NULL);
g_rt = SQLGetConnectAttr(m_h, attribute, pValue, SQL_IS_UINTEGER, pcbWritten);
_ASSERTE(SQL_SUCCEEDED(g_rt));
if (SQL_SUCCEEDED(g_rt) == FALSE)
return FALSE;

return TRUE;
}
};

class __declspec(novtable) CStatementHandle :
public CHandle< CStatementHandle, SQL_HANDLE_STMT>
{
public:
bool _SetAttribute(_In_ SQLINTEGER attribute, _In_ SQLPOINTER value)
{
_ASSERTE(m_h != NULL);
g_rt = SQLSetStmtAttr(m_h, attribute, value, SQL_NTS);
_ASSERTE(SQL_SUCCEEDED(g_rt));
if (SQL_SUCCEEDED(g_rt) == FALSE)
return FALSE;

return TRUE;
}
// TODO : i might need last parameter. For now ignoreing
bool _GetAttribute(_In_ SQLINTEGER attribute, _Inout_ SQLPOINTER pValue, _Inout_ SQLINTEGER* pcbWritten)
{
_ASSERTE(m_h != NULL);
g_rt = SQLGetStmtAttr(m_h, attribute, pValue, SQL_IS_UINTEGER, pcbWritten);
_ASSERTE(SQL_SUCCEEDED(g_rt));
if (SQL_SUCCEEDED(g_rt) == FALSE)
return FALSE;

return TRUE;
}
};
bubu LV
bubu LV

I don't see any reason for __declspec(novtable) because you don't have any virtual methods.

nuclear123
nuclear123
thank you i will rid of it. I was thinking it meant self documentation and to prevent virtual functions from being included within the code but it seems from msdn it just prevents initialization of the vtable within the constructor to prevent wasting time of initializing something that might get overwritten later from deeper inheritance( if i understood it correctly )

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.