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

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

  • Friday, August 03, 2012 1:43 AM
     
      Has Code

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

All Replies

  • Monday, August 06, 2012 6:00 AM
    Moderator
     
     

    Hi v3nOm,

    Welcome here.

    Based on your description, you want criticism on design problems people might see; there is not a solid answer of it, so I will change the thread type to general discussion.

    Thanks for your understanding.

    Regards,


    Elegentin Xie [MSFT]
    MSDN Community Support | Feedback to us