You will normally use the Find message to find a record and all of its parents. A typical find operation can be described as follows:
Prepare your File Buffer with properly seeded Field values. Note that you prepare the File Buffer and not DDO-Field values (see Understanding File Buffers and DDO Field Buffers).
Send the Find message to the DDO, passing the find mode and find index as parameters.
Check status of the find and react accordingly.
A Find actually sends the Request_Find message passing the mode, file-number and index. Request_Find does the actual find performing the following steps:
Perform a parent to child attach for all parents (Attach_Main_File)
Perform the find based on constraints and filters
If the find is successful, perform a relate for all parents
Perform custom relates by sending Relate_Main_File to all DDOs
If DDO has a related-to child, inform the child DDO of the new record
The Child DDO will clear or find as needed
Send OnNewCurrentRecord to all DDOs with newly found or cleared records.
Send Refresh to all DEOs attached to DDOs
Note that all DEO objects attached to the DDO performing a find will immediately display the results of a find.
When DEOs perform finds they use the Request_Find message. When performing finds in your code you will usually the Find message. The examples shown here show how to use the Find messages for manually coded operations.
The following example shows a typical find operation:
Function FindUser String sCustNo Returns Boolean
Boolean bFound
Handle hoDD
Move oCustomer_DD to hoDD
// Step 1: Prepare the File Buffers for a find
Send Clear of hoDD
Move sCustNo to Customer.Customer_Number
// Step 2: Perform the find Operation
Send Find of hoDD EQ 1
// Step 3: Process the information after the find.
Move (Found) to bFound
Function_Return bFound
End_Function // SearchUser
The Found indicator is always set after a find. Because this indicator is global and easily changed you should always move the status of this indicator to some other variable.
You can also test if a find succeeded by checking the DDO’s HasRecord function if the DDO buffer did not contain a record prior to the find operation (otherwise, check the Found indicator).
It can also be used to determine if a save will result in a new record save (if HasRecord is false) or an edit of an existing record (if HasRecord is true).
Send Find of hoDD EQ 1
Get HasRecord of hoDD to bFound
In some cases, you may wish to return the value of the record’s RowId.
Function FindUser String sCustNo Returns RowId
Rowid riRecId
Handle hoDD
Move oCustomer_DD to hoDD
// Step 1: Prepare the File Buffers for a find
Send Clear of hoDD
Move sCustNo to Customer.Customer_Number
// Step 2: Perform the find Operation
Send Find of hoDD EQ 1
// Step 3: Process the information after the find.
Get CurrentRowId of hoDD to riRecId
Function_Return riRecId
End_Function // SearchUser
The first step in performing a find is to prepare file buffer for the find. This usually consists of clearing the DDO (send Clear) and then seeding the file-buffer with the information needed to find the record.
Very Important: When you are seeding field values for a find, you must seed the file-buffer and not DDO-field buffer. Do not use the set File_Field_Current_Value message to seed data for a find – it will not work. In this example we cleared the customer DDO and moved a unique Customer identifier into the Customer_Number field. For more about using File-Buffers and DDO-Field Buffers see Understanding File Buffers and DDO Field Buffers.
Once the file buffers are prepared, you find the record using the Find message. This message requires that you pass a find mode (LT, LE, EQ, GE, GT, NEXT_RECORD, FIRST_RECORD, or LAST_RECORD) and a find index number. In the above example we are performing a "find equal" using Index 1, which presumably is an index of Customer_Number (if it is not, this find will not work).
After the find, all DEO objects that are attached to any of DDOs involved in the find will be refreshed. The DDOs do this by sending the message Refresh to all DEOs. This is an automatic process of DDOs and makes it very simple for your DEOs to stay synchronized. This also means that your DEOs will change as you find records. If you do not want this behavior see Finding without Updating the DDO.
If the find succeeds, the data will be loaded into the DDO, CurrentRowId will contain the record’s ID, HasRecord will be true, and the Found indicator will be set to true. If the find failed, the DDO will not be changed and the found indicator will be set to False.
If you use the Find message to find multiple records, you will usually use a slightly different method of preparing your file buffers. Normally, you will prepare your file buffer for the first find, and perform a find using the "Find greater than or equal to" mode (GE). Successive finds will perform a "Find Greater than" (GT), using the state of the file buffer from the previous find.
Procedure ListUsers
Handle hoDD
Move oUser_DD to hoDD
Send Clear of hoDD
Send Find of hoDD GE 1
While (Found)
Send ProcessThisUser
Send Find of hoDD GT 1
Loop
End_Procedure
You can also use FIRST_RECORD and NEXT_RECORD.
Note that Find mode Next_Record will use the same find direction as the prior Find operation. Using find mode Next_Record <B>must</B> be preceded by a find using one of the other modes, or it will result in an error.
Procedure ListUsers
Handle hoDD
Move oUser_DD to hoDD
Send Find of hoDD FIRST_RECORD 1
While (Found)
Send ProcessThisUser
Send Find of hoDD NEXT_RECORD 1
Loop
End_Procedure
Instead of clearing the DDO and using GE, you can also use FIRST_RECORD (or LAST_RECORD with LT, if you wished to find in reverse order).
Procedure ListUsers
Handle hoDD
Move oUser_DD to hoDD
Send Find of hoDD FIRST_RECORD 1
While (Found)
Send ProcessThisUser
Send Find of hoDD GT 1
Loop
End_Procedure
A word or caution when using the Found indicator. This indicator is global and is easily changed. If you are using this, you should only use it immediately after a find operation. If you have additional commands or messages between the find and the test of the Found indicator, you may be testing on a Found value that was changed by some other process. The following code may not work as expected:
// this demonstrates improper technique
Procedure ListUsers
Handle hoDD
Move oUser_DD to hoDD
Send Find of hoDD FIRST_RECORD 1
While (Found)
Send ProcessThisUser
Send Find of hoDD GT 1
Send LogLineChange // THIS COULD CHANGE FOUND!!!
Loop
End_Procedure
In the situation where Found may be altered by other processes, you should immediately move this value to another variable as follows:
// this demonstrates a proper technique
Procedure ListUsers
Handle hoDD
Boolean bOK
Move oUser_DD to hoDD
Send Find of hoDD FIRST_RECORD 1
Move (Found) to bOK
While (bOK)
Send ProcessThisUser
Send Find of hoDD GT 1
Move (Found) to bOK
Send LogLineChange
Loop
End_Procedure
It is considered good programming practice to always move the Found indicator to a local variable.
You will primarily use finding loops like this in non-DEO batch processes. If you use this with DDOs that have DEOs, the DEOs will get refreshed with every find – probably not something you want.
Find and Clear Operations in DDOs