Legacy Documentclose button

Important: The information in this document is obsolete and should not be used for new development.

Previous Book Contents Book Index Next

Inside Macintosh: Interapplication Communication /
Chapter 12 - Data Access Manager / Using the Data Access Manager


Writing a Status Routine for High-Level Functions

Both of the two main high-level functions, DBStartQuery and DBGetQueryResults, call low-level functions repeatedly. After each time they call a low-level function, these high-level functions call a routine that you provide, called a status routine. Your status routine can check the result code returned by the low-level function and can cancel execution of the high-level function before it calls the next low-level function. Your status routine can also update your application's windows after the DBStartQuery function has displayed a dialog box.

You provide a pointer to your status routine in the statusProc parameter to the DBStartQuery and DBGetQueryResults functions.

Here is a function declaration for a status routine:

FUNCTION MyStatusFunc (message: Integer; result: OSErr; 
                       dataLen: Integer; dataPlaces: Integer; 
                       dataFlags: Integer; dataType: DBType; 
                       dataPtr: Ptr): Boolean;
Your status routine should return a value of TRUE if you want to continue execution of the DBStartQuery or DBGetQueryResults function, or a value of FALSE if you want to cancel execution of the function. In the latter case, the high-level function returns the userCanceledErr result code.

Note
If you call the DBStartQuery or DBGetQueryResults function asynchronously, you cannot depend on the A5 register containing a pointer to your application's global variables when the Data Access Manager calls your status routine.
The message parameter tells your status routine the current status of the high-level function that called it. The possible values for the message parameter depend on which function called your routine.

The value of the result parameter depends on the value of the message parameter, as summarized in the following list:
MessageResult
kDBUpdateWind0
kDBAboutToInit0
kDBInitCompleteResult of DBInit
kDBSendCompleteResult of DBSend
kDBExecCompleteResult of DBExec
kDBStartQueryCompleteResult of DBStartQuery
kDBGetItemCompleteResult of DBGetItem
kDBGetQueryResultsCompleteResult of DBGetQueryResults

The dataLen, dataPlaces, dataFlags, dataType, and dataPtr parameters are returned only by the DBGetQueryResults function, and only when the message parameter equals kDBGetItemComplete. When the DBGetQueryResults function calls your status routine with this message, the dataLen, dataPlaces, and dataType parameters contain the length, decimal places, and type of the data item retrieved, respectively, and the dataPtr parameter contains a pointer to the data item.

The least significant bit of the dataFlags parameter is set to 1 if the data item is in the last column of the row. The third bit of the dataFlags parameter is set to 1 if the data item is NULL. You can use this information, for example, to check whether the data meets some criteria of interest to the user, or to display each data item as the DBGetItem function receives it. You can use the constants kDBLastColFlag and kDBNullFlag to test for these flag bits.

The DBGetQueryResults function returns a results record, which contains a handle to the retrieved data. The address in the dataPtr parameter points inside the array specified by this handle. Because the dataPtr parameter is not a pointer to a block of memory allocated by the Memory Manager, but just a pointer to a location inside such a block, you cannot use this pointer in any Memory Manager routines (such as the GetPtrSize function). Note also that you cannot rely on this pointer remaining valid after you return control to the DBGetQueryResults function.

The DBStartQuery function can send to your status routine the following constants in the message parameter:

CONST {DBStartQuery status messages}
      kDBUpdateWind           = 0;     {update windows}
      kDBAboutToInit          = 1;     {about to call DBInit}
      kDBInitComplete         = 2;     {DBInit has completed}
      kDBSendComplete         = 3;     {DBSend has completed}
      kDBExecComplete         = 4;     {DBExec has completed}
      kDBStartQueryComplete   = 5;     {DBStartQuery is about to }
                                       { complete} 
The DBGetQueryResults function can send to your status routine the following constants in the message parameter:

CONST {DBGetQueryResults status messages}
      kDBGetItemComplete         = 6;  {DBGetItem has completed}
      kDBGetQueryResultsComplete = 7;  {DBGetQueryResults has }
                                       { completed} 
