From 0bcc223b1494e9bbc74ed61cfa7b2a10ce4e0cb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Czerpak?= Date: Mon, 23 Feb 2015 17:47:54 +0100 Subject: [PATCH] 2015-02-23 17:47 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) * contrib/hbodbc/odbc.c * rewritten function SQLGetData() - new code is much simpler and fixes few bugs * contrib/hbodbc/todbc.prg % eliminated unnecessary AAdd() when final array size is already known ! do not round numbers read number to default number of decimal places --- ChangeLog.txt | 9 +++++ contrib/hbodbc/odbc.c | 84 +++++++++++++++------------------------- contrib/hbodbc/todbc.prg | 28 +++++++------- 3 files changed, 55 insertions(+), 66 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 9a807f01cf..3a516cbdc5 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -10,6 +10,15 @@ * Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment */ +2015-02-23 17:47 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) + * contrib/hbodbc/odbc.c + * rewritten function SQLGetData() - new code is much simpler and + fixes few bugs + + * contrib/hbodbc/todbc.prg + % eliminated unnecessary AAdd() when final array size is already known + ! do not round numbers read number to default number of decimal places + 2015-02-21 15:33 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) * ChangeLog.txt * src/compiler/hbmain.c diff --git a/contrib/hbodbc/odbc.c b/contrib/hbodbc/odbc.c index 4625c3a34c..41939f9834 100644 --- a/contrib/hbodbc/odbc.c +++ b/contrib/hbodbc/odbc.c @@ -581,68 +581,46 @@ HB_FUNC( SQLGETDATA ) /* hStmt, nField, nType, nLen, @cBuffer --> nRetCode */ if( hStmt ) { - SQLLEN nLen; - SQLLEN nInitBuff; - SQLLEN nBuffLen = 0; - char * buffer; - char * outbuf = NULL; - SQLSMALLINT iType = ( SQLSMALLINT ) hb_parnidef( 3, SQL_BINARY ); - int iReallocs = 0; - SQLRETURN result; + SQLUSMALLINT uiColumn = ( SQLUSMALLINT ) hb_parni( 2 ); + SQLSMALLINT iType = ( SQLSMALLINT ) hb_parnidef( 3, SQL_BINARY ); + SQLLEN nLen = ( SQLLEN ) hb_parnint( 4 ); + SQLLEN nInitBuff; + char * buffer; + SQLRETURN result; - nLen = ( SQLLEN ) hb_parnint( 4 ); - if( nLen <= 0 ) + /* driver does not check the nLen parameter for fixed length types + so caller has to provide enough space */ + if( nLen < 64 ) nLen = 64; nInitBuff = nLen; - buffer = ( char * ) hb_xgrab( ( HB_SIZE ) nLen + 1 ); + buffer = ( char * ) hb_xgrab( ( HB_SIZE ) nLen + 1 ); - result = ! SQL_NO_DATA; - while( result != SQL_NO_DATA ) + result = SQLGetData( hStmt, uiColumn, iType, ( SQLPOINTER ) buffer, + nLen, &nLen ); + if( result == SQL_SUCCESS_WITH_INFO ) { - result = SQLGetData( hStmt, - ( SQLUSMALLINT ) hb_parni( 2 ), - ( SQLSMALLINT ) iType, - ( SQLPOINTER ) buffer, - ( SQLLEN ) nLen, - ( SQLLEN * ) &nLen ); - - if( result == SQL_SUCCESS && iReallocs == 0 ) + if( nLen > nInitBuff ) { - hb_storclen( buffer, ( HB_SIZE ) ( nLen < 0 ? 0 : ( nLen < ( SQLLEN ) hb_parnint( 4 ) ? nLen : ( SQLLEN ) hb_parnint( 4 ) ) ), 5 ); - break; + /* data right truncated! */ + buffer = ( char * ) hb_xrealloc( buffer, ( HB_SIZE ) nLen + 1 ); + result = SQLGetData( hStmt, uiColumn, iType, + ( SQLPOINTER ) ( buffer + nInitBuff ), + nLen - nInitBuff, &nInitBuff ); + if( result == SQL_SUCCESS_WITH_INFO ) + result = SQL_SUCCESS; } - else if( result == SQL_SUCCESS_WITH_INFO && iReallocs == 0 ) - { - /* Perhaps a data truncation */ - if( nLen >= nInitBuff ) - { - /* data right truncated! */ - nBuffLen = nLen; - outbuf = ( char * ) hb_xgrab( ( HB_SIZE ) nBuffLen + 1 ); - hb_strncpy( outbuf, buffer, nLen ); - nLen = nLen - nInitBuff + 2; - buffer = ( char * ) hb_xrealloc( buffer, ( HB_SIZE ) nLen ); - iReallocs++; - } - else - { - hb_storclen( buffer, ( HB_SIZE ) ( nLen < 0 ? 0 : ( nLen < ( SQLLEN ) hb_parnint( 4 ) ? nLen : ( SQLLEN ) hb_parnint( 4 ) ) ), 5 ); - break; - } - } - else if( ( result == SQL_SUCCESS || result == SQL_SUCCESS_WITH_INFO ) && iReallocs > 0 ) - { - hb_strncat( outbuf, buffer, nBuffLen ); - hb_storclen( outbuf, ( HB_SIZE ) ( nLen + nInitBuff - 1 ), 5 ); + else if( nLen == nInitBuff ) result = SQL_SUCCESS; - break; - } - else - break; } - hb_xfree( buffer ); - if( outbuf ) - hb_xfree( outbuf ); + if( result != SQL_SUCCESS && result != SQL_SUCCESS_WITH_INFO ) + nLen = 0; + if( nInitBuff - nLen > 32 ) + hb_storclen( buffer, ( HB_SIZE ) ( nLen < 0 ? 0 : nLen ), 5 ); + else if( hb_storclen_buffer( buffer, nLen, 5 ) ) + buffer = NULL; + + if( buffer ) + hb_xfree( buffer ); hb_retni( result ); } else diff --git a/contrib/hbodbc/todbc.prg b/contrib/hbodbc/todbc.prg index 9026d2ee85..b9df660c08 100644 --- a/contrib/hbodbc/todbc.prg +++ b/contrib/hbodbc/todbc.prg @@ -270,6 +270,7 @@ METHOD Open() CLASS TODBC LOCAL nNul LOCAL nResult LOCAL aCurRow + LOCAL oField DO WHILE .T. @@ -309,20 +310,20 @@ METHOD Open() CLASS TODBC ::nRecCount := nRows ENDIF - ::Fields := {} + ::Fields := Array( nCols ) FOR i := 1 TO nCols SQLDescribeCol( ::hStmt, i, @cColName, 255, @nNameLen, @nDataType, ; @nColSize, @nDecimals, @nNul ) - AAdd( ::Fields, TODBCField():New() ) - ::Fields[ Len( ::Fields ) ]:FieldID := i - ::Fields[ Len( ::Fields ) ]:FieldName := cColName - ::Fields[ Len( ::Fields ) ]:DataSize := nColsize - ::Fields[ Len( ::Fields ) ]:DataType := nDataType - ::Fields[ Len( ::Fields ) ]:DataDecs := nDecimals - ::Fields[ Len( ::Fields ) ]:AllowNull := ( nNul != 0 ) + ::Fields[ i ] := oField := TODBCField():New() + oField:FieldID := i + oField:FieldName := cColName + oField:DataSize := nColsize + oField:DataType := nDataType + oField:DataDecs := nDecimals + oField:AllowNull := ( nNul != 0 ) NEXT @@ -331,9 +332,9 @@ METHOD Open() CLASS TODBC ::aRecordSet := {} DO WHILE ::Fetch( SQL_FETCH_NEXT, 1 ) == SQL_SUCCESS - aCurRow := {} + aCurRow := Array( nCols ) FOR i := 1 TO nCols - AAdd( aCurRow, ::Fields[ i ]:value ) + aCurRow[ i ] := ::Fields[ i ]:value NEXT AAdd( ::aRecordSet, aCurRow ) ENDDO @@ -650,7 +651,7 @@ METHOD LoadData( nPos ) CLASS TODBC CASE SQL_TIMESTAMP CASE SQL_DATE - uData := hb_SToD( SubStr( uData, 1, 4 ) + SubStr( uData, 6, 2 ) + SubStr( uData, 9, 2 ) ) + uData := hb_odbcSToD( uData ) EXIT CASE SQL_BIT @@ -666,8 +667,9 @@ METHOD LoadData( nPos ) CLASS TODBC CASE SQL_INTEGER CASE SQL_FLOAT CASE SQL_REAL - uData := Round( Val( StrTran( uData, ",", "." ) ), ::Fields[ i ]:DataDecs ) - uData := hb_odbcNumSetLen( uData, ::Fields[ i ]:DataSize, ::Fields[ i ]:DataDecs ) + uData := hb_odbcNumSetLen( Val( StrTran( uData, ",", "." ) ), ; + ::Fields[ i ]:DataSize, ; + ::Fields[ i ]:DataDecs ) EXIT ENDSWITCH