Important: The information in this document is obsolete and should not be used for new development.
Writing a Query Definition Function
Before theDBStartQuery
function sends a query to a data server, it calls the query definition function specified by thequeryProc
field in the query record. The purpose of the query definition function is to modify the query and the query record before the query is sent to the data server. The query definition function can use dialog boxes to request information from the user. Because a query document is most useful if it can be used by many different applications, no query definition function should depend on the presence of a particular application.If you want to include a query definition function, you must make it the first piece of code in a resource of type
'qdef'
in the query document.Here is a function declaration for a query definition function.
FUNCTION MyQDef (VAR sessID: LongInt; query: QueryHandle): OSErr;If the application has already initiated a session with the data server, theDBStartQuery
function passes the session ID for that session in thesessID
parameter to the query definition function. If the query definition function receives a 0 in this parameter, then the Data Access Manager has not initiated a session. In this case, the query definition function can return a 0 in thesessID
parameter, or it can call theDBInit
function to initiate a session and then return the session ID in this parameter.If the query definition function returns a 0 in the
sessID
parameter, theDBStartQuery
function calls theDBInit
function and then calls theDBSend
function to send a query to the data server. If the query definition function returns a session ID in this parameter, theDBStartQuery
function calls theDBSend
function immediately.The
query
parameter to the query definition function specifies a handle to the query record. The query definition function can modify any of the fields in the query record, including thecurrQuery
field that specifies which query is to be sent to the data server. In addition, the query definition function can modify an existing query or create a new query, adding the handle to the new query to the query list. Note that, because a query in memory consists only of a 2-byte length value followed by a character string, the query definition function has to know the exact contents and structure of a query in order to modify it.The query definition function must return the
noErr
result code as the function result if the function executed successfully. If it returns any other value, theDBStartQuery
function does not call theDBSend
function. The query definition function can return any result code, includingnoErr
,userCanceledErr
, orrcDBError
.When the
DBStartQuery
function calls the query definition function, the current resource file is the file that contains the'qrsc'
resource from which the Data Access Manager created the query record. When the query definition function returns control to the Data Access Manager, the current resource file must be unchanged. See the chapter "Resource Manager" in Inside Macintosh: More Macintosh Toolbox for more information on the current resource file.The query definition function can allocate memory and use the
dataHandle
field in the query record to store a handle to it. The query definition function must free any memory it allocates before terminating.Listing 12-7 shows a query definition function that uses a dialog box to prompt the user for a user name and password and then modifies the query record accordingly.
Listing 12-7 A query definition function
FUNCTION MyQDef(VAR sessID: LongInt; query: QueryHandle): OSErr; CONST myNameItem = 7; myPassWordItem = 8; VAR myNumRes: Integer; myResList: ResListHandle; myResLPtr: ResListPtr; myIndex: Integer; myDialog: DialogPtr; myDlogID: Integer; itemType: Integer; itemHName: Handle; itemHPasswd: Handle; itemBox: Rect; mySTR: ARRAY[1..2] OF Str255; itemHit: Integer; myQErr: OsErr; BEGIN {If sessID = 0 no session has been initiated. Your qdef may } { optionally initiate a session, or it can let DBStartQuery } { take care of this. In this example, the qdef doesn't } { check the sessID parameter.} HLock(Handle(query)); myNumRes := query^^.numRes; myResList := query^^.resList; HLock(Handle(myResList)); myResLPtr := myResList^; myIndex := 0; {look for a 'DLOG' resource} WHILE (myIndex < myNumRes) AND (myResLPtr^[myIndex].theType <> 'DLOG') DO BEGIN myIndex := myIndex + 1; END; IF (myIndex < myNumRes) THEN {found the 'DLOG' resource} myDlogID := myResLPtr^[myIndex].id ELSE BEGIN {The 'DLOG' wasn't found; exit with no error. This } { is probably OK; it just means that the query } { and the query record don't get modified.} MyQDEF := noErr; HUnlock(Handle(query)); HUnlock(Handle(myResList)); EXIT(MyQDef); END; {found the 'DLOG' and its ID; now display the dialog box} myDialog := GetNewDialog(myDlogID, Ptr(NIL), WindowPtr(-1)); SetPort(GrafPtr(myDialog)); REPEAT ModalDialog(@MyEventFilter, itemHit); UNTIL ((itemHit = kOK) OR (itemHit = kCancel)); IF itemHit = kOK THEN BEGIN {The user clicked the OK button. Update the user } { and password fields of the query record.} GetDialogItem(myDialog, myNameItem, itemType, itemHName, itemBox); GetDialogItemText(itemHName, mySTR[1]); GetDialogItem(myDialog, myPassWordItem, itemType, itemHPasswd, itemBox); GetDialogItemText(itemHPasswd, mySTR[2]); {Now you can change the query record or the query itself. } { What you change is entirely up to you. In this example, } { the qdef changes only the user and password fields } { of the query record.} query^^.user := mySTR[1]; query^^.password := mySTR[2]; MyQDef := noErr; END ELSE MyQDef := userCanceledErr; HUnlock(Handle(query)); HUnlock(Handle(myResList)); DisposDialog(myDialog); END;