FIX: Incorrect Return Value From CRecordset::IsOpen()

ID: Q120206


The information in this article applies to:


SYMPTOMS

When CRecordset::IsOpen() is called, it returns TRUE even if the CRecordset has not been opened.

This happens only if a CRecordset is constructed with a CDatabase pointer being passed to it.


CAUSE

CRecordset::IsOpen() checks whether the statement handle of the recordset has been allocated as follows:


_AFXDBCORE_INLINE BOOL CRecordset::IsOpen() const
     { ASSERT_VALID(this); return m_hstmt != SQL_NULL_HSTMT; } 
The statement handle is usually allocated when CRecordset::Open() is called (that is, when a recordset is opened).

But, if a CRecordset is constructed with a CDatabase pointer being passed to it, the CRecordset constructor allocates a statement handle and assigns a value to the member variable m_hstmt. So, if a call to CRecordset::IsOpen() is made after creating a CRecordset in this fashion, it returns TRUE even if the recordset is not open.


RESOLUTION

To work around this problem, use one of the following methods:

Create a Custom IsOpen Routine

  1. Because IsOpen() is not a virtual function, create another function, such as "IsMyOpen()", and call IsMyOpen() instead of IsOpen().


  2. In your custom IsMyOpen(), call the ODBC API function SQLNumResultCols() to check whether the recordset has been opened. SQLNumResultCols returns the number of columns in the result set. If the function does not return an error message and the number of columns is not 0, then the recordset has been opened. The sample code for such a IsMyOpen() function is given in the "MORE INFORMATION" section, below.


Use a Flag to Track Whether the Recordset Has Been Opened

Derive a class from CRecordset and create a new member variable that would be set whether the recordset has been opened. Override CRecordset::Open and set the flag in the function. Create a CRecordset::IsMyOpen that would check whether the flag is set. Then call IsMyOpen instead of IsOpen to check whether the recordset has been opened.


STATUS

Microsoft has confirmed this to be a bug in the products listed at the beginning of this article. This bug was corrected in the 32-bit version of MFC.


MORE INFORMATION

Sample Code


   BOOL CMyRecordset::IsMyOpen() const
   {
      if (m_hstmt == NULL)
         return FALSE;
      RETCODE nRetCode;
      SWORD nCols;
      AFX_SQL_SYNC(::SQLNumResultCols(m_hstmt, &nCols));
      if (nRetCode == SQL_ERROR)
      {
         TRACE0("Error: SQLNumResultCols failed during IsOpen().\n");
         return FALSE;
      }
      else if (nCols == 0)
         return FALSE;
      return TRUE;
   } 

Additional query words: 1.50 1.51 1.52 2.50 2.51 2.52 2.53


Keywords          : kb16bitonly kbDatabase kbMFC kbODBC kbVC 
Version           : 1.50 1.51 1.52 1.52b
Platform          : WINDOWS 
Issue type        : 

Last Reviewed: July 21, 1999