Jump to content
  • Advertisement
Sign in to follow this  
nuclear123

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

This topic is 2174 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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;
}
};

Share this post


Link to post
Share on other sites
Advertisement
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 ) Edited by nuclear123

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!