Listing 12-3 shows a status routine for the DBStartQuery function. This routine updates the application's windows in response to the kDBUpdateWind message, displays a dialog box giving the user the option of canceling before the data access is initiated, and checks the results of calls to the DBInit, DBSend, and DBExec functions. If one of these functions returns an error, the status routine displays a dialog box describing the error.

Listing 12-3 A sample status routine

FUNCTION MyStartStatus(message: Integer; result: OSErr;
                        dataLen: Integer; dataPlaces: Integer;
                        dataFlags: Integer; dataType: DBType; 
                        dataPtr: Ptr): Boolean;
VAR
   myString:   Str255;
   continue:   Boolean;
BEGIN
   continue := TRUE; {assume user wants to continue with query}
   CASE message OF
   kDBUpdateWind:    {a qdef function has just been called; }
      BEGIN          { handle activate and update events}
         MyDoActivate;  {find and handle activate events}
         MyDoUpdate;    {find and handle update events}
      END;  {kDBUpdateWind}
   kDBAboutToInit:   {about to initiate a session}
      BEGIN {MyDisplayDialog displays a dialog box. The value }
            { returned in the continue variable indicates }
            { whether DBStartQuery should continue.}
         myString := 'The Data Access Manager is about to open a 
                     session.  This could take a while.  Do you
                     want to continue?';
         MyDisplayDialog(@myString, continue);
      END;  {kDBAboutToInit}
   kDBInitComplete:  {the DBInit function has completed execution}
      BEGIN
         IF result <> noErr THEN {if there's an error, }
         BEGIN                   { let the user know what it is}
            CASE result OF
            rcDBError:
            BEGIN
               myString := 'The Data Access Manager was unable to
                           open the session.  Please check your
                           connections and try again later.';
               MyDisplayString(@myString);
            END;  {rcDBError}
            rcDBBadDDev:
            BEGIN
               myString := 'The Data Access Manager cannot find
                           the database extension file it needs to
                           open a session.  Check with your system
                           administrator for a copy of the file.';
               MyDisplayString(@myString);
            END;  {rcDBBadDDev}
            OTHERWISE
            BEGIN
               myString := 'The Data Access Manager was unable to
                           open the session.  The error code 
                           returned was';
               MyDisplayError(@myString, result);
            END; {of otherwise}
         END;  {of CASE result}
         END; {of result <> noErr}
      END; {kDBInitComplete}
   kDBSendComplete:  {the DBSend function has completed execution} 
      BEGIN
         {if there's an error, let the user know what it is}
         IF result <> noErr THEN
         BEGIN
            IF result = rcDBError THEN
            BEGIN
               myString := 'An error occurred while the Data 
                           Access Manager was trying to send the 
                           query. Please try again later.';
               MyDisplayString(@myString);
            END
            ELSE
            BEGIN
               myString := 'An error occurred while the Data 
                           Access Manager was trying to send the 
                           query. The error code returned was';
               MyDisplayError(@myString, result);
            END;
         END;  {of result <> noErr}
      END;  {kDBSendComplete}
   kDBExecComplete:  {the DBExec function has completed execution}
      BEGIN
         IF result <> noErr THEN {if there's an error, }
         BEGIN                   { let the user know what it is}
            IF result = rcDBError THEN
            BEGIN
               myString := 'The Data Access Manager was unable to
                        execute the query. There may be a problem
                        with the query document or the database.
                        Check with your system administrator.';
               MyDisplayString(@myString);
            END
            ELSE
            BEGIN
               myString := 'An error occurred while the Data
                        Access Manager was trying to execute the
                        query.  The error code returned was';
               MyDisplayError(@myString, result);
            END;
         END;  {of result <> noErr}
      END;  {kDBExecComplete}
   kDBStartQueryComplete:{the DBStartQuery function is about }
      BEGIN             { to return control to your application}
         {clean up memory and any dialog boxes left on the screen}
         MyCleanUpWindows;
      END;  {kDBStartQueryComplete}
   END; {CASE message}
   MyStartStatus := continue;
END;

Previous Book Contents Book Index Next

© Apple Computer, Inc.
7 JUL 1996