Force the ProDataSet to be passed BY-VALUE
- Last Updated: February 11, 2026
- 4 minute read
- OpenEdge
- Version 13.0
- Documentation
You might notice that there is an extra keyword
on the ProDataSet parameter at the top of fetchOrders,
as shown:
|
Why is this here? After all, as you learned
earlier, passing ProDataSets by value (that is, by copying the data
from one procedure to the other) is the default behavior, and you
have to explicitly specify BY-REFERENCE in the RUN statement
to pass the ProDataSet by simply pointing the called procedure at
the same instance the calling procedure is using.
To answer the question, let us look at a sketch of how the ProDataSet definitions are used in these two procedures, the window procedure that represents the client and the support procedure that represents the server code, as shown in the following figure.

Here are the steps these procedures go through using the default behavior of passing the ProDataSet by value:
- The ProDataSet that is going to supply the data to the client is defined
in orderSupport.p. The
SET-CALLBACK-PROCEDUREmethods that attach its behavior to it all point to that definition by using the local ProDataSet handle or one of its buffer handles. - When the client procedure calls
fetchOrders, the ProDataSet parameter infetchOrdersfetchOrders also references the local ProDataSetdsOrderwhose definition it shares. - When
fetchOrdersfetchOrders does aFILL, thatFILLalso references the local ProDataSetdsOrder. - Because the
FILLcallback events have been attached to that local instance ofdsOrder, they all execute correctly to prepare the query, attach Data-Sources, and take other actions as part of theFILL. - When
fetchOrdersreturns ProDataSetdsOrderasOUTPUT, it again refers to the local ProDataSet, which is copied back to the window procedure's own instance of ProDataSetdsOrder.
In this way, the ProDataSet in (enclosed in the dotted line) maintains its integrity. All the behavior that has been attached to it executes properly. This is always how a procedure call like this operates when the application is actually distributed. If the window procedure truly executes in a client session and the support procedure in an application server session, then the ProDataSet is always copied back to the client from the server. Given this expectation, the way you have set up the server procedure is entirely appropriate.
However, you also want to code your procedures so that even when they are all run in the same session, even if only for initial testing purposes, they run correctly. Because ProDataSets are passed by value by default, the default behavior in a strictly local situation is also correct. The potential problem lies in the fact that orderSupport.p depends on the ProDataSet always being passed by value.
The following
figure shows what happens if the client procedure in the same session
decides to ask for the OUTPUT DATASET dsOrder BY-REFERENCE.

The following describes the execution flow in the above figure:
- The
SET-CALLBACK-PROCEDUREmethods still act on the ProDataSet instance in orderSupport.p. - When the window procedure runs
fetchOrderslocally with the ProDataSet passedBY-REFERENCE, it is forcing the support procedure to use its instance ofdsOrderin order to avoid copying the ProDataSet back. - Because the AVM adjusts the parameter reference to
dsOrderinfetchOrdersto point to the ProDataSet in the caller, theFILLis done relative to the ProDataSet in the window procedure PickOrder.w. - Unfortunately, the callback procedures are still attached to the (now unused) ProDataSet
instance in orderSupport.p. Therefore they do not run when the
FILLhappens because theFILLis on a different instance of the ProDataSet. - When
fetchOrdersreturns, it does not copy anything back to PickOrder.w because theBY-REFERENCEqualifier tells the AVM to use the caller's instance of the ProDataSet. Because the fill events never fire to prepare the query and attach the Data-Sources, nothing happened and there is no data on the client.
The
design of orderSupport.p in this case requires
that the ProDataSet be passed by value. For this reason, you can
assure that the calls will be made properly by forcing the parameter
to be passed by value by using the BY-VALUE keyword
on the parameter definition in the called procedure. Then everything
works properly even if a local caller tries to use BY-REFERENCE.
The qualifier is simply overridden by the definition in the called
procedure, without error.
As with the earlier discussion about
when and how to use BY-REFERENCE, the implications
of its use can seem confusing. The best guideline is to pass ProDataSets BY-REFERENCE when
you expect that the procedure call will always, or at least sometimes,
be made locally (within the same session) in the deployed application
(where performance counts), and when you have structured your procedures
such that you will not have references to the wrong ProDataSet instance,
as could happen in the second example here. Passing a ProDataSet BY-REFERENCE can
be a valuable optimization, but it is only an optimization, and
you must always make sure that sharing the same ProDataSet instance
will not have unintended consequences.
Now, let us return to completing the example.