Dynamic query methods and attributes
- Last Updated: October 15, 2024
- 10 minute read
- OpenEdge
- Version 13.0
- Documentation
Once you create a dynamic query or assign a handle to a static one, you can retrieve (and, in some cases, set) information about the query using its methods and attributes. This section provides a summary of those methods and attributes. Unless otherwise noted, they all apply to handles for both static and dynamic queries.
DYNAMIC attribute
The DYNAMIC attribute returns TRUE if the query is dynamic and FALSE if it is static.
SET-BUFFERS() method
The SET-BUFFERS( ) method takes a buffer handle or a comma-separated list of buffer handles and sets the query’s buffer list to those buffers. It returns TRUE if the operation succeeded and FALSE otherwise.
- Using the
BUFFER buffer-name:HANDLEsyntax, which provides a handle for a static buffer on a known table. - Using a handle variable or field that you associate with a static buffer in
a separate statement, such as
hBuffer = BUFFER buffer-name:HANDLE. - Using the handle for a dynamic buffer, where you name the table only at run time.
Order and Customer
buffers:
|
|
|
This raises the basic question of when to use static and when to use dynamic queries.
Typically, unless your procedure is of such general use that you do not know the
tables or buffers it will use until run time, you can define a static query and then
use its handle to modify it as needed at run time. This is the case if, for example,
you need to modify the WHERE clause or sort order of the query in a
variety of ways at run time. If you start with a static query, you can use any
combination of the static statements you’re familiar with to manipulate it, such as
GET FIRST, OPEN QUERY, and so forth, or their
dynamic equivalents, which are introduced in the following section. If you start
with a dynamic query, you can use only dynamic methods to manipulate it.
The one aspect of a static query you cannot modify at run time is its buffer
list, so the SET-BUFFERS() method applies only to
dynamic queries.
ADD-BUFFER() method
The ADD-BUFFER( ) method takes a single buffer handle as an argument and adds it to the list of buffers for the query. In this way, you can have a programming loop that adds a sequence of buffers to a query one at a time, when that is appropriate and when your query needs to join two or more buffers. It returns TRUE if the operation succeeded and FALSE otherwise.
ADD-BUFFER()
method to add a third buffer to the query that already has the Order and Customer
buffers assigned to it:
|
Like the SET-BUFFERS() method, ADD-BUFFER() is
supported only for dynamic queries for the same reason that you cannot modify the
buffer list of a static query.
NUM-BUFFERS attribute
|
GET-BUFFER-HANDLE() method
|
This is the result of running the code:
NAME attribute
NAME attribute
only applies to static queries:
|
QUERY-PREPARE() method
FOR EACH statement that it should use to retrieve order data when
you open the query. The QUERY-PREPARE( ) method takes the FOR
EACH statement as its argument. It returns TRUE if the operation
succeeded and FALSE otherwise. You can use QUERY-PREPARE() to
define the record selection for a dynamic query or to change the selection for a
static one. This sample code prepares the dynamic query for the
Order, Customer, and SalesRep
tables:
|
QUERY-PREPARE() raise ERROR if the block they occur in
contains a CATCH block. Thus, you could replace the
IF statement with a CATCH block for more
readable code. See ABL Error Handling for more information.- Remember that when you use a one-to-one join in a
FOR EACHstatement for a query, you must include theFIRSTorEACHkeyword in each table phrase, as is shown in the following code example. Since there is just oneCustomerfor eachOrder, and oneSalesRepfor eachOrder, there is no need to iterate through potentially multipleCustomersorSalesRepsfor anOrder, so theFIRSTkeyword suffices.In aFOR EACHstatement in a block header, theFIRSTkeyword would be optional, as in this example:FOR EACH Order WHERE OrderStatus = "Ordered", Customer OF Order, SalesRep OF Order: DISPLAY OrderNum Order.CustNum Customer.NAME SalesRep.RepName. END. - If you know exactly what the
WHEREclause andBYclause are when you write the procedure, you might not need to use dynamic constructs at all. More realistically, you use theQUERY-PREPARE()method when you don’t know the selection and sort criteria until run time. - Since you normally use the
QUERY-PREPARE()method in cases where theWHEREclause is truly variable, it is essential that you always assign the result of the method to a logical variable, and then check the value of that variable and theERROR-STATUS:NUM-MESSAGESvalue to be sure that the prepare succeeded. If it does not and you continue without intercepting the error, your procedure generates a whole series of error statements as you attempt to open and use the query.
PREPARE-STRING attribute
FOR EACH
statement is using through the PREPARE-STRING attribute, which returns the effect of the most recent
QUERY-PREPARE() method, as in this example:
|
The PREPARE-STRING attribute applies only to dynamic queries. It does not
return the FOR EACH statement used in an OPEN
QUERY statement for a static query.
.
QUERY-OPEN() method
|
The QUERY-PREPARE() and QUERY-OPEN() methods
together accomplish what the OPEN QUERY statement does for a static
query. The two methods are separated out to enable you to define the selection and
sort criteria for a query separately from opening it. You might want to reopen the
same query several times with the same FOR EACH statement, for
example, to capture changes to the underlying data the FOR EACH
statement retrieves. Having two separate methods gives you this flexibility. It also
allows you to verify that the FOR EACH statement in a
QUERY-PREPARE() is valid before you try to open the query.
QUERY-PREPARE() and QUERY-OPEN()
methods with static queries as well, even after the query has been opened one or
more times with a static OPEN QUERY statement. Here’s an example
that extends the static query shown earlier:
|
PREPARE-STRING
attribute on a static OPEN:
Using the QUOTER function to assemble a query
FOR EACH statement:
|
The first literal ends with a single quote mark, which precedes the
SalesRep initials. This, in turn, is followed by another
literal that begins with a single quote mark to balance the first one. This kind of
assemblage of strings with and without quote marks can get very tricky and lead to
code that is hard to read and programming errors that are hard to identify. Here,
for example, you need to remember not only to put the quote marks into the statement
before and after the cSalesRep value, but also to use single quotes
so that they don’t interfere with the use of double-quotes around the literals
themselves. You could reverse these and use double quotes inside single quotes, but
either way you need to be sure to balance them and embed them properly.
QUERY-PREPARE() as arguments to the
QUOTER function, the ABL Virtual Machine (AVM) assembles the
string properly so that you don’t need to worry about where the embedded quote marks
go. For instance, here’s an alternative version of the
QUERY-PREPARE() method that uses
QUOTER:
|
SalesRep initials for you:
You can use QUOTER to avoid parsing errors for numeric values as
well as string values. For example, DECIMAL formats in parts of the world outside
the United States typically reverse the meaning of the decimal point or period/full
stop (.) and comma (,) characters. If you use
QUOTER on all such values, the AVM assembles a query string
that compiles properly without causing confusion to the syntax analyzer, which must
interpret whether the “.” character is a decimal point, a separator
between thousands in a numeric value, or the end of a statement.
QUERY-CLOSE() method
|
QUERY-CLOSE() returns TRUE if the operation succeeded and FALSE
otherwise. As with the CLOSE QUERY statement, you don’t need to use
QUERY-CLOSE() if you are immediately again preparing and
reopening a query, but you should close a query when you are done using it. You can
freely mix and match static OPEN and CLOSE
statements and QUERY-OPEN() and QUERY-CLOSE()
methods for static queries but, as with all the query syntax, you can use the static
statements only for static queries.
QUERY-OFF-END attribute
The QUERY-OFF-END attribute corresponds to the
QUERY-OFF-END function for static queries. It returns TRUE if
the query is no longer positioned to a record in the result set, either because you
have proceeded beyond the last row or moved backward beyond the first row.
IS-OPEN attribute
The LOGICAL IS-OPEN attribute returns TRUE is the query is open and FALSE otherwise.