2008-05-18 18:58 UTC+0100 Viktor Szakats (harbour.01 syenar hu)
+ contrib/rddads/tests/datad.prg
+ Added new test program for ADS DD/SQL functionality.
Kindly sent by Brian Hays.
NOTE: The code will show some errors on SQL execution.
I couldn't investigate, but it does the same with older
versions of rddads, too.
* contrib/rddads/ads1.c
! Two occurences of AdsShowError() calls guarded with
DEBUG. This call pops up a visual dialog box on screen
and halts execution until this is confirmed by the user.
Not very desirable inside RDD code in real life
environments. Proper error code were and are still
returned in these cases.
* contrib/rddads/adsfunc.c
* Final reformat and optimization.
! Fixed to not call AdsShowError() by default, only when
DEBUG is #define-d. For about the same reason as above.
Caller should use AdsGetLastError() to get the error
code and string and present it to the user as required.
+ QUESTIONs added.
* contrib/rddads/adsmgmnt.c
* ADSMGGETOPENTABLES() changed to return empty array
instead of error code in case of error. This way it
now behaves consistently with the rest of the mgmnt
functions. Error code and string can be get by
the caller using ADSGETLASTERROR().
+ ADSMGGETOPENTABLES2() added, which is similar to
ADSMGGETOPENTABLES(), but will also return lock type
for all tables, this way clearing a long standing
TODO in the source.
This commit is contained in:
@@ -8,6 +8,42 @@
|
||||
2008-12-31 13:59 UTC+0100 Foo Bar <foo.bar@foobar.org>
|
||||
*/
|
||||
|
||||
2008-05-18 18:58 UTC+0100 Viktor Szakats (harbour.01 syenar hu)
|
||||
+ contrib/rddads/tests/datad.prg
|
||||
+ Added new test program for ADS DD/SQL functionality.
|
||||
Kindly sent by Brian Hays.
|
||||
NOTE: The code will show some errors on SQL execution.
|
||||
I couldn't investigate, but it does the same with older
|
||||
versions of rddads, too.
|
||||
|
||||
* contrib/rddads/ads1.c
|
||||
! Two occurences of AdsShowError() calls guarded with
|
||||
DEBUG. This call pops up a visual dialog box on screen
|
||||
and halts execution until this is confirmed by the user.
|
||||
Not very desirable inside RDD code in real life
|
||||
environments. Proper error code were and are still
|
||||
returned in these cases.
|
||||
|
||||
* contrib/rddads/adsfunc.c
|
||||
* Final reformat and optimization.
|
||||
! Fixed to not call AdsShowError() by default, only when
|
||||
DEBUG is #define-d. For about the same reason as above.
|
||||
Caller should use AdsGetLastError() to get the error
|
||||
code and string and present it to the user as required.
|
||||
+ QUESTIONs added.
|
||||
|
||||
* contrib/rddads/adsmgmnt.c
|
||||
* ADSMGGETOPENTABLES() changed to return empty array
|
||||
instead of error code in case of error. This way it
|
||||
now behaves consistently with the rest of the mgmnt
|
||||
functions. Error code and string can be get by
|
||||
the caller using ADSGETLASTERROR().
|
||||
+ ADSMGGETOPENTABLES2() added, which is similar to
|
||||
ADSMGGETOPENTABLES(), but will also return lock type
|
||||
for all tables, this way clearing a long standing
|
||||
TODO in the source.
|
||||
|
||||
|
||||
2008-05-18 09:22 UTC+0100 Viktor Szakats (harbour.01 syenar hu)
|
||||
* contrib/rddads/adsfunc.c
|
||||
+ QUESTION added.
|
||||
|
||||
@@ -2710,7 +2710,9 @@ static ERRCODE adsCreate( ADSAREAP pArea, LPDBOPENINFO pCreateInfo )
|
||||
|
||||
if( uRetVal != AE_SUCCESS )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
AdsShowError( ( UNSIGNED8 * ) "Error" );
|
||||
#endif
|
||||
return FAILURE;
|
||||
}
|
||||
/*
|
||||
@@ -4485,7 +4487,9 @@ static ERRCODE adsLock( ADSAREAP pArea, LPDBLOCKINFO pLockInfo )
|
||||
|
||||
default :
|
||||
/* This should probably throw a real error... */
|
||||
#ifdef DEBUG
|
||||
AdsShowError( ( UNSIGNED8 * ) "Error in pLockInfo->uiMethod" );
|
||||
#endif
|
||||
pLockInfo->fResult = FALSE;
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -439,21 +439,18 @@ HB_FUNC( ADSMGGETUSERNAMES )
|
||||
*/
|
||||
HB_FUNC( ADSMGGETLOCKOWNER )
|
||||
{
|
||||
UNSIGNED32 ulRetVal;
|
||||
UNSIGNED16 pusLockType;
|
||||
UNSIGNED16 pusLockType = 0;
|
||||
UNSIGNED16 usStructSize = sizeof( ADS_MGMT_USER_INFO );
|
||||
ADS_MGMT_USER_INFO * pstUserInfo;
|
||||
|
||||
pstUserInfo = ( ADS_MGMT_USER_INFO * ) hb_xgrab( sizeof( ADS_MGMT_USER_INFO ) );
|
||||
|
||||
ulRetVal = AdsMgGetLockOwner( s_hMgmtHandle,
|
||||
( UNSIGNED8 * ) hb_parcx( 1 ) /* pucTableName */,
|
||||
( UNSIGNED32 ) hb_parnl( 2 ) /* ulRecordNumber */,
|
||||
pstUserInfo,
|
||||
&usStructSize,
|
||||
&pusLockType );
|
||||
|
||||
if( ulRetVal == AE_SUCCESS )
|
||||
if( AdsMgGetLockOwner( s_hMgmtHandle,
|
||||
( UNSIGNED8 * ) hb_parcx( 1 ) /* pucTableName */,
|
||||
( UNSIGNED32 ) hb_parnl( 2 ) /* ulRecordNumber */,
|
||||
pstUserInfo,
|
||||
&usStructSize,
|
||||
&pusLockType ) == AE_SUCCESS )
|
||||
{
|
||||
hb_reta( 5 );
|
||||
hb_storc( ( char * ) pstUserInfo->aucUserName , -1, 1 ); /* Machine name under NT */
|
||||
@@ -468,7 +465,7 @@ HB_FUNC( ADSMGGETLOCKOWNER )
|
||||
hb_stornl( pusLockType, -1, 5 ); /* type of lock */
|
||||
}
|
||||
else
|
||||
hb_retnl( ulRetVal );
|
||||
hb_reta( 0 );
|
||||
|
||||
hb_xfree( pstUserInfo );
|
||||
|
||||
@@ -478,11 +475,8 @@ HB_FUNC( ADSMGGETLOCKOWNER )
|
||||
#endif
|
||||
}
|
||||
|
||||
/* TODO: We're throwing away the locktype info. First edition
|
||||
* should have returned a 2-dim array. Perhaps see if a 4th arg
|
||||
* is passed as an (empty) array, if so populate parallel array
|
||||
* of locktypes. OR pass a logical to tell it to return 2-dim array.
|
||||
*/
|
||||
/* NOTE: For a newer edition of this function, which also returns locktype
|
||||
info, see ADSMGGETOPENTABLES2(). */
|
||||
HB_FUNC( ADSMGGETOPENTABLES ) /* nMaxNumberOfFilesToReturn, cUserName, nConnection */
|
||||
{
|
||||
UNSIGNED16 usArrayLen = ISNUM( 1 ) ? ( UNSIGNED16 ) hb_parni( 1 ) : 300;
|
||||
@@ -502,10 +496,50 @@ HB_FUNC( ADSMGGETOPENTABLES ) /* nMaxNumberOfFilesToReturn, cUserName, nConnecti
|
||||
UNSIGNED16 ulCount;
|
||||
|
||||
for( ulCount = 1; ulCount <= usArrayLen; ulCount++ )
|
||||
{
|
||||
hb_itemPutC( hb_arrayGetItemPtr( pArray, ( ULONG ) ulCount ), ( char * ) astOpenTableInfo[ ulCount - 1 ].aucTableName );
|
||||
/* UNSIGNED16 astOpenTableInfo[ ulCount - 1 ].usLockType; */ /* Advantage locking mode */
|
||||
|
||||
hb_itemReturnRelease( pArray );
|
||||
}
|
||||
else
|
||||
hb_reta( 0 );
|
||||
|
||||
hb_xfree( astOpenTableInfo );
|
||||
|
||||
#if HB_TR_LEVEL >= HB_TR_INFO
|
||||
if( usStructSize > sizeof( ADS_MGMT_TABLE_INFO ) )
|
||||
HB_TRACE(HB_TR_INFO, ("%s returned extra data; available with newer client lib.", "AdsMgGetOpenTables()"));
|
||||
#endif
|
||||
}
|
||||
|
||||
HB_FUNC( ADSMGGETOPENTABLES2 ) /* nMaxNumberOfFilesToReturn, cUserName, nConnection */
|
||||
{
|
||||
UNSIGNED16 usArrayLen = ISNUM( 1 ) ? ( UNSIGNED16 ) hb_parni( 1 ) : 300;
|
||||
UNSIGNED16 usStructSize = sizeof( ADS_MGMT_TABLE_INFO );
|
||||
ADS_MGMT_TABLE_INFO * astOpenTableInfo;
|
||||
|
||||
astOpenTableInfo = ( ADS_MGMT_TABLE_INFO * ) hb_xgrab( sizeof( ADS_MGMT_TABLE_INFO ) * usArrayLen );
|
||||
|
||||
if( AdsMgGetOpenTables( s_hMgmtHandle,
|
||||
( UNSIGNED8 * ) ( hb_parclen( 2 ) > 0 ? hb_parc( 2 ) : NULL ) /* pucUserName */,
|
||||
( UNSIGNED16 ) hb_parni( 3 ) /* usConnNumber */, /* = HB_ADS_PARCONNECTION( 3 ) only valid for netware so don't default to current, only take a passed value */
|
||||
astOpenTableInfo,
|
||||
&usArrayLen,
|
||||
&usStructSize ) == AE_SUCCESS )
|
||||
{
|
||||
PHB_ITEM pArray = hb_itemArrayNew( usArrayLen );
|
||||
UNSIGNED16 ulCount;
|
||||
|
||||
for( ulCount = 1; ulCount <= usArrayLen; ulCount++ )
|
||||
{
|
||||
PHB_ITEM pArrayItm = hb_arrayGetItemPtr( pArray, ulCount );
|
||||
hb_arrayNew( pArrayItm, 2 );
|
||||
|
||||
hb_itemPutC( hb_arrayGetItemPtr( pArrayItm, 3 ),
|
||||
( char * ) astOpenTableInfo[ ulCount - 1 ].aucTableName );
|
||||
hb_itemPutNI( hb_arrayGetItemPtr( pArrayItm, 2 ),
|
||||
astOpenTableInfo[ ulCount - 1 ].usLockType ); /* Advantage locking mode */
|
||||
}
|
||||
|
||||
hb_itemReturnRelease( pArray );
|
||||
}
|
||||
else
|
||||
|
||||
152
harbour/contrib/rddads/tests/datad.prg
Normal file
152
harbour/contrib/rddads/tests/datad.prg
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/*
|
||||
Demo of ADS Connection handling and Data Dictionaries
|
||||
*/
|
||||
|
||||
|
||||
#include "ads.ch"
|
||||
REQUEST ADS
|
||||
|
||||
FUNCTION MAIN
|
||||
local n
|
||||
local cErr, cStr
|
||||
local aStru := {{ "ID", "A", 1, 0}, {"Name", "C", 50, 0}, {"address", "C", 50, 0}, {"city", "C", 30, 0}, {"Age", "n", 3, 0}}
|
||||
local hConnection1, hConnection2
|
||||
local lIsDict := .f.
|
||||
|
||||
CLS
|
||||
|
||||
RddSetDefault("ADT")
|
||||
AdsSetServerType ( 7 )
|
||||
SET Filetype to ADT
|
||||
|
||||
? "Default connection is 0:", adsConnection()
|
||||
|
||||
fErase("harbour.add")
|
||||
fErase("harbour.ai")
|
||||
fErase("harbour.am")
|
||||
fErase("Table1.adt")
|
||||
fErase("Table1.adi")
|
||||
fErase("Table2.adt")
|
||||
fErase("Table2.adi")
|
||||
|
||||
// now Create a Data dictionary and the files if not exist
|
||||
IF !File("harbour.add")
|
||||
ADSDDCREATE("harbour.add",, "(x)Harbour ADS demo for data dictionary")
|
||||
// This also creates an Administrative Handle that is set as the default
|
||||
? "Default connection is now this admin handle:", adsConnection()
|
||||
AdsDisconnect() // disconnect current default.
|
||||
// if you wanted to retain this connection for later, you could use
|
||||
// hAdminCon := adsConnection(0)
|
||||
// This get/set call would return the current connection, then set it to 0
|
||||
|
||||
? "Default connection is now this handle (zero):", adsConnection()
|
||||
|
||||
// now create two free tables with same structure
|
||||
DbCreate("Table1", aStru)
|
||||
DbCreate("Table2", aStru)
|
||||
//now create an index
|
||||
USE table1 new
|
||||
INDEX ON id TAG codigo
|
||||
USE
|
||||
|
||||
USE table2 new
|
||||
INDEX ON id TAG codigo
|
||||
USE
|
||||
ENDIF
|
||||
|
||||
// now the magic
|
||||
IF adsConnect60("harbour.add", 7/* All types of connection*/, "ADSSYS", "", , @hConnection1 )
|
||||
// The connection handle to harbour.add is now stored in hConnection1,
|
||||
// and this is now the default connection
|
||||
|
||||
? "Default connection is now this handle:", adsConnection()
|
||||
? " Is it a Data Dict connection? (ADS_DATABASE_CONNECTION=6, "
|
||||
? " ADS_SYS_ADMIN_CONNECTION=7):", AdsGetHandleType()
|
||||
|
||||
// Add one user
|
||||
AdsDDCreateUser(, "Luiz", "papael", "This is user Luiz")
|
||||
|
||||
|
||||
IF adsddGetUserProperty("Luiz", ADS_DD_COMMENT, @cStr, hConnection1)
|
||||
? "User comment:", cStr
|
||||
ELSE
|
||||
? "Error retrieving User comment"
|
||||
ENDIF
|
||||
|
||||
|
||||
? "Add the tables"
|
||||
AdsDDaddTable("Table1", "table1.adt", "table1.adi")
|
||||
?
|
||||
IF ! AdsDDaddTable("Customer Data", "table2.adt", "table2.adi")
|
||||
// notice the "long table name" for file Table2.adt. Later open it with "Customer Data" as the table name
|
||||
? "Error adding table:", adsGetLastError(@cErr), cErr
|
||||
ENDIF
|
||||
? "Set new admin pword on default connection:", AdsDDSetDatabaseProperty( ADS_DD_ADMIN_PASSWORD, "newPWord" )
|
||||
? "Set new admin pword on explicit connection:", AdsDDSetDatabaseProperty( ADS_DD_ADMIN_PASSWORD, "newPWord", hConnection1 )
|
||||
? "Clear admin pword:", AdsDDSetDatabaseProperty( ADS_DD_ADMIN_PASSWORD, "" )
|
||||
|
||||
|
||||
ELSE
|
||||
? "Error connecting to harbour.add!"
|
||||
ENDIF
|
||||
AdsDisconnect(hConnection1)
|
||||
hConnection1 := nil // you should always reset a variable holding a handle that is no longer valid
|
||||
|
||||
? "Default connection is back to 0:", adsConnection()
|
||||
? "Is a Data Dict connection? (AE_INVALID_HANDLE = 5018):", AdsGetHandleType()
|
||||
|
||||
// now open the tables and put some data
|
||||
|
||||
IF AdsConnect60("harbour.add", 7/* All types of connection*/, "Luiz", "papael", , @hConnection1)
|
||||
? "Default connection is now this handle:", adsConnection()
|
||||
? "Connection type?", AdsGetHandleType()
|
||||
|
||||
FOR n := 1 TO 100
|
||||
IF AdsCreateSqlStatement("Data2", 3)
|
||||
IF !AdsExecuteSqlDirect(" insert into Table1( name,address,city,age) VALUES( '" + strzero(n)+"','"+strzero(n)+"','"+strzero(n)+"'," +str(n)+ ")" )
|
||||
ShowAdsError()
|
||||
ENDIF
|
||||
USE
|
||||
ENDIF
|
||||
NEXT
|
||||
|
||||
FOR n := 1 TO 100
|
||||
IF AdsCreateSqlStatement("Data1", 3)
|
||||
IF !AdsExecuteSqlDirect(" insert into " +'"Customer Data"'+"( name,address,city,age) VALUES( '"+ strzero(n)+"','"+strzero(n)+"','"+strzero(n)+"'," +str(n)+")" )
|
||||
ShowAdsError()
|
||||
ENDIF
|
||||
USE
|
||||
ENDIF
|
||||
NEXT
|
||||
|
||||
|
||||
// AdsUseDictionary(.t.) this function no longer is needed; the system knows if it's using a Data Dictionary connection
|
||||
|
||||
// Open the "long table name" for Table2
|
||||
DbUseArea(.t.,, "Customer Data", "custom", .t., .f.)
|
||||
? "Press a key to browse", alias()
|
||||
inkey(0)
|
||||
Browse()
|
||||
USE
|
||||
USE table1 new
|
||||
Browse()
|
||||
USE
|
||||
ENDIF
|
||||
|
||||
AdsDisconnect(hConnection1)
|
||||
@ 24, 0 say ""
|
||||
|
||||
RETURN NIL
|
||||
|
||||
PROC ShowAdsError()
|
||||
LOCAL cMsg
|
||||
|
||||
AdsGetLastError( @cMsg )
|
||||
|
||||
Alert( cMsg )
|
||||
|
||||
RETURN
|
||||
Reference in New Issue
Block a user