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;