|
VisualPQL | Control Flow |
The simple IF
,IFNOT
commands test a logical condition and execute one or more commands immediately if the condition is satisfied.
The JUMP
command transfers control to a specific point in the program identified by a statement label.
Subprocedures are parts of a routine that can be executed from any point within that routine, returning control to the next statement. Subprocedures are defined at the end of the routine and share data with the routine.
END
command. Block structures are used for all database and table access.
Blocks consist of a command that starts the block and an end command that ends the block (e.g. LOOP / END LOOP
). Blocks may be nested within other blocks and an inner block
must be completely within an outer block. Blocks may not overlap. The block structures are:
A block of commands executed after all other processing. (There is no END AFTER
; this block is delimited by the end of the program or retrieval.)
BEGIN
A block of commands executed at this point.
FOR
A block of commands executed a specified number of times.
IFTHEN
A block of commands executed when a condition is true. IFNOTTHEN
is a variant that executes the block when a condition is false.
CASE IS
, RECORD IS
and ROW IS
.
These blocks relate to one occurrence of a particular database record or row. Specify the key to identify the record on the command. The commands have variants using the keywords NEW
and OLD
. These specify that the block is only executed if the record created/already
exists.
The JOURNAL RECORD IS
creates a block that processes data from a journal entry that matches the specified record type. This can only be used inside a PROCESS JOURNAL
block.
LOOP
A block of commands executed repeatedly until specifically ended (typically by an EXIT LOOP
).
PROCESS CASE
, PROCESS RECORD
, PROCESS DATA
and PROCESS ROW
.
A block of commands executed once for each occurrence of a record in a database or row in a table.
PROCESS JOURNAL
specifies a block of commands that is executed once for each occurrence of matching records on a database journal.
UNTIL
A block of commands executed until a specified condition is met.
WHILE
A block of commands executed as long as a specified condition is met.
The EXIT
and NEXT
commands further control processing within the block. EXIT
passes control to the first command after the end of the block; NEXT
goes to the next iteration of a looping block.
The logical condition can also contain the NOT operator:
NOT
|
NOT operates on a logical expression and negates its logical value. A true (non-zero, non-missing) expression is made false and a false expression is made true. NOT operates on the expression that follows up through the next relational operator or the next un-matched right parenthesis. NOT is evaluated and resolved after the entire expression to which it applies has been resolved and before other logical operators at the same level of nesting are evaluated. For example:
IF( NOT 1 GT 2 ) WRITE 'TRUE' |
AND
|
Intersection. True if both expressions are true.
|
OR
|
Inclusive Union. True if either expression is true.
|
XOR
| Exclusive Union. True if one but not both expressions are true. |
These logical expressions resolve to either true or false. For example,
IF(1 LT 2 AND 'A' LT 'B') WRITE 'Both statements are true'
IF(ID EQ 1 OR 3 OR 12 OR 16) WRITE IDThe phrase 'ID EQ' is assumed to follow each 'OR' making this equivalent to:
IF(ID EQ 1 OR ID EQ 3 OR ID EQ 12 OR ID EQ 16) WRITE ID
The following two statements are equivalent:
IF (ID EQ 1 OR ID GT 10) WRITE 'TRUE' IF (ID EQ 1 OR GT 10) WRITE 'TRUE'The following two statements are also equivalent:
IF (ID EQ A OR B AND NOT C) WRITE 'TRUE' IF (ID EQ A OR ID EQ B AND NOT ID EQ C) WRITE 'TRUE'
IF
commands can directly test expressions that resolve to numeric values. Zero tests to false, missing tests to false and all other values test to true. In the following example, LOGICVAR
contains the value 0 (zero) if the value of A does not equal the value of B, or 1 if it does:
COMPUTE LOGICVAR = (A EQ B)
IF (LOGICVAR) WRITE 'TRUE'
Because of the simple syntax for multiple tests on a single variable, compound conditions on logical variables must be specified with care. Consider the following two statements,
IF ( LOGVAR1 AND AGE GT 21) WRITE 'TRUE' IF ( AGE GT 21 AND LOGVAR1) WRITE 'TRUE'
The first statement test LOGVAR1
to be 1 (true) and AGE
greater than 21. However the second statement is expanded to:
IF ( AGE GT 21 AND AGE GT LOGVAR1) WRITE 'TRUE'
IF ( logical expression ) command(s) IFNOT ( logical expression ) command(s)
IF
executes the specified command or commands when the logical expression is true. When the logical expression is false, program execution continues with the next executable command. IFNOT
executes the specified command or commands when the logical expression is false. When the logical expression is true, program execution continues with the next executable command.
Any VisualPQL command may be specified as the executable result of an IF/IFNOT
except:
Separate multiple commands with semi-colons (;). For example:
IF (1 EQ 1) SET X(1); WRITE 'OK' IF (X EQ 1) SET X(0); WRITE 'OK 2'; EXIT RETRIEVAL PROCESS REC EMPLOYEE . IFNOT(SALARY GE 2000) NEXT REC . WRITE NAME SALARY END RECThe example goes to the next record when salary is not greater than or equal to 2000 and also when salary is missing (because the expression is treated as false).
JUMP statement label JUMP (statement label , statement label, ...) variable
JUMP
transfers control to the point in the program identified by the specified statement label. Execution continues serially from that point. It is possible to jump to a statement label or to fall through to it from the normal flow of control. A JUMP
command must be at an equal or higher level of nesting and within the same nested set as the statement label that it references. JUMP
can jump out of a block, but not into the middle of a more deeply nested block. JUMP
can not jump out of or into a SUBROUTINE
or SUBPROCEDURE
.
Specify a statement labels as the first element on a line. A statement label is a name followed by a colon (:). When referenced in the JUMP
command, do not specify the colon. If you need to use a non-standard name (enclosed in curly brackets {}) as a label in PQL, there is a possible conflict with the syntax for command labels used to control command processing. Avoid this conflict by indenting the label and specifying a full stop in column 1.
The first form of JUMP
specifies a single statement label and transfers control to the command after the label.
The second form of the command, the computed JUMP
, transfers control to the nth label in a specified list of labels, where the numeric variable contains the value N.
AFTER PROGRAM
or AFTER RETRIEVAL
Specifies a block of commands executed when the program or retrieval is complete. The block is typically used to print report ending information and for actions that are taken just before ending the program.
Table, case or record processing commands are not allowed. Reference may not be made to any data in the database or table files. Local variables are available for output.
This command is typically used with the Full Report Procedure.
AFTER PROGRAM
is identical to AFTER RETRIEVAL
, except that it is used in programs rather than retrievals.
BEGIN
Specifies the beginning of a block of commands. The commands in a BEGIN
block are executed when control reaches this point.
END BEGIN
Delimits the BEGIN
block.
EXIT BEGIN
Transfers program control to the statement following the END BEGIN
command. It is usually used conditionally to terminate processing of the block.
BEGIN
can be used to anywhere in a program to group a set of commands that have some common purpose. For example, initialisation at the start of the program.
PROGRAM
BEGIN
. COMPUTE TOTAL = 0
. other initialisation commands
END BEGIN
PROCESS ROWS SCHOOLS.STUDENTS
. COMPUTE TOTAL = TOTAL
+ 1
. other commands performed for every row
END ROW
END PROGRAM
BEGIN
is often used to create a better structure in a program with complex logical conditions and to avoid the use of JUMP
or very complex IFTHEN / ELSEIF
constructs. For example:
BEGIN
. IF (logical condition) EXIT BEGIN
. visualpql code
. IF (logical condition) EXIT BEGIN
. IF (logical condition) EXIT BEGIN
. visualpql code
END BEGIN
EXIT [ blocktype ]
EXIT
blocktype stops execution of the block at that point and transfers control to the first command following the END
blocktype command. An EXIT
can be used in any block. If the blocktype is specified, the command exits the innermost block of that type. If the blocktype is not specified, the command exits the innermost block. It is good practice to specify blocktype. An EXIT
command may be specified in the following blocks:
FOR control_var = startvalue, endvalue [ ,increment ]
The FOR
command specifies the number of times the commands in a FOR
block are executed. FOR
assigns a new value to the control variable each time the block is repeated.
The following sequence is executed in a FOR
block:
FOR
block is skipped.
FOR
block is within a record or case block), the database variable is updated on each pass through the block.
FOR
block is not performed when the start value is larger than the end value. When increment is negative the FOR
block is not performed when the start value is smaller than the end value.
IFTHEN (logical_expression) IFNOTTHEN (logical_expression)
The IFTHEN
command defines a block of commands that is executed conditionally.
In its simplest form, IFTHEN
defines a block of commands that is executed when a logical expression is true. An IFNOTTHEN
block of commands is executed when the logical expression is false. Any command may be included within an IFTHEN
or IFNOTTHEN
block, including other complete blocks of commands and other logical test commands.
Other conditional blocks within the condition, can be defined with the ELSE , ELSEIF
, and ELSEIFNOT
commands. Each conditional block is terminated with another ELSEIF
, ELSE
or the END IF
. An IFTHEN
block may contain multiple ELSEIF
and ELSEIFNOT
blocks. It may only contain one ELSE
block.
IFTHEN (logical expression) . commands executed when above expression is TRUE . ELSEIF (logical expression) . commands executed when above expression is TRUE . ELSEIFNOT (logical expression) . commands executed when above expression is FALSE . ELSE . commands executed when no other blocks are executed END IF
LOOP
LOOP
repeatedly executes a block of commands. By definition, a LOOP
block is an infinite loop and a command such as EXIT
or JUMP
must be used to terminate looping. The compiler does not check for the existence of these commands within a LOOP
.
NEXT [ blocktype ]
Some blocks (e.g. WHILE
) are looping structures and execute repeatedly until some controlling condition is met. In looping blocks, the NEXT blocktype
command transfers control to the first command in the block at the next iteration.
If the blocktype is specified, the command transfers control to the next iteration of the innermost block of that type. If blocktype is not specified, control is transferred to the next iteration of the innermost looping block. It is good practice to specify blocktype. NEXT
may be specified in the following looping blocks:
NEXT CASE
|
Transfers control to the next iteration of PROCESS CASES if another case exists.
|
NEXT FOR
|
Transfers control to the next iteration of the FOR , if the end condition specified on the FOR has not yet been reached. |
NEXT LOOP
|
Transfers control to the next iteration of the
LOOP .
|
NEXT REC
|
Transfers control to the next iteration of PROCESS RECORDS if another record exists. |
NEXT DATA
|
Transfers control to the next iteration of PROCESS DATA if another record exists. |
NEXT ROW
|
Transfers control to the next iteration of PROCESS ROWS if another row exists.
|
NEXT UNTIL
|
Transfers control to the next iteration of the UNTIL , if the end condition specified on the UNTIL has not yet been reached. |
NEXT WHILE
|
Transfers control to the next iteration of the WHILE , if the end condition specified on the WHILE has not yet been reached. |
For example:
PROCESS REC EMPLOYEE . IF ( GENDER = 1 ) NEXT PROCESS REC ... END PROCESS REC
UNTIL (logical expression)
UNTIL
repeatedly executes a block of commands until the logical expression becomes true. When the expression becomes true, the block is exited and program control is transferred to the statement following the END UNTIL
command.
The condition of the logical expression is tested at the start of each pass through the UNTIL
block. If the condition is initially true, the block is skipped entirely.
WAIT num_expPauses execution of this program for the specified number of tenths of a second.
PROCESS RECORD PATIENT LOCK = 4 | get the patient record . LOOP . IF(SYSTEM(36) = 1) EXIT LOOP | exit if we get the record . WRITE 'Waiting for locked record' . WAIT 5 | wait half a second . RETRY RECORD | try to get the record . END LOOP ... END PROCESS RECORD
WHILE (logical expression)
WHILE
repeatedly executes a block of commands while the expression is true. When the expression becomes false, execution of the block is terminated and program control is transferred to the statement following the END WHILE
. The condition of the expression is tested at the start of each pass through the WHILE
block. If the condition is initially false, the block is skipped entirely.
SUBPROCEDURE name [ NOAUTOCASE ]
A subprocedure is a named, structurally complete, block of commands that may be executed from any point within a routine with the EXECUTE SUBPROCEDURE
command. Subprocedure names must be unique within the routine. A subprocedure is compiled with, and belongs to, the routine it is defined in. A subprocedure shares variables with the routine and other subprocedures and has access to all variables available to the routine in which it is defined. Declare any variables used by the routine before they are referenced. (i.e. do not declare new variables in the subprocedure that are referenced by the routine.)
Define subprocedures at the end of the routine ahead of any VisualPQL Procedures or an AFTER RETRIEVAL
block. There is an implicit STOP
(or RETURN
if the routine is a subroutine) just before the first subprocedure.
The SUBPROCEDURE
command begins a subprocedure definition. The subprocedure definition ends with the END SUBPROCEDURE
command.
END SUBPROCEDURE
END SUBPROCEDURE
ends the block of subprocedure code. Control is passed back to the first command following the EXECUTE SUBPROCEDURE
command that invoked the subprocedure.
EXIT SUBPROCEDURE
EXIT SUBPROCEDURE
exits the subprocedure and control is passed to the first statement following the EXECUTE SUBPROCEDURE
command that invoked the subprocedure.
EXECUTE SUBPROCEDURE name
Transfers control to the first line of code in the named subprocedure. When the subprocedure is exited, control returns to the first statement following the EXECUTE SUBPROCEDURE
. This command may appear anywhere in a routine including within a subprocedure.
Subprocedure Example:
PROGRAM TIME NOON NOWTIME ('HHiMM') | declare time variables COMPUTE NOON = '12:00' | set the value of midday COMPUTE NOWTIME = NOW(0) | get the current time IFTHEN (NOWTIME LT NOON) . EXECUTE SUBPROCEDURE MORNING | execute MORNING . ELSE . EXECUTE SUBPROCEDURE AFTERN | execute AFTERN ENDIF SUBPROCEDURE MORNING . WRITE 'Good Morning' END SUBPROCEDURE SUBPROCEDURE AFTERN . WRITE 'Good Afternoon' END SUBPROCEDURE END PROGRAM