Programming Interfaces Guide
CHAPTER 3. The Database Tools Interface
This section provides an overview of how to develop applications that use the DBTools interface for managing databases.
In order to use the DBTools functions, you must link your application against a DBTools import library which contains the required function definitions.
Import libraries are operating system-specific and can be compiler-specific. Import libraries for the DBTools interface are provided with Adaptive Server Anywhere, and can be found in the lib subdirectory of each operating system directory, under your installation directory. The provided DBTools import libraries are as follows:
Operating system |
Compiler |
Library |
---|---|---|
Windows NT/95 |
Watcom |
win32\dbtlstw.lib |
Windows NT/95 |
Microsoft |
win32\dbtlstM.lib |
Windows NT/95 |
Borland |
win32\dbtlstB.lib |
Windows 3.x |
All |
win\dbtoolsw.lib |
OS/2 |
All |
OS2\dbtools2.lib |
Before using any other DBTools functions, you must call DBToolsInit. When you are finished using the DBTools DLL, you must call DBToolsFini.
The primary purpose of the DBToolsInit and DBToolsFini functions is to allow the DBTools dll to load the Adaptive Server Anywhere language DLL. The language DLL contains localized versions of all error messages and prompts that DBTools uses internally. If DBToolsFini is not called, the reference count of the language DLL is not decremented, and it will not be unloaded, so be careful to ensure there is a matched pair of DBToolsInit/DBToolsFini calls.
The following code fragment illustrates how to initialize and clean up DBTools:
// Declarations a_dbtools_info info; short ret; //Initialize the a_dbtools_info structure memset( &info, 0, sizeof( a_dbtools_info) ); info.errorrtn = (MSG_CALLBACK)MyErrorRtn; // initialize DBTools ret = DBToolsInit( &info ); if( ret != EXIT_OKAY ) { // DLL initialization failed ... } // call some DBTools routines . . . ... // cleanup the DBTools dll DBToolsFini( &info );
All the tools are run by first filling out a structure, and then calling a function (or entry point) in the DBTools DLL. Each entry point takes a pointer to a single structure as argument.
The following example shows how to use the DBBackup function. The example is for either Windows 95 or Windows NT operating systems.
// Initialize the structure a_backup_db backup_info; memset( &backup_info, 0, sizeof( backup_info ) ); // Fill out the structure backup_info.version = DB_TOOLS_VERSION_NUMBER; backup_info.output_dir = "C:\BACKUP"; backup_info.connectparms ="uid=dba;pwd=sql;dbf=asademo.db"; backup_info.startline = "DBENG6.EXE"; backup_info.confirmrtn = (MSG_CALLBACK) ConfirmRtn ; backup_info.errorrtn = (MSG_CALLBACK) ErrorRtn ; backup_info.msgrtn = (MSG_CALLBACK) MessageRtn ; backup_info.statusrtn = (MSG_CALLBACK) StatusRtn ; backup_info.backup_database = TRUE; // start the backup DBBackup( &backup_info );
For information about the members of the DBTools structures, see DBTools structures.
Several elements in DBTools structures are of type MSG_CALLBACK. These are pointers to callback functions.
Callback functions allow DBTools functions to return control of operation to the user's calling application. The DBTools library uses callback functions to handle messages sent to the user by the DBTools functions, for four purposes:
Confirmation Called when an action needs to be confirmed by the user. For example, if the backup directory does not exist, the tools DLL asks if it needs to be created.
Error message Called to handle a message when an error occurs, such as when an operation is out of disk space.
Information message Called for the tools to display some message to the user (such as the name of the current table being backed up).
Status information Called for the tools to display the status of an operation (such as the percentage done when unloading a table).
In operating systems other than Windows 3.x, you can directly assign a callback routine to the structure. The following statement is an example using a backup structure:
backup_info.errorrtn = (MSG_CALLBACK) MyFunction
MSG_CALLBACK is defined in the dllapi.h header file supplied with Adaptive Server Anywhere. Tools routines can call back to the Calling application with messages that should be displayed in the appropriate user interface, whether that be a windowing environment, standard output on a character-based systems, or other user interface.
If you are developing for Windows 3.x, you must use the MakeProcInstance Windows API thunking function when assigning values to the elements. A thunking function changes 16-bit values to equivalent 32-bit values. The following statement is an example using a backup structure:
backup_info.errorrtn = (MSG_CALLBACK)MakeProcInstance( (FARPROC)MyFunction, hInst );
After you have finished with the DLL, you must free Callback thunk using the FreeProcInstance Windows API function:
FreeProcInstance( (FARPROC) backup_info.errorrtn );
If no function is assigned to the structure member, the message is ignored.
The following example confirmation routine asks the user to answer YES or NO to a prompt, and returns the user's selection:
extern short _callback ConfirmRtn( char far * question ) { int ret; if( question != NULL ) { ret = MessageBox( HwndParent, question, "Confirm", MB_ICONEXCLAMTION|MB_YESNO ); } return( 0 ); }
The following is an example of an error message handling routine, which displays the error message in a message box.
extern short _callback ErrorRtn( char far * errorstr ) { if( errorstr != NULL ) { ret = MessageBox( HwndParent, errorstr, "Backup Error", MB_ICONSTOP|MB_OK ); } return( 0 ); }
A common implementation of a message callback function outputs the message to the screen:
extern short _callback MessageRtn( char far * errorstr ) { if( messagestr != NULL ) { OutputMessageToWindow( messagestr ); } return( 0 ); }
A status callback routine is called when the tools needs to display the status of an operation (like the percentage done unloading a table). Again, a common implementation would just output the message to the screen:
extern short _callback StatusRtn( char far * statusstr ) { if( statusstr == NULL ) { return FALSE; } OutputMessageToWindow( statustr ); return TRUE; }
Each structure has a member that indicates the version number. You should use this version member to hold the version of the DBTools library that your application was developed against. The current version of the DBTools library is included as the constant in the dbtools.h header file.
Assign the version constant to the version member of the structure before calling the DBTools function. The following line assigns the current version to a backup structure:
backup_info.version = DB_TOOLS_VERSION_NUMBER;
The version number allows your application to continue working against newer versions of the DBTools library. The DBTools functions use the version number supplied by your application to allow the application to work, even if new members have been added to the DBTools structure.
Applications will not work against older versions of the DBTools library.
Many of the DBTools structures use bit fields to hold Boolean information in a compact manner. For example, the backup structure has the following bit fields:
char backup_database : 1; char backup_logfile : 1; char backup_writefile: 1; char no_confirm : 1; char quiet : 1; char rename_log : 1; char truncate_log : 1; char rename_local_log: 1;
Each bit field is one bit long, indicated by the 1 to the right of the colon in the structure declaration..
You assign an integer value of 0 or 1 to a bit field to pass Boolean information to the structure.
The following program illustrates the use of the DBTools library in the context of a backup program:
# define WINNT #include <stdio.h> #include "windows.h" #include "string.h" #include "dbtools.h" extern short _callback ConfirmCallBack(char far * str){ if( MessageBox( NULL, str, "Backup", MB_YESNO|MB_ICONQUESTION ) == IDYES ) { return 1; } return 0; } extern short _callback MessageCallBack( char far * str){ if( str != NULL ) { fprintf( stdout, "%s", str ); fprintf( stdout, "\n" ); fflush( stdout ); } return 0; } extern short _callback StatusCallBack( char far * str ){ if( str != NULL ) { fprintf( stdout, "%s", str ); fprintf( stdout, "\n" ); fflush( stdout ); } return 0; } extern short _callback ErrorCallBack( char far * str ){ if( str != NULL ) { fprintf( stdout, "%s", str ); fprintf( stdout, "\n" ); fflush( stdout ); } return 0; } // Main entry point into the program. int main( int argc, char * argv[] ){ a_backup_db backup_info; a_dbtools_info dbtinfo; char dir_name[ _MAX_PATH + 1]; char connect[ 256 ]; HINSTANCE hinst; FARPROC dbbackup; FARPROC dbtoolsinit; FARPROC dbtoolsfini; // Always initialize to 0 so new versions //of the structure will be compatible. memset( &backup_info, 0, sizeof( a_backup_db ) ); backup_info.version = DB_TOOLS_VERSION_6_0_01; backup_info.quiet = 0; backup_info.no_confirm = 0; backup_info.confirmrtn = (MSG_CALLBACK)ConfirmCallBack; backup_info.errorrtn = (MSG_CALLBACK)ErrorCallBack; backup_info.msgrtn = (MSG_CALLBACK)MessageCallBack; backup_info.statusrtn = (MSG_CALLBACK)StatusCallBack; if( argc > 1 ) { strncpy( dir_name, argv[1], _MAX_PATH ); } else { // DBTools does not expect (or like) the // trailing slash strcpy( dir_name, "c:\\temp" ); } backup_info.output_dir = dir_name; if( argc > 2 ) { strncpy( connect, argv[2], 255 ); } else { // Assume that the engine is already running. strcpy( connect, "UID=dba;PWD=sql;DBN=asademo" ); } backup_info.connectparms = connect; backup_info.startline = ""; backup_info.quiet = 0; backup_info.no_confirm = 0; backup_info.backup_database = 1; backup_info.backup_logfile = 1; backup_info.backup_writefile = 1; backup_info.rename_log = 0; backup_info.truncate_log = 0; hinst = LoadLibrary( "dbtool6.dll" ); if( hinst == NULL ) { // Failed return 0; } dbtinfo.errorrtn = (MSG_CALLBACK)ErrorCallBack; dbbackup = GetProcAddress( (HMODULE)hinst, "_DBBackup@4" ); dbtoolsinit = GetProcAddress( (HMODULE)hinst, "_DBToolsInit@4" ); dbtoolsfini = GetProcAddress( (HMODULE)hinst, "_DBToolsFini@4" ); (*dbtoolsinit)( &dbtinfo ); (*dbbackup)( &backup_info ); (*dbtoolsfini)( &dbtinfo ); FreeLibrary( hinst ); return 0; }