Conditions are widely used in Jazz; the IF statement, WHERE and UNTIL options of FOR and I/O statements (GET, PROCESS , UPDATE, DELETE) all use the same basic rules for conditions. Conditions in Jazz are similar to those in most programming languages but the way you write the conditions, and the scope of the THEN and ELSE, are more flexible and powerful than you might be used to.
It is helpful to distinguish several kinds of condition
· Simple Conditions.
· Compound Conditions
· WHERE conditions
Conditions are written
Reference Comparison-operator Value
For example: -
IF R1.Name = LastRecord.Name THEN
“Reference” must refer to a single field if R1 has TYPE SQL, but for other types it may refer to a single field or a GROUP. If it is a GROUP then comparison treats the group as a CHAR field of appropriate length. “Reference” may not be a generic reference.
Value can be another field, a constant, or a numeric expression. If “field” is a group the value is treated as a CHAR field of appropriate length.
When you compare a reference and a constant, the reference must come first. For example you cannot write
IF 1000 < Record1.
If the field has BOOLEAN type then you may omit the rest of the comparison. Jazz treats
DEFINE R1 DATA(
IF R1.Flag THEN;
as equivalent to
IF R1.Flag = true THEN;
Comparison operators are: -
Not equal to
Greater than or equal to
Less than or equal to
Operators and values must be compatible with the field being tested. For example, if the field is numeric then the value must also be numeric. If the field is a group then the value is treated as a CHAR field of appropriate length, and may be a string constant like 'Abcdefg', another group, or a CHAR or VARCHAR field. Arithmetic (numeric) expressions are allowed: for example you can write
IF JZ.IX1 > JZ.IX2 * 2 THEN;
but string expressions are not: it is not permitted to write IF R.Name = JR.Name1 && R.Name2 THEN;
Fields defined as type BOOLEAN or with CODES or CONDITIONS properties get special handling, particularly in conditions. You can only test these fields for their special values, and you may only use comparison operators = or <>. Other operators like > imply an order, but coded values don’t have an order: you can’t say that “true is greater than false”. Such a statement is simply meaningless, it is neither true nor false.
A BOOLEAN field is a field that can have only two values, true or false. There are three different formats of BOOLEAN fields, CHAR(1), TINYINT, and SMALLINT, but whichever format you use you will always test the values for the special values true or false, never for the code representation. For example: -
DEFINE W DATA(
Bool2 CHAR(1) BOOLEAN,
Bool3 TINYINT BOOLEAN,
Bool4 SMALLINT BOOLEAN,
IF W.Bool2 = true THEN;
W.X = 1;
You may know that CHAR(1) BOOLEAN fields store true as 'Y', but writing a test for 'Y' will result in error messages
IF W.Bool2 = 'Y' then;
#065 S Code or condition value required here
#029 E ''Y'' is invalid here
If the field is BOOLEAN then the condition may simply name the field, implying a test for true. For example: -
IF W.Bool2 THEN;
is equivalent to the earlier condition
IF W.Bool2 = true THEN;
Tests for false are actually tests for “Not true”. Thus a condition
IF W.Bool2 = false THEN;
is true if W.Bool2 has anything other than the true value, which for this format is 'Y'. The value does not have to be 'N' for the condition to be true, and the following condition is identical to the one above: -
IF W.Bool2 <> true THEN;
As with BOOLEAN, for a field defined with CODES the condition will refer to the field’s value, not its code. For example, if State is defined: -
State CHAR(3) CODES(NSW:'
then you’d test
IF W.State =
IF W.State = Vic THEN;
#065 S Code or condition value required here
#029 E 'Vic' is invalid here
As with BOOLEAN, the only valid operators are = and <>.
If a field’s definition includes a CONDITIONS property then there is a predefined condition that can easily be tested for = or <>. For example a record CondTs2 contains
DECLINE-REASON PIC '9(03)' CONDITIONS(284 TO 295:IBS-VALID-DECL-REASON),
This allows us to write
IF CondTs2.DECLINE-REASON = IBS-VALID-DECL-REASON THEN;
to test whether the value of the PIC '9(03)' field is in the range 284 to 295 (inclusive).
CONDITIONS properties can be simple
AFF2 CHAR(4) CONDITIONS('M1 D':MC-STD-CR, …
or give lists of values
AFF2 CHAR(4) CONDITIONS(… , … 'E11M','E12M','E13M','E14M','E15M','E16M','E17M':VALID-AFF, …),
as well as ranges as above.
COBOL programmers will recognise CONDITIONS as “Level 88 definitions”. Note the different syntax: in Jazz write the reference to a condition as a normal condition expressed with the = or <> operator: -
IF CondTs2.AFF2 = VALID-AFF THEN;
You do not simply name the condition as you would in COBOL: -
IF VALID-AFF THEN; <= THIS IS NOT VALID
If the value is $Null then the field must have property OPTIONAL, and the comparison can only be = or <>.
You can combine several conditions using & (meaning AND) and | (meaning OR). & and | are called “Boolean Operators”. For example: -
IF R1.X > R1.Y & R1.Flag THEN;
Here we have combined a simple comparison of two numbers with a test of a BOOLEAN field, using an implied = true. In the absence of parentheses conditions are evaluated left to right. Parentheses are particularly vital when you are using | (OR): for example the two tests
IF R1.X > R1.Y & R1.Flag | R1.Flag2 THEN;
IF R1.X > R1.Y & (R1.Flag | R1.Flag2) THEN;
give different results.
WHERE conditions are written just like conditions in IF statements, but in some circumstances they may behave slightly differently as they way that a WHERE works depends on the file type from which records are being read.
Case #1: filtering a sequential file. In a BATCH program you can read a physical-sequential file (type F, FB, etc). Every record is read into your program, but you can use WHERE to discard the records that you don’t want: -
File WHERE (File.
END PROCESS File;
Here the WHERE clause is exactly like an IF, and this logic is equivalent to
END PROCESS File;
Case #2. Reading VSAM with PROCESS or GET. As with a sequential file you can write PROCESS file WHERE(condition);, but unlike a sequential file you can write such statements within a loop (perhaps an outer PROCESS), and within CICS programs. Here the WHERE is not simply a filter: it specifies that particular records are read using a “Browse”, and the fields named must have been defined with a key property (KEY, DKEY, or UKEY), or be within a key GROUP. Comparison operators must be = or >=: the PROCESS will attempt a keyed read and then return all the records meeting the criteria. With GET, if there are many records meeting the criteria the first will be returned.
Case #3. Reading SQL with PROCESS or GET. Within Jazz PROCESS File WHERE(condition) is the same whether File is a VSAM record set or a table in an SQL database. In COBOL however the implementation is very different: in the case of VSAM records are read and considered by your program whereas for SQL your program uses a SELECT statement that instructs the database which records it wants, and the unwanted records are never seen. You may not know which fields within the database are keys, and only your program’s performance will tell you whether you are scanning the whole database to find the record that you want or going straight to them with keyed retrieval.
Null values (in Jazz, $Null) are handled differently in SQL. To SQL a NULL field does not have a value at all, so its value can never be equal to, or greater than or less than, any other value. Even another NULL value! So that
SQLT2.Charfield = $Null;
PROCESS SQLTab WHERE (SQLTab.charfield = SQLT2.charfield) …
returns NO RECORDS. It DOES NOT return all the records from SQLTab with NULL values. If you want these records then you write
PROCESS SQLTab WHERE (SQLTab.charfield = $NULL) …
The following notes are some ideas that might be implemented in future releases.
Add comparison operator ~ for LIKE, as in SQL. Initially this will be implemented for SQL WHERE clauses, but eventually this could be implemented in general conditions as well.
A Function condition is a condition in which a function is used that returns a result of True or False. Here are some examples: -
IF $Same(AccountNbr) THEN
IF $Change(AccountNbr) THEN
Here we write a list of values, separated by commas: -
IF A = 2, 3, 5, 7, 11, 13, 17 THEN
Record.Text = “A is a prime number’;
This is equivalent to writing the condition like this: -
IF A = 2 OR A = 3 OR A = 5 OR A = 7 OR A = 11 OR A = 13 OR A = 17 THEN
Alternatively the syntax might use IN(…): -
IF A IN(2,3,5,7,11,13,17) THEN
With a list condition the comparison operator must be =, <>. <> means “Not in”. .
Here we write a pair of values separated by TO: -
IF Month = 6 TO 8 THEN
Season = ‘Winter’;
The comparison operator must be = or <>. Values must be given in order: if you write
IF Month = 8 TO 6 THEN
it will never be true, because the test is equivalent to
IF Month >= 8 & Month <= 6 THEN
List and range forms could be combined, for example
IF Month = 1 TO 2, 12 THEN
Season = ‘Summer’