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.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user