From 061f35cc83a0879a37fc107fb5869b423ef6d37d Mon Sep 17 00:00:00 2001 From: Luis Krause Date: Tue, 17 Feb 2004 01:50:19 +0000 Subject: [PATCH] 2004-02-16 17:40 UTC-0800 Luis Krause Mantilla --- harbour/ChangeLog | 24 ++ harbour/contrib/rdd_ads/ace.h | 176 +++++--- harbour/contrib/rdd_ads/ads1.c | 285 ++++++++----- harbour/contrib/rdd_ads/adsfunc.c | 449 +++++++++++++++++--- harbour/contrib/rdd_ads/adsmgmnt.c | 57 ++- harbour/contrib/rdd_ads/doc/en/adsfuncs.txt | 212 +++++++-- harbour/contrib/rdd_ads/rddads.h | 13 +- 7 files changed, 977 insertions(+), 239 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 3478bb83fa..1dbc943601 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,30 @@ 2002-12-01 23:12 UTC+0100 Foo Bar */ +2004-02-16 17:40 UTC-0800 Luis Krause Mantilla + * contrib/rdd_ads/ads1.c + * contrib/rdd_ads/adsfunc.c + * contrib/rdd_ads/adsmgmnt.c + * contrib/rdd_ads/ace.h + * contrib/rdd_ads/rddads.h + * contrib/rdd_ads/doc/en/adsfuncs.txt + ! Renamed Data Dictionary functions for consistency: + adsAddTable() to adsDDAddTale() + adsAddUserToGroup to adsDDAddUserToGroup() + ! Moved adsGetNumActiveLinks() inside the ADS_REQUIRE_VERSION6 to avoid + compile errors with ADS version older than v. 6.0 + + Syncronized with xHarbour - Thanks to Brian Hays, Toninho, et. al. + added the following functions: + adsConnect60() + adsCopyTableContents() + adsDDCreate() + adsDDCreateUser() + adsDDGetDatabaseProperty() + adsDDGetUserProperty() + adsDDSetDatabaseProperty() + adsGetTableCharType() + adsMGGetLockOwner() + 2004-02-16 15:52 UTC+0100 Viktor Szakats * src/rtl/set.c diff --git a/harbour/contrib/rdd_ads/ace.h b/harbour/contrib/rdd_ads/ace.h index 9186ea2a59..193411befa 100644 --- a/harbour/contrib/rdd_ads/ace.h +++ b/harbour/contrib/rdd_ads/ace.h @@ -459,7 +459,7 @@ #define ADS_MAX_TAG_NAME 128 #define ADS_MAX_TAGS 50 /* maximum for CDX/ADI file */ #define ADS_MAX_OBJECT_NAME 200 /* maximum length of DD object name */ - +#define ADS_MAX_TABLE_AND_PATH ADS_MAX_TABLE_NAME + ADS_MAX_PATH /* * Valid range of page sizes for ADI indexes. The default page size is 512 @@ -501,14 +501,14 @@ #define ADS_AUTOINC 15 /* 4 byte auto-increment value */ #define ADS_RAW 16 /* Untranslated data */ #define ADS_CURDOUBLE 17 /* IEEE 8 byte floating point currency */ - +#define ADS_MONEY 18 /* 8 byte, 4 implied decimal Currency Field */ +#define ADS_LONGLONG 19 /* 8 byte integer */ /* * supported User Defined Function types to be used with AdsRegisterUDF */ #define ADS_INDEX_UDF 1 - /* * Constant for AdsMgGetConfigInfo */ @@ -618,6 +618,11 @@ typedef struct UNSIGNED16 usMaxConnFailures; /* Maximum Internet connection failures allowed. */ UNSIGNED32 ulInternetKeepAlive; /* In Milliseconds */ + UNSIGNED16 usCompressionLevel; /* Compression option at server. ADS_COMPRESS_NEVER, + * ADS_COMPRESS_INTERNET, or ADS_COMPRESS_ALWAYS */ + UNSIGNED16 usReserved5; /* reserved */ + UNSIGNED32 ulReserved6; /* reserved */ + } ADS_MGMT_CONFIG_PARAMS; typedef struct @@ -730,18 +735,22 @@ typedef struct _ADD_FIELD_DESC_ #define ADS_DD_MAX_PROPERTY_LEN 0xFFFE #define ADS_DD_MAX_OBJECT_NAME_LEN 200 -#define ADS_DD_TABLE_OBJECT 1 -#define ADS_DD_RELATION_OBJECT 2 -#define ADS_DD_INDEX_FILE_OBJECT 3 -#define ADS_DD_FIELD_OBJECT 4 -#define ADS_DD_COLUMN_OBJECT 4 -#define ADS_DD_INDEX_OBJECT 5 -#define ADS_DD_VIEW_OBJECT 6 -#define ADS_DD_VIEW_OR_TABLE_OBJECT 7 /* Used in AdsFindFirst/NextTable */ -#define ADS_DD_USER_OBJECT 8 -#define ADS_DD_USER_GROUP_OBJECT 9 -#define ADS_DD_PROCEDURE_OBJECT 10 -#define ADS_DD_DATABASE_OBJECT 11 +#define ADS_DD_UNKNOWN_OBJECT 0 +#define ADS_DD_TABLE_OBJECT 1 +#define ADS_DD_RELATION_OBJECT 2 +#define ADS_DD_INDEX_FILE_OBJECT 3 +#define ADS_DD_FIELD_OBJECT 4 +#define ADS_DD_COLUMN_OBJECT 4 +#define ADS_DD_INDEX_OBJECT 5 +#define ADS_DD_VIEW_OBJECT 6 +#define ADS_DD_VIEW_OR_TABLE_OBJECT 7 /* Used in AdsFindFirst/NextTable */ +#define ADS_DD_USER_OBJECT 8 +#define ADS_DD_USER_GROUP_OBJECT 9 +#define ADS_DD_PROCEDURE_OBJECT 10 +#define ADS_DD_DATABASE_OBJECT 11 +#define ADS_DD_LINK_OBJECT 12 +#define ADS_DD_TABLE_VIEW_OR_LINK_OBJECT 13 /* Used in v6.2 AdsFindFirst/NextTable */ +#define ADS_DD_TRIGGER_OBJECT 14 /* Common properties numbers < 100 */ @@ -762,7 +771,8 @@ typedef struct _ADD_FIELD_DESC_ #define ADS_DD_INTERNET_SECURITY_LEVEL 108 #define ADS_DD_MAX_FAILED_ATTEMPTS 109 #define ADS_DD_ALLOW_ADSSYS_NET_ACCESS 110 - +#define ADS_DD_VERSION_MAJOR 111 /* properties for customer dd version */ +#define ADS_DD_VERSION_MINOR 112 /* Table properties between 200 and 299 */ #define ADS_DD_TABLE_VALIDATION_EXPR 200 @@ -781,6 +791,9 @@ typedef struct _ADD_FIELD_DESC_ #define ADS_DD_TABLE_DEFAULT_INDEX 213 #define ADS_DD_TABLE_ENCRYPTION 214 #define ADS_DD_TABLE_MEMO_BLOCK_SIZE 215 +#define ADS_DD_TABLE_PERMISSION_LEVEL 216 +#define ADS_DD_TABLE_TRIGGER_TYPES 217 +#define ADS_DD_TABLE_TRIGGER_OPTIONS 218 /* Field properties between 300 - 399 */ #define ADS_DD_FIELD_DEFAULT_VALUE 300 @@ -792,14 +805,20 @@ typedef struct _ADD_FIELD_DESC_ #define ADS_DD_FIELD_TYPE 306 #define ADS_DD_FIELD_LENGTH 307 #define ADS_DD_FIELD_DECIMAL 308 +#define ADS_DD_FIELD_NUM 309 /* Index tag properties between 400 - 499 */ -#define ADS_DD_INDEX_FILE_NAME 400 -#define ADS_DD_INDEX_EXPRESSION 401 -#define ADS_DD_INDEX_CONDITION 402 -#define ADS_DD_INDEX_OPTIONS 403 -#define ADS_DD_INDEX_KEY_LENGTH 404 -#define ADS_DD_INDEX_KEY_TYPE 405 +#define ADS_DD_INDEX_FILE_NAME 400 +#define ADS_DD_INDEX_EXPRESSION 401 +#define ADS_DD_INDEX_CONDITION 402 +#define ADS_DD_INDEX_OPTIONS 403 +#define ADS_DD_INDEX_KEY_LENGTH 404 +#define ADS_DD_INDEX_KEY_TYPE 405 +#define ADS_DD_INDEX_FTS_MIN_LENGTH 406 +#define ADS_DD_INDEX_FTS_DELIMITERS 407 +#define ADS_DD_INDEX_FTS_NOISE 408 +#define ADS_DD_INDEX_FTS_DROP_CHARS 409 +#define ADS_DD_INDEX_FTS_CONDITIONAL_CHARS 410 /* RI properties between 500-599 */ #define ADS_DD_RI_PARENT_GRAPH 500 @@ -809,17 +828,8 @@ typedef struct _ADD_FIELD_DESC_ #define ADS_DD_RI_FOREIGN_INDEX 504 #define ADS_DD_RI_UPDATERULE 505 #define ADS_DD_RI_DELETERULE 506 - -/* Referential Integrity (RI) update and delete rules */ -#define ADS_DD_RI_CASCADE 1 -#define ADS_DD_RI_RESTRICT 2 -#define ADS_DD_RI_SETNULL 3 -#define ADS_DD_RI_SETDEFAULT 4 - -/* Default Field Value Options */ -#define ADS_DD_DFV_UNKNOWN 1 -#define ADS_DD_DFV_NONE 2 -#define ADS_DD_DFV_VALUES_STORED 3 +#define ADS_DD_RI_NO_PKEY_ERROR 507 +#define ADS_DD_RI_CASCADE_ERROR 508 /* User properties between 600-699 */ #define ADS_DD_USER_GROUP_NAME 600 @@ -836,40 +846,108 @@ typedef struct _ADD_FIELD_DESC_ #define ADS_DD_PROC_INVOKE_OPTION 804 /* Index file properties 900-999 */ -#define ADS_DD_INDEX_FILE_PATH 900 -#define ADS_DD_INDEX_FILE_PAGESIZE 901 +#define ADS_DD_INDEX_FILE_PATH 900 +#define ADS_DD_INDEX_FILE_PAGESIZE 901 /* * Object rights properties 1001 - 1099 . They can be used * with either user or user group objects. */ -#define ADS_DD_TABLES_RIGHTS 1001 -#define ADS_DD_VIEWS_RIGHTS 1002 -#define ADS_DD_PROCS_RIGHTS 1003 -#define ADS_DD_OBJECTS_RIGHTS 1004 -#define ADS_DD_FREE_TABLES_RIGHTS 1005 +#define ADS_DD_TABLES_RIGHTS 1001 +#define ADS_DD_VIEWS_RIGHTS 1002 +#define ADS_DD_PROCS_RIGHTS 1003 +#define ADS_DD_OBJECTS_RIGHTS 1004 +#define ADS_DD_FREE_TABLES_RIGHTS 1005 /* User Properties 1101 - 1199 */ #define ADS_DD_USER_PASSWORD 1101 #define ADS_DD_USER_GROUP_MEMBERSHIP 1102 +#define ADS_DD_USER_BAD_LOGINS 1103 + +/* User group Properties 1201 - 1299 */ +/* None at this moment. */ + +/* Link properties 1301 - 1399 */ +#define ADS_DD_LINK_PATH 1300 +#define ADS_DD_LINK_OPTIONS 1301 +#define ADS_DD_LINK_USERNAME 1302 + +/* Trigger properties 1400 - 1499 */ +#define ADS_DD_TRIG_TABLEID 1400 +#define ADS_DD_TRIG_EVENT_TYPE 1401 +#define ADS_DD_TRIG_TRIGGER_TYPE 1402 +#define ADS_DD_TRIG_CONTAINER_TYPE 1403 +#define ADS_DD_TRIG_CONTAINER 1404 +#define ADS_DD_TRIG_FUNCTION_NAME 1405 +#define ADS_DD_TRIG_PRIORITY 1406 +#define ADS_DD_TRIG_OPTIONS 1407 +#define ADS_DD_TRIG_TABLENAME 1408 + #define ADS_DD_LEVEL_0 0 #define ADS_DD_LEVEL_1 1 #define ADS_DD_LEVEL_2 2 +/* Referential Integrity (RI) update and delete rules */ +#define ADS_DD_RI_CASCADE 1 +#define ADS_DD_RI_RESTRICT 2 +#define ADS_DD_RI_SETNULL 3 +#define ADS_DD_RI_SETDEFAULT 4 -/* User group Properties 1201 - 1299 */ -/* None at this moment. */ -/* Also object rights properties 1001 - 1099 */ +/* Default Field Value Options */ +#define ADS_DD_DFV_UNKNOWN 1 +#define ADS_DD_DFV_NONE 2 +#define ADS_DD_DFV_VALUES_STORED 3 /* Supported permissions in the data dictionary */ -#define ADS_PERMISSION_READ 1 -#define ADS_PERMISSION_UPDATE 2 -#define ADS_PERMISSION_INSERT 3 -#define ADS_PERMISSION_DELETE 4 -#define ADS_PERMISSION_EXECUTE 5 -#define ADS_PERMISSION_INHERIT 6 +#define ADS_PERMISSION_READ 0x00000001 +#define ADS_PERMISSION_UPDATE 0x00000002 +#define ADS_PERMISSION_EXECUTE 0x00000004 +#define ADS_PERMISSION_INHERIT 0x00000008 +#define ADS_PERMISSION_INSERT 0x00000010 +#define ADS_PERMISSION_DELETE 0x00000020 +#define ADS_PERMISSION_LINK_ACCESS 0x00000040 +#define ADS_PERMISSION_ALL 0xFFFFFFFF +/* Link DD options */ +#define ADS_LINK_GLOBAL 0x00000001 +#define ADS_LINK_AUTH_ACTIVE_USER 0x00000002 +#define ADS_LINK_PATH_IS_STATIC 0x00000004 + +/* Trigger event types */ +#define ADS_TRIGEVENT_INSERT 1 +#define ADS_TRIGEVENT_UPDATE 2 +#define ADS_TRIGEVENT_DELETE 3 + +/* Trigger types */ +#define ADS_TRIGTYPE_BEFORE 0x00000001 +#define ADS_TRIGTYPE_INSTEADOF 0x00000002 +#define ADS_TRIGTYPE_AFTER 0x00000004 + +/* Trigger container types */ +#define ADS_TRIG_WIN32DLL 1 +#define ADS_TRIG_COM 2 +#define ADS_TRIG_SCRIPT 3 + +/* + * Trigger options, if changed or adding more please inspect code + * in RemoveTriggerFromDictionary + */ +#define ADS_TRIGOPTIONS_NO_VALUES 0x00000000 +#define ADS_TRIGOPTIONS_WANT_VALUES 0x00000001 +#define ADS_TRIGOPTIONS_WANT_MEMOS_AND_BLOBS 0x00000002 +#define ADS_TRIGOPTIONS_DEFAULT 0x00000003 /* default is to include vals and memos */ +#define ADS_TRIGOPTIONS_NO_TRANSACTION 0x00000004 /* don't use implicit transactions */ + +/* + * Table permission verification levels. + * level 1 is all columns searchable, even those without permission. + * level 2 is default. Permission to the column is required to search or filter on a column. + * level 3 is most restricted. Only static SQL cursor is allowed. + */ +#define ADS_DD_TABLE_PERMISSION_LEVEL_1 1 +#define ADS_DD_TABLE_PERMISSION_LEVEL_2 2 +#define ADS_DD_TABLE_PERMISSION_LEVEL_3 3 /* stored procedure functions must be of this type */ diff --git a/harbour/contrib/rdd_ads/ads1.c b/harbour/contrib/rdd_ads/ads1.c index 7b0af732b1..6357409760 100644 --- a/harbour/contrib/rdd_ads/ads1.c +++ b/harbour/contrib/rdd_ads/ads1.c @@ -59,6 +59,7 @@ #include "hbinit.h" #include "hbapiitm.h" #include "hbapierr.h" +#include "hbdbferr.h" #include "hbapilng.h" #include "hbdate.h" #include "rddads.h" @@ -77,6 +78,7 @@ extern int adsFileType; /* current global setting */ extern int adsLockType; extern int adsRights; extern int adsCharType; +extern BOOL bTestRecLocks; extern BOOL bDictionary; extern ADSHANDLE adsConnectHandle; @@ -133,20 +135,21 @@ void adsSetListener_callback( HB_set_enum setting, HB_set_listener_enum when ) /* Possible TODO? case HB_SET_MFILEEXT : - if( hb_set.HB_SET_MFILEEXT ) hb_retc( hb_set.HB_SET_MFILEEXT ); + if( hb_set.HB_SET_MFILEEXT ) + hb_retc( hb_set.HB_SET_MFILEEXT ); break; case HB_SET_STRICTREAD : hb_retl( hb_set.HB_SET_STRICTREAD ); break; - */ + default: + break; } } } - static void commonError( ADSAREAP pArea, USHORT uiGenCode, USHORT uiSubCode, char* filename ) { PHB_ITEM pError; @@ -192,7 +195,6 @@ static void DumpArea( ADSAREAP pArea ) /* For debugging: call this to dump ads if( pArea->hOrdCurrent ) { - pusLen = MAX_STR_LEN; AdsGetIndexName( pArea->hOrdCurrent, pucIndexName, &pusLen); pusLen = MAX_STR_LEN; @@ -354,13 +356,13 @@ static ERRCODE hb_adsCheckBofEof( ADSAREAP pArea ) if( pArea->fBof && !pArea->fEof ) { - if( AdsSkip ( (pArea->hOrdCurrent) ? pArea->hOrdCurrent:pArea->hTable, 1 ) == - AE_NO_CURRENT_RECORD ) + if( AdsSkip ( (pArea->hOrdCurrent) ? pArea->hOrdCurrent:pArea->hTable, 1 ) == AE_NO_CURRENT_RECORD ) pArea->fEof = TRUE; /* empty data set trying to skip back to first record. ADS will set eof to False when hit Bof even if there are no records */ return SUPER_SKIPFILTER( (AREAP)pArea, 1 ); - }else + } + else return SUCCESS; } @@ -436,7 +438,7 @@ ERRCODE adsEof( ADSAREAP pArea, BOOL * pEof ) AdsAtEOF( pArea->hTable, (UNSIGNED16 *)&(pArea->fEof) ); *pEof = pArea->fEof; } - return SUPER_EOF( (AREAP)pArea,pEof ); + return SUPER_EOF( (AREAP) pArea, pEof ); } #define adsFound NULL @@ -570,7 +572,8 @@ static ERRCODE adsSeek( ADSAREAP pArea, BOOL bSoftSeek, PHB_ITEM pKey, BOOL bFin dTemp = hb_itemGetDL( pKey ); AdsSeekLast( pArea->hOrdCurrent, (UNSIGNED8 *) &dTemp, 8, ADS_DOUBLEKEY, (UNSIGNED16*) &(pArea->fFound) ); - }else + } + else { hb_itemGetNLen( pKey, &uiLen, &uiDec ); hb_ndtoa( hb_itemGetND( pKey ), ( char * ) szText, uiLen, uiDec ); @@ -671,11 +674,12 @@ static ERRCODE adsSkip( ADSAREAP pArea, LONG lToSkip ) if ( lToSkip==0 ) - { + { AdsSkip ( (pArea->hOrdCurrent) ? pArea->hOrdCurrent : pArea->hTable, lToSkip ); AdsRefreshRecord(pArea->hTable); return SUCCESS; /*bh: dbskip(0) created infinite loop; this should never move the record pointer via skipfilter */ - }else + } + else { if ( lToSkip < 0 ) { @@ -693,7 +697,8 @@ static ERRCODE adsSkip( ADSAREAP pArea, LONG lToSkip ) pArea->fBottom = TRUE; AdsGotoBottom ( (pArea->hOrdCurrent) ? pArea->hOrdCurrent : pArea->hTable ); } - }else + } + else AdsSkip ( (pArea->hOrdCurrent) ? pArea->hOrdCurrent : pArea->hTable, lUnit ); hb_adsCheckBofEof( pArea ); @@ -709,7 +714,7 @@ static ERRCODE adsSkip( ADSAREAP pArea, LONG lToSkip ) } return (ERRCODE) lReturn; - } + } } #define adsSkipFilter NULL @@ -790,14 +795,12 @@ static ERRCODE adsCreateFields( ADSAREAP pArea, PHB_ITEM pStruct ) switch( iData ) { case 'C': - if( strlen(szFieldType) == 1 || - !hb_stricmp( szFieldType,"char" ) ) + if( strlen(szFieldType) == 1 || ! hb_stricmp( szFieldType, "char" ) ) { pFieldInfo.uiType = HB_IT_STRING; pFieldInfo.uiLen = uiLen + uiDec * 256; } - else if( !hb_stricmp( szFieldType,"curdouble" ) && - adsFileType == ADS_ADT ) + else if( ! hb_stricmp( szFieldType, "curdouble" ) && adsFileType == ADS_ADT ) { pFieldInfo.uiType = HB_IT_LONG; pFieldInfo.uiTypeExtended = ADS_CURDOUBLE; @@ -816,17 +819,16 @@ static ERRCODE adsCreateFields( ADSAREAP pArea, PHB_ITEM pStruct ) case 'M': pFieldInfo.uiType = HB_IT_MEMO; - pFieldInfo.uiLen = (adsFileType == ADS_ADT)? 9:10; + pFieldInfo.uiLen = (adsFileType == ADS_ADT) ? 9 : 10; break; case 'D': - if( strlen(szFieldType) == 1 || - !hb_stricmp( szFieldType,"date" ) ) + if( strlen(szFieldType) == 1 || ! hb_stricmp( szFieldType, "date" ) ) { pFieldInfo.uiType = HB_IT_DATE; - pFieldInfo.uiLen = (adsFileType == ADS_ADT)? 4:8; + pFieldInfo.uiLen = (adsFileType == ADS_ADT) ? 4 : 8; } - else if( !hb_stricmp( szFieldType,"double" ) ) + else if( ! hb_stricmp( szFieldType, "double" ) ) { pFieldInfo.uiType = HB_IT_LONG; pFieldInfo.uiTypeExtended = ADS_DOUBLE; @@ -877,14 +879,13 @@ static ERRCODE adsCreateFields( ADSAREAP pArea, PHB_ITEM pStruct ) break; case 'S': - if( !hb_stricmp( szFieldType,"shortdate" ) ) + if( !hb_stricmp( szFieldType, "shortdate" ) ) { pFieldInfo.uiType = HB_IT_DATE; pFieldInfo.uiTypeExtended = ADS_COMPACTDATE; pFieldInfo.uiLen = 4; } - else if( !hb_stricmp( szFieldType,"shortint" ) && - adsFileType == ADS_ADT ) + else if( !hb_stricmp( szFieldType, "shortint" ) && adsFileType == ADS_ADT ) { pFieldInfo.uiType = HB_IT_LONG; pFieldInfo.uiTypeExtended = ADS_SHORTINT; @@ -895,15 +896,13 @@ static ERRCODE adsCreateFields( ADSAREAP pArea, PHB_ITEM pStruct ) break; case 'T': - if( !hb_stricmp( szFieldType,"timestamp" ) && - adsFileType == ADS_ADT ) + if( ! hb_stricmp( szFieldType, "timestamp" ) && adsFileType == ADS_ADT ) { pFieldInfo.uiType = HB_IT_LONG; pFieldInfo.uiTypeExtended = ADS_TIMESTAMP; pFieldInfo.uiLen = 8; } - else if( !hb_stricmp( szFieldType,"time" ) && - adsFileType == ADS_ADT ) + else if( !hb_stricmp( szFieldType, "time" ) && adsFileType == ADS_ADT ) { pFieldInfo.uiType = HB_IT_LONG; pFieldInfo.uiTypeExtended = ADS_TIME; @@ -914,13 +913,13 @@ static ERRCODE adsCreateFields( ADSAREAP pArea, PHB_ITEM pStruct ) break; case 'I': - if( !hb_stricmp( szFieldType,"integer" ) ) + if( !hb_stricmp( szFieldType, "integer" ) ) { pFieldInfo.uiType = HB_IT_LONG; pFieldInfo.uiTypeExtended = ADS_INTEGER; pFieldInfo.uiLen = 4; } - else if( !hb_stricmp( szFieldType,"image" ) ) + else if( !hb_stricmp( szFieldType, "image" ) ) { pFieldInfo.uiType = HB_IT_MEMO; pFieldInfo.uiTypeExtended = ADS_IMAGE; @@ -950,17 +949,20 @@ static ERRCODE adsDeleteRec( ADSAREAP pArea ) static ERRCODE adsDeleted( ADSAREAP pArea, BOOL * pDeleted ) { - UNSIGNED16 bDeleted; + UNSIGNED16 bDeleted = (UNSIGNED16) FALSE; + UNSIGNED32 ulRetVal; HB_TRACE(HB_TR_DEBUG, ("adsDeleted(%p, %p)", pArea, pDeleted)); if ( pArea->fEof ) { *pDeleted = FALSE; /* ADS by default returns True at eof */ - }else + } + else { - AdsIsRecordDeleted ( pArea->hTable, &bDeleted); - *pDeleted = (BOOL) bDeleted; + ulRetVal = AdsIsRecordDeleted( pArea->hTable, &bDeleted ); + if( ulRetVal == AE_SUCCESS ) + *pDeleted = (BOOL) bDeleted; } return SUCCESS; } @@ -969,7 +971,7 @@ static ERRCODE adsFieldCount( ADSAREAP pArea, USHORT * uiFields ) { HB_TRACE(HB_TR_DEBUG, ("adsFieldCount(%p, %p)", pArea, uiFields)); - AdsGetNumFields ( pArea->hTable, uiFields ); + AdsGetNumFields( pArea->hTable, uiFields ); return SUCCESS; } @@ -1234,90 +1236,170 @@ static ERRCODE adsPutValue( ADSAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) LPFIELD pField; USHORT uiCount; BYTE * szText; - BOOL bError = TRUE; + BOOL bTypeError = TRUE; long lDay, lMonth, lYear; UNSIGNED8 pucFormat[ 11 ]; - UNSIGNED16 pusLen = 10; - UNSIGNED32 ulRetVal; + UNSIGNED16 pusLen = 11; + UNSIGNED32 ulRetVal = 0; HB_TRACE(HB_TR_DEBUG, ("adsPutValue(%p, %hu, %p)", pArea, uiIndex, pItem)); + /* -----------------10/30/2003 3:54PM---------------- + + ADS has Implicit Record locking that can mask programming errors. + Implicit locking can occur the first time a value is written to a + field with no lock in effect. The lock can potentially remain in + effect indefinitely if the record pointer is not moved. + + The bTestRecLocks flag can be set using + AdsTestRecLocks( lOnOff ) in adsfunc.c. + If ON, we see if the file is open exclusively or locked, and whether + the record has been explicitly locked already. If not, we throw + an error so the developer can catch the missing lock condition. + For performance reasons, Release code should leave this OFF. + Although the call to AdsIsRecordLocked is documented as a client + call, not a server request, and should be fast, it will be + called for EACH FIELD as it is assigned a value. + + --------------------------------------------------*/ + if( bTestRecLocks && pArea->fShared && !pArea->fFLocked ) + { + UNSIGNED16 pbLocked = FALSE; + + ulRetVal = AdsIsRecordLocked( pArea->hTable, 0, &pbLocked ) ; + if( ulRetVal != AE_SUCCESS ) + { + hb_errRT_DBCMD( EG_LOCK, ulRetVal, "Lock Required by TestRecLocks", "ADSISRECORDLOCKED" ); + } + + if( !pbLocked ) + { + commonError( pArea, EG_UNLOCKED, EDBF_UNLOCKED, NULL ); + //hb_errRT_DBCMD( EG_LOCK, EDBF_UNLOCKED, "Record not locked", "adsPutValue" ); + } + } + + if( pArea->uiParents ) { hb_adsCheckBofEof( pArea ); } if( uiIndex > pArea->uiFieldCount || pArea->fEof ) + { return FAILURE; + } pField = pArea->lpFields + uiIndex - 1; szText = pArea->pRecord; /* This code was optimized for use ADSFIELD() macro instead */ - /* AdsGetFieldName() function for speed. Toninho@fwi, 16/07/2003 */ + /* AdsGetFieldName() function for speed. Toninho@fwi, 22/07/2003 */ switch( pField->uiType ) { case HB_IT_STRING: if( HB_IS_STRING( pItem ) ) { + bTypeError = FALSE; uiCount = ( USHORT ) hb_itemGetCLen( pItem ); if( uiCount > pField->uiLen ) + { uiCount = pField->uiLen; - AdsSetString( pArea->hTable, ADSFIELD( uiIndex ), (UNSIGNED8*)hb_itemGetCPtr( pItem ), uiCount ); - bError = FALSE; + } + + ulRetVal = AdsSetString( pArea->hTable, ADSFIELD( uiIndex ), (UNSIGNED8*)hb_itemGetCPtr( pItem ), uiCount ); + } break; case HB_IT_LONG: if( HB_IS_NUMERIC( pItem ) ) { + bTypeError = FALSE; ulRetVal = AdsSetDouble( pArea->hTable, ADSFIELD( uiIndex ), hb_itemGetND( pItem ) ); - if( ulRetVal != AE_DATA_TOO_LONG ) - bError = FALSE; + // write to autoincrement field will gen error 5066 + // if( pField->uiTypeExtended == ADS_AUTOINC ) + //AdsShowError( (UNSIGNED8 *) "Error" ); } break; case HB_IT_DATE: if( HB_IS_DATE( pItem ) ) { + bTypeError = FALSE; AdsGetDateFormat ( pucFormat, &pusLen ); AdsSetDateFormat ( (UNSIGNED8*)"YYYYMMDD" ); hb_dateDecode( hb_itemGetDL( pItem ), &lYear, &lMonth, &lDay ); hb_dateStrPut( ( char * ) szText, lYear, lMonth, lDay ); - AdsSetDate( pArea->hTable, ADSFIELD( uiIndex ), szText, 8 ); + ulRetVal = AdsSetDate( pArea->hTable, ADSFIELD( uiIndex ), szText, 8 ); AdsSetDateFormat ( pucFormat ); - bError = FALSE; } break; case HB_IT_LOGICAL: if( HB_IS_LOGICAL( pItem ) ) { + bTypeError = FALSE; *szText = hb_itemGetL( pItem ) ? 'T' : 'F'; - bError = FALSE; - AdsSetLogical( pArea->hTable, ADSFIELD( uiIndex ), hb_itemGetL( pItem ) ); + ulRetVal = AdsSetLogical( pArea->hTable, ADSFIELD( uiIndex ), hb_itemGetL( pItem ) ); } break; case HB_IT_MEMO: if( HB_IS_STRING( pItem ) ) { + bTypeError = FALSE; uiCount = ( USHORT ) hb_itemGetCLen( pItem ); - AdsSetString( pArea->hTable, ADSFIELD( uiIndex ), + ulRetVal = AdsSetString( pArea->hTable, ADSFIELD( uiIndex ), (UNSIGNED8*)hb_itemGetCPtr( pItem ), uiCount ); - bError = FALSE; } break; } - if( bError ) + if( bTypeError ) { commonError( pArea, EG_DATATYPE, 1020, NULL ); pArea->fRecordChanged = FALSE; + /* bh: + It seems wrong for this to be reset if OTHER fields have been + written successfully already. But + this flag is apparently not used by RDDADS. It has been there + since the beginning and may be implmented later. In the + internal RDDs it is apparently just used as a short-circuit flag for + avoiding repeated calls to GoHot, a method rddads never used. + If in fact GoHot does get implemented, it may be better if + fRecordChanged *is* set to False in case error handling is + retrying and another call to GoHot may be desirable. + If this happens, this needs to be integrated to the other error + conditions handled below. + */ return FAILURE; } + + if( ulRetVal != AE_SUCCESS ) + { + if( ulRetVal == AE_LOCK_FAILED || ulRetVal == AE_RECORD_NOT_LOCKED ) + { + commonError( pArea, EG_UNLOCKED, EDBF_UNLOCKED, NULL ); + } + else if( ulRetVal == AE_TABLE_READONLY ) + { + commonError( pArea, EG_READONLY, EDBF_READONLY, NULL ); + } + else if( ulRetVal == AE_DATA_TOO_LONG ) + { + commonError( pArea, EG_WRITE, (USHORT) ulRetVal, NULL ); + } + else + { + commonError( pArea, EG_WRITE, (USHORT) ulRetVal, NULL ); + } + + return FAILURE; + } + pArea->fRecordChanged = TRUE; return SUCCESS; } @@ -1388,7 +1470,7 @@ static ERRCODE adsCreate( ADSAREAP pArea, LPDBOPENINFO pCreateInfo) ADSHANDLE hTable; UNSIGNED32 uRetVal; UNSIGNED8 *ucfieldDefs; - UNSIGNED8 ucBuffer[MAX_STR_LEN+1], ucField[ADS_MAX_FIELD_NAME+1]; + UNSIGNED8 ucBuffer[MAX_STR_LEN + 1], ucField[ADS_MAX_FIELD_NAME + 1]; USHORT uiCount, uiLen; LPFIELD pField; char cType[8]; @@ -1415,48 +1497,48 @@ static ERRCODE adsCreate( ADSAREAP pArea, LPDBOPENINFO pCreateInfo) { case HB_IT_DATE: if( pField->uiTypeExtended == 0 ) - strcpy(cType,"D"); + strcpy(cType, "D"); else - strcpy(cType,"ShortD"); + strcpy(cType, "ShortD"); break; case HB_IT_LOGICAL: - strcpy(cType,"L"); + strcpy(cType, "L"); break; case HB_IT_MEMO: if( pField->uiTypeExtended == 0 ) - strcpy(cType,"M"); + strcpy(cType, "M"); else if( pField->uiTypeExtended == ADS_VARCHAR ) - strcpy(cType,"VarC"); + strcpy(cType, "VarC"); else if( pField->uiTypeExtended == ADS_BINARY ) - strcpy(cType,"Binary"); + strcpy(cType, "Binary"); else if( pField->uiTypeExtended == ADS_IMAGE ) - strcpy(cType,"Image"); + strcpy(cType, "Image"); break; case HB_IT_STRING: if( pField->uiTypeExtended == 0 ) - strcpy(cType,"C"); + strcpy(cType, "C"); else if( pField->uiTypeExtended == ADS_RAW ) - strcpy(cType,"Raw"); + strcpy(cType, "Raw"); break; case HB_IT_INTEGER: case HB_IT_LONG: case HB_IT_DOUBLE: if( pField->uiTypeExtended == 0 ) - strcpy(cType,"N"); + strcpy(cType, "N"); else if( pField->uiTypeExtended == ADS_INTEGER ) - strcpy(cType,"Int"); + strcpy(cType, "Int"); else if( pField->uiTypeExtended == ADS_SHORTINT ) - strcpy(cType,"ShortI"); + strcpy(cType, "ShortI"); else if( pField->uiTypeExtended == ADS_DOUBLE ) - strcpy(cType,"Double"); + strcpy(cType, "Double"); else if( pField->uiTypeExtended == ADS_TIME ) - strcpy(cType,"Time"); + strcpy(cType, "Time"); else if( pField->uiTypeExtended == ADS_TIMESTAMP ) - strcpy(cType,"TimeSt"); + strcpy(cType, "TimeSt"); else if( pField->uiTypeExtended == ADS_AUTOINC ) - strcpy(cType,"Auto"); + strcpy(cType, "Auto"); else if( pField->uiTypeExtended == ADS_CURDOUBLE ) - strcpy(cType,"CurD"); + strcpy(cType, "CurD"); break; } switch ( pField->uiType ) @@ -1466,7 +1548,7 @@ static ERRCODE adsCreate( ADSAREAP pArea, LPDBOPENINFO pCreateInfo) case HB_IT_MEMO: if( pField->uiTypeExtended != ADS_VARCHAR ) { - if(strlen((( PHB_DYNS ) pField->sym )->pSymbol->szName) > (unsigned int) pArea->uiMaxFieldNameLength ) + if( strlen((( PHB_DYNS ) pField->sym )->pSymbol->szName) > (unsigned int) pArea->uiMaxFieldNameLength ) { ucField[0]='\0'; strncat((char*)ucField, (( PHB_DYNS ) pField->sym )->pSymbol->szName, @@ -1479,7 +1561,7 @@ static ERRCODE adsCreate( ADSAREAP pArea, LPDBOPENINFO pCreateInfo) break; } default : - if(strlen((( PHB_DYNS ) pField->sym )->pSymbol->szName) > (unsigned int) pArea->uiMaxFieldNameLength ) + if( strlen( ( ( PHB_DYNS ) pField->sym )->pSymbol->szName) > (unsigned int) pArea->uiMaxFieldNameLength ) { ucField[0]='\0'; strncat((char*)ucField, (( PHB_DYNS ) pField->sym )->pSymbol->szName, @@ -1547,10 +1629,10 @@ static ERRCODE adsInfo( ADSAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) puLocks = (UNSIGNED32 *) hb_xgrab( (uiIndex + 1) * sizeof( UNSIGNED32 ) ); AdsGetAllLocks(pArea->hTable, puLocks, &uiIndex); - if(uiIndex) + if( uiIndex ) { hb_arraySize( pItem, uiIndex ); - for(uiCount=0; uiCount < uiIndex; uiCount++) + for( uiCount=0; uiCount < uiIndex; uiCount++ ) hb_itemPutNL( hb_arrayGetItemPtr( pItem, (ULONG) uiCount+1 ), puLocks[ uiCount ] ); } @@ -1568,8 +1650,7 @@ static ERRCODE adsInfo( ADSAREAP pArea, USHORT uiIndex, PHB_ITEM pItem ) { UNSIGNED8 aucBuffer[MAX_STR_LEN + 1]; UNSIGNED16 pusLen = MAX_STR_LEN; - AdsGetTableFilename (pArea->hTable, - ADS_FULLPATHNAME, aucBuffer, &pusLen); + AdsGetTableFilename (pArea->hTable, ADS_FULLPATHNAME, aucBuffer, &pusLen); hb_itemPutCL( pItem, (char*)aucBuffer, pusLen ); break; } @@ -1643,15 +1724,15 @@ static ERRCODE adsNewArea( ADSAREAP pArea ) /* Size for deleted records flag */ pArea->uiRecordLen = 1; - pArea->uiMaxFieldNameLength = (pArea->iFileType == ADS_ADT) ? ADS_MAX_FIELD_NAME : ADS_MAX_DBF_FIELD_NAME; pArea->iFileType = adsFileType; + pArea->uiMaxFieldNameLength = (pArea->iFileType == ADS_ADT) ? ADS_MAX_FIELD_NAME : ADS_MAX_DBF_FIELD_NAME; return SUCCESS; } static ERRCODE adsOpen( ADSAREAP pArea, LPDBOPENINFO pOpenInfo ) { - ADSHANDLE hTable; + ADSHANDLE hTable = 0; UNSIGNED32 ulRetVal, pulLength, ulRecCount; USHORT uiFields, uiCount; UNSIGNED8 szName[ ADS_MAX_FIELD_NAME + 1 ]; @@ -1717,13 +1798,15 @@ static ERRCODE adsOpen( ADSAREAP pArea, LPDBOPENINFO pOpenInfo ) AdsGetFieldLength( pArea->hTable, szName, &pulLength ); dbFieldInfo.uiLen = ( USHORT ) pulLength; dbFieldInfo.uiDec = 0; - if( pulLength > pArea->maxFieldLen ) pArea->maxFieldLen = pulLength; + if( pulLength > pArea->maxFieldLen ) + pArea->maxFieldLen = pulLength; dbFieldInfo.uiTypeExtended = pusType; switch( pusType ) { case ADS_STRING: dbFieldInfo.uiTypeExtended = 0; + case ADS_RAW: dbFieldInfo.uiType = HB_IT_STRING; break; @@ -1989,8 +2072,7 @@ static ERRCODE adsOrderListFocus( ADSAREAP pArea, LPDBORDERINFO pOrderInfo ) strncpy( ( char * ) pucTagName, pSrc, ulLen); pucTagName[ulLen] = '\0'; - ulRetVal = AdsGetIndexHandle( pArea->hTable, - pucTagName, &phIndex ); + ulRetVal = AdsGetIndexHandle( pArea->hTable, pucTagName, &phIndex ); } if( ulRetVal != AE_SUCCESS ) return FAILURE; @@ -2105,7 +2187,8 @@ static ERRCODE adsOrderCreate( ADSAREAP pArea, LPDBORDERCREATEINFO pOrderInfo ) { commonError( pArea, EG_CREATE, ( USHORT ) ulRetVal, (char*) pOrderInfo->abBagName ); return FAILURE; - }else + } + else pArea->hOrdCurrent = phIndex; if( pArea->lpdbOrdCondInfo && !pArea->lpdbOrdCondInfo->fAll && @@ -2236,7 +2319,8 @@ static ERRCODE adsOrderInfo( ADSAREAP pArea, USHORT uiIndex, LPDBORDERINFO pOrde default: hb_itemPutC( pOrderInfo->itmResult, "" ); } - }else + } + else hb_itemPutC( pOrderInfo->itmResult, "" ); break; @@ -2252,7 +2336,7 @@ static ERRCODE adsOrderInfo( ADSAREAP pArea, USHORT uiIndex, LPDBORDERINFO pOrde case DBOI_KEYVAL: if ( !pArea->fEof && phIndex ) { - AdsExtractKey( phIndex, aucBuffer, &pusLen); + 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 @@ -2281,9 +2365,10 @@ static ERRCODE adsOrderInfo( ADSAREAP pArea, USHORT uiIndex, LPDBORDERINFO pOrde aucBuffer[pus16] = (SIGNED8) 0x5C - aucBuffer[pus16++]; } - hb_itemPutND( pOrderInfo->itmResult, hb_strVal((char*)aucBuffer, pusLen)); - }else + hb_itemPutND( pOrderInfo->itmResult, hb_strVal((char*)aucBuffer, pusLen)); + } + else { /* ADS_CDX, ADS_ADT */ double nValue; FoxToDbl(aucBuffer, &nValue); @@ -2305,16 +2390,23 @@ static ERRCODE adsOrderInfo( ADSAREAP pArea, USHORT uiIndex, LPDBORDERINFO pOrde default: hb_itemPutC( pOrderInfo->itmResult, "" ); } - }else + } + else hb_itemPutC( pOrderInfo->itmResult, "" ); break; case DBOI_POSITION : if( phIndex ) - AdsGetKeyNum ( phIndex, ADS_RESPECTFILTERS, &pul32); + { + UNSIGNED16 usFilterOption = ( pArea->dbfi.itmCobExpr ? ADS_RESPECTFILTERS : ADS_RESPECTSCOPES ) ; + AdsGetKeyNum( phIndex, usFilterOption, &pul32 ); + } else - AdsGetRecordNum ( pArea->hTable, ADS_RESPECTFILTERS, &pul32); + { + UNSIGNED16 usFilterOption = ( pArea->dbfi.itmCobExpr ? ADS_RESPECTFILTERS : ADS_IGNOREFILTERS ) ; + AdsGetRecordNum( pArea->hTable, usFilterOption, &pul32 ); + } /* TODO: This count will be wrong if server doesn't know full filter! */ @@ -2373,7 +2465,8 @@ static ERRCODE adsOrderInfo( ADSAREAP pArea, USHORT uiIndex, LPDBORDERINFO pOrde AdsOpenIndex (pArea->hTable, (UNSIGNED8*) hb_itemGetCPtr( pOrderInfo->atomBagName ), NULL, &pus16); - }else /* no specific bag requested; get all current indexes */ + } + else /* no specific bag requested; get all current indexes */ { AdsGetNumIndexes(pArea->hTable, &pus16); } @@ -2405,7 +2498,8 @@ static ERRCODE adsOrderInfo( ADSAREAP pArea, USHORT uiIndex, LPDBORDERINFO pOrde } else /* no scope set */ AdsGetRecordCount ( phIndex, ADS_RESPECTFILTERS, &pul32); - }else + } + else AdsGetRecordCount( pArea->hTable, ADS_RESPECTFILTERS, &pul32); hb_itemPutNL(pOrderInfo->itmResult, pul32); @@ -2503,7 +2597,6 @@ DBOI_AUTOSHARE static ERRCODE adsClearFilter( ADSAREAP pArea ) { - HB_TRACE(HB_TR_DEBUG, ("adsClearFilter(%p)", pArea)); /* We don't know if an AOF was used. @@ -2590,7 +2683,7 @@ static ERRCODE adsSetFilter( ADSAREAP pArea, LPDBFILTERINFO pFilterInfo ) --------------------------------------------------*/ /* must do this first as it calls clearFilter */ - if (SUPER_SETFILTER( ( AREAP ) pArea, pFilterInfo ) == SUCCESS ) + if( SUPER_SETFILTER( ( AREAP ) pArea, pFilterInfo ) == SUCCESS ) { AdsIsExprValid( pArea->hTable, (UNSIGNED8*) hb_itemGetCPtr( pFilterInfo->abFilterText), (UNSIGNED16*) &bValidExpr ); @@ -2995,20 +3088,20 @@ HB_FUNC( ADSSETRELKEYPOS ) pArea = (ADSAREAP) hb_rddGetCurrentWorkAreaPointer(); if( pArea ) { - if ( pdPos >= 1.0) + if ( pdPos >= 1.0 ) adsGoBottom( pArea ) ; - else if ( pdPos <= 0) + else if ( pdPos <= 0 ) adsGoTop( pArea ) ; else { if ( pArea->hOrdCurrent ) - hb_retnl(AdsSetRelKeyPos ( pArea->hOrdCurrent, pdPos)) ; + hb_retnl( AdsSetRelKeyPos( pArea->hOrdCurrent, pdPos) ) ; else { ULONG ulRecCount; AdsGetRecordCount( pArea->hTable, ADS_IGNOREFILTERS, &ulRecCount ); if ( ulRecCount > 0 ) - hb_retnl(AdsGotoRecord( pArea->hTable, (ULONG) (ulRecCount * pdPos) ) ); + hb_retnl( AdsGotoRecord( pArea->hTable, (ULONG) (ulRecCount * pdPos) ) ); else { if ( pArea->fEof ) diff --git a/harbour/contrib/rdd_ads/adsfunc.c b/harbour/contrib/rdd_ads/adsfunc.c index 48dafb0654..4c5683b6d4 100644 --- a/harbour/contrib/rdd_ads/adsfunc.c +++ b/harbour/contrib/rdd_ads/adsfunc.c @@ -73,9 +73,21 @@ int adsRights = 1; int adsCharType = ADS_ANSI; ADSHANDLE adsConnectHandle = 0; BOOL bDictionary = FALSE; /* Use Data Dictionary? */ +BOOL bTestRecLocks = FALSE; /* Debug Implicit locks */ PHB_ITEM itmCobCallBack = 0; + +HB_FUNC( ADSTESTRECLOCKS ) /* Debug Implicit locks Set/Get call */ +{ + BOOL oldSetting = bTestRecLocks; + + if( ISLOG(1) ) + bTestRecLocks = hb_parl( 1 ); + + hb_retl( oldSetting ); +} + HB_FUNC( ADSSETFILETYPE ) { int fileType, oldType = adsFileType; @@ -171,6 +183,35 @@ HB_FUNC( ADSISSERVERLOADED ) hb_retnl( pusConnectType ); } */ +HB_FUNC( ADSGETSERVERTIME ) +{ + + UNSIGNED32 ulRetVal ; + UNSIGNED8 pucDateBuf[ 16 ]; + UNSIGNED8 pucTimeBuf[ 16 ]; + + UNSIGNED16 pusDateBufLen = 16; + UNSIGNED16 pusTimeBufLen = 16; + + SIGNED32 plTime = 0; + + ADSHANDLE hConnect = ISNUM( 1 ) ? hb_parnl( 1 ) : adsConnectHandle; + + ulRetVal = AdsGetServerTime( hConnect, pucDateBuf, &pusDateBufLen, &plTime, pucTimeBuf, &pusTimeBufLen ); + + if( ulRetVal == AE_SUCCESS ) + { + hb_reta( 3 ) ; + hb_storc( (char * )pucDateBuf, -1, 1 ); + hb_storc( (char *) pucTimeBuf, -1, 2 ); + hb_stornl( plTime, -1, 3 ); + } else + { + AdsShowError( (UNSIGNED8 *) "AdsGetServerTime error:" ); + hb_ret(); + } +} + HB_FUNC( ADSISTABLELOCKED ) { UNSIGNED32 ulRetVal ; @@ -243,6 +284,16 @@ HB_FUNC( ADSSETCHARTYPE ) return; } +// return whether the current table is opened with OEM or ANSI character set +HB_FUNC( ADSGETTABLECHARTYPE ) +{ + UNSIGNED16 usCharType; + ADSAREAP pArea = (ADSAREAP) hb_rddGetCurrentWorkAreaPointer(); + AdsGetTableCharType(pArea->hTable, &usCharType ); + hb_retni( usCharType ); + return; +} + HB_FUNC( ADSSETDEFAULT ) { UNSIGNED8 pucDefault[ MAX_STR_LEN+1]; @@ -1332,61 +1383,6 @@ HB_FUNC( ADSSHOWERROR ) AdsShowError( pucTitle ); } -HB_FUNC( ADSGETNUMACTIVELINKS ) -{ - UNSIGNED16 pusNumLinks = 0; - - if( adsConnectHandle ) - { - AdsGetNumActiveLinks( adsConnectHandle, &pusNumLinks ); - } - hb_retnl( pusNumLinks ); -} - -#ifdef ADS_REQUIRE_VERSION6 - -HB_FUNC(ADSADDTABLE) -{ - UNSIGNED32 ulRetVal; - UNSIGNED8 *pTableName = hb_parc( 1 ); - UNSIGNED8 *pTableFileName = hb_parc( 2 ); - UNSIGNED8 *pTableIndexFileName = hb_parc( 3 ); - - ulRetVal= AdsDDAddTable( adsConnectHandle, pTableName, pTableFileName, adsFileType, adsCharType, pTableIndexFileName, NULL); - - if ( ulRetVal == AE_SUCCESS ) - hb_retl(1); - else - hb_retl(0); -} - -HB_FUNC( ADSADDUSERTOGROUP ) -{ - UNSIGNED32 ulRetVal; - UNSIGNED8 *pGroup = hb_parc( 1 ); - UNSIGNED8 *pName = hb_parc( 2 ); - - ulRetVal = AdsDDAddUserToGroup( adsConnectHandle, - pGroup, - pName); - - if ( ulRetVal == AE_SUCCESS ) - hb_retl(1); - else - hb_retl(0); -} - -HB_FUNC( ADSUSEDICTIONARY ) -{ - BOOL bOld = bDictionary; - if ( ISLOG( 1 ) ) - bDictionary = hb_parl( 1 ) ; - - hb_retl(bOld); -} - -#endif - HB_FUNC( ADSBEGINTRANSACTION ) { ADSHANDLE hConnect = ISNUM( 1 ) ? hb_parnl( 1 ) : 0; @@ -1463,6 +1459,29 @@ HB_FUNC( ADSCACHERECORDS ) hb_retl( ulRetVal ); } +/* + Reindex all tags of the currently selected table + Returns true if successful, false if fails. + Error code available by calling AdsGetLastError() +*/ + +HB_FUNC( ADSREINDEX ) +{ + UNSIGNED32 ulRetVal ; + ADSAREAP pArea; + + pArea = (ADSAREAP) hb_rddGetCurrentWorkAreaPointer(); + if( pArea ) + ulRetVal = AdsReindex( pArea->hTable); + else + ulRetVal = AdsReindex( -1 ); // should return error! + + if( ulRetVal == AE_SUCCESS ) + hb_retl( 1 ); + else + hb_retl( 0 ); +} + HB_FUNC( ADSVERSION ) { int iVersionType = ISNUM(1) ? hb_parni(1) : 0; @@ -1487,6 +1506,324 @@ HB_FUNC( ADSVERSION ) ucVersion[0] = 0; } - hb_retc(ucVersion); + hb_retc( ucVersion ); } +#ifdef ADS_REQUIRE_VERSION6 + +HB_FUNC( ADSGETNUMACTIVELINKS ) // requires 6.2 ! +{ + UNSIGNED16 pusNumLinks = 0; + + if( adsConnectHandle ) + { + AdsGetNumActiveLinks( adsConnectHandle, &pusNumLinks ); + } + hb_retnl( pusNumLinks ); +} + +HB_FUNC( ADSDDADDTABLE ) +{ + UNSIGNED32 ulRetVal; + UNSIGNED8 *pTableName = hb_parc( 1 ); + UNSIGNED8 *pTableFileName = hb_parc( 2 ); + UNSIGNED8 *pTableIndexFileName = hb_parc( 3 ); + + ulRetVal= AdsDDAddTable( adsConnectHandle, pTableName, pTableFileName, adsFileType, adsCharType, pTableIndexFileName, NULL); + + if ( ulRetVal == AE_SUCCESS ) + hb_retl(1); + else + hb_retl(0); +} + +HB_FUNC( ADSDDADDUSERTOGROUP ) +{ + UNSIGNED32 ulRetVal; + UNSIGNED8 *pGroup = hb_parc( 1 ); + UNSIGNED8 *pName = hb_parc( 2 ); + + ulRetVal = AdsDDAddUserToGroup( adsConnectHandle, + pGroup, + pName); + + if ( ulRetVal == AE_SUCCESS ) + hb_retl(1); + else + hb_retl(0); +} + +HB_FUNC( ADSUSEDICTIONARY ) +{ + BOOL bOld = bDictionary; + if ( ISLOG( 1 ) ) + bDictionary = hb_parl( 1 ) ; + + hb_retl(bOld); +} + +HB_FUNC( ADSCONNECT60 ) +{ + UNSIGNED32 ulRetVal ; + UNSIGNED8 *pucServerPath = hb_parc( 1 ); + UNSIGNED16 usServerTypes = hb_parnl( 2 ); + UNSIGNED8 *pucUserName = ISCHAR( 3 ) ? hb_parc( 3 ) : NULL ; + UNSIGNED8 *pucPassword = ISCHAR( 4 ) ? hb_parc( 4 ) : NULL ; + UNSIGNED32 ulOptions = ISNUM( 5 ) ? hb_parnl( 5 ) : ADS_DEFAULT ; + + ulRetVal = AdsConnect60( pucServerPath, + usServerTypes, + pucUserName, + pucPassword, + ulOptions, + &adsConnectHandle ); + + if( ulRetVal == AE_SUCCESS ) + hb_retl( 1 ) ; + else + hb_retl( 0 ) ; + +} + +HB_FUNC( ADSDDCREATE ) +{ + UNSIGNED32 ulRetVal; + UNSIGNED8 *pucDictionaryPath = hb_parc( 1 ) ; + UNSIGNED16 usEncrypt = ISNUM(2) ? hb_parnl( 0 ) : 0 ; + UNSIGNED8 *pucDescription = ISCHAR( 3 ) ? hb_parc( 3 ) : NULL ; + + ulRetVal = AdsDDCreate( ( UNSIGNED8 *)pucDictionaryPath, + usEncrypt, + ( UNSIGNED8 *)pucDescription, + &adsConnectHandle ); + + if( ulRetVal == AE_SUCCESS ) + hb_retl( 1 ); + else + hb_retl( 0 ); + +} + +HB_FUNC( ADSDDCREATEUSER ) +{ + UNSIGNED32 ulRetVal; + UNSIGNED8 *pucGroupName = ISCHAR(1) ? hb_parc(1) : NULL; + UNSIGNED8 *pucUserName = ISCHAR(2) ? hb_parc(2) : NULL; + UNSIGNED8 *pucPassword = ISCHAR(3) ? hb_parc(3) : NULL; + UNSIGNED8 *pucDescription = ISCHAR(4) ? hb_parc(4) : NULL; + ulRetVal = AdsDDCreateUser( adsConnectHandle, pucGroupName, + pucUserName, pucPassword, pucDescription ); + hb_retl( ulRetVal == AE_SUCCESS ); +} + +HB_FUNC( ADSDDGETDATABASEPROPERTY ) +{ + #define ADS_MAX_PARAMDEF_LEN 2048 + UNSIGNED16 ulProperty = ( UNSIGNED16 ) hb_parni( 1 ); + char sBuffer[ADS_MAX_PARAMDEF_LEN]; + UNSIGNED16 ulLength; + UNSIGNED16 ulBuffer; + BOOL bChar = FALSE ; + + + switch ( ulProperty ) + { + case ADS_DD_COMMENT: + case ADS_DD_DEFAULT_TABLE_PATH: + case ADS_DD_USER_DEFINED_PROP: + case ADS_DD_TEMP_TABLE_PATH: + case ADS_DD_VERSION: + { + ulLength = ADS_MAX_PARAMDEF_LEN ; + AdsDDGetDatabaseProperty( adsConnectHandle, ulProperty, &sBuffer, &ulLength ); + bChar = TRUE ; + break; + } + case ADS_DD_LOG_IN_REQUIRED: + case ADS_DD_VERIFY_ACCESS_RIGHTS: + case ADS_DD_ENCRYPT_TABLE_PASSWORD: + case ADS_DD_ENCRYPT_NEW_TABLE: + { + ulLength = sizeof( UNSIGNED16 ); + AdsDDGetDatabaseProperty( adsConnectHandle, ulProperty, &ulBuffer, &ulLength ); + break; + } + } + + if( ulProperty == ADS_DD_LOG_IN_REQUIRED || ulProperty == ADS_DD_VERIFY_ACCESS_RIGHTS || ulProperty == ADS_DD_ENCRYPT_NEW_TABLE ) + hb_retl( ulBuffer ); + else if( bChar ) + hb_retclen( sBuffer, ulLength ); + else + hb_retnl( ulBuffer ); +} + +HB_FUNC( ADSDDSETDATABASEPROPERTY ) +{ + char * szProperty; + UNSIGNED16 ulLength; + UNSIGNED32 ulRetVal; + UNSIGNED16 ulBuffer; + UNSIGNED16 ulProperty = ( UNSIGNED16 ) hb_parni( 1 ); + PHB_ITEM pParam = hb_param( 2, HB_IT_ANY ) ; + + switch( ulProperty ) + { + case ADS_DD_COMMENT: + case ADS_DD_DEFAULT_TABLE_PATH: + case ADS_DD_USER_DEFINED_PROP: + case ADS_DD_TEMP_TABLE_PATH: + case ADS_DD_ADMIN_PASSWORD: + case ADS_DD_ENCRYPT_TABLE_PASSWORD: + { + ulRetVal = AdsDDSetDatabaseProperty( adsConnectHandle, ulProperty, hb_itemGetCPtr( pParam ), hb_itemGetCLen( pParam ) ); + break; + } + case ADS_DD_MAX_FAILED_ATTEMPTS: + case ADS_DD_INTERNET_SECURITY_LEVEL: + case ADS_DD_VERSION_MAJOR: + case ADS_DD_VERSION_MINOR: + { + ulBuffer = hb_itemGetNI( pParam ); + ulRetVal = AdsDDSetDatabaseProperty( adsConnectHandle, ulProperty, &ulBuffer, 2 ); + break; + } + case ADS_DD_LOG_IN_REQUIRED: + case ADS_DD_VERIFY_ACCESS_RIGHTS: + case ADS_DD_ENCRYPT_NEW_TABLE: + case ADS_DD_ENABLE_INTERNET: + { + ulBuffer = hb_itemGetL( pParam ); + ulRetVal = AdsDDSetDatabaseProperty( adsConnectHandle, ulProperty, &ulBuffer, 2 ); + break; + } + } + hb_retl( ulRetVal == AE_SUCCESS ); +} + +/* +UNSIGNED32 ENTRYPOINT AdsDDGetUserProperty( ADSHANDLE hObject, + UNSIGNED8 *pucUserName, + UNSIGNED16 usPropertyID, + VOID *pvProperty, + UNSIGNED16 *pusPropertyLen ); +*/ +HB_FUNC( ADSDDGETUSERPROPERTY ) +{ + UNSIGNED32 ulRetVal; + UNSIGNED8 *pucUserName = hb_parc(1); + UNSIGNED16 usPropertyID = hb_parni(2); + UNSIGNED8 *pvProperty = hb_parc(3); + UNSIGNED16 usPropertyLen = hb_parni(4); + ulRetVal = AdsDDGetUserProperty( adsConnectHandle, pucUserName, usPropertyID, + pvProperty, &usPropertyLen ); + hb_retl( ulRetVal == AE_SUCCESS ); +} +/* + Verify if a username/password combination is valid for this database + Call : ADSTESTLOGIN(serverpath,servertypes,username,password,options, + [userproperty,buffer,bufferlength]) + Returns : True if login succeeds + + Notes: This creates a temporary connection only during the execution of this + function, without disturbing the stored one for any existing connection + + If the optional last 3 parameters are supplied, then it queries the + requested user property and returns it in the buffer. This is useful + fo example to get the groups of which the user is a member +*/ + +HB_FUNC( ADSTESTLOGIN ) +{ + UNSIGNED32 ulRetVal ; + UNSIGNED8 *pucServerPath = hb_parc( 1 ); + UNSIGNED16 usServerTypes = hb_parnl( 2 ); + UNSIGNED8 *pucUserName = ISCHAR( 3 ) ? hb_parc( 3 ) : NULL ; + UNSIGNED8 *pucPassword = ISCHAR( 4 ) ? hb_parc( 4 ) : NULL ; + UNSIGNED32 ulOptions = ISNUM( 5 ) ? hb_parnl( 5 ) : ADS_DEFAULT ; + UNSIGNED16 usPropertyID = ISNUM( 6 ) ? hb_parni( 6 ) : 0; + UNSIGNED8 *pvProperty = ISCHAR( 7 ) ? hb_parc( 7 ) : NULL ; + UNSIGNED16 usPropertyLen = ISNUM( 8 ) ? hb_parni( 8 ) : 0; + ADSHANDLE adsTestHandle; + + ulRetVal = AdsConnect60( pucServerPath, + usServerTypes, + pucUserName, + pucPassword, + ulOptions, + &adsTestHandle ); + + if( ulRetVal == AE_SUCCESS ) + { + if( usPropertyLen > 0 ) + AdsDDGetUserProperty( adsTestHandle, pucUserName, usPropertyID, + pvProperty, &usPropertyLen ); + AdsDisconnect( adsTestHandle ); + hb_retl( 1 ) ; + } + else + hb_retl( 0 ) ; +} + +HB_FUNC( ADSRESTRUCTURETABLE ) +{ + // call: + // AdsRestructureTable( cTable, cAddFields, cDeleteFields, cChangeFields ) + + //UNSIGNED32 AdsRestructureTable( ADSHANDLE hConnect,UNSIGNED8 *pucName, + // UNSIGNED8 *pucAlias,UNSIGNED16 usTableType,UNSIGNED16 usCharType, + // UNSIGNED16 usLockType,UNSIGNED16 usCheckRights,UNSIGNED8 + // *pucAddFields,UNSIGNED8 *pucDeleteFields,UNSIGNED8 *pucChangeFields ); + //adsFileType ADS_DEFAULT, ADS_ADT, ADS_NTX and ADS_CDX + + UNSIGNED32 ulRetVal; + UNSIGNED8 *pTableName = hb_parc( 1 ); + UNSIGNED8 *pucAddFields = hb_parc( 2 ); + UNSIGNED8 *pucDeleteFields = hb_parc( 3 ); + UNSIGNED8 *pucChangeFields = hb_parc( 4 ); + + + ulRetVal = AdsRestructureTable( adsConnectHandle, pTableName, NULL, + adsFileType, adsCharType, adsLockType, + adsRights, + pucAddFields, + pucDeleteFields, + pucChangeFields ); + + + hb_retl( (long) ulRetVal ); +} + +HB_FUNC( ADSCOPYTABLECONTENTS ) +{ + ADSAREAP pArea; + ADSAREAP pDest; + UNSIGNED32 ulRetVal; + char * szAlias = hb_parc(1); + + pArea = (ADSAREAP) hb_rddGetCurrentWorkAreaPointer(); // Source + if( pArea ) + { + if( hb_rddSelectWorkAreaAlias(szAlias) == SUCCESS ) + { + pDest = (ADSAREAP) hb_rddGetCurrentWorkAreaPointer(); // Destination + if (pDest) + { + ulRetVal = AdsCopyTableContents( pArea->hTable, + pDest->hTable, + ADS_IGNOREFILTERS ); + if ( ulRetVal == AE_SUCCESS ) + hb_retl(1); + else + hb_retl(0); + } + } + else + hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, "ADSCOPYTABLECONTENTS" ); + } + else + hb_errRT_DBCMD( EG_NOTABLE, 2001, NULL, " ADSCOPYTABLECONTENTS" ); +} + +#endif /* ADS_REQUIRE_VERSION6 */ +/* Please add all-version functions above this block */ diff --git a/harbour/contrib/rdd_ads/adsmgmnt.c b/harbour/contrib/rdd_ads/adsmgmnt.c index bd193641c8..199ce4a6da 100644 --- a/harbour/contrib/rdd_ads/adsmgmnt.c +++ b/harbour/contrib/rdd_ads/adsmgmnt.c @@ -230,7 +230,6 @@ HB_FUNC( ADSMGGETACTIVITYINFO ) } } - } HB_FUNC( ADSMGGETCOMMSTATS ) @@ -400,12 +399,60 @@ HB_FUNC( ADSMGGETUSERNAMES ) /* Return array of connected users */ { hb_storc ( (char *) pastUserInfo[ulCount].aucUserName , -1, ulCount+1); } - }else + } + else hb_reta( 0 ); hb_xfree( pastUserInfo ); } + +HB_FUNC( ADSMGGETLOCKOWNER ) +{ + // UNSIGNED32 AdsMgGetLockOwner (ADSHANDLE hMgmtConnect, + // UNSIGNED8 *pucTableName, + // UNSIGNED32 ulRecordNumber, + // ADS_MGMT_USER_INFO *pstUserInfo, + // UNSIGNED16 *pusStructSize, + // UNSIGNED16 *pusLockType); + // + // returns an array of 5 elements if successful + // [1] Client machine name when server runs on NT/2000 + // Client Username when server runs on Netware + // [2] Netware connection number + // [3] Login user name for data dictionary connections (ADS 6.0 and above) + // [4] Client machine IP address + // [5] lock type ADS_MGMT_NO_LOCK ADS_MGMT_RECORD_LOCK ADS_MGMT_FILE_LOCK + // + // returns the advantage error code if it fails + // + UNSIGNED32 ulRetVal ; + UNSIGNED16 usStructSize = sizeof( ADS_MGMT_USER_INFO ); + UNSIGNED16 pusLockType; + ADS_MGMT_USER_INFO * pstUserInfo; + pstUserInfo = (ADS_MGMT_USER_INFO *) hb_xgrab( sizeof( ADS_MGMT_USER_INFO ) ); + + ulRetVal = AdsMgGetLockOwner( hMgmtHandle, + (UNSIGNED8 *) hb_parc( 1 ), + (UNSIGNED32) hb_parnl(2), + pstUserInfo, + &usStructSize, + &pusLockType ); + if (ulRetVal== AE_SUCCESS) + { + hb_reta(5); + hb_storc ( (char *) pstUserInfo->aucUserName , -1, 1 ); /* Machine name under NT */ + hb_stornl( (UNSIGNED16) pstUserInfo->usConnNumber, -1, 2 ); /* NetWare conn # (NLM only) */ + hb_storc ( (char *) pstUserInfo->aucAuthUserName, -1, 3 ); /* logon name with Data Dictionary */ + hb_storc ( (char *) pstUserInfo->aucAddress, -1, 4 ); /* IP adddress */ + hb_stornl( pusLockType, -1, 5 ); /* type of lock */ + } + else + { + hb_retnl ( ulRetVal ); + } +} + /* HB_FUNC( ADSMGGETOPENTABLES ) @@ -442,12 +489,6 @@ HB_FUNC( ADSMGGETWORKERTHREADACTIVITY ) AdsMgGetWorkerThreadActivity(); } -HB_FUNC( ADSMGGETLOCKOWNER ) -{ - UNSIGNED32 ulRetVal = AE_SUCCESS; - AdsMgGetLockOwner(); -} - HB_FUNC( ADSMGKILLUSER ) { UNSIGNED32 ulRetVal = AE_SUCCESS; diff --git a/harbour/contrib/rdd_ads/doc/en/adsfuncs.txt b/harbour/contrib/rdd_ads/doc/en/adsfuncs.txt index b497404a7c..3d4ae7669d 100644 --- a/harbour/contrib/rdd_ads/doc/en/adsfuncs.txt +++ b/harbour/contrib/rdd_ads/doc/en/adsfuncs.txt @@ -143,7 +143,7 @@ * ADS_AOF_ADD_RECORD Add the record to the AOF (set the bit). This is the default operation. * ADS_AOF_REMOVE_RECORD Remove the record from the AOF (clear the bit). * ADS_AOF_TOGGLE_RECORD Switch the record into or out of the AOF. - * + * * $RETURNS$ * ADS error code, or 0 for success. * $DESCRIPTION$ @@ -432,16 +432,20 @@ * $ONELINER$ * Estimated key position of current record within the specified index * $SYNTAX$ - * ADSGetRelKeyPos([]) --> nKeyPos + * ADSGetRelKeyPos() --> nKeyPos * $ARGUMENTS$ - * Index to use. Default is current index. + * None. Only accesses the current index, if any. * $RETURNS$ - * The relative key position within the current index. - * This function estimates the position of the current key in the indicated - * index order. The value returned is between 0.0 and 1.0, inclusive. - * If there are scopes set on the index order, the position returned - * is relative to the visible records. + * A value between 0.0 and 1.0, inclusive. * $DESCRIPTION$ + * This function estimates the relative key position within the current index, + * respecting any scope setting. + * It also works with no active index to yield the relative position of the + * current record number. + * The value returned is between 0.0 and 1.0, inclusive. + * + * This is the recommended function for positioning a scrollbar + * or other "coarse" position interface. * See ACE.HLP for full details about the Advantage Database Server. * $EXAMPLES$ * $TESTS$ @@ -455,7 +459,45 @@ * Library is RddAds * Header is ads.ch * $SEEALSO$ - * ADSKeyNo(),ADSKeyCount() + * ADSKeyNo(),ADSKeyCount(),ADSSetRelKeyPos() + * $END$ + */ + +/* $DOC$ + * $FUNCNAME$ + * ADSSetRelKeyPos() + * $CATEGORY$ + * Advantage Database RDD + * $ONELINER$ + * GoTo the given estimated key position within the current index + * $SYNTAX$ + * ADSSetSelKeyPos( ) --> nError + * $ARGUMENTS$ + * Relative key position between 0.0 and 1.0, inclusive. + * $RETURNS$ + * The return/error value of the ADS API call. + * $DESCRIPTION$ + * This function moves the record pointer to the estimated relative position + * within the current index order, respecting any scope setting. + * It also works with no active index to go to the relative position of the + * current record number. + * + * This is the recommended function for re-positioning in reaction to + * a dragged scrollbar thumb or other "coarse" navigation interface. + * See ACE.HLP for full details about the Advantage Database Server. + * $EXAMPLES$ + * $TESTS$ + * $STATUS$ + * R + * $COMPLIANCE$ + * Harbour extension + * $PLATFORMS$ + * Windows 32-bit + * $FILES$ + * Library is RddAds + * Header is ads.ch + * $SEEALSO$ + * ADSKeyNo(),ADSKeyCount(),ADSGetRelKeyPos() * $END$ */ @@ -535,17 +577,15 @@ * ADS_RESPECTFILTERS Respect filters and scopes * ADS_IGNOREFILTERS Ignore filters and scopes * ADS_RESPECTSCOPES Respect scopes only - + * * $RETURNS$ * The logical key number of the current record in the given index. * $DESCRIPTION$ * See ACE.HLP for full details about the Advantage Database Server. * Wrapper for AdsGetKeyNum. - This function may be slow on a large database with - ADS_RESPECTFILTERS set because it walks through the keys to get the - current position. Compare to ADSGetRelKeyPos(). - * $EXAMPLES$ - * $TESTS$ + * This function may be slow on a large database with + * ADS_RESPECTFILTERS set because it walks through the keys to get the + * current position. Compare to ADSGetRelKeyPos(). * $STATUS$ * R * $COMPLIANCE$ @@ -560,8 +600,6 @@ * $END$ */ - - /* $DOC$ * $FUNCNAME$ * ADSLocking() @@ -583,19 +621,17 @@ * The Advantage Database Server has a fast Proprietary locking mode that * is more efficient than traditional network locking. It is only available * when using the remote server (not the local server). - + * * If a file is opened in the proprietary mode, other applications cannot * open it in a "write" mode. So if non-Advantage applications need * concurrent access to the data files, use the Compatibility locking mode * by calling ADSLocking( .F. ). - + * * ADSLocking() is a Get/Set function for the locking mode. It affects * files at the time they are opened. So when a data * file is opened, the current setting is used for that file until it is * closed. Different files can have different locking modes by changing * the setting before opening a second file. - * $EXAMPLES$ - * $TESTS$ * $STATUS$ * R * $COMPLIANCE$ @@ -632,7 +668,7 @@ * Database Server will use the rights of the connected user when * opening the file. If the user does not have rights to the * directory or server, then the open call will fail. - + * * If the setting is .F., then the ADS will * ignore the connected user's rights and open the file * regardless. This lets you allow only @@ -678,7 +714,6 @@ * DLLs doing all the indexing. So to do progress meters * you need to implement this. * $EXAMPLES$ - * * FUNCTION Main() * ... * AdsRegCallBack( {|nPercent| outputstuff(nPercent)} ) @@ -693,8 +728,6 @@ * ? "output stuff", nPercent * RETURN inkey() == 27 * /* If press ESC, returns .T. to abort. */ - *
- * $TESTS$ * $STATUS$ * R * $COMPLIANCE$ @@ -958,14 +991,135 @@ * $END$ */ +/* $DOC$ + * $FUNCNAME$ + * AdsTestRecLocks() + * $CATEGORY$ + * Advantage Database RDD + * $ONELINER$ + * Turn On or Off a "debug mode" for trapping missed record locks. + * $SYNTAX$ + * AdsTestRecLocks( ) --> lPriorSetting + * $ARGUMENTS$ + * New setting. Default is FALSE. + * $RETURNS$ + * Prior Setting. + * $DESCRIPTION$ + * AdsTestRecLocks() is a Get/Set function for a "record lock checking" mode. + * ADS has Implicit Record locking that can mask programming errors. + * Implicit locking can occur the first time a value is written to a + * field with no lock in effect. The lock can potentially remain in + * effect indefinitely if the record pointer is not moved, causing + * bugs later in program execution that are hard to find. + * In Harbour internal RDDs, a runtime error occurs if an attempt is made + * to write to a shared file without a proper lock. + * + * AdsTestRecLocks( .T. ) will turn on a debugging mode to mimic this behavior + * and throw an error instead of allowing an implicit lock. Each time a field + * is set, we see if the file is open exclusively or locked, and whether + * the record has been explicitly locked already. If not, we throw + * an error so the developer can catch the missing lock condition. + * For performance reasons, Release code should leave this OFF. + * Although the call to AdsIsRecordLocked is documented as a client + * call, not a server request, and should be fast, it will be + * called for EACH FIELD as it is assigned a value. + * + * See ACE.HLP for full details about the Advantage Database Server. + * $EXAMPLES$ + * $TESTS$ + * $STATUS$ + * R + * $COMPLIANCE$ + * Harbour extension + * $PLATFORMS$ + * Windows 32-bit, Linux + * $FILES$ + * Library is RddAds + * Header is ads.ch + * $SEEALSO$ + * $END$ + */ + + +/* $DOC$ + * $FUNCNAME$ + * AdsGetLastError() + * $CATEGORY$ + * Advantage Database RDD + * $ONELINER$ + * Returns any error code generated by the most recent ADS API call + * $SYNTAX$ + * AdsGetLastError() --> nErrorCode + * $ARGUMENTS$ + * None. + * $RETURNS$ + * The error code generated by the most recent ADS API call. Zero for success. + * $DESCRIPTION$ + * See ACE.HLP for full details about the Advantage Database Server. + * $EXAMPLES$ + * $TESTS$ + * $STATUS$ + * R + * $COMPLIANCE$ + * Harbour extension + * $PLATFORMS$ + * Windows 32-bit, Linux + * $FILES$ + * Library is RddAds + * Header is ads.ch + * $SEEALSO$ + * $END$ + */ + +/* $DOC$ + * $FUNCNAME$ + * AdsIsExprValid() + * $CATEGORY$ + * Advantage Database RDD + * $ONELINER$ + * Determine if the ADS server can parse an expression + * $SYNTAX$ + * AdsIsExprValid( ) --> lSuccess + * $ARGUMENTS$ + * Any hopefully valid expression; often a filter string + * $RETURNS$ + * .T. if the expression is understood by ADS. + * $DESCRIPTION$ + * ADS has its own limitations for the logical or string expressions + * used in indexes, filters, scopes, etc. Unlike internal RDDs like DBFNTX, + * the server is independent of the applications code, so it cannot understand + * references to PUBLIC variables or User-Defined Functions (UDFs). + * (See ACE.HLP under Advantage Expression Engine for a list of functions + * allowed by ADS.) + * Call AdsIsExprValid() to determine if the server can process the expression. + * + * For illustration, consider filter expressions. + * Since Harbour attempts to be as compatible with Clipper as possible, + * you CAN set a filter that ADS DOES NOT understand, but the filtering + * will be done by the RDD layer itself and ADS will be unaware of the + * filter setting. This means more data will be sent "across the wire" from + * the server to the client, and the client (in RDDADS) will be doing the + * processing. Since the value of a database server is to have more processing + * done by the server itself to reduce network traffic, it is better to only use + * filter expressions ADS can understand. + * $EXAMPLES$ + * $TESTS$ + * $STATUS$ + * R + * $COMPLIANCE$ + * Harbour extension + * $PLATFORMS$ + * Windows 32-bit, Linux + * $FILES$ + * Library is RddAds + * Header is ads.ch + * $SEEALSO$ + * $END$ + */ /* TO-DO: -AdsIsExprValid ADSGETCONNECTIONHANDLE -AdsGetLastError -AdsSetRelKeyPos -AdsGetRelKeyPos v6: AdsAddTable diff --git a/harbour/contrib/rdd_ads/rddads.h b/harbour/contrib/rdd_ads/rddads.h index 53051bdb89..be622e1670 100644 --- a/harbour/contrib/rdd_ads/rddads.h +++ b/harbour/contrib/rdd_ads/rddads.h @@ -59,7 +59,7 @@ * Change to be one higher than the current version number in the Id string. */ -#define HB_RDD_ADS_VERSION_STRING "ADS RDD 1.12" +#define HB_RDD_ADS_VERSION_STRING "ADS RDD 1.4" /* * ADS WORKAREA @@ -125,3 +125,14 @@ typedef struct _ADSAREA_ } ADSAREA; typedef ADSAREA * ADSAREAP; + +UNSIGNED32 ENTRYPOINT AdsSetFieldRaw( ADSHANDLE hObj, + UNSIGNED8 *pucFldName, + UNSIGNED8 *pucBuf, + UNSIGNED32 ulLen ); + +UNSIGNED32 ENTRYPOINT AdsGetFieldRaw( ADSHANDLE hTbl, + UNSIGNED8 *pucFldName, + UNSIGNED8 *pucBuf, + UNSIGNED32 *pulLen ); +