Submenus
A submenu is a separate menu of choices that appears following the display of each master row in the retrieved data set for an attached query (either a simple attached query or a Master/Detail query). Choosing an operation from the submenu causes the designated action to be performed, such as incrementing a salary field or displaying the next master row. Submenu operations always apply to the master row.
When a query with a submenu is executed, the query runs to completion, and a data set is created in a temporary file to hold the selected rows. A submenu appears at the bottom of the frame. Each next statement (associated with an item on the submenu) causes the next row in the data set to be displayed. If this is a Master/Detail query, the master query is performed as above, and another query runs to completion to retrieve the matching detail rows for each master row.
The syntax used to create a submenu is:
objectname := select statement
[objectname := select statement]
begin | {
initialize = begin | {
statements /* statements executed before first row */
/* is displayed */
end | }
"menuitem1" = begin | {
code /* code for menuitem1 operation */
end | }
"menuitem2" = begin | {
code /* code for menuitem2 operation */
end | }
end | }
The submenu is separated from the rest of the select statement by braces or by a begin and end pair. In the syntax of a Master/Detail query, the submenu appears after both assignment statements.
Submenus can contain all the same components as main menus. Generally at least one of the menu operations must contain the 4GL next statement, which causes the next row selected to display.
You stay within the submenu until either (1) a next statement is executed after all the rows have been displayed, or (2) an endloop statement is executed. When either situation occurs, the frame's main menu is redisplayed, and control returns to the statement immediately following the assignment statement that contained the submenu.
A submenu is only displayed if the query retrieves rows. The submenu remains active after a resume or a failed validation with the validate statement.
The following example of a simple attached query selects a series of complex values from the database and creates a submenu for the current form:
empform := select lname, age, empnum
from empnum
where empnum <=10
begin
initialize =
begin
/* Statements here are executed once */
/* before the first row is displayed */
message 'Now within submenu';
sleep 3;
end
field 'lname' =
begin
message 'You just entered value: ' +
lname;
sleep 3;
resume next;
end
'Increment' =
begin
age := age + 1;
end
'NextRow' =
begin
next;
end
'End' =
begin
endloop;
end
end;
When you choose an operation from the main menu containing this assignment statement, the following submenu appears at the bottom of the frame:
Increment NextRow End
The first row retrieved is displayed in the three fields specified. Each time you choose the NextRow operation from the submenu, the next row is displayed. When there are no more rows, the message "No rows selected" appears at the bottom of the window, and you exit from the current submenu. The main menu for the frame reappears.
If no rows in the database satisfy the query, the message "No rows retrieved" appears at the bottom of the frame, and control transfers to the statements immediately following the assignment containing the submenu.
The submenu definition can contain any legal operations, including menu, key, and field activations.
The first submenu operation definition can be an initialize block. Unlike the initialize block for a frame, the initialize block in an attached query cannot contain variable declarations. The initialize block for the attached query is executed only once, after the master row and matching details have been selected from the database and before their values have been displayed. Both 4GL and SQL statements appears in the initialize block.
The submenu initialization can be used to change the from mode. The default mode is Update. When you exit the submenu, you return to the mode that was in effect when the submenu was invoked, regardless of whether this initial mode was set by the set_forms or mode statement.
The code in the submenu can contain any legal 4GL code. This includes query statements, such as update and delete, as well as other assignment statements involving selects. A return or exit statement within the submenu has the same effect as a corresponding statement from the main menu of the frame. The resume and validate statements operate in the same manner as they do in the main menu; however, if they close the current operation, the submenu is still displayed.
While the submenu is running, the value of the rowcount FRS constant is undefined. Rowcount only has a value when the submenu ends. The single exception is when a query statement in the submenu code is executed; then rowcount is set for that query statement.
Note that when the assignment statement containing the submenu is executed, ABF displays the current form in update mode. You can change this mode in the initialize section of the submenu. When the end user exits from the submenu, the display mode in effect prior to the submenu again takes effect.
Queries with a submenu, like any other query, are always part of a transaction. Shared locks are held on the selected data until the next commit or rollback statement.
You can override this default behavior and cause no locks to be held on the selected data by one of the following methods:
• If your application has previously issued set autocommit on, then a commit is automatically performed after every successfully executed query.
• If you have turned off read locks with the set lockmode statement on the table from which you are selecting, then no locks are held on the table. However, a transaction is still in progress.
It is possible to use a submenu without using an attached query. For this purpose, 4GL provides the run submenu and display submenu statements. See the appropriate sections in this chapter.
Nesting Attached Queries
4GL provides the capability to nest attached queries to any level. Each nested query is placed within the submenu of the higher-level query. Thus, the following syntax is valid:
formobject := database_expression
formobject := database_expression
{
"menuitem1" = {
formobject := database_expression
formobject := database_expression
{submenu}
}
};
In nested queries, if the from clause is the last clause in a master query, then the last table name in the from clause must be followed by a correlation variable (corrname in the syntax diagrams for select).
For nested queries with a submenu, the value of the rowcount FRS constant is undefined while the submenu is running. Rowcount only has a value when the submenu ends. The single exception is when a query statement in the submenu code is executed; then the rowcount is set for that query statement.