Importance of optimized code with BY-REFERENCE
- Last Updated: March 30, 2020
- 3 minute read
- OpenEdge
- Version 12.2
- Documentation
The information in this set of topics applies to the use of BIND as well, which you will read about in the next topic.
This diversion into a discussion of BY-REFERENCE might
seem overly complex, but it has been introduced here for a reason.
If you get into the habit of structuring your procedures and their
ProDataSet parameters properly from the beginning, you will be well
positioned to optimize most calls that are sometimes made locally
and sometimes remotely by adding the BY-REFERENCE keyword
to your calls without any undesirable consequences. It is always
best to design your procedures so that they work properly when run
locally—even when in a deployed application they may be distributed
on different machines. This makes the initial development and testing
of your application more straightforward, and supports the case
(even if it is only for demo purposes) where everything is running
in a single session. Since the BY-REFERENCE optimization
is such a valuable one, it is worth making the effort to prepare
for it right from the start, even if you first code and test your
application without it and then add the keyword to your calls to
improve performance.
You can pass a ProDataSet reference locally as a HANDLE
PARAMETER as you can with other objects such as temp-tables. This gives the called
procedure access to the ProDataSet instance defined in the caller, but has two essential
limitations. First, the called procedure must be in the same OpenEdge session as the calling
procedure. You cannot pass an object handle of any kind across an application server call and
have it maintain its validity. Second, the called procedure can only reference the ProDataSet
using dynamic attributes and methods if it receives it as a HANDLE. In other words, the called procedure cannot receive the HANDLE parameter into a static DATASET definition and reference it using static table and field names.
By contrast, when you pass or receive a ProDataSet as a DATASET-HANDLE,
this simply means that the procedure using the DATASET-HANDLE parameter
form sees the ProDataSet as a dynamic object. The procedure on the
other side of the call can see it as a static object. The table
below shows the different combinations. Normally, passing a ProDataSet
as a DATASET-HANDLE causes its definition and data
to be copied to the receiving procedure. Using the BY-REFERENCE option
on the parameter makes passing a ProDataSet as a DATASET-HANDLE cost
no more within a single session than passing a reference to it as
a HANDLE. For this reason, we recommend that you
normally use the DATASET-HANDLE form. In this way,
if the call is ever moved to a remote procedure, it will still work
properly, whereas the HANDLE parameter will fail
on a remote call.
Passing a ProDataSet BY-REFERENCE is particularly valuable
when the called procedure uses the DATASET parameter
form to receive the ProDataSet into a static definition. This will
be the norm in most server-side procedures, and especially in most
event handling procedures. The business logic in these procedures
is much simpler to write if it uses static ABL statements to refer
to and manipulate the records in the ProDataSet's temp-tables. All
the elements of the ProDataSet definition, along with all the data
in its temp-tables, are available to the called procedure. The default buffers
that are part of the ProDataSet, which have the same names as their temp-tables,
are in fact shared between caller and callee. Therefore, if the
called procedure changes the record position in any of these buffers,
this will be visible to the caller after the procedure returns.
The called procedure can define buffers of its own to avoid this.
Any changes to the ProDataSet data made by the called procedure
are visible to the caller, as if the object were SHARED.
There are several restrictions in ProDataSet usage that are at least partially related to this parameter support:
- You cannot define a ProDataSet inside an internal procedure or trigger. This is the same restriction that applies to temp-tables.
- The static parameter form (that is,
DEFINE INPUT/OUTPUT PARAMETER DATASET FORdataset-name) cannot be used in the main block of a procedure that is runPERSISTENT.
As a final note, it is possible to specify a ProDataSet as a
parameter for a dynamic call object, which lets you set up the entire
definition of a RUN statement dynamically. You
can also specify the BY-REFERENCE qualifier in
the arguments to the dynamic CALL. For more information,
see the reference documentation or online help for the SET-PARAMETER( ) method
on the dynamic call object.