[sqlapi-announce] SQLAPI++ 3.7.22 MySQL statement affected rows and datetime/timestamp second part bugfixes

  • From: Sergey Chumakov <support@xxxxxxxxxx>
  • To: sqlapi-announce@xxxxxxxxxxxxx
  • Date: Tue, 21 Aug 2007 15:32:03 +0300

Hi All,

The statement affected rows problem occurs because SQLAPI executes mysql_next_result just after mysql_real_query. The patch uses saved rows affected value and fix the problem.

Thanks to Christoph Merten.

The patch also fixes the problem with datetime/timestamp second part/fraction (the binding SADateTime values produces an empty MySQL field values.).

Thanks to Helmut Ebersmann.

The patch is attached.

--
Best regards,
Sergey Chumakov, SQLAPI++ development team








*** myClient.cpp        30 Jun 2007 09:41:25 -0000      1.31
--- myClient.cpp        10 Aug 2007 08:33:46 -0000
***************
*** 358,368 ****
--- 358,370 ----
  
  #define SA_MYSQL_MAX_NUMERIC_LENGTH 72
  #define SA_MYSQL_MAX_INTERVAL_LENGTH 11
+ #define SA_MYSQL_NO_ROWS_AFFECTED (my_ulonglong)(-1)
  
  class ImyCursor : public ISACursor
  {
        // private handles
        myCommandHandles        m_handles;
+       my_ulonglong cRows;
  
        // private handles (OLD API)
        MYSQL_ROW m_mysql_row;
***************
*** 491,496 ****
--- 493,500 ----
        SACommand *pCommand) :
        ISACursor(pImyConnection, pCommand)
  {
+       cRows = SA_MYSQL_NO_ROWS_AFFECTED;
+ 
        m_bOpened = false;
        m_bResultSetCanBe = false;
  
***************
*** 539,545 ****
  
        date_time = SADateTime(dtInternal.year, dtInternal.month, 
dtInternal.day,
                dtInternal.hour, dtInternal.minute, dtInternal.second);
!       date_time.Fraction() = dtInternal.second_part;
  }
  
  /*virtual */
--- 543,549 ----
  
        date_time = SADateTime(dtInternal.year, dtInternal.month, 
dtInternal.day,
                dtInternal.hour, dtInternal.minute, dtInternal.second);
!       date_time.Fraction() = dtInternal.second_part * 1000;
  }
  
  /*virtual */
***************
*** 759,768 ****
        SAString &sInternal)
  {
        // format should be YYYY-MM-DD HH:MM:SS.fraction
!       sInternal.Format(_TSA("%.4d-%.2d-%.2d %.2d:%.2d:%.2d.%.9ld"),
                date_time.GetYear(), date_time.GetMonth(), date_time.GetDay(),
                date_time.GetHour(), date_time.GetMinute(), 
date_time.GetSecond(),
!               date_time.Fraction());
  }
  
  /*static */
--- 763,772 ----
        SAString &sInternal)
  {
        // format should be YYYY-MM-DD HH:MM:SS.fraction
!       sInternal.Format(_TSA("%.4d-%.2d-%.2d %.2d:%.2d:%.2d.%.6d"),
                date_time.GetYear(), date_time.GetMonth(), date_time.GetDay(),
                date_time.GetHour(), date_time.GetMinute(), 
date_time.GetSecond(),
!               (int)(date_time.Fraction() / 1000));
  }
  
  /*static */
***************
*** 780,786 ****
        dtInternal.hour = date_time.GetHour();
        dtInternal.minute = date_time.GetMinute();
        dtInternal.second = date_time.GetSecond();
!       dtInternal.second_part = date_time.Fraction();
  }
  
  /*virtual */
--- 784,790 ----
        dtInternal.hour = date_time.GetHour();
        dtInternal.minute = date_time.GetMinute();
        dtInternal.second = date_time.GetSecond();
!       dtInternal.second_part = (unsigned long)(date_time.Fraction() / 1000);
  }
  
  /*virtual */
***************
*** 1227,1232 ****
--- 1231,1238 ----
        }
        else
                m_bResultSetCanBe = false;
+ 
+       cRows = SA_MYSQL_NO_ROWS_AFFECTED;
  }
  
  // executes statement (also binds parameters if needed)
***************
*** 1402,1407 ****
--- 1408,1416 ----
                if(g_myAPI.mysql_query(pConH->mysql, 
sBoundStmt.GetMultiByteChars()))
                        Check(pConH->mysql);
  
+               // save affected rows
+               GetRowsAffected();
+ 
                // procedure can return result set
                MYSQL_RES *localResult = 
g_myAPI.mysql_store_result(pConH->mysql);
                Check(pConH->mysql);
***************
*** 1436,1441 ****
--- 1445,1453 ----
        } 
        else
        {
+               // save affected rows
+               GetRowsAffected();
+ 
                SAString sOption = m_pCommand->Option(_TSA("HandleResult"));
                if(sOption.CompareNoCase(_TSA("store")) == 0)
                        m_handles.result = 
g_myAPI.mysql_store_result(pConH->mysql);
***************
*** 2014,2028 ****
  /*virtual */
  long ImyCursor::GetRowsAffected()
  {
!       my_ulonglong cRows = 0;
!       
!       if( NULL != m_handles.stmt ) // Use satetment API
!               cRows = g_myAPI.mysql_stmt_affected_rows(m_handles.stmt);
!       else
        {
!               myConnectionHandles *pConH =
!                       (myConnectionHandles 
*)m_pCommand->Connection()->NativeHandles();
!               cRows = g_myAPI.mysql_affected_rows(pConH->mysql);
        }
  
        return (long)cRows;
--- 2026,2041 ----
  /*virtual */
  long ImyCursor::GetRowsAffected()
  {
!       if( SA_MYSQL_NO_ROWS_AFFECTED == cRows )
        {
!               if( NULL != m_handles.stmt ) // Use satetment API
!                       cRows = 
g_myAPI.mysql_stmt_affected_rows(m_handles.stmt);
!               else
!               {
!                       myConnectionHandles *pConH =
!                               (myConnectionHandles 
*)m_pCommand->Connection()->NativeHandles();
!                       cRows = g_myAPI.mysql_affected_rows(pConH->mysql);
!               }
        }
  
        return (long)cRows;

Other related posts:

  • » [sqlapi-announce] SQLAPI++ 3.7.22 MySQL statement affected rows and datetime/timestamp second part bugfixes