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;