From c8e85f3c48ff9c87e32f4e177d66e95f6fb61148 Mon Sep 17 00:00:00 2001 From: Przemyslaw Czerpak Date: Mon, 27 Apr 2009 17:09:46 +0000 Subject: [PATCH] 2009-04-27 19:17 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/contrib/rddads/ads1.c ! fixed very bad bug in code compiled for ADS_LIB_VERSION < 600 in ANSI<->OEM translations - the HVM item value was overloaded with translation results + added direct support for ADS_TIME, ADS_TIMESTAMP and ADS_MODTIME fields and HVM TIMESTAMP values in field get/put operations, seek and scopes. Warning! Support for timestamp values in VFP tables is limited and does not fully respect whole Harbour timestamp arithmetic, f.e. timestamp values read from index keys are rounded to whole seconds or setting scopes to data values on timestamp indexes does not work like in native RDDs or in ADT tables. TOVERIFY: please check in which ACE version Ads[SG]etMilliseconds() functions were added and if necessary add #if ADS_LIB_VERSION >= ??? protection. I do not have older ACE headers and I cannot make it myself. To ADS users: please make some real life tests and report problems if any. --- harbour/ChangeLog | 21 ++++ harbour/contrib/rddads/ads1.c | 205 ++++++++++++++++++++++++++-------- 2 files changed, 178 insertions(+), 48 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 709ef7cf1a..9e9dfa34e9 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,27 @@ 2009-12-31 13:59 UTC+0100 Foo Bar (foo.bar foobar.org) */ +2009-04-27 19:17 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/contrib/rddads/ads1.c + ! fixed very bad bug in code compiled for ADS_LIB_VERSION < 600 + in ANSI<->OEM translations - the HVM item value was overloaded + with translation results + + added direct support for ADS_TIME, ADS_TIMESTAMP and ADS_MODTIME + fields and HVM TIMESTAMP values in field get/put operations, seek + and scopes. + Warning! Support for timestamp values in VFP tables is limited + and does not fully respect whole Harbour timestamp arithmetic, f.e. + timestamp values read from index keys are rounded to whole seconds + or setting scopes to data values on timestamp indexes does not work + like in native RDDs or in ADT tables. + TOVERIFY: please check in which ACE version Ads[SG]etMilliseconds() + functions were added and if necessary add + #if ADS_LIB_VERSION >= ??? + protection. I do not have older ACE headers and I cannot + make it myself. + To ADS users: please make some real life tests and report problems + if any. + 2009-04-27 08:59 UTC-0800 Pritpal Bedi (pritpal@vouchcac.com) * harbour/contrib/gtqtc/gtqtc.cpp ! Fixed a very important issue of focussing. Now F3 and F4 diff --git a/harbour/contrib/rddads/ads1.c b/harbour/contrib/rddads/ads1.c index 49205fb34d..0f1e4f9f36 100644 --- a/harbour/contrib/rddads/ads1.c +++ b/harbour/contrib/rddads/ads1.c @@ -416,6 +416,31 @@ static void adsGetKeyItem( ADSAREAP pArea, PHB_ITEM pItem, int iKeyType, ADT files can use ";" concatentation operator, which returns index key types as Raw */ case ADS_RAW: + /* hack for timestamp values, we need sth better yo detect timestamp indexes */ + if( pArea->iFileType == ADS_ADT && pKeyBuf[ 0 ] == 0 && ( iKeyLen == 8 || iKeyLen == 4 ) ) + { + LONG lDate, lTime; + lDate = HB_GET_BE_UINT32( pKeyBuf ); + if( iKeyLen == 8 ) + { + lTime = HB_GET_BE_UINT32( &pKeyBuf[ 4 ] ); + /* ADS stores milliseconds in raw ADT form increased by one */ + if( lTime ) + --lTime; + hb_itemPutTDT( pItem, lDate, lTime ); + } + else + hb_itemPutDL( pItem, lDate ); + break; + } +#if ADS_LIB_VERSION >= 900 + else if( pArea->iFileType == ADS_VFP && iKeyLen == 8 ) + { + HB_ORD2DBL( pKeyBuf, &dValue ); + hb_itemPutTD( pItem, dValue ); + break; + } +#endif case ADS_STRING: hb_itemPutCL( pItem, pKeyBuf, iKeyLen ); break; @@ -501,13 +526,10 @@ static void adsScopeGet( ADSAREAP pArea, ADSHANDLE hOrder, USHORT nScope, PHB_IT static HB_ERRCODE adsScopeSet( ADSAREAP pArea, ADSHANDLE hOrder, USHORT nScope, PHB_ITEM pItem ) { - UNSIGNED16 u16DataType = ADS_STRINGKEY ; - UNSIGNED8 *pucScope; + HB_TRACE(HB_TR_DEBUG, ("adsScopeSet(%p, %lu, %hu, %p)", pArea, hOrder, nScope, pItem)); HB_SYMBOL_UNUSED( pArea ); - HB_TRACE(HB_TR_DEBUG, ("adsScopeSet(%p, %lu, %hu, %p)", pArea, hOrder, nScope, pItem)); - if( hOrder ) { nScope = ( nScope == 0 ) ? ADS_TOP : ADS_BOTTOM; @@ -520,56 +542,79 @@ static HB_ERRCODE adsScopeSet( ADSAREAP pArea, ADSHANDLE hOrder, USHORT nScope, switch( u16KeyType ) { case ADS_RAW: /* adt files need the ";" concatenation operator (instead of "+") to be optimized */ + /* ADS timestamp values */ + if( HB_IS_DATETIME( pItem ) ) + { + if( pArea->iFileType == ADS_ADT ) + { + UNSIGNED8 pKeyBuf[ 8 ]; + long lDate, lTime; + hb_itemGetTDT( pItem, &lDate, &lTime ); + /* ADS stores milliseconds in raw ADT form increased by one */ + ++lTime; + HB_PUT_BE_UINT32( pKeyBuf, lDate ); + HB_PUT_BE_UINT32( &pKeyBuf[ 4 ], lTime ); + AdsSetScope( hOrder, nScope, pKeyBuf, HB_IS_TIMESTAMP( pItem ) ? 8 : 4, ADS_RAWKEY ); + break; + } +#if ADS_LIB_VERSION >= 900 + else if( pArea->iFileType == ADS_VFP ) + { + double dTemp; + dTemp = hb_itemGetTD( pItem ); + AdsSetScope( hOrder, nScope, + ( UNSIGNED8 * ) &dTemp, + ( UNSIGNED16 ) sizeof( dTemp ), ADS_DOUBLEKEY ); + break; + } +#endif + } case ADS_STRING: if( HB_IS_STRING( pItem ) ) { - /* bTypeError = FALSE; */ - pucScope = ( UNSIGNED8 * ) hb_itemGetCPtr( pItem ); + UNSIGNED16 u16DataType = ADS_STRINGKEY ; + UNSIGNED16 ucLen = ( UNSIGNED16 ) hb_itemGetCLen( pItem ); + UNSIGNED8 *pucScope = ( UNSIGNED8 * ) hb_itemGetCPtr( pItem ); +#if defined( ADS_USE_OEM_TRANSLATION ) && ADS_LIB_VERSION < 600 + UNSIGNED8 pszKeyFree = NULL; +#endif #ifdef ADS_USE_OEM_TRANSLATION if( hb_ads_bOEM ) { #if ADS_LIB_VERSION >= 600 u16DataType = ADS_RAWKEY; #else - USHORT uiLen = ( USHORT ) hb_itemGetCLen( pItem ); - - char * pBuffer = hb_adsOemToAnsi( ( char * ) pucScope, uiLen ); - memcpy( ( char * ) pucScope, pBuffer, uiLen ); - hb_adsOemAnsiFree( pBuffer ); + pucScope = pszKeyFree = ( UNSIGNED8 * ) hb_adsOemToAnsi( ( char * ) pucScope, uiLen ); #endif } #endif - AdsSetScope( hOrder, nScope, - ( UNSIGNED8 * ) pucScope, - ( UNSIGNED16 ) hb_itemGetCLen( pItem ), u16DataType ); + AdsSetScope( hOrder, nScope, pucScope, ucLen, u16DataType ); +#if defined( ADS_USE_OEM_TRANSLATION ) && ADS_LIB_VERSION < 600 + if( pszKeyFree ) + hb_adsOemAnsiFree( pszKeyFree ); +#endif } break; case ADS_NUMERIC: - { if( HB_IS_NUMERIC( pItem ) ) { double dTemp; - /* bTypeError = FALSE; */ dTemp = hb_itemGetND( pItem ); - u16DataType = ADS_DOUBLEKEY ; AdsSetScope( hOrder, nScope, - ( UNSIGNED8 * ) &dTemp, - ( UNSIGNED16 ) sizeof( dTemp ), u16DataType ); + ( UNSIGNED8 * ) &dTemp, + ( UNSIGNED16 ) sizeof( dTemp ), ADS_DOUBLEKEY ); } break; - } case ADS_DATE: - if( HB_IS_DATE( pItem ) ) + if( HB_IS_DATETIME( pItem ) ) { double dTemp; - /* bTypeError = FALSE; */ dTemp = hb_itemGetDL( pItem ); - u16DataType = ADS_DOUBLEKEY ; AdsSetScope( hOrder, nScope, - ( UNSIGNED8 * ) &dTemp, - ( UNSIGNED16 ) sizeof( dTemp ), u16DataType ); + ( UNSIGNED8 * ) &dTemp, + ( UNSIGNED16 ) sizeof( dTemp ), ADS_DOUBLEKEY ); } break; @@ -899,10 +944,13 @@ static HB_ERRCODE adsSeek( ADSAREAP pArea, BOOL bSoftSeek, PHB_ITEM pKey, BOOL b UNSIGNED32 u32RecNo = 0, u32NewRec; UNSIGNED16 u16SeekType = ( bSoftSeek ) ? ADS_SOFTSEEK : ADS_HARDSEEK, u16KeyType, u16Found, u16KeyLen; - UNSIGNED8 *pszKey; + UNSIGNED8 *pszKey, pKeyBuf[ 8 ]; double dValue; UNSIGNED8 *pucSavedKey = NULL; UNSIGNED16 u16SavedKeyLen = ADS_MAX_KEY_LENGTH; /* this may be longer than the actual seek expression, so we don't pass it along */ +#if defined( ADS_USE_OEM_TRANSLATION ) && ADS_LIB_VERSION < 600 + UNSIGNED8 pszKeyFree = NULL; +#endif HB_TRACE(HB_TR_DEBUG, ("adsSeek(%p, %d, %p, %d)", pArea, bSoftSeek, pKey, bFindLast)); @@ -913,7 +961,7 @@ static HB_ERRCODE adsSeek( ADSAREAP pArea, BOOL bSoftSeek, PHB_ITEM pKey, BOOL b } /* build a seek key */ - if( hb_itemType( pKey ) & HB_IT_STRING ) + if( HB_IS_STRING( pKey ) ) { pszKey = ( UNSIGNED8* ) hb_itemGetCPtr( pKey ); u16KeyLen = ( UNSIGNED16 ) hb_itemGetCLen( pKey ); @@ -924,30 +972,46 @@ static HB_ERRCODE adsSeek( ADSAREAP pArea, BOOL bSoftSeek, PHB_ITEM pKey, BOOL b u16KeyType = ADS_STRINGKEY; if( hb_ads_bOEM ) { - char * pBuffer = hb_adsOemToAnsi( ( char * ) pszKey, u16KeyLen ); - memcpy( ( char * ) pszKey, pBuffer, u16KeyLen ); - hb_adsOemAnsiFree( pBuffer ); + pszKey = pszKeyFree = ( UNSIGNED8 * ) hb_adsOemToAnsi( ( char * ) pszKey, u16KeyLen ); } #endif #else u16KeyType = ADS_STRINGKEY; #endif } - else if( hb_itemType( pKey ) & HB_IT_NUMERIC ) + else if( HB_IS_DATETIME( pKey ) ) + { + u16KeyType = 0; + AdsGetKeyType( pArea->hOrdCurrent, &u16KeyType ); + /* index on timestamp values */ + if( pArea->iFileType == ADS_ADT && u16KeyType == ADS_RAW ) + { + long lDate, lTime; + hb_itemGetTDT( pKey, &lDate, &lTime ); + /* ADS stores milliseconds in raw ADT form increased by one */ + ++lTime; + HB_PUT_BE_UINT32( pKeyBuf, lDate ); + HB_PUT_BE_UINT32( &pKeyBuf[ 4 ], lTime ); + pszKey = pKeyBuf; + u16KeyLen = HB_IS_TIMESTAMP( pKey ) ? 8 : 4; + u16KeyType = ADS_RAWKEY; + } + else + { + dValue = hb_itemGetTD( pKey ); + pszKey = ( UNSIGNED8* ) &dValue; + u16KeyLen = ( UNSIGNED16 ) sizeof( double ); + u16KeyType = ADS_DOUBLEKEY; + } + } + else if( HB_IS_NUMERIC( pKey ) ) { dValue = hb_itemGetND( pKey ); pszKey = ( UNSIGNED8* ) &dValue; u16KeyLen = ( UNSIGNED16 ) sizeof( double ); u16KeyType = ADS_DOUBLEKEY; } - else if( hb_itemType( pKey ) & HB_IT_DATE ) - { - dValue = ( double ) hb_itemGetDL( pKey ); - pszKey = ( UNSIGNED8* ) &dValue; - u16KeyLen = ( UNSIGNED16 ) sizeof( double ); - u16KeyType = ADS_DOUBLEKEY; - } - else if( hb_itemType( pKey ) & HB_IT_LOGICAL ) + else if( HB_IS_LOGICAL( pKey ) ) { pszKey = ( UNSIGNED8* ) ( hb_itemGetL( pKey ) ? "1" : "0" ); u16KeyLen = 1; @@ -956,6 +1020,10 @@ static HB_ERRCODE adsSeek( ADSAREAP pArea, BOOL bSoftSeek, PHB_ITEM pKey, BOOL b else { commonError( pArea, EG_DATATYPE, 1020, 0, NULL, 0, NULL ); +#if defined( ADS_USE_OEM_TRANSLATION ) && ADS_LIB_VERSION < 600 + if( pszKeyFree ) + hb_adsOemAnsiFree( pszKeyFree ); +#endif return HB_FAILURE; } @@ -1002,6 +1070,10 @@ static HB_ERRCODE adsSeek( ADSAREAP pArea, BOOL bSoftSeek, PHB_ITEM pKey, BOOL b HB_ERRCODE errCode = SELF_GOTO( ( AREAP ) pArea, 0 ); /* HB_ERRCODE errCode = SELF_GOTOP( ( AREAP ) pArea ); */ pArea->fBof = FALSE; +#if defined( ADS_USE_OEM_TRANSLATION ) && ADS_LIB_VERSION < 600 + if( pszKeyFree ) + hb_adsOemAnsiFree( pszKeyFree ); +#endif return errCode; } @@ -1074,6 +1146,10 @@ static HB_ERRCODE adsSeek( ADSAREAP pArea, BOOL bSoftSeek, PHB_ITEM pKey, BOOL b { if( pucSavedKey ) hb_xfree( pucSavedKey ); +#if defined( ADS_USE_OEM_TRANSLATION ) && ADS_LIB_VERSION < 600 + if( pszKeyFree ) + hb_adsOemAnsiFree( pszKeyFree ); +#endif return HB_FAILURE; } @@ -1109,6 +1185,10 @@ static HB_ERRCODE adsSeek( ADSAREAP pArea, BOOL bSoftSeek, PHB_ITEM pKey, BOOL b if( pucSavedKey ) hb_xfree( pucSavedKey ); +#if defined( ADS_USE_OEM_TRANSLATION ) && ADS_LIB_VERSION < 600 + if( pszKeyFree ) + hb_adsOemAnsiFree( pszKeyFree ); +#endif return HB_SUCCESS; } @@ -1574,7 +1654,11 @@ static HB_ERRCODE adsCreateFields( ADSAREAP pArea, PHB_ITEM pStruct ) break; case 'T': +#if ADS_LIB_VERSION >= 900 + if( ( pArea->iFileType == ADS_ADT || pArea->iFileType == ADS_VFP ) && +#else if( pArea->iFileType == ADS_ADT && +#endif ( iNameLen == 1 || ( iNameLen >= 4 && hb_strnicmp( szFieldType, "timestamp", iNameLen ) == 0 ) ) ) { @@ -1591,6 +1675,7 @@ static HB_ERRCODE adsCreateFields( ADSAREAP pArea, PHB_ITEM pStruct ) dbFieldInfo.uiLen = 4; } } +/* #if ADS_LIB_VERSION >= 900 else if( pArea->iFileType == ADS_VFP && ( iNameLen >= 4 && @@ -1604,6 +1689,7 @@ static HB_ERRCODE adsCreateFields( ADSAREAP pArea, PHB_ITEM pStruct ) } } #endif +*/ else return HB_FAILURE; break; @@ -1942,19 +2028,30 @@ static HB_ERRCODE adsGetValue( ADSAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) hb_itemPutCL( pItem, ( char * ) pBuffer, pField->uiLen ); break; + case HB_FT_TIME: case HB_FT_DAYTIME: case HB_FT_MODTIME: - case HB_FT_TIME: + { + SIGNED32 lTime = 0, lDate = 0; u32Length = pArea->maxFieldLen + 1; - ulRetVal = AdsGetField( pArea->hTable, ADSFIELD( uiIndex ), pBuffer, &u32Length, ADS_NONE ); + ulRetVal = AdsGetMilliseconds( pArea->hTable, ADSFIELD( uiIndex ), &lTime ); if( ulRetVal == AE_NO_CURRENT_RECORD ) { - memset( pBuffer, ' ', pArea->maxFieldLen + 1 ); + lTime = 0; pArea->fEof = TRUE; } - hb_itemPutCL( pItem, ( char * ) pBuffer, u32Length ); + else if( pField->uiType != HB_FT_TIME ) + { + ulRetVal = AdsGetJulian( pArea->hTable, ADSFIELD( uiIndex ), &lDate ); + if( ulRetVal == AE_NO_CURRENT_RECORD ) + { + pArea->fEof = TRUE; + lDate = 0; + } + } + hb_itemPutTDT( pItem, lDate, lTime ); break; - + } case HB_FT_INTEGER: { SIGNED32 lVal = 0; @@ -2285,8 +2382,6 @@ static HB_ERRCODE adsPutValue( ADSAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) case HB_FT_LONG: case HB_FT_INTEGER: case HB_FT_DOUBLE: - case HB_FT_TIME: - case HB_FT_DAYTIME: case HB_FT_AUTOINC: case HB_FT_CURDOUBLE: case HB_FT_CURRENCY: @@ -2303,11 +2398,25 @@ static HB_ERRCODE adsPutValue( ADSAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) } break; + case HB_FT_TIME: + case HB_FT_DAYTIME: + case HB_FT_MODTIME: + if( HB_IS_DATETIME( pItem ) ) + { + long lDate, lTime; + bTypeError = FALSE; + hb_itemGetTDT( pItem, &lDate, &lTime ); + ulRetVal = AdsSetMilliseconds( pArea->hTable, ADSFIELD( uiIndex ), lTime ); + if( ulRetVal == AE_SUCCESS && pField->uiType != HB_FT_TIME ) + ulRetVal = AdsSetJulian( pArea->hTable, ADSFIELD( uiIndex ), lDate ); + } + break; + case HB_FT_DATE: - if( HB_IS_DATE( pItem ) ) + if( HB_IS_DATETIME( pItem ) ) { bTypeError = FALSE; - ulRetVal = AdsSetJulian( pArea->hTable, ADSFIELD( uiIndex ), hb_itemGetDL( pItem ) ); + ulRetVal = AdsSetJulian( pArea->hTable, ADSFIELD( uiIndex ), hb_itemGetDL( pItem ) ); } break;