You have already been introduced to many of the ABL statements that manage data, either by reading records from a data source and making them available to the application in record buffers or by displaying data to the screen and saving changes from the screen. The chart in the following figure summarizes the scope of each of these statements relative to the four layers of interaction.
Figure 43. Data handling statements
From the chart in the previous figure, you can see that some single statements span more than one of the following layers in the system:
A record in a database table or temp-table
A record in a record buffer
A record in the screen buffer as the user sees it
An action by the user on the screen buffer
This makes these statements very economical (in terms of syntax requirements) in a host-based or client/server system, but problematic in a distributed system where the user and the screen buffer do not exist in the same session with the database. This means that some of these statements are not of great use in a distributed application and, as a result, you rarely (if ever) use them. These include:
INSERT table-name. — You saw a brief example of this statement in ProcedureBlocks and Data Access. As you can see from the previous figure, the INSERT statement starts at the database level with the creation of a new record, which the ABL Virtual Machine (AVM) then displays (with its initial values) in the screen buffer. The statement pauses to let the user enter values into the record's fields, and then saves the record back to the record buffer.
OPEN QUERY query-name (with a browse on a query against a database table) — There is a direct association between a browse object and its query. When you open the query, records from the underlying table are automatically displayed in the browse.
SET table-name or field-list. — The SET statement accepts input from the user in the screen buffer for one or more fields and assigns them directly to the record buffer.
UPDATE table-name or field-list. — The UPDATE statement displays the current values for one or more fields to the screen, accepts changes to those fields from the user, and assigns them back to the record buffer.
Each of these statements is implicitly (if not explicitly) followed by a record RELEASE that actually writes the record with its changes back to the database. The exact timing of that record release is discussed later in Makingsure you release record locks, but this means that these statements carry data all the way from the user to the database. Since this can't be done in a single session of a distributed application, you won't generally use these statements with database tables.
When can you still use them? As you've already seen, ABL provides the temp-table as a way to present and manage a set of records independent of the database and, in particular, as the way you should pass data from server to client and back. So you could use any of these statements against a temp-table in the client session, because the Database Record layer is, in fact, just the temp-table record in the client session. In particular, opening a query against a client-side temp-table and seeing that query's data in a related browse is the standard way to present tables of data on the client.
You've already seen the following statements in action:
ASSIGN table-name or field-list. — You can use this statement to assign one or more fields from the screen buffer to the record buffer, for example, on a LEAVE trigger for a field. You can also use it to do multiple programmatic assignments of values in a single statement, as in the ASSIGN field = valuefield = value . . . statement.
DISPLAY table-name or field-list. — This statement moves one or more values from a record buffer to the screen buffer. You could use this statement in a client procedure with a temp-table record, or with a list of local variables.
ENABLE field-list. — This statement enables one or more fields in the screen buffer to allow user input. Its counterpart, DISABLE, disables one or more fields.
FIND table-name. — This statement locates a single record in the underlying table and moves it into the record buffer. You could use this statement in server-side logic using a database table, or in a client-side procedure using a temp-table.
FOR EACH table-name: — This block header statement iterates through a set of related records in the underlying table and moves each one in turn into the record buffer. You could use this statement in server-side logic on a database table or client-side logic on a temp-table.
GET query-name. — This statement locates a single record in an open query and moves it into the record buffer.
REPOSITION (with browse) — The REPOSITION statement on a browsed query moves the new record into the record buffer.
There remain several new statements you'll learn about in the next chapter. These include:
CREATE table-name. — This statement creates a new record in a table and makes it available in the record buffer.
DELETE table-name. — This statement deletes the current record in the record buffer, removing it from the underlying table.
RELEASE table-name. — This statement explicitly removes a record from the record buffer and releases any lock on the record, making it available for another user.
In addition to these transaction-oriented statements, the PROMPT-FOR statement enables a field in the screen buffer and lets the user enter a value for it. In an event-driven application, you do not normally want the user interface to wait on a single field and force the user to enter a value into that field before doing anything else, so the PROMPT-FOR statement is also not a frequent part of a modern application. The INSERT, SET, and UPDATE statements similarly have their own built-in WAIT-FOR, which demands input into the fields before the user can continue. For this reason, these statements are also of limited usefulness in an event-driven application, even when you are updating records in a client-side temp-table.