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.