Examples

The examples that follow illustrate how result set references are compiled and indicate situations to be avoided.

Example 1

procedure test()
   find all Employees -> EmpSet
   . . . other non-FIND commands . . .
   find all Departments -> DeptSet
   . . . other non-FIND commands . . .
endprocedure

 

This procedure contains two set-processing commands that create result sets. Between the two FIND commands, the Compiler assumes that references to the current set are to EmpSet. After the second FIND, all such references are assumed to apply to DeptSet. The references would be handled in exactly the same way if the procedure were being executed interpretively.

Example 2

procedure GetEmps (DeptNo, NewDeptNo)
   if DeptNo = 'D01'
      find all Employees where DeptNum = DeptNo
   else
      find all Departments where DeptNum = DeptNo
   endif
   change all CurrentSet let DeptNum = NewDeptNo
endprocedure

 

In this example, both Employees and Departments have a DeptNum field, but the DeptNum reference in the CHANGE command is understood by the Compiler to be a reference to the (implicit) result set created by the second FIND command (because the Compiler works top-to-bottom).

In other words, the current set at the time the CHANGE command is compiled is the result set created by the second FIND. Consequently, the compiled version of this procedure does not work in the same manner as the source version.

Example 3

procedure test2()
   form open MyForm
   change MyForm from EmpSet
   form display
endprocedure

 

Here, a procedure fills the form MyForm with data from the result set EmpSet and then displays the form. Note that EmpSet was not created by a set-processing command within the test2 procedure.

To compile test2, either EmpSet must be a set object in the application database or you must issue a set-processing command that creates EmpSet before you issue the COMPILE command (e.g., find 0 Employees -> EmpSet).

In the latter case, the "dummy" EmpSet that is created before test2 is compiled must have the structure that the procedure expects (i.e., all the components in the correct order).

Example 4

procedure GetSet1 (a,b)
   if a=b
     find all Employees WorkIn Departments -> set1
   else
      find all Employees -> set1
   endif
% List the first and last members of set1
list set1
   bottom set1
   list set1
endprocedure

 

Here, one set name, set1, is used in different contexts: the FIND commands use two different structures for set1.

The Compiler treats these references to set1 in the same manner as it treated the references to the current set in Example 2. Consequently, the compiled program does not work as expected.

If all FIND commands that produce set1 have the same component structure (unlike the case here), then any explicit reference to set1 always refers to a set with the correct structure (demonstrated in Example 5).

If necessary, SET CHECKSETS ON can be used to enforce continuity of structure for temporary result sets using the same name.

Example 5

procedure GetSet1 (a,b)
   if a=b
      find all Employees WorkIn Departments -> set1
   else
      find all Employees WorkIn Departments \
         where LastName = 'Smith' -> set1
   endif
% List the first and last members of set1
   list set1
   bottom set1
   list set1
endprocedure

 

In this example, when the compiled program is executed, the references to set1 all refer to a result set with the same structure (Employees WorkIn Departments).

But, because the Compiler works top-to-bottom, situations can arise in which the Compiler is unable to resolve a reference to a component or field of the result set even though no problem exists when the program is executed interpretively (see Example 6).

Example 6

procedure test3 (a,b)
   if a=b
      find Employees -> EmpSet
   else
      find Departments -> DeptSet
   endif
   if a=b
      let a = LastName
   endif
endprocedure

 

Here, the Compiler is unable to resolve LastName in the LET command.

The LET command can refer only to fields in the current set. LastName is a field in EmptSet; no field called LastName exists in the current set (which is DeptSet, the set created by the last set-producing command encountered). The software therefore treats LastName as a character literal, setting the value of variable a to the characters LastName rather than to the current value of the LastName field (e.g., Smith).

Obviously, test3 could be restructured to avoid this problem. One solution is to save the value of LastName in a variable immediately after finding EmpSet. This solution is shown in Example 7. Another solution is to remove the FIND of DeptSet to another procedure. This solution is shown in Example 8. A third alternative is to use the SET CURRENTSET command to make EmpSet the current set inside the second IF statement. This alternative is shown in Example 9.

Example 7

procedure test3 (a, b, SavedLastName)
   if a=b
      find Employees -> EmpSet
      let SavedLastName = LastName
   else
      find Departments -> DeptSet
   endif
   if a=b
      let a = SavedLastName
   endif
endprocedure

 

LastName is saved in a variable immediately after EmpSet is found.

Example 8

procedure test3 (out a, b)
   if a=b
      find Employees -> EmpSet
   else
      findDeptSet % Call a program to find DeptSet.
   endif
   if a=b
   let a = LastName
   endif
endprocedure

 

The command FIND Departments -> DeptSet is removed from this procedure.

Example 9

procedure test3 (a, b)
   if a=b
      find Employees -> EmptSet
   else
      find Departments -> DeptSet
   endif
   if a=b
      set currentset EmpSet
      let a = LastName
   endif
endprocedure

 

SET CURRENTSET is used to make EmpSet the current set inside the second IF statement.