This chapter describes two important capabilities within ACCENT R: Conditional Clauses and Expressions. Conditional Clauses, which limit or restricts execution the scope of a command or statement, are made up of an introductory preposition (e.g., IF or ; WHEN) followed by an expression. Conditional Clauses must always contain expressions.
Expressions, on the other hand, have many uses outside conditional clauses. The: most notably are as function arguments and in any context that assigns a value to a field.
The different operators - relational, logical, arithmetic, string, and date - are all explained here, since they are the "action elements" of expressions.
ACCENT R provides a particularly valuable set of capabilities for manipulating dates, and these are discussed in the last part of this chapter.
Since Conditional Clauses and Expressions are language elements and allowed in most commands and statements, they are presented first.
Many ACCENT R commands and statements enable execution to be controlled through the use of conditional clauses. A conditional clause specifies the criteria that must be met for the specified action to take place. For example, the command:
EXTRACT IF DIST='DENVER' AND QTY GT 100
Specifies that each record in the Data Set (DS) is to be tested, and only those records are to be extracted in which the field DIST contains the value DENVER and the field QTY contains a value greater than 100. Similarly, the clause
UNLESS ONHAND<QTY
Specifies that the current ACCENT R command is to execute unless the field ONHAND contains a value less than the field QTY.
Most conditional clauses begin with the word IF or the word UNLESS, and contain one or more relational expressions separated by AND or OR.
Some valid conditional clauses follow:
UNLESS AGE GE 21
IF LNAME BEGINS WITH 'SE' OR 'SI'
IF (DIST=1 OR 4) AND WAREHOUSE=9 IF
ONHAND+ONORDER<200 AND >0
UNLESS QTY*PRICE LT 2000-DISCOUNT
IF DIV=5 AND (SALESMAN=41 OR 42 OR 93)
There are two additional kinds of conditional clauses; each used in a special processing situation. Each is introduced by a unique word that alerts ACCENT R to the special processing wanted.
The STOP/END conditional clause terminates processing of a Data Set (DS) when the conditions are met. Since this clause does not examine all records in the DS, it uses fewer computer resources than the IF/UNLESS clause.
If you have a data set with 100,000 records and you are looking for the record with the name “ADAM”, it might be record 841 and the following command would prevent you from reading the 99159 records.
EXTRACT END IF NAME = “ADAM” IF NAME = “ADAM” SHOW ADDRI, ADDR2
The END clause will process no other record after this record is found and the if clause instructs the EXTRACT command to only display the records containing “ADAM”.
The difference between STOP and END is that with STOP record processing terminates when the condition is satisfied and the record meeting the criteria is not considered for processing. On the other hand, with the END clause, this record is processed.
The WHEN conditional clause is used only when access to a DS is through a DI. It can only test fields that are key fields in the domain used, but it is very efficient, because it examines the index rather than the DS. See Chapter 9 on Interactive Commands for a complete description.
A relational expression consists of an operand and a relational operator, usually followed by another operand. The operands can be arithmetic expressions, constants, string expressions, fields, functions, or date expressions. Note that processing of a Data Set (DS) can be preceded by the clarity word IS or DOES. Any relational operator can be negated by preceding it with NOT. If a clarity word and NOT are used together, the IS or DOES must precede the NOT:
"IF FLD DOES NOT BEGIN WITH 'A'".
The valid relational operators are shown in the following two tables.
When alpha or character data are compared, two ENABLE; DISABLE options will affect the result: FIELDTRIM and SEQUENCE LOWER.
The general relational operators, in Table 6-1, can be used with expressions of any data type.
RELATIONAL OPERATOR | MEANING | EXAMPLE |
> or GT | Greater Than | QTY>50 |
= or EQ | Equal To | DIST='DENVER' |
< or LT | Less Than | AGE<21 |
#, <>, ><, or NE | Not Equal To | MODEL#4 |
>=, =>, or GE | Greater Than or Equal To | PAY GE 300 |
<=, =<, or LE | Less Than or Equal To | PAY LE 300 |
BETWEEN...AND |
Between...and, inclusive. Same as > = x AND < = y. The AND is not a logical operator in this context. |
QTY BETWEEN 5 AND 10 |
Table 6-1 General Relational Operators
The relational string operators, in Table 6-2, are valid only with character or alpha data or expressions. If ENABLE FIELDTRIM is in effect, or if the system function @RTRIM is applied to the value, trailing blanks are trimmed when the string value in a field or literal is tested. Leading blanks can be trimmed with the system function @LTRIM.
Four of the string operators are unary: that is, they take only one operand. They are ALPHA, CALENDRICAL, INTEGRAL, and NUMERIC.
RELATIONAL OPERATOR |
MEANING | EXAMPLE |
ALPHA |
Contain(s) only letters and spaces. |
NAME ALPHA |
BEGIN/S/ |
All characters of first operand match beginning characters of second operand. |
FLDA BEGINS "YES", "NO" |
BEGIN/S/ WITH |
Beginning characters of first operand match all characters of second operand. |
CITY BEGINS WITH 'SAN' |
CALENDRICAL |
Resembles a date and could be converted to one with the @CAL function. Note: CALENDRICAL does not work with strings that can be processed with @DTVAL. |
INV.DATE CALENDRICAL |
DESCRIBE/S/ |
Represents a value defined by the quoted mask. See mask description that follows this table. |
'###-####' DESCRIBES PHONE |
END/S/ |
All characters of first operand match ending characters of second operand. |
'SON' ENDS LNAME |
END/S/ WITH |
Ending characters of first operand match all characters of second operand. |
LNAME ENDS WITH 'SON' |
HAS, HAVE |
First operand contains second operand. |
DESC HAS 'ELEC' |
IN |
First operand is contained in second operand. |
'BIN' IN LICENSES |
INTEGRAL |
Contain(s) only digits, plus sigh (+), minus sign (-), and blanks. Resembles an integer and could be converted to one with the @IVAL function. |
PCODE INTEGRAL |
LOOK/S/ LIKE |
Conforms to the specified description. See mask description that follow this table. |
FIELD LOOKS LIKE ###=#### |
NUMERIC |
Contain(s) only digits, periods (.), plus (+), or minus (-) signs, and leading or trailing blanks; must contain at least one digit. Resembles a real or numeric value and could be converted to one using the @RVAL or @NVAL function. |
PRICE NUMERIC |
Table 6-2 Relational String Operators Continued
The relational operators that are made up of letters must be preceded and followed with blanks, e.g., QTY GT 25. The operators made up of signs need not, but can, be preceded and followed with blanks, e.g., QTY>25.
The masks for LOOK/S/LIKE and DESCRIBE/S/ contain wildcard characters that are used in a one-to-one positional comparison as follows:
MASK CHARACTER | CORRESPONDING CHARACTER |
* | Can be anything |
C | Must be a letter, digit, or space |
A | Must be a letter or space |
# | Must be a digit |
. | Must be a space |
= | Must match the next character in the mask |
There are three types of string comparisons (or tests) and each has its own rules.
OPERATOR | EXAMPLE | |||||
= | or | EQ | "A" | = | "A" | |
# | or | NE | "A" | # | "Z" | |
> | or | GT | "W" | > | "M" | |
>= | or | GE | "B" | >= | "A" | |
< | or | LT | "A" | < | "B" | |
<= | or | LE | "A" | <= | "B" |
If one operand is shorter, it is extended with blanks to the length of the longer operand.
The ASCII collating sequence (see appendix D) determines character magnitudes. Hence "A" (@CHR 65) is less than "B" (@CHR 66).
The setting of SEQUENCE LOWER affects string comparisons of upper and lowercase characters. DISABLE SEQUENCE LOWER is the default, with ACCENT R treating lowercase characters as if they were upper case, e.g. "abc" = "ABC".
Containment, position, or pattern tests: The operators in this group are:
OPERATOR | EXAMPLE |
BEGINS | "A" BEGINS "ABCDE" |
BEGINS WITH | "ABCDE" BEGINS WITH "A" |
ENDS | "E" ENDS "ABCDE" |
ENDS WITH | "ABCDE" ENDS WITH "E" |
IN | "C" IN "ABCDE" |
HAS | "ABCDE" HAS "C" |
DESCRIBES | "C###" DESCRIBES "A123" |
LOOKS LIKE | "A123" LOOKS LIKE "C###" |
Operands must not be null strings. A null string causes the comparison to evaluate to FALSE. Exception: The DESCRIBES and LOOKS LIKE comparisons allows their pattern operand to be either null or shorter than the data string operand. In which case the pattern operand is assumed to be filled with the wild card mask character (*) to the length of the data string operand. Hence, for FIELD, CHAR, 8:
FIELD LOOKS LIKE "CCC"
is evaluated as
FIELD LOOKS LIKE "CCC*****"
Leading and trailing spaces in the operands will affect the result of the comparison; "JOHNSON" ends with "SON", but "JOHNSON " (with trailing blanks) does not.
The setting of SEQUENCE LOWER affects string comparisons of upper and lowercase character. Hence, with DISABLE SEQUENCE LOWER, "johnson" ends with "SON", but with ENABLE SEQUENCE LOWER, "johnson" does not end with "SON".
Data Type Tests
OPERATOR |
EXAMPLE |
ALPHA |
"AB XYZ" ALPHA |
CALENDRICAL |
"12-25-86" CALENDRICAL |
INTEGRAL |
"12345" INTEGRAL |
NUMERIC |
"12.34" NUMERIC |
The operand may be a null (empty) string or all blanks filled.
Leading and trailing spaces do not affect the result of these operations. For example, the string "123 " (with leading and trailing blanks) is recognized as being an integer string.
The special modifiers ANY and ALL allow all occurrences of an array to be tested with a single expression. The form "{ANY; ALL} field_name" can be the first operand in a relational expression. ANY evaluates to true if any of the occurrences meets the condition set. ALL evaluates to true if all occurrences meet the condition set. The field name used with ANY or ALL must be that of an array field, and it must be expressed without a subscript. No arithmetic operation may be performed on the ANY/ALL field.
The first expression below is valid; the second is not, since the ANY/ALL modifiers can only be used to the left of the operator.
IF ANY FLDA = 1
IF 1 = ANY FLDA
All 12 occurrences of the field
MO_SALES,FLOAT,10,2, OCCURS 12
Are checked by the IF;UNLESS clauses
IF ANY MO_SALES LE 10000
UNLESS ALL MO_SALES > 0
Arithmetic Operators are used in conditional expressions, function arguments, assignment statements, and other locations where a value is needed. An arithmetic expression represents an arithmetic value, which is integer, numeric, or real.
Numerical fields or constants of any type (INT, FLOAT, REAL, BIT, and SIGNEDBIT) can be intermixed in the same expression; INT values are converted to FLOAT values as necessary when they are encountered in an expression. Calculations are performed as either integer or numeric (double precision) unless all values are REAL. BIT and SIGNEDBIT data are treated as binary INT. Division operations on integer fields or constants produce truncated integer results. For example
5/2 = 2, not 2.5
If one of the values in this example is integer and the other is numeric, ACCENT R converts all values to numeric. Thus
5./2 = 2.5
5/2. = 2.5
Note, however, that
1/2 + 1./2. = .5, not 1.0
Since the result of the first division is truncated to zero before, the second division and addition are performed.
The functions @NUM, @REAL, and @INT can be used to alter values to get the arithmetic precision needed. For example,
*TYPE @INT 5.1/2
2
*TYPE @NUM 5/2
2.5
*TYPE @REAL 5/2
2.5
Table 6-3 lists the valid arithmetic operators. It also groups together those operators that have the same precedence in an expression that contains several operators, and lists the groups in the order of precedence.
Operators of equal precedence are listed in the same group, and the groups are listed in the order of precedence.
OPERATOR |
MEANING |
** or ^ |
Exponentiation; a value raised to a power. The form is value ** power. |
- |
Unary minus; negates the value following it. For example: -7.1 |
+ |
Unary plus; can be used but is ignored. |
BNOT |
Binary bit-wise NOT; one's complement. For INT, SIGNEDBIT, or BIT data only. |
* |
Multiplication |
/ |
Division. Dividing an integer by an integer produces a truncated integer result. For example: 5/2 = 2. |
MOD |
Modulo. Produces the remainder of a division operation. For example: 5 MOD 2 = 1/ |
+ |
Addition |
- |
Subtraction |
Binary bit-wise equivalence. |
|
Binary bit-wise AND and OR |
|
Binary bit-wise exclusive OR. |
|
Binary left and right shift. |
|
Binary arithmetic left and right shift. |
|
Binary left and right rotation. |
Table 6-3 Arithmetic Operators and Their Order of Evaluation
Arithmetic expressions can appear on both sides of a relational operator; for example,
QTY*PRICE GT 2000-DISCOUNT
The binary operators are used with INT, SIGNEDBIT, or BIT data only.
Results of AND, OR, and equivalence bit-wise operation, where a and b are individual bits, are as follows:
a | b | a BAND b | a BOR b | a BXOR b | a BEQV b |
0 | 0 | 0 | 0 | 0 | 1 |
0 | 1 | 0 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 | 0 |
1 | 1 | 1 | 1 | 0 | 1 |
Shift and rotate binary operations produce the following results:
OPERATOR | OPERATION | IF N IS POSITIVE | IF N IS NEGATIVE |
X BLSH N | Left Shift |
X shifted left N bits, zero fill |
X shifted right @ABS(N) bits, zero fill |
X BRSH N |
Right Shift |
X shifted right N bits, zero fill |
X shifted left @ABS(N) bits, zero fill |
X BALSH N |
Arithmetic Left Shift |
X shifted left N bits, sign bit preserved if possible |
X shifted to the right @ABS(N) bits, sign bit unchanged |
X BARSH N |
Arithmetic Right Shift |
X shifted right N bits, sign bit fill |
X shifted to the left @ABS(N) bits, sign bit unchanged |
X BLCY N |
Left Cycle |
X Cycled Left N bits |
X Cycled Right @ABS(N) bits, |
X BRCY N |
Right Cycle |
X Cycled Right N bits |
X Cycled Left @ABS(N) bits, |
The string operator + can be used to concatenate literals, functions, or fields, as long as the values are strings.
*SET "A" + "B" + "C" TO @STRING
*TYPE @STRING
ABC
An IF/UNLESS clause can contain one or more relational expressions connected by one of the logical operators AND or OR. A third logical operator, NOT, is used to reverse the value of a relational operator.
The AND operator means that the relational expressions on both sides must be true for the conditional clause to be satisfied. For example, the conditional clause requires that both the DIST field must equal the character string DENVER and the QTY field must contain a value greater than 100.
IF DIST='DENVER' AND QTY GT 100
The OR operator means that at least one of the relational expressions on either side of the OR operator must be true for the conditional clause to be satisfied. For example, the conditional clause can be satisfied in three ways: when the value of the DIST field is DENVER, when the value of the QTY field is greater than 100, or when both these conditions exist.
IF DIST='DENVER' OR QTY GT 100
The AND operator has precedence over the OR operator. For example, the conditional clause;
IF DIST='DENVER' OR QTY GT 100 AND BAL LT 200
is equivalent to:
IF DIST='DENVER' OR (QTY GT 100 AND BAL LT 200)
Similarly, the conditional clause;
UNLESS DIST='DENVER' AND QTY GT 100 OR BAL LT 200
Is equivalent to:
UNLESS (DIST='DENVER' AND QTY GT 100) OR BAL LT 200
The logical operator NOT can precede any of the relational operators to negate the condition. For example, the conditional clause;
IF 'BIN' NOT IN LICENSES
Is satisfied when the LICENSES field does not contain the character string BIN.
Care must be used when combining a negative relational operator with one or more logical operators. For example, the expression;
IF 2 NE 1 OR 2 OR 3
Will always evaluate to true, since two is not equal to one. However,
IF 2 NE 1 AND 2 AND 3
Always evaluate to false, since 2 is equal to 2.
In ACCENT R, parentheses ( ) can be used to change the normal order of evaluation or simply to improve readability. ACCENT R evaluates expressions enclosed in parentheses first, following the usual order of evaluation within the parentheses. When several sets of parentheses appear, ACCENT R proceeds from left to right, evaluating expressions enclosed in parentheses first. If parentheses appear within parentheses, the innermost parenthetical expression is evaluated first.
For example, the desired result could not be obtained in the following conditional clause without parentheses.
IF (BAL+QTY*PRICE)*1.18>350
If the parentheses were omitted, ACCENT R would evaluate it according to the usual order, specifically: First do QTY * PRICE, then results * 1.18, then + BAL.
Similarly, parentheses can be used to alter the normal order of evaluation of logical operators. For example, the following conditional clause could not be easily specified without parentheses.
IF (AREA='MATH' OR JOB=17) AND DEPT=5
If the parentheses were omitted, ACCENT R would evaluate it according to the usual order discussed in “Logical Operators” above, that is:
IF AREA='MATH' OR (JOB=17 AND DEPT=5)
The same uses of parentheses also apply in the evaluation of arithmetic expressions.
(A+B) * C TO D
Mean: add A and B then multiple by C
The rules for abbreviating IF/UNLESS clauses are as follows:
When the left side of a relational expression and the relational operator are to be repeated in succession, they can be omitted after the initial specification if there are no intervening parentheses.
When the left side of a relational expression is to be repeated in succession, it can be omitted after the initial specification if there are no intervening parentheses.
When a series of expressions would normally be separated by OR operators, the word OR can be replaced with a comma (,).
The relational operator BETWEEN…AND cannot be included in abbreviated clauses.
The following three examples illustrate these rules.
IF A=1 OR 2 OR 3 means IF A=1 OR A=2 OR A=3
IF B>1 AND <10 OR =77 means IF B>1 AND B<10 OR B=77
IF C=2,4,6 OR 8 means IF C=2 OR C=4 OR C=6 OR C=8
Since a comma and OR are synonymous, a comma cannot be followed immediately by the word OR. Thus, the following is an invalid clause:
IF X=1,2,3, OR 4
The correct form is:
IF X=1,2,3 OR 4 or IF X=1,2,3,4
Several of the relational string operators have reverse forms, as shown in the table earlier, to facilitate abbreviating. For example, the conditional clause;
IF 'ELEC' IN DESC OR NAME
Could not be abbreviated using the reverse HAS operator. The conditional clause "IF DESC OR NAME HAS 'ELEC'" is invalid because the first expression DESC must be followed by a relational operator. To use the HAS operator, enter:
IF DESC HAS 'ELEC' OR NAME HAS 'ELEC'
Consider the abbreviated conditional clause:
IF PROJECT ENDS WITH 'RDD' OR 'DOC'
This could not be abbreviated with the reverse ENDS operator. Similarly, the abbreviated conditional clause;
UNLESS 'DOC' ENDS PROJECT OR EFFORT
Could not be abbreviated with the reverse ENDS WITH operator. Using the ENDS WITH operator, enter:
UNLESS PROJECT ENDS WITH 'DOC' OR EFFORT ENDS WITH 'DOC'
ACCENT R provides a powerful capability for manipulating dates. It is possible to add and subtract dates with special integer expressions, or subtract one date from another. Any of the general relational operators shown in the subsection "Relational Operators" can also be used to compare dates.
The ENABLE DATE command affects the format in which ACCENT R accepts date input and in which dates are output. Default date format is AMERICAN (see ENABLE DATE command in Chapter 8).
A date field of any valid type can be used in an expression with a date field of any other valid type. ACCENT R takes care of conversion.
Dates that are stored in alpha or character fields or literal dates must be converted with the @CAL or @DVAL function before being used in date arithmetic or comparison. Integer values can be converted to dates with the @MAKDAT function.
There are two general forms for date arithmetic-one for integers and one for dates.
FORM 1:
date + ae DAYS + ae MONTHS + ae EMONTHS + ae YEARS
date + ae HOURS + ae MINUTES + ae SECONDS
is a date field, function, or expression. |
|
ae |
is an integer-valued expression, function, field, or constant. It is used to indicate the quantity of SECONDS, MINUTES, HOURS, DAYS, MONTHS, EMONTHS, and YEARS to add or subtract from date. |
indicates days to be added to or subtracted from date |
|
indicates months to be added to or subtracted from date |
|
adds or subtracts the given number of months, and rounds up to the last day of the month |
|
indicates years to be added to or subtracted from date |
|
indicates hours to be added to or subtracted from date |
|
indicates minutes to be added to or subtracted from date |
|
indicates seconds to be added to or subtracted from date |
FORM 2:
date1 - date2 |
|
date1, date2 |
can be any date field, function, or expression |
FORM 1:
If the result of the expression exceeds the last day of the month, the last valid day of the appropriate month will be returned.
*TYPE @CAL "01/31/1993" + 1 MONTHS
02/28/1993
Rounding to the end of the month with EMONTHS.
*TYPE @CAL "02/15/1993" + 1 EMONTHS
03/31/1993
In general, any combination and any number of operations that make sense are allowed, so long as one of the first two operands is a date expression. Thus, both of the following are valid:
date + ae DAYS + ae YEARS - ae DAYS + ae MONTHS + ae YEARS
ae DAYS + date
*SET @CAL "12/31/92" TO %DAT
*TYPE %DAT+2 DAYS
01/02/1993
@CAL "01/12/93" - 13 DAYS = 12/30/1993
@CAL "10/22/93" + 2 MONTHS = 12/22/1993
@CAL "10/22/93" + 2 EMONTHS = 12/31/1993
@CAL "10/22/90" - 15 YEARS = 10/22/1975
@CAL "10/22/90" - 15 YEARS + 3 MONTHS = 1/22/1976
@CAL "10/22/90" + 15 YEARS = 10/22/2005
GIVEN:
@DTSTR (@DATE) = "05/04/1993 00:00:00.000"
THEN:
@DTSTR (@DATE - 1 HOURS) = "05/03/1993 23:00:00.000"
@DTSTR (@DATE - 23 MINUTES) = "05/03/1993 23:37:00.000"
@DTSTR (@DATE + 8 SECONDS) = "05/04/1993 00:00:08.000"
FORM 2:
The value of Form 2 is always an integer representing the number of days between the two dates. Only the minus operator can be used.
@CAL "04/30/93" - @CAL "-04/01/93" = 29
@CAL "04/30/93" - @CAL "-03/01/93" = 60
NOTES: The two general forms can be combined in one expression: for example, date1 + (date2 - date3) DAYS.
ACCENT R handles leap years and centuries correctly.
Excessive values as arguments to HOURS, MINUTES, and SECONDS will trigger a floating-point rounding error, which causes variances in the expected time value for the seconds-of-the-day.
Date constants can be used in any ACCENT R date function or in date arithmetic where a date value needs to be specified.
\dYYYYMMDD or \DYYYYMMDD
\dYYMMDD or \DYYMMDD
WHERE:
YYYY and YY are digits representing the year
MM are digits representing the month
DD are the digits representing the day
*TYPE \D19880121
01/21/1988
*TYPE \D880121
01/21/1988
*TYPE \D19880121 + 2 DAYS
01/23/1988
*TYPE @DATSTR(\D19880121, "WWW, MMM DD, YYYY")
Thu, Jan 21, 1988
Octal and hexadecimal constants can be used at any place in ACCENT R where an integer value can be specified.
\o <integer> or \O <integer> |
|
\h <integer> or \H <integer> |
*TYPE \O1000
512
*TYPE\Habc1
43969