|
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 REC
The 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 RETRIEVALSpecifies 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 SUBPROCEDUREEXIT 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
![]() ![]() ![]() ![]() |