diff --git a/harbour/ChangeLog b/harbour/ChangeLog index dd02fb0a4b..c2ca6c880b 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,30 @@ 2002-12-01 23:12 UTC+0100 Foo Bar */ +2002-10-03 0:40 UTC-0800 Brian Hays + * contrib/rdd_ads/ace.h + + added (void) to AdsApplicationExit( void ); + This removes a compiler warning about missing the prototype. + Let me know if this creates a problem with any other compilers. + + * contrib/rdd_ads/adsfunc.c + + added AdsGetLastError() contrib. by Randy Portnoff (Thanks!) + + * contrib/rdd_ads/ads1.c + * Cleaned up adsPutValue and adsGetValue formatting, + * Fixed fieldname length references + * Removed errant setting of uiLen in adsGetValue since these + are set in adsOpen now. + * adsOrderInfo(DBOI_KEYVAL): fixed ntx handling of numerics + Added special decoding for keys of Negative values. + * adsCreate: fixed fielddefs buffer sizing + * adsOpen: fixed fieldname length references + set uiLen of extended types + + * adsInfo: reformatted, prepared for fleshing out the rest + of the options. + Added support for dbinfo(DBI_ISFLOCK) + 2002-10-01 08:25 UTC+0300 Chen Kedem * doc/es/browse.txt * doc/es/cmdline.txt @@ -120,7 +144,7 @@ * include/hbrddntx.h * Improved algorithm of record append in shared mode - that should result in better speed. - * Maximum number of keys in the index page is now Clipper compatible - + * Maximum number of keys in the index page is now Clipper compatible - as I just discovered for myself, in Clipper it is already ( hm... I forgot appropriate English word - is divided by 2 ). diff --git a/harbour/contrib/rdd_ads/ace.h b/harbour/contrib/rdd_ads/ace.h index e16e662f78..fdb9a72203 100644 --- a/harbour/contrib/rdd_ads/ace.h +++ b/harbour/contrib/rdd_ads/ace.h @@ -935,7 +935,7 @@ UNSIGNED32 ENTRYPOINT AdsAddCustomKey( ADSHANDLE hIndex ); UNSIGNED32 ENTRYPOINT AdsAppendRecord( ADSHANDLE hTable ); -UNSIGNED32 ENTRYPOINT AdsApplicationExit(); +UNSIGNED32 ENTRYPOINT AdsApplicationExit( void ); UNSIGNED32 ENTRYPOINT AdsAtBOF( ADSHANDLE hTable, UNSIGNED16 *pbBof ); diff --git a/harbour/contrib/rdd_ads/ads1.c b/harbour/contrib/rdd_ads/ads1.c index e2a12068bb..7b92f3b3e7 100644 --- a/harbour/contrib/rdd_ads/ads1.c +++ b/harbour/contrib/rdd_ads/ads1.c @@ -65,8 +65,6 @@ #include "hbset.h" #include -#undef HARBOUR_MAX_RDD_FIELDNAME_LENGTH -#define HARBOUR_MAX_RDD_FIELDNAME_LENGTH 150 static ERRCODE adsRecCount( ADSAREAP pArea, ULONG * pRecCount ); static ERRCODE adsScopeInfo( ADSAREAP pArea, USHORT nScope, PHB_ITEM pItem ); @@ -758,6 +756,7 @@ static ERRCODE adsCreateFields( ADSAREAP pArea, PHB_ITEM pStruct ) pFieldInfo.uiType = HB_IT_LONG; pFieldInfo.uiTypeExtended = ADS_CURDOUBLE; pFieldInfo.uiLen = 8; + pFieldInfo.uiDec = uiDec; } else return FAILURE; @@ -995,7 +994,7 @@ ERRCODE adsFieldInfo( AREAP pArea, USHORT uiIndex, USHORT uiType, PHB_ITEM pItem static ERRCODE adsFieldName( ADSAREAP pArea, USHORT uiIndex, void * szName ) { - UNSIGNED16 pusBufLen = HARBOUR_MAX_RDD_FIELDNAME_LENGTH; + UNSIGNED16 pusBufLen = pArea->uiMaxFieldNameLength + 1; HB_TRACE(HB_TR_DEBUG, ("adsFieldName(%p, %hu, %p)", pArea, uiIndex, szName)); @@ -1033,8 +1032,13 @@ static ERRCODE adsGetValue( ADSAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) { LPFIELD pField; BYTE * pBuffer = pArea->pRecord; - UNSIGNED8 szName[ HARBOUR_MAX_RDD_FIELDNAME_LENGTH + 1 ]; - UNSIGNED16 pusBufLen = HARBOUR_MAX_RDD_FIELDNAME_LENGTH; + UNSIGNED8 szName[ ADS_MAX_FIELD_NAME ]; + /* For fast stack allocations, we use the largest possible + sized buffer. Even though 128 bytes is overkill for 10 byte + ADSCDX access, the speed over hb_xgrab(pArea->uiMaxFieldNameLength+1) + seems worth it. */ + + UNSIGNED16 pusBufLen = ADS_MAX_FIELD_NAME + 1; UNSIGNED32 pulLength; DOUBLE dVal; @@ -1061,38 +1065,36 @@ static ERRCODE adsGetValue( ADSAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) break; case HB_IT_LONG: - pulLength = pArea->maxFieldLen; - if (AdsGetField( pArea->hTable, szName, pBuffer, &pulLength, ADS_NONE ) == AE_NO_CURRENT_RECORD ) - { - memset( pBuffer, ' ', pField->uiLen ); - pArea->fEof = TRUE; - } - AdsGetDouble(pArea->hTable, szName,&dVal); + pulLength = pArea->maxFieldLen; + if (AdsGetField( pArea->hTable, szName, pBuffer, &pulLength, ADS_NONE ) == AE_NO_CURRENT_RECORD ) + { + memset( pBuffer, ' ', pField->uiLen ); + pArea->fEof = TRUE; + } + AdsGetDouble(pArea->hTable, szName, &dVal); if( pField->uiDec ) { - hb_itemPutNDLen( pItem, dVal, - ( int ) pField->uiLen - ( ( int ) pField->uiDec + 1 ), - ( int ) pField->uiDec ); - } - else { - switch ( pField->uiTypeExtended) { - case ADS_CURDOUBLE : - case ADS_DOUBLE : { - int iNewLen =( int ) pField->uiLen +(( int ) hb_set.HB_SET_DECIMALS*2) ; - hb_itemPutNDLen( pItem, dVal, - ( int ) iNewLen , - ( int ) hb_set.HB_SET_DECIMALS ); - } - break; - case ADS_AUTOINC: - hb_itemPutNLen( pItem, dVal, ( int ) 10 , (int) 0 ); - break; + hb_itemPutNDLen( pItem, dVal, + ( int ) pField->uiLen - ( ( int ) pField->uiDec + 1 ), + ( int ) pField->uiDec ); + } + else + { + switch ( pField->uiTypeExtended) { + case ADS_CURDOUBLE : + case ADS_DOUBLE : + hb_itemPutNDLen( pItem, dVal, + ( int ) pField->uiLen, + ( int ) pField->uiDec /*hb_set.HB_SET_DECIMALS*/ ); - default: + break; + /*case ADS_AUTOINC: + hb_itemPutNLen( pItem, dVal, ( int ) 10 , (int) 0 ); + break; */ - hb_itemPutNLen( pItem, dVal, ( int ) pField->uiLen , (int) 0 ); + default: + hb_itemPutNLen( pItem, dVal, ( int ) pField->uiLen, (int) 0 ); } - } - break; + } break; case HB_IT_DATE: @@ -1181,8 +1183,10 @@ static ERRCODE adsPutValue( ADSAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) BYTE * szText; BOOL bError; long lDay, lMonth, lYear; - UNSIGNED8 szName[ HARBOUR_MAX_RDD_FIELDNAME_LENGTH + 1 ]; - UNSIGNED16 pusBufLen = HARBOUR_MAX_RDD_FIELDNAME_LENGTH; + UNSIGNED8 szName[ ADS_MAX_FIELD_NAME + 1 ]; + /* See adsGetValue() for why we don't use pArea->uiMaxFieldNameLength here */ + + UNSIGNED16 pusBufLen = ADS_MAX_FIELD_NAME + 1; UNSIGNED8 pucFormat[ 11 ]; UNSIGNED16 pusLen = 10; UNSIGNED32 ulRetVal; @@ -1218,26 +1222,7 @@ static ERRCODE adsPutValue( ADSAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) case HB_IT_LONG: if( HB_IS_NUMERIC( pItem ) ) { - /* - if( pField->uiDec ) - bError = !hb_ndtoa( hb_itemGetND( pItem ), ( char * ) szText, - pField->uiLen, pField->uiDec ); - else - bError = !hb_nltoa( hb_itemGetNL( pItem ), ( char * ) szText, - pField->uiLen ); - if( bError ) - { - commonError( pArea, EG_DATAWIDTH, 1021, NULL ); - } - else - AdsSetField ( pArea->hTable, szName, - szText, pField->uiLen ); - bError = FALSE; - */ - if( pField->uiDec ) - ulRetVal = AdsSetDouble( pArea->hTable, szName, hb_itemGetND( pItem ) ); - else - ulRetVal = AdsSetDouble( pArea->hTable, szName, hb_itemGetND( pItem ) ); + ulRetVal = AdsSetDouble( pArea->hTable, szName, hb_itemGetND( pItem ) ); if( ulRetVal != AE_DATA_TOO_LONG ) bError = FALSE; } @@ -1352,7 +1337,7 @@ static ERRCODE adsCreate( ADSAREAP pArea, LPDBOPENINFO pCreateInfo) ADSHANDLE hTable; UNSIGNED32 uRetVal; UNSIGNED8 *ucfieldDefs; - UNSIGNED8 ucBuffer[MAX_STR_LEN+1], ucField[HARBOUR_MAX_RDD_FIELDNAME_LENGTH+1]; + UNSIGNED8 ucBuffer[MAX_STR_LEN+1], ucField[ADS_MAX_FIELD_NAME+1]; USHORT uiCount, uiLen; LPFIELD pField; char cType[8]; @@ -1361,7 +1346,15 @@ static ERRCODE adsCreate( ADSAREAP pArea, LPDBOPENINFO pCreateInfo) pArea->szDataFileName = (char *) hb_xgrab( strlen( (char *) pCreateInfo->abName ) + 1 ); strcpy( pArea->szDataFileName, ( char * ) pCreateInfo->abName ); - uiLen = (pArea->uiFieldCount * HARBOUR_MAX_RDD_FIELDNAME_LENGTH) + 1; + + /* uiLen = length of buffer for all field definition info times number of fields. + For extended types cType may be up to 6 chars, and + there are up to 4 punctuation symbols ( ,; ), + field length (8) and number of decimals (2). + So, per field it should be ( 6 + 4 + 8 + 2 = 20 ): + uiMaxFieldNameLength + 20 */ + uiLen = (pArea->uiFieldCount * (pArea->uiMaxFieldNameLength + 20)) + 1; + ucfieldDefs = (UNSIGNED8 *) hb_xgrab( uiLen ); ucfieldDefs[0]='\0'; pField = pArea->lpFields; @@ -1422,11 +1415,11 @@ static ERRCODE adsCreate( ADSAREAP pArea, LPDBOPENINFO pCreateInfo) case HB_IT_MEMO: if( pField->uiTypeExtended != ADS_VARCHAR ) { - if(strlen((( PHB_DYNS ) pField->sym )->pSymbol->szName) > HARBOUR_MAX_RDD_FIELDNAME_LENGTH ) + if(strlen((( PHB_DYNS ) pField->sym )->pSymbol->szName) > (unsigned int) pArea->uiMaxFieldNameLength ) { ucField[0]='\0'; strncat((char*)ucField, (( PHB_DYNS ) pField->sym )->pSymbol->szName, - HARBOUR_MAX_RDD_FIELDNAME_LENGTH); + pArea->uiMaxFieldNameLength); sprintf((char*)ucBuffer,"%s,%s;", ucField, cType ); } else @@ -1435,11 +1428,11 @@ static ERRCODE adsCreate( ADSAREAP pArea, LPDBOPENINFO pCreateInfo) break; } default : - if(strlen((( PHB_DYNS ) pField->sym )->pSymbol->szName) > HARBOUR_MAX_RDD_FIELDNAME_LENGTH ) + if(strlen((( PHB_DYNS ) pField->sym )->pSymbol->szName) > (unsigned int) pArea->uiMaxFieldNameLength ) { ucField[0]='\0'; strncat((char*)ucField, (( PHB_DYNS ) pField->sym )->pSymbol->szName, - HARBOUR_MAX_RDD_FIELDNAME_LENGTH); + pArea->uiMaxFieldNameLength); sprintf((char*)ucBuffer,"%s,%s,%d,%d;", ucField, cType, pField->uiLen, pField->uiDec ); } else @@ -1472,35 +1465,23 @@ static ERRCODE adsInfo( ADSAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) switch( uiIndex ) { - case DBI_DBFILTER: -/* XXX must have locally unless server can't handle it... adsFilterText( pArea, pItem ); */ - break; - case DBI_ISDBF: case DBI_CANPUTREC: hb_itemPutL( pItem, TRUE ); break; - case DBI_SHARED: - hb_itemPutL( pItem, pArea->fShared ); + case DBI_GETHEADERSIZE: + hb_itemPutNL( pItem, pArea->uiHeaderLen ); break; - case DBI_FULLPATH : - { - UNSIGNED8 aucBuffer[MAX_STR_LEN + 1]; - UNSIGNED16 pusLen = MAX_STR_LEN; - AdsGetTableFilename (pArea->hTable, - ADS_FULLPATHNAME, aucBuffer, &pusLen); - hb_itemPutCL( pItem, (char*)aucBuffer, pusLen ); - break; - } - case DBI_TABLEEXT: - hb_itemPutC( pItem, ((adsFileType==ADS_ADT) ? ".adt" : ".dbf") ); + case DBI_LASTUPDATE: + hb_itemPutDL( pItem, hb_dateEncode( pArea->bYear, + pArea->bMonth, + pArea->bDay ) ); break; - case DBI_MEMOEXT: - hb_itemPutC( pItem, ((adsFileType==ADS_ADT) ? ".adm" : - (adsFileType==ADS_CDX) ? ".fpt" : ".dbt") ); + case DBI_GETRECSIZE: + hb_itemPutNL( pItem, pArea->uiRecordLen ); break; case DBI_GETLOCKARRAY: @@ -1526,18 +1507,55 @@ static ERRCODE adsInfo( ADSAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) break; } - case DBI_LASTUPDATE: - hb_itemPutDL( pItem, hb_dateEncode( pArea->bYear, - pArea->bMonth, - pArea->bDay ) ); + case DBI_TABLEEXT: + hb_itemPutC( pItem, ((adsFileType==ADS_ADT) ? ".adt" : ".dbf") ); break; - case DBI_GETRECSIZE: - hb_itemPutNL( pItem, pArea->uiRecordLen ); + case DBI_FULLPATH : + { + UNSIGNED8 aucBuffer[MAX_STR_LEN + 1]; + UNSIGNED16 pusLen = MAX_STR_LEN; + AdsGetTableFilename (pArea->hTable, + ADS_FULLPATHNAME, aucBuffer, &pusLen); + hb_itemPutCL( pItem, (char*)aucBuffer, pusLen ); + break; + } + + case DBI_ISFLOCK: + hb_itemPutL( pItem, pArea->fFLocked ); break; - case DBI_GETHEADERSIZE: - hb_itemPutNL( pItem, pArea->uiHeaderLen ); + + case DBI_SHARED: + hb_itemPutL( pItem, pArea->fShared ); + break; + + case DBI_MEMOEXT: + hb_itemPutC( pItem, ((adsFileType==ADS_ADT) ? ".adm" : + (adsFileType==ADS_CDX) ? ".fpt" : ".dbt") ); + break; + +/* TODO ... */ + //case DBI_DBFILTER: + /* XXX must have locally unless server can't handle it... adsFilterText( pArea, pItem ); */ + // break; + + case DBI_CHILDCOUNT : /* Number of opened relations */ + case DBI_FILEHANDLE : /* Handle of opened file */ + case DBI_BOF : /* BOF flag - alternate to bof() */ + case DBI_EOF : /* EOF flag - alternate to eof() */ + case DBI_DBFILTER : /* Filter expression */ + case DBI_FOUND : /* FOUND flag - alternate to found */ + case DBI_FCOUNT : /* Number of fields */ + case DBI_LOCKCOUNT : /* Locked records */ + case DBI_VALIDBUFFER : /* Is the current buffer valid */ + case DBI_ALIAS : /* Alias name of workarea */ + case DBI_GETSCOPE : /* Locate codeblock */ + case DBI_LOCKOFFSET : /* New locking offset */ + case DBI_MEMOHANDLE : /* Dos handle for memo file */ + case DBI_MEMOBLOCKSIZE : /* Blocksize in memo files */ + case DBI_DB_VERSION : /* HOST driver Version */ + case DBI_RDD_VERSION : /* RDD version (current RDD) */ break; } return SUCCESS; @@ -1552,7 +1570,8 @@ static ERRCODE adsNewArea( ADSAREAP pArea ) /* Size for deleted records flag */ pArea->uiRecordLen = 1; - pArea->uiMaxFieldNameLength = 150; /* this is temporarily, must be changed */ + + pArea->uiMaxFieldNameLength = (adsFileType == ADS_ADT) ? ADS_MAX_FIELD_NAME : ADS_MAX_DBF_FIELD_NAME; return SUCCESS; } @@ -1561,7 +1580,8 @@ static ERRCODE adsOpen( ADSAREAP pArea, LPDBOPENINFO pOpenInfo ) ADSHANDLE hTable; UNSIGNED32 ulRetVal, pulLength, ulRecCount; USHORT uiFields, uiCount; - UNSIGNED8 szName[ HARBOUR_MAX_RDD_FIELDNAME_LENGTH + 1 ]; + UNSIGNED8 szName[ ADS_MAX_FIELD_NAME + 1 ]; + /* See adsGettValue() for why we don't use pArea->uiMaxFieldNameLength here */ UNSIGNED16 pusBufLen, pusType; DBFIELDINFO dbFieldInfo; @@ -1608,7 +1628,7 @@ static ERRCODE adsOpen( ADSAREAP pArea, LPDBOPENINFO pOpenInfo ) for( uiCount = 1; uiCount <= uiFields; uiCount++ ) { - pusBufLen = HARBOUR_MAX_RDD_FIELDNAME_LENGTH; + pusBufLen = pArea->uiMaxFieldNameLength + 1; AdsGetFieldName( pArea->hTable, uiCount, szName, &pusBufLen ); dbFieldInfo.atomName = szName; * ( dbFieldInfo.atomName + pusBufLen ) = '\0'; @@ -1629,12 +1649,12 @@ static ERRCODE adsOpen( ADSAREAP pArea, LPDBOPENINFO pOpenInfo ) case ADS_NUMERIC: dbFieldInfo.uiTypeExtended = 0; - case ADS_DOUBLE: + case ADS_DOUBLE: /* uiLen of extended types is set in following switch */ + case ADS_CURDOUBLE: case ADS_INTEGER: case ADS_SHORTINT: case ADS_TIME: case ADS_TIMESTAMP: - case ADS_CURDOUBLE: case ADS_AUTOINC: dbFieldInfo.uiType = HB_IT_LONG; AdsGetFieldDecimals( pArea->hTable, szName, ( UNSIGNED16 * ) &pulLength ); @@ -1660,6 +1680,29 @@ static ERRCODE adsOpen( ADSAREAP pArea, LPDBOPENINFO pOpenInfo ) dbFieldInfo.uiType = HB_IT_MEMO; break; } + + if ( dbFieldInfo.uiTypeExtended ) + { + switch( pusType ) /* set any special display lengths */ + { + case ADS_DOUBLE: + case ADS_CURDOUBLE: + dbFieldInfo.uiLen = ( USHORT ) 20; + break; + case ADS_SHORTINT: + dbFieldInfo.uiLen = ( USHORT ) 6; + break; + case ADS_AUTOINC: + case ADS_INTEGER: + case ADS_TIME: + dbFieldInfo.uiLen = ( USHORT ) 11; + break; + case ADS_TIMESTAMP: + dbFieldInfo.uiLen = ( USHORT ) 20; + break; + } + } + SELF_ADDFIELD( ( AREAP ) pArea, &dbFieldInfo ); } @@ -2098,27 +2141,52 @@ static ERRCODE adsOrderInfo( ADSAREAP pArea, USHORT uiIndex, LPDBORDERINFO pOrde if ( !pArea->fEof && phIndex ) { AdsExtractKey( phIndex, aucBuffer, &pusLen); + /* ---------------------------------- + From ads docs: It is important to note that the key generated + by this function is built on the client, and the key may not + exist in the index. + -----------------------------------*/ AdsGetKeyType( phIndex, &pus16); switch( pus16 ) { case ADS_STRING: hb_itemPutCL( pOrderInfo->itmResult, (char*)aucBuffer, pusLen); break; + case ADS_NUMERIC: + if ( adsFileType == ADS_NTX ) /* TODO: This should be a table-specific switch */ { + if ( aucBuffer[0] == '-' || aucBuffer[0] == ',') /* negative number encoding */ + { + pus16 = 0; + while ( pus16 < pusLen && aucBuffer[pus16] == ',') /* leading zeros were set as commas for sorting */ + aucBuffer[pus16++] = '0'; + if ( aucBuffer[pus16] == '-' ) pus16++; /* skip past the minus */ + while ( pus16 < pusLen ) + aucBuffer[pus16] = (SIGNED8) 0x5C - aucBuffer[pus16++]; + + } + hb_itemPutND( pOrderInfo->itmResult, hb_strVal((char*)aucBuffer, pusLen)); + + }else + { /* ADS_CDX, ADS_ADT */ double nValue; FoxToDbl(aucBuffer, &nValue); hb_itemPutND( pOrderInfo->itmResult, nValue ); - break; } + break; + case ADS_DATE: hb_itemPutDS( pOrderInfo->itmResult, (char*)aucBuffer ); break; + case ADS_LOGICAL: hb_itemPutL( pOrderInfo->itmResult, (int) *aucBuffer ); break; + case ADS_RAW: /* TODO: convert correctly from raw data in the buffer for other types (what's below is wrong or untested at best) */ + default: hb_itemPutC( pOrderInfo->itmResult, "" ); } diff --git a/harbour/contrib/rdd_ads/adsfunc.c b/harbour/contrib/rdd_ads/adsfunc.c index d1abd357c7..8a20baa557 100644 --- a/harbour/contrib/rdd_ads/adsfunc.c +++ b/harbour/contrib/rdd_ads/adsfunc.c @@ -1233,3 +1233,19 @@ HB_FUNC( ADSGETCONNECTIONHANDLE ) hb_retni( adsConnectHandle ); } +HB_FUNC( ADSGETLASTERROR ) +{ + /* nLastErr := AdsGetLastError( [ @cLastErr ] ) */ + + UNSIGNED32 ulLastErr; + UNSIGNED16 usLength = ADS_MAX_ERROR_LEN + 1; + UNSIGNED8 aucError[ ADS_MAX_ERROR_LEN + 1 ]; + + AdsGetLastError( &ulLastErr, aucError, &usLength ); + + if ( hb_pcount() > 0 ) + hb_storclen( ( char far * ) aucError, usLength, 1 ); + + hb_retnl( ulLastErr ); +} +