Sign in to follow this  

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

This topic is 1960 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 )


[CODE]
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;
}
};
[/CODE]

Share this post


Link to post
Share on other sites
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

This topic is 1960 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this