Release 10.1A: OpenEdge Development:
Progress 4GL Handbook

> ## Queries versus block-oriented data access

> The first and most obvious characteristic of queries is precisely that they are not block-oriented. The language statements you’ve used in the last few chapters are all tied to blocks of 4GL code. You define a result set inside a block beginning with `DO`, `FOR`, or `REPEAT`. The result set is generally scoped to the block where it is defined. The term result set denotes the set of rows that satisfy a query.

> You learned which of the block types iterate through the result set automatically and which require you to explicitly find the next record.

> Even the `FIND` statement itself, although it does not define a block, is subject to the same rules of record scoping. You’ve learned how the presence of record-oriented blocks like a `FOR EACH` block and `FIND` statements together define the scope of a record buffer within a procedure.

> These are among the most powerful features in the Progress 4GL. They help give it its unique flexibility and strength for defining complex business logic in a way that ties data access statements closely to the logic that uses the data.

> However, there are times when you don’t want your data access tied to the nested blocks of 4GL logic in your procedures. Earlier chapters briefly discussed the notion of event-driven applications. The examples you built in the chapter on the AppBuilder are a small but representative example of this. Think about the procedure `h-CustOrderWin1.w`, for instance. When you run this, a Customer and its Orders are displayed for you, as shown in Figure 10–1.

> Figure 10–1: Customers and Orders sample window

> Iterating through the data, for example through all the Customers in New Hampshire, isn’t done inside a block of 4GL logic. It’s done entirely under user control. Defining the Customer result set and its Order result set using queries is essential to this. When the user clicks the Next button, the code retrieves and displays the next record in the result set:

>     DO:
>       GET NEXT CustQuery.
>       IF AVAILABLE Customer THEN
>         DISPLAY Customer.CustNum Customer.Name Customer.Address Customer.City
>                 Customer.State
>           WITH FRAME CustQuery IN WINDOW CustWin.
>       {&OPEN-BROWSERS-IN-QUERY-CustQuery}
>     END.

> This happens independently of the block of code where the query is defined, or where it is opened. This gives you great flexibility as a developer to let user interface events, or other programmatic events, determine the flow of the application and the processing of data. By contrast, the examples you built in Chapter 7, "Record Buffers and Record Scope,"were chunks of logic that executed independently of the user interface, such as in the procedure `h-BinCheck.p`, which does some calculations and returns the results to another procedure.

> This is the essence of the difference between queries and block-oriented data access. You use queries when you need to keep the data access separate from the structure of the procedure, and instead control it by events. You use block-oriented data access when you need to define business logic for data within a defined scope.

> Thus queries give your data access language these important characteristics:

> - Scope independence — You can refer to the records in the query anywhere in your procedure.

> - Block independence — You aren’t required to do all your data access within a given block.

> - Record retrieval independence — You can move through the result set under complete control of either program logic or user events.

> - Repositioning flexibility — You can position to any record in the result set at any time.

Copyright © 2005 Progress Software Corporation www.progress.com Voice: (781) 280-4000 Fax: (781) 280-4095