From 640164f6066533b8a2929bbee799a6e283dda4f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Czerpak?= Date: Fri, 19 May 2017 00:54:22 +0200 Subject: [PATCH] 2017-05-19 00:54 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) * contrib/rddads/ads1.c + added support for "VarCharFox" and "VarBinaryFox" field types. ! fixed accessing "VarChar" fields longer then their size defined in table header (rest of longer fields is stored in memo file) ! do not reduce size of data stored in "VarChar" fields to the size of region allocated for them in table record. Such fields allows to store up to 64000 bytes and rest is saved in memo file. ! fixed RTE when strings longer then 64000 bytes are assigned to "VarChar" fields. ! fixed RTE when strings longer then declared field size are assigned to Unicode character fields (i.e. "nChar" or "C:U") ! fixed possible use of memcpy() with the same source and destination addresses --- ChangeLog.txt | 15 ++++++ contrib/rddads/ads1.c | 106 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 106 insertions(+), 15 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 6a73318ad4..5ec7d69628 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -10,6 +10,21 @@ * Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment */ +2017-05-19 00:54 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) + * contrib/rddads/ads1.c + + added support for "VarCharFox" and "VarBinaryFox" field types. + ! fixed accessing "VarChar" fields longer then their size defined in + table header (rest of longer fields is stored in memo file) + ! do not reduce size of data stored in "VarChar" fields to the size + of region allocated for them in table record. Such fields allows + to store up to 64000 bytes and rest is saved in memo file. + ! fixed RTE when strings longer then 64000 bytes are assigned to + "VarChar" fields. + ! fixed RTE when strings longer then declared field size are assigned + to Unicode character fields (i.e. "nChar" or "C:U") + ! fixed possible use of memcpy() with the same source and destination + addresses + 2017-05-15 14:34 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) * contrib/hbgs/hbgs.hbp ! respect HB_BUILD_3RDEXT=no diff --git a/contrib/rddads/ads1.c b/contrib/rddads/ads1.c index 78a30af6ab..131fa63514 100644 --- a/contrib/rddads/ads1.c +++ b/contrib/rddads/ads1.c @@ -1697,6 +1697,19 @@ static HB_ERRCODE adsCreateFields( ADSAREAP pArea, PHB_ITEM pStruct ) } else if( ! hb_strnicmp( szFieldType, "rowversion", 2 ) ) iData = '^'; +#if ADS_LIB_VERSION >= 900 + else if( ! hb_strnicmp( szFieldType, "varcharfox", 8 ) ) + { + iData = 'Q'; + dbFieldInfo.uiTypeExtended = ADS_VARCHAR_FOX; + } + else if( ! hb_strnicmp( szFieldType, "varbinaryfox", 10 ) ) + { + iData = 'Q'; + dbFieldInfo.uiTypeExtended = ADS_VARBINARY_FOX; + dbFieldInfo.uiFlags |= HB_FF_BINARY; + } +#endif else if( ! hb_strnicmp( szFieldType, "varchar", 4 ) ) { iData = 'Q'; @@ -1782,16 +1795,19 @@ static HB_ERRCODE adsCreateFields( ADSAREAP pArea, PHB_ITEM pStruct ) } else #endif - /* TOCHECK: I've used ADS_VARBINARY_FOX here since there is no - better constant for this [Mindaugas] */ - if( dbFieldInfo.uiFlags & HB_FF_BINARY ) + if( dbFieldInfo.uiTypeExtended == 0 ) + { + /* TOCHECK: I've used ADS_VARBINARY_FOX here since there is no + better constant for this [Mindaugas] */ + if( dbFieldInfo.uiFlags & HB_FF_BINARY ) #if ADS_LIB_VERSION >= 900 - dbFieldInfo.uiTypeExtended = ADS_VARBINARY_FOX; + dbFieldInfo.uiTypeExtended = ADS_VARBINARY_FOX; #else - dbFieldInfo.uiTypeExtended = ADS_RAW; + dbFieldInfo.uiTypeExtended = ADS_RAW; #endif - else - dbFieldInfo.uiTypeExtended = ADS_VARCHAR; + else + dbFieldInfo.uiTypeExtended = ADS_VARCHAR; + } dbFieldInfo.uiLen = uiLen; dbFieldInfo.uiFlags &= HB_FF_NULLABLE | HB_FF_BINARY | HB_FF_COMPRESSED | HB_FF_ENCRYPTED | @@ -2201,19 +2217,59 @@ static HB_ERRCODE adsGetValue( ADSAREAP pArea, HB_USHORT uiIndex, PHB_ITEM pItem { #if ADS_LIB_VERSION >= 600 u32RetVal = AdsGetFieldRaw( pArea->hTable, ADSFIELD( uiIndex ), pBuffer, &u32Length ); + if( u32RetVal == AE_INSUFFICIENT_BUFFER && pField->uiType == HB_FT_VARLENGTH ) + { + UNSIGNED8 * pucBuf = ( UNSIGNED8 * ) hb_xgrab( u32Length ); + u32RetVal = AdsGetFieldRaw( pArea->hTable, ADSFIELD( uiIndex ), pucBuf, &u32Length ); + if( u32RetVal == AE_SUCCESS ) + { + hb_itemPutCLPtr( pItem, ( char * ) pucBuf, u32Length ); + break; + } + hb_xfree( pucBuf ); + } #else u32RetVal = AdsGetField( pArea->hTable, ADSFIELD( uiIndex ), pBuffer, &u32Length, ADS_NONE ); if( u32RetVal == AE_SUCCESS ) { char * pBufOem = hb_adsAnsiToOem( ( char * ) pBuffer, u32Length ); - memcpy( pBuffer, pBufOem, u32Length ); + hb_itemPutCL( pItem, pBufOem, u32Length ); hb_adsOemAnsiFree( pBufOem ); + break; + } + else if( u32RetVal == AE_INSUFFICIENT_BUFFER && pField->uiType == HB_FT_VARLENGTH ) + { + UNSIGNED8 * pucBuf = ( UNSIGNED8 * ) hb_xgrab( u32Length ); + u32RetVal = AdsGetField( pArea->hTable, ADSFIELD( uiIndex ), pucBuf, &u32Length, ADS_NONE ); + if( u32RetVal == AE_SUCCESS ) + { + char * pBufOem = hb_adsAnsiToOem( ( char * ) pucBuf, u32Length ); + hb_itemPutCL( pItem, pBufOem, u32Length ); + hb_adsOemAnsiFree( pBufOem ); + hb_xfree( pucBuf ); + break; + } + else + hb_xfree( pucBuf ); } #endif } #endif else + { u32RetVal = AdsGetField( pArea->hTable, ADSFIELD( uiIndex ), pBuffer, &u32Length, ADS_NONE ); + if( u32RetVal == AE_INSUFFICIENT_BUFFER && pField->uiType == HB_FT_VARLENGTH ) + { + UNSIGNED8 * pucBuf = ( UNSIGNED8 * ) hb_xgrab( u32Length ); + u32RetVal = AdsGetField( pArea->hTable, ADSFIELD( uiIndex ), pucBuf, &u32Length, ADS_NONE ); + if( u32RetVal == AE_SUCCESS ) + { + hb_itemPutCLPtr( pItem, ( char * ) pucBuf, u32Length ); + break; + } + hb_xfree( pucBuf ); + } + } if( ! pArea->fPositioned || u32RetVal != AE_SUCCESS ) { @@ -2438,7 +2494,7 @@ static HB_ERRCODE adsGetValue( ADSAREAP pArea, HB_USHORT uiIndex, PHB_ITEM pItem #if ADS_LIB_VERSION >= 1000 else if( ( pField->uiFlags & HB_FF_UNICODE ) != 0 ) { - HB_WCHAR * pwBuffer = ( HB_WCHAR * ) hb_xgrab( ( ++u32Length ) << 1 ); + HB_WCHAR * pwBuffer = ( HB_WCHAR * ) hb_xgrab( ++u32Length * sizeof( HB_WCHAR ) ); u32RetVal = AdsGetStringW( pArea->hTable, ADSFIELD( uiIndex ), ( WCHAR * ) pwBuffer, &u32Length, ADS_NONE ); if( u32RetVal != AE_SUCCESS ) hb_itemPutC( pItem, NULL ); @@ -2641,7 +2697,7 @@ static HB_ERRCODE adsPutValue( ADSAREAP pArea, HB_USHORT uiIndex, PHB_ITEM pItem void * hString; const HB_WCHAR * pwBuffer = hb_itemGetStrU16( pItem, HB_CDP_ENDIAN_LITTLE, &hString, &nLen ); - if( nLen > ( HB_SIZE ) pField->uiLen ) + if( nLen > ( HB_SIZE ) pField->uiLen && pField->uiType == HB_FT_STRING ) nLen = pField->uiLen; u32RetVal = AdsSetStringW( pArea->hTable, ADSFIELD( uiIndex ), ( WCHAR * ) HB_UNCONST( pwBuffer ), @@ -2653,8 +2709,17 @@ static HB_ERRCODE adsPutValue( ADSAREAP pArea, HB_USHORT uiIndex, PHB_ITEM pItem { nLen = hb_itemGetCLen( pItem ); if( nLen > ( HB_SIZE ) pField->uiLen ) - nLen = pField->uiLen; - + { +#if ADS_LIB_VERSION >= 900 + if( pField->uiType == HB_FT_STRING || pArea->iFileType == ADS_VFP ) +#else + if( pField->uiType == HB_FT_STRING ) +#endif + nLen = pField->uiLen; + else if( nLen > 64000 ) + /* maximum VarChar field size is 64000 */ + nLen = 64000; + } #ifdef ADS_USE_OEM_TRANSLATION if( hb_ads_bOEM ) { @@ -2672,6 +2737,11 @@ static HB_ERRCODE adsPutValue( ADSAREAP pArea, HB_USHORT uiIndex, PHB_ITEM pItem u32RetVal = AdsSetString( pArea->hTable, ADSFIELD( uiIndex ), ( UNSIGNED8 * ) HB_UNCONST( hb_itemGetCPtr( pItem ) ), ( UNSIGNED32 ) nLen ); } } + /* varchar unicode fields in ADT tables and varchar/varbinary + fields in VFP DBFs have fixed size so we should ignore this + error when longer data is passed [druzus] */ + if( u32RetVal == AE_DATA_TRUNCATED ) + u32RetVal = AE_SUCCESS; } break; @@ -3094,13 +3164,19 @@ static HB_ERRCODE adsCreate( ADSAREAP pArea, LPDBOPENINFO pCreateInfo ) break; case HB_FT_VARLENGTH: - if( pField->uiFlags & HB_FF_BINARY ) - cType = "VarBinary"; - else if( pField->uiFlags & HB_FF_UNICODE ) + if( pField->uiFlags & HB_FF_UNICODE ) { fUnicode = HB_TRUE; cType = "NVarChar"; } +#if ADS_LIB_VERSION >= 900 + else if( pField->uiTypeExtended == ADS_VARCHAR_FOX ) + cType = "VarCharFox"; + else if( pField->uiTypeExtended == ADS_VARBINARY_FOX ) + cType = "VarBinaryFox"; +#endif + else if( pField->uiFlags & HB_FF_BINARY ) + cType = "VarBinary"; else cType = "VarChar"; break;