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

Last reviewed: September 18, 1997
Article ID: Q120206
1.50 1.51 1.52 1.52b WINDOWS kbprg kbfixlist kbbuglist

The information in this article applies to:

  • The Microsoft Foundation Classes (MFC), included with: Microsoft Visual C++ for Windows, version 1.5, 1.51, 1.52, and 1.52b

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 reference words: 1.50 1.51 1.52 2.50 2.51 2.52 2.53
KBCategory: kbprg kbfixlist kbbuglist
KBSubcategory: MfcDatabase
Keywords : kb16bitonly MfcDatabase kbbuglist kbfixlist kbprg
Technology : kbMfc
Version : 1.50 1.51 1.52 1.52b
Platform : WINDOWS
Solution Type : kbfix


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: September 18, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.