Try OpenEdge Now
skip to main content
ProDataSets
ProDataSet Attributes and Methods : Enhanced query support for ProDataSet buffers
 

Enhanced query support for ProDataSet buffers

As you have seen from looking at the WHERE-STRING attribute for the Data-Relation and FILL-WHERE-STRING for the Data-Source, the AVM generates default queries for the purpose of copying database data into the ProDataSet during a FILL, and navigating and filtering that data after the FILL. Note that a query expression, such as WHERE OrderLine.OrderNum = ttOrder.OrderNum, is not usable in a QUERY-PREPARE for a query that is not part of a ProDataSet. In a standard query, you have to construct the where-clause out of multiple strings, one of which evaluates to the value of the field in the parent table at the time the QUERY-PREPARE is done. You then have to re-execute the QUERY-PREPARE and the QUERY-OPEN each time the value changes. For example, look at this stand-alone procedure:
DEFINE VARIABLE hQuery AS HANDLE NO-UNDO.

DEFINE TEMP-TABLE ttOrder NO-UNDO LIKE Order.

CREATE ttOrder.
FIND Order WHERE Order.OrderNum = 1.
BUFFER-COPY Order TO ttOrder.

CREATE QUERY hQuery.
hQuery:ADD-BUFFER(BUFFER OrderLine:HANDLE).
hQuery:QUERY-PREPARE
  ("FOR EACH OrderLine WHERE OrderLine.OrderNum = ttOrder.OrderNum").
This compiles successfully, but generates the following error at run time:
This has been a limitation ever since dynamic queries were introduced into the language. The AVM cannot parse out ttOrder.OrderNum from the rest of the where-clause and insert the current value of the field. Instead you must code it this way:
DEFINE VARIABLE hQuery AS HANDLE NO-UNDO.

DEFINE TEMP-TABLE ttOrder NO-UNDO LIKE Order.

CREATE ttOrder.
FIND Order WHERE Order.OrderNum = 1.
BUFFER-COPY Order TO ttOrder.

CREATE QUERY hQuery.
hQuery:ADD-BUFFER(BUFFER OrderLine:HANDLE).
hQuery:QUERY-PREPARE
  ("FOR EACH OrderLine WHERE OrderLine.OrderNum = " +
  STRING(ttOrder.OrderNum)).
However, when a query is associated with a buffer that is a member of a ProDataSet, it has enhanced rules for what will compile in its dynamic predicate. As you can see from this example, the predicate of a normal query on a normal buffer is limited to an expression involving exclusively either constants or fields from the buffer's table itself. But if the buffer is part of a ProDataSet, this restriction is relaxed to allow references to any other member buffers in the ProDataSet. Also, if the buffer is part of a Data-Source, you might be able to do a dynamic FIND on it using the tables in any attached ProDataSet buffer. If the buffer is part of a query that is attached to a Data-Source, you also might be able to do a dynamic QUERY-PREPARE on it, referencing the Data-Source's ProDataSet target buffers.
This means, for example, that given a ProDataSet for ttOrder and its ttOrderlines, the Data-Source query for populating the ProDataSet temp-table ttOrderline from the OrderLine database table can reference the parent temp-table ttOrder directly. In such a case, the AVM automatically generates and manages queries that use the information in the Data-Relations to filter the current set of ttOrderLine records for a ttOrder. Internally, the AVM can take advantage of internal buffer references to insert a key value such as ttOrder.OrderNum into the ttOrderline query without having to re-prepare the ttOrderline query each time the selected ttOrder changes. This greatly increases the run time efficiency compared to what you would have to do in ABL code to re-prepare and re-open a child query each time the parent row changes.
* QUERY attribute for Data-Sources, Data-Relations, and buffers
* KEYS attribute for buffers
* TOP-NAV-QUERY attribute