DECIMAL(total-digits[,precision]),
MONEY(total-digits[,precision])
REAL, DOUBLE (synonyms FLOAT, LONG)
CODES (Code1:value1[, Code2:value2]…) or CODES (value1[, value2]…)
CONDITIONS (ValueList]:ConditionName [,ValueList]:ConditionName ]…)
OPTIONAL (NULL) or REQUIRED (NOTNULL)
This describes the properties of each field and data-group
in the record. For example
DEFINE FDist VSAM DATA(
Keys GROUP KEY,
Region PIC '999',
District PIC '999',
END GROUP,
Name CHAR(30) Value ('No District Record Found'),
Fill CHAR(44));
Each item in the list has the form: -
Name [(dimension)] Format-Option [Option]…
Items are separated from the next item with a comma.
Special rules apply to some record definition types, especially System which is used to define functions
and COBOL figurative constants. Click this link to see how to define
functions, and the argument types that can be used with the built-in functions
like $Today.
These usually can be any valid Jazz “Word” up to 25 characters long. A “Word”
· Starts with a letter,
· Contains letters, numbers, and hyphens
· Does not contain special characters: punctuation, operators, etc
· Item names are not case-sensitive. Thus a field named “Account” can be referred to as “account”, “ACCOUNT”, “aCcOuNt” and any other case combination. Defining a record with fields “Account” and “ACCOUNT” would cause a “Duplicate name” error.
· Item names may not start with “JZ”, except when defined by MANASYS Jazz. Jazz sometimes needs to define variables for its own use, these are usually named starting with “JZ” and so this rule makes it less likely that these names conflict with yours.
There may be extra rules imposed by the definition type; for example with type SYSTEM definitions item names starting with $ are permitted, allowing Jazz to use names like $Self and $Today for its own special names. Jazz has very few reserved words: keywords are recognized in context, and so can also be re-used as field names. With two exceptions you may use COBOL reserved words as Jazz item names. The exceptions are: -
·
A field within a group (see
below) may not be called “END”: this indicates the end of the group.
·
If you name a field “Filler” this is treated as
it would be in COBOL, i.e. the “field” cannot be referred to, serving only to
indicate that there is a field or space of some kind between real fields. Fields named “Filler” are omitted from
generic references. You can re-use the
name “Filler” any number of times within a record.
For VSAM, sequential files, and working data you can define
items with a dimension meaning that there are several occurrences of the
item. For example, this record contains
sales totals for each of the last 12 months: -
DEFINE SalesSummary VSAM DATA(
Month (12) CHAR(10),
Sales (12) MONEY(7,2))
You might retrieve the month name and corresponding sales with
a loop like this : -
FOR MonthNbr
= 1 TO 12;
PRINT (SalesSummary.Month(MonthNbr), SalesSummary.Sales(MonthNbr));
END FOR;
Note that the first occurrence is (1). In some languages, for example Java and C#,
arrays are zero-based.
You can give up to 7 dimensions: this example gives 2: -
Sales
(5,12) MONEY(7,2))
(Perhaps this means sales by month for the last 5 years)
You can specify that a dimension may vary: -
Nbr
SMALLINT,
Sales
(12(Nbr)) MONEY(7,2));
Here Nbr is a field defined earlier in the same record that contains the actual number of occurrences of Sales. Because of its appearance in (12(Nbr)) RANGE (0:12) is implied and will be checked by an ACCEPT statement.
Nothing must follow a table defined with a variable dimension, so Sales must be the last field or group in the record.
The use of dimensions can get a little complicated, and you
may have to be careful that you don’t introduce errors into your program. Refer to the section “Using Dimensioned
Fields” in Section 4.
Fields in relational database tables (TYPE(SQL)) may not have dimensions.
Format properties describe how the data are stored, and
affect the way it can be used and displayed.
Format properties are: -
BOOLEAN, CHAR(length), VARCHAR(length)
DATE, DATETIME, TIME
DECIMAL(total-digits[,precision]), MONEY(total-digits[,precision])
TINYINT, SMALLINT, INDEX, INTEGER, BIGINT
FLOAT, LONG,
PIC 'picture
specification'
LIKE like-name
GROUP
A format property is required unless the field has general
property BOOLEAN, which can imply CHAR(1),
and CODES,
which can imply TINYINT: -
Region CODES('New Zealand',
'New South Wales',
For SQL definitions, GROUP, PIC, and INDEX are invalid. However PIC can be used as a property of CHAR fields, for example
EMPNO CHAR(6) PIC '999999',
Here we’ve specified that field EMPNO is a CHAR(6) column as far as SQL is concerned, but each of these 6 characters must be a number. This rule will be used when an input value is checked by ACCEPT.
For Web Service Input records, except for special fields defined by MANASYS Jazz, all input fields must have type CHAR. The reason for this is that otherwise the sending program MUST validate that the data it sends is valid for the field that is to receive it. Sending a non-numeric value to a SMALLINT, for example, will cause a CICSFault which aborts the transaction before the message arrives in your COBOL program, and you have no opportunity to handle this error properly. We have implemented this rule so that you can detect and handle these errors with ACCEPT, and so a typical Web Service container definition will look like this: -
COPY Custf;
COPY TYPES;
DEFINE MySvce-WSPG1 SYSTEM DATA([Not in COBOL
INPUT VARCHAR(30) VALUE 'IWSPG1',
OUTPUT VARCHAR(30) VALUE 'OWSPG1');
DEFINE IWSPG1 SERVICE INPUT DATA(
Function CHAR(1) CAPS CODES(E:Enquiry,U:Update,A:Add,D:Delete)
VALUE Enquiry,
JZ-Custf-Skip SMALLINT VALUE 0,
Custf GROUP,
Account CHAR(6) ASSIGN CustF.Account,
Region CHAR(4) ASSIGN CustF.Region,
…
END GROUP,
ViewState GROUP, [Must not be changed
CheckSum-Custf CHAR(40),
END GROUP);
DEFINE OWSPG1 SERVICE OUTPUT DATA(
ERROR VARCHAR(80),
ViewState LIKE IWSPG1.ViewState,
JZ-Custf-ReadTo
SMALLINT VALUE 0,
JZ-Custf-NbrReturned
SMALLINT VALUE 0,
JZ-Custf-ReturnCode
LIKE Types.ReturnCode,
Custf (1) GROUP,
Account LIKE CustF.Account ASSIGN CustF.Account,
Region LIKE CustF.Region ASSIGN CustF.Region,
…
END GROUP);
Both input and
output records use ASSIGN to relate the message field to
another field, but only the output record actually defines the message fields
to COBOL in their format. When the input
fields are wanted they will be handled with ACCEPT: -
WHEN (Update);
ACCEPT (CustF.Account=IWSPG1.Account) MESSAGE OWSPG1.ERROR;
GET Custf
KEY(CustF.Account) UPDATE CHECKSUM IWSPG1.CheckSum-Custf;
ACCEPT (IWSPG1.Custf.*) EXCEPT(CustF.Account) MESSAGE OWSPG1.ERROR;
#207 I Custf.Region,Custf.District,Custf.Name,Custf.SalesThisMonth,Custf.SalesYTD,Custf.Billingcycle,Custf.DateCommenced,
included in generic assignment
END GET Custf UPDATE RESPOND OWSPG1;
A (potentially) very large whole number, ranging in value
from -999999999999999999 to +999999999999999999. You may not specify a length; it is always 8
bytes. This form is a double-length INTEGER.
Like CODES, BOOLEAN is really an individual property, but it may appear as if it is a data type: -
Flag BOOLEAN …
This is equivalent to
Flag CHAR(1) BOOLEAN …
BOOLEAN may also appear with an explicit data format: -
NullIndicator SMALLINT BOOLEAN ….
Refer to TINYINT and SMALLINT for more information on these data formats, and to BOOLEAN for more information on the BOOLEAN property.
Character string. The maximum length is 32767. CHAR data has fixed length, for example NAME CHAR(30) is always 30 characters, and shorter data will be extended with blanks. VARCHAR data can vary in length up to the maximum value given in (length). See VARCHAR(length) below for more information on VARCHAR.
Within definitions with type WORK you can write the length of a CHAR or VARCHAR field as *. Jazz will determine the length of the character string from assignments within the program. For example: -
PROGRAM
TestIF BATCH;
COPY
IN1R;
DEFINE
W DATA(Note CHAR(*));
...
IF IN1R.SalesThisMonth >
70000;
W.Note= 'Well Done!';
ELSEIF
IN1R.SalesThisMonth < 10000 THEN;
W.Note =
'This is not good enough';
ELSE;
W.Note =
'';
END IF;
Here W.Note is effectively CHAR(23) because that is the longest value assigned to it. It doesn’t matter if the assignment is never executed, the value 'This is not good enough' is still used in calculating the length of W.Note. The length of W.Note does not change as the program executes: when the statement
W.Note= 'Well Done!';
is executed the value is extended with 13 blanks, exactly as if you’d defined it with CHAR(23) from the start.
Like BOOLEAN, CODES is really an individual property, but it may appear as if it is a data type: -
STATUS CODES …
This is equivalent to
STATUS TINYINT CODES …
CODES may also appear with an explicit data format: -
STATES CHAR(1) CODES ….
Refer to TINYINT and CHAR for more information on these data formats, and to CODES for more information on the CODES property.
DATE items are used to store values representing dates, TIME
represents time of day with a 24 hour clock, while DATETIME combines both.
Although data is stored in INTEGER form, you should not try to use them as integers. DATE values are stored in the order year, month, day, (ccyymmdd) so that the 23rd March, 1986, would be stored as 19860323. TIME values are stored as hours, minutes, seconds, and milliseconds, e.g. value 131735000 represents 17 minutes and 35 seconds after 1PM (13:00 hrs). DATETIME values are essentially a DATE field followed by a TIME field. The property DPIC (Display Picture) is used to control the way in which a DATE, TIME, and DATETIME field are displayed on reports and screens, it is particularly important for DATE fields.
Refer to the Users’ Guide chapter
“DATE, TIME, and DATETIME Fields” for more information.
Total-digits specifies the number of digits, and must be an
integer between 1 and 18. You may also specify
how many of those digits are precision (that is, how many follow the decimal
point). Precision must be an integer
between 1 and total-digits. Thus: -
NBR DECIMAL(5)
can store values from -99999 to +99999.
NBR2 DEC
(5,2)
can store values from -999.99 to +999.99.
COBOL
programmers: note that the first field is the total number of digits including
precision, which is different to the COBOL PICTURE rule. The COBOL definition of NBR2 would be
03 NBR2 PIC S9(3)V9(2)
COMP-3.
DECIMAL and MONEY are identical except that the default display format for MONEY includes a currency symbol, which is normally a “$”.
PACKED is a synonym for DECIMAL.
Floating point numbers are used to store extremely large and extremely small numbers using a format that is like the exponential notation used by scientists, for example 5*10**12 (Five times 10 to the power of 12). REAL and DOUBLE can both store positive and negative values ranging in size from about 10**-256 to 10**+256, but DOUBLE (meaning “Double precision) stores the number more accurately. FLOAT is a synonym for REAL, LONG is a synonym for DOUBLE.
For most types except TYPE(SQL) you can arrange fields into groups. For example,
DEFINE FDist VSAM DATA(
Keys GROUP KEY,
Region PIC '999',
District PIC '999',
END GROUP,
Name CHAR(30) Value ('No District
Record Found'),
Fill CHAR(44));
A group is ended by END GROUP. You are strongly recommended NOT to use END
as a field name – sometimes it is valid, but usually a field definition such as
END
SMALLINT,
will be confused with the end of
the group and Jazz will produce one or several error messages.
You can repeat field names in another group within the same record. Thus while
DEFINE FDist VSAM DATA(
Region PIC '999',
District PIC '999',
Name CHAR(30) Value ('No District
Record Found'),
Fill CHAR(44),
REGION DECIMAL(3));
will produce an error message (REGION is a duplicate field name), a field name may be repeated if it is within a group (in both cases). For example, here the names NbrPurchases and Value are repeated: -
DEFINE FSales VB DATA(
ThisMonth GROUP,
NbrPurchases Smallint,
Value Money(7,2),
END GROUP,
LastMonth GROUP,
NbrPurchases Smallint,
Value Money(7,2),
END GROUP);
When you refer to a field name
without any qualification then Jazz will resolve this to the first reference
found from the top of the program, and qualify the name you wrote with the file
name. Thus you may have written
PRINT (Region);
but Jazz will have changed this to
PRINT (FDIST.REGION);
When the name is unique within the
DEFINE statement it makes no difference whether or not the field
is within a group: the reference is to FDist.Region
in both cases. However where the name is
not unique Jazz inserts the full qualification, so that
PRINT (NbrPurchases);
will become
PRINT (FSales.ThisMonth.NbrPurchases);
When fields are within a group then you can use a generic reference to the group in the same way as you use a generic reference to a definition. Thus
PRINT (FSales.*);
means “Print all the fields of FSales”, and is equivalent to
PRINT (FSales.ThisMonth.NbrPurchases, FSales.ThisMonth.Value, FSales.LastMonth.NbrPurchases, FSales.LastMonth.Value);
while
PRINT (FSales.ThisMonth.*);
is equivalent to
PRINT (FSales.ThisMonth.NbrPurchases, FSales.ThisMonth.Value);
Groups are also useful with generic assignments: you can write
FSales.LastMonth.* = FSales.ThisMonth.*;
This is equivalent to the individual assignments
FSales.LastMonth.NbrPurchases = FSales.ThisMonth.NbrPurchases;
FSales.LastMonth.Value = FSales.ThisMonth.Value;
GUID is a “Globally Unique
Identifier”, it is a value that is guaranteed unique. GUID values are useful for record keys,
locks, and similar situations where you must be able to guarantee that no other
value can coincidentally be the same.
You can give a GUID field a value
in one of three ways: -
1.
Assign the value $NEWGUID, i.e.
Record.Key = $NewGUID;
2.
Assign the value $EMPTYGUID, i.e.
Record.key = $EMPTYGUID;
3.
Assign it a value from another GUID field
Record.Key = Record2.Key
You cannot assign a GUID field
to/from any other type of field, except that you can assign it to a CHAR or
VARCHAR field. However you cannot assign
a CHAR or VARCHAR field to a GUID field.
In characters a GUID field will
appear like this: -
2096f97d-9910-48f3-a138-f7d8ee2be6b1
with hyphens after the 8th, 12th,
16th, and 20th hexadecimal character.
$EMPTYGUID has value
00000000-0000-0000-0000-000000000000
In comparisons you can only
compare it = or <> another GUID field.
Other comparisons (>, <, etc) have no meaning and are
prohibited. You cannot compare it to $NewGUID: the result of
If Record.Key = $NEWGUID
would always be false, even
immediately following an assignment of $NEWGUID to Record.Key. You can compare it to $EMPTYGUID.
Whole numbers, ranging in value from -2147483648 to + 2147483647 (+- 2**31). You may not specify a length; it is always 4 bytes. This form provides compact storage and fast arithmetic.
INDEX should be used for fields which are going to
be used as index variables to access arrays, or when you want the most
efficient type of binary arithmetic. INDEX may be given as a data type, as in W.A below, or as a property of SMALLINT, INTEGER, or BIGINT fields. Fields like W.B2 defined SMALLINT INDEX are identical in format to fields
defined INDEX (W.A).
DEFINE W DATA(
A INDEX,
B SMALLINT,
B2 SMALLINT INDEX,
C INTEGER,
C2 INTEGER INDEX,
D BIGINT,
D2 BIGINT INDEX,
S VARCHAR(50),
SR GROUP REDEFINES W.S,
SL INDEX,
CA (50) CHAR(1),
END GROUP);
If you
redefine a VARCHAR field (W.S), the
redefining length field (W.SL) should be defined as INDEX (or as SMALLINT INDEX).
You should
not redefine INDEX fields, particularly if you are going to be generating COBOL for an x86
platform.
Instead of giving a format code and other
options you can say that this item is LIKE
another: -
DEFINE Record1 VSAM DATA(
AccountNbr
Integer,
NameAndAddress
Group,
Name
Char(30),
Address-1 Char(30),
Address-2 Char(30),
City
Char(20),
Country Char(20),
Code
Char(10)
EndGroup,
Name2
LIKE Name,
PreviousNameAndAddress
LIKE NameAndAddress,
LastTransaction
DateTime,
Current
LIKE can be applied to a GROUP (as here), a field, or a record: -
DEFINE Record2 LIKE Record1 TYPE(Workingdata);
If you say that this item is LIKE
another, then it has all the same properties except Key (KEY, UKEY,
and DKEY options).
·
For a field this means that it has all the same
properties, including format, CODES
etc, display options, and validation options.
·
For a group it means that it has the same
contained fields with their properties: for example there is now a field Record1.PreviousNameAndAddress.Name with the same
definition as Record1.NameAndAddress.Name.
For LIKE to
be valid: -
· The LIKE subject (= NameAndAddress in the example above) must be defined above the LIKE reference.
· It must not be a containing group for the definition. I.e., PreviousNameAndAddress LIKE NameAndAddress would be invalid if it were written within the NameAndAddress group.
· The LIKE Item must not specify a variable dimension
Like items can replace properties other than format properties (SMALLINT, CHAR, etc). For example you may write
Account2 LIKE Account HEADING ‘Previous Account’,
and Account2 will have the characteristics of Account plus a HEADING of ‘Previous Account’. If Account already had a HEADING option then there will be a warning message telling you that the option has been replaced. Options may not conflict with other options: for example the following example is invalid because Field2 would have both BOOLEAN and CODES options, but these options conflict: -
Field1 TINYINT CODES(Value1, Value2, Value3),
Field2 LIKE Field1 BOOLEAN,
Inheriting dimension. If the LIKE subject (= pattern) is dimensioned, then the LIKE field will also be dimensioned. Thus
DEFINE INDim DATA(
X1 (2) SMALLINT,
A LIKE INDim.X1,
B(3,5) LIKE INDim.X1)
Here A has dimension (2), like its pattern. However B has dimension (3,5). If you re-dimension an object you can not only change the numbers, but you can change the number of dimensions to more or fewer than the pattern. However you cannot get rid of all dimensions: if LIKE refers to a dimensioned object, e.g. LIKE INDim.X1, then the new field must have at least one dimension. Thus if you wanted A to have a single occurrence you’d have to write
A(1) LIKE INDim.X1,
and you’d have to refer to it with a subscript value of 1 even though this is the only possible value, e.g.
PRINT (INDim.A(1));
Although you may write the LIKE reference without qualification, Jazz will qualify the reference. For example “Account” may become “Table1.Account”. This ensures that the meaning of these definitions doesn’t change should you subsequently change your program in ways that would resolve “Account” to a field in another definition. Before doing its normal top-to-bottom search, Jazz first looks in the current definition, so that LIKE NameAndAddress within Record1 becomes Record1.NameAndAddress.
The LIKE object must be defined earlier in the program. Thus you cannot write: -
DEFINE Record2 … DATA(
Field1 LIKE Record1.field1,
unless this follows
DEFINE Record1 … DATA(
If a LIKE reference refers to a preceding DEFINE statement then it is recommended that you add a suitable COPY statement to the definition so that you can guarantee that the definition is present and precedes its use in LIKE. For example: -
1. Save the definition of Record1 so that COPY Record1; includes this definition in your program.
2.
Write the definition of Record2 like this, and
then save it as Record2: -
COPY Record1;
DEFINE Record2 … DATA(
Field1 LIKE Record1.field1,
…
A feature of COPY
is that duplicate COPY
statements are ignored, i.e.
COPY
Record1;
COPY
Record1; <= this is ignored.
Because of this rule you can safely include COPY
Record1 in the definition of Record2, whether or not the program already
contains
COPY
Record1;
The data is numeric, but is
carried in character form, and its format is explicitly specified by the
picture-specification. Note that in Jazz
you do not use PIC for alphabetic data:
write CHAR(5) rather than PIC
‘XXXXX’. Picture-specifications are
similar to those of PL/I or COBOL; Jazz follows the basic rules of both these
languages, but prohibits options where the two languages' options differ. So, most PL/I or COBOL numeric pictures are
valid provided that:
• The
picture characters A, P, O, and X are not used, and
• The decimal point is always preceded by a V.
COBOL programmers: note that
the PIC value is enclosed in quotes.
If you use PIC formats you are expected to know the rules of COBOL or
PL/I PICTURE clauses, as Jazz does not analyse the picture-specification
rigorously: Jazz checks the property to ensure that it has only characters
valid for a Jazz PIC, but not that they are arranged in a valid way.
You may specify PIC fields in SQL tables by adding PIC as a property of a CHAR definition: -
DEFINE EMPLOYUP SQL DATA(
EMPNO CHAR(6) PIC '999999' …
If CHAR is omitted a warning message is produced: -
DEFINE EMPLOYUP SQL DATA(
EMPNO PIC '999999' REQUIRED KEY,
#635 W TYPE(SQL), so PIC format handled
as CHAR
Either way they will be handled as numbers within Jazz, for example you’ll write
EMPLOYUP.EMPNO = 1234;
Not
EMPLOYUP.EMPNO = '001234';
Jazz will
ensure that such fields are validated according to the PIC and correctly formatted. However SQL does not support PICTURE field
definitions, so that in COBOL the fields are created as CHAR, i.e. PIC X(n).
Small integer, able to store values from -32768 to +32767. You may not specify a length - it is always two bytes - and you may not specify a precision.
BINARY is a synonym for SMALLINT.
A very small integer, able to store values from
0 to 255. Note that this form cannot
handle negative values. TINYINT data is especially suitable for
coded values, for example
Region
TINYINT CODES (1:'
If you define a field with CODES but without any format then TINYINT will be assumed. It is recommended that you avoid the use of TINYINT data in arithmetic expressions as TINYINT arithmetic requires extra logic as it cannot be handled directly by COBOL.
Unsigned Packed. Maximum length 8 characters. This data type has been added to support Easytrieve Conversion, and will contain part of a Packed Decimal number. For most purposes USPCKD is handled like CHAR, it is non-numeric and so can’t be used in arithmetic expressions. However, when an EZT format U data definition is converted, an associated DECIMAL number is created, and you can assign the USPCKD field to it to convert the data into DECIMAL that you can print or manipulate. The associated field will use the same name prefixed with JZ-. For example
DEFINE PERSNL1 DATA(
DEPT USPCKD(3) [Unsigned Packed]);
DEFINE EZT-EZTU-Data DATA(
JZ-DEPT DECIMAL(7) HEADING 'DEPT');
EZT-EZTU-Data.JZ-DEPT = PERSNL1.DEPT;
For example, if PERSNL1.DEPT has value X'123456', then EZT-EZTU-Data.JZ-DEPT will now be a DECIMAL number with this numeric value.
VARCHAR fields are like CHAR fields except that the length of the field is recorded, and may have a value up to the maximum specified. They are stored in memory as a length variable (format SMALLINT) and a CHAR variable. The following example shows the differences between CHAR and VARCHAR: -
DEFINE R1 DATA(
FFamilyName CHAR(20),
FGivenName CHAR(20))
DEFINE R2 DATA(
VFamilyName VARCHAR(20),
VGivenName VARCHAR(20))
DEFINE R3 DATA(
FName CHAR(42),
VName CHAR(42))
R1.FFamilyName = ‘Barnes’;
R2.VFamilyName = ‘Barnes’;
R1.FGivenName = ‘Robert’;
R2.VGivenName = ‘Robert’;
R3.FName = R1.FFamilyName
&& ‘, ‘ && R1.FGivenName;
R3.VName = R2.VFamilyName
&& ‘, ‘ && R2.VGivenName;
Now R3.VName will have value 'Barnes, Robert' but R3.FName will have value 'Barnes , Robert ' as the two CHAR(20) fields will have been padded with blanks to fill 20 characters.
Both R1 and R2 are records containing FamilyName and GivenName. In memory enough space is allocated to ensure that up to 20 characters of data can be stored in each field. Actually R2 is slightly larger, as space is also required for two SMALLINT fields to hold the current lengths of the two name fields.
If R1 is stored in a file or SQL table, then each field will take 20 bytes (characters)
of storage. However if R2 is stored in a
SQL
table then only the current length of VFamilyName and
VGivenName will be stored, plus an extra two bytes
for the length. While this won’t make
much difference with a VARCHAR(20) field, this could be significant with longer
fields.
Assigning a value to a VARCHAR field follows the same rules as for a CHAR
field: -
In addition, the current length is set. Thus after
R2.VFamilyName = ‘Barnes’;
the length of VFamilyName is set
to 6. In contrast, the length of a
fixed-length CHAR field is always the maximum length.
Note therefore that if we had written
R1.FFamilyName = ‘Barnes’;
R2.VFamilyName
= R1.FFamilyName;
then the length of R2.VFamilyName would have been set to 20.
We can find out the length of a string with the $LEN
built-in function. $LEN(R1.FFamilyName)
is always 20.
When we concatenate strings the differences between CHAR and
VARCHAR fields are most obvious.
R3.FName = R1.FFamilyName
&& ‘, ‘ && R1.FGivenName;
This sets R3.FName to 'Barnes
,
Robert
'.
R3.VName = R2.VFamilyName
&& ‘, ‘ && R2.VGivenName;
In contrast, R3.FName is now set to 'Barnes, Robert'.
Following the format there may be further options giving
more information about the item. You
should give as much information as possible about the data as this ensures
consistency from one program to another and reduces the amount of logic that
you will have to write into the programs that use the data. For example, you might give rules defining
what data in a field is valid and what is not.
By putting this data into the data definition you do not have to put it
into the logic of programs that input this data from screens, yet incur no
overhead in other programs that merely display the data.
Options are discussed in several categories: -
These may be given both for GROUP
items and for individual fields.
These are properties like Value,
Constant, NULL
or NOTNULL, and
virtual-field-expression, that cannot be applied to groups, and that
don’t fit into the categories of “Display Properties” and “Validation
Properties”.
You can specify criteria like VALID
and RANGE to define the rules to be used to determine
if an input value is valid or not.
Properties Heading and DPIC affect how a field appears when it is displayed
on a screen or a report.
These may be given both for GROUP items and for individual fields
CHECKR and EXISTS are described below in Validation
Properties
These are
only valid for SQL and VSAM definitions.
An item may
be defined with only one of these options, e.g. you cannot write
DEFINE File TYPE(VSAM) DATA(
Field1 CHAR(10) KEY UKEY, …
KEY is the primary key of the file/table. There may be only one item (field or group)
defined with KEY. For TYPE(VSAM)
files there must be a KEY
item.
UKEY is a secondary but unique key
DKEY is a secondary key that allows duplications.
For
example, a customer record might be defined with
DEFINE Custfile TYPE(VSAM)
DATA(
CustID PIC '999999' KEY,
SocialSecurity
CHAR(15) UKEY,
NAME CHAR(30)
DKEY,
Other fields …
For SQL
tables key options are less important, as Jazz will generate appropriate SELECT
statements whether or not the definition records the key fields. However it’s strongly recommended that you
identify keys: they are relevant when Jazz generates the SQL
table definitions (Create table … etc) and you use a dialog to generate a
program, and in CICS and Web Service programs the use of a KEY
option allows Jazz to determine whether or not a GET statement needs to provide Next/Previous
record paging.
For VSAM
they determine the validity of WHERE clauses. For a VSAM definition there MUST be at least
one field defined with KEY.
A SQL
record’s primary key, for which the KEY option is used, may require several
fields. For example, in record CustFS the key is not simply CustFS.Account,
but also includes the fields CustFS.Region and CustFS.District. In
a VSAM record we’d define these three
fields in a group: -
DEFINE
CustFS VSAM DATA(
CustFKey GROUP KEY,
Account
CHAR(6) HEADING 'Account Number',
Region
LIKE Types.Region,
District
DECIMAL(3) RANGE(1:10),
End GROUP,
Name CHAR(40) DKEY,
Etc …);
However SQL definitions don’t permit a GROUP, so instead the various parts of the KEY are
identified using PART: -
DEFINE
CustFS SQL DATA(
Account CHAR(6) HEADING 'Account Number'
KEY,
Region LIKE Types.Region
KEY PART 2,
District DECIMAL(3) RANGE(1:10) KEY PART 3,
Name CHAR(40) DKEY,
Etc …);
The various
key parts do not have to be contiguous, but they do have to be in order.
For VSAM
files the UKEY and DKEY options refer to an alternate index
that has been defined with the file (using the utility IDCAMS). These alternate index are accessed with their
own DD statements. For example, if you
have defined a file: -
DEFINE CustF VSAM DATA(
Account PIC '999999' HEADING 'Account Number' KEY,
Subgroup GROUP,
Region DECIMAL(3),
District DECIMAL(3),
END GROUP,
Name CHAR(15) REQUIRED DKEY 'ibmuser.vsam.custfN' ,
SalesThisMonth MONEY(7,2),
SalesYTD MONEY(7,2),
Billingcycle LIKE types.month,
DateCommenced CHAR(10))
DSNAME 'ibmuser.vsam.custf';
then in the
JCL generated for a program using this file there will be
//CUSTF DD DISP=SHR,DSN=IBMUSER.VSAM.CUSTF
//CUSTF1 DD DISP=SHR,DSN=
IBMUSER.VSAM.CUSTFN
If no dsname value has been given for a UKEY
or DKEY parameter then Jazz will create a default data
set name by suffixing the DSNAME value with 1, 2, 3, etc. For example, if the definition above had
specified
NAME CHAR(15) DKEY,
then the second DD statement would have been
//CUSTF1 DD DISP=SHR,DSN=IBMUSER.VSAM.CUSTF1
Dsname might
be omitted for VSAM, and is always omitted (because it would have
no meaning) for SQL. If a DKEY
or UKEY option omits the dsname
then it should be the last option of the field, or else the next item option
may be flagged as invalid. Thus write
Name CHAR(15) REQUIRED DKEY,
However
writing
Name CHAR(15) DKEY REQUIRED,
incorrectly
causes the keyword REQUIRED to be rejected
You may
wish to search for a partial key (whether KEY, DKEY, or UKEY).
For example, suppose that you have defined CustF.Name as
NAME CHAR(30) DKEY,
and your
file contains records with these NAME values: -
ISABELLE,
Isabeau |
ISOBEL,
Isabel |
JACKSON,
Lionel George |
JACKSON,
Caroline Alicia |
JACOBUS,
Jacques |
JAMES, |
You could
use this DKEY to find records with a particular value of Custf.Name, but of course if you write
GET Custf WHERE
(Custf.Name = '
you’re
looking for a record with exactly this value, and neither 'JACKSON,
Lionel George' nor 'JACKSON,
Caroline Alicia' qualify. By using one of the options WILDCARD, GENERIC, or FULL you indicate how you want searches
such as this to be handled. They apply only to CHAR
fields, but do not
apply to PIC 'pic’
fields (including CHAR(n) PIC 'pic’ fields), groups, or any other
type.
These
options do not apply and are ignored when a VSAM file is used in a batch
program, as COBOL’s READ … KEY statement does not support generic access, but
EXEC CICS READ … does.
When they
apply (e.g., not GET for a VSAM file in a Batch program): -
·
If
the index field is defined with FULL then the full length of the key is
used. If you give a shorter value it will be extended with blanks, so it will
behave as above, i.e. 'JACKSON'
does not find 'JACKSON, Lionel George'.
· If the index field is defined with GENERIC, then the length that you enter is used for searches. You enter 'JACKSON' and the system uses the first 7 characters of the key field, so that the GET will find one of these records with this value. A PROCESS will find them all, or in a CICS program PF8 and PF7 can be used to move to the next and previous records.
·
With
WILDCARD you use a special character to denote the end
of the string for searching purposes.
For example, with WILDCARD '*' you’d
enter 'JACKSON*' to search for names starting with “JACKSON”.
Validation (ACCEPT statements): a CHAR
field may not contain
the WILDCARD character.
The default wildcard is '*'. With WILDCARD 'character' you can use another character such
as '%'. With VSAM
files the wildcard must
be the last character of the value sought. SQL is more flexible.
A GET statement is designed to return one
record. If a wildcard character is used
then it returns the first.
FKEY indicates a foreign key relationship used to
access a related field. It is generated
into definitions based on EXISTS relationships.
For example, EMPLOYEE in my test system is defined like this: -
COPY Department;
DEFINE EMPLOYEE SQL DATA(
EMPNO CHAR(6) PIC '999999' REQUIRED KEY,
…
WORKDEPT CHAR(3) CAPS DKEY 'XEMP2' EXISTS DEPARTMENT.DEPTNO,
…
When a web service is generated from EMPLOYEE,
as the generation logic creates the web service message formats it recognizes
the EXISTS property, and displays a dialog
allowing you to select fields from the Department record as well: -
Here we’ve selected DEPTNAME, causing this field definition: -
DEPTNAME LIKE DEPARTMENT.DEPTNAME
ASSIGN DEPARTMENT.DEPTNAME
FKEY EMPLOYEE.WORKDEPT,
to be added into the EMPLOYEE group in the Web
Service Output Message: -
DEFINE OJSPG2E SERVICE OUTPUT DATA(
… header fields
JZ-Employee
(6) GROUP,
JZ-Employee-ReturnCode LIKE Types.ReturnCode,
… various fields from EMPLOYEE
Checksum
CHAR(40),
DEPTNAME
LIKE DEPARTMENT.DEPTNAME
ASSIGN DEPARTMENT.DEPTNAME
FKEY EMPLOYEE.WORKDEPT,
END GROUP);
This returns a DEPTNAME field with each
EMPLOYEE record. It is an output field, FKEY is not valid in
the INPUT message. If EMPLOYEE.WORKDEPT is null, or gives a value that does not exist in DEPARTMENT.DEPTNO, then the DEPTNAME value will be blank.
FKEY is only valid within a web service output
message.
These are only valid in SERVICE definitions. You normally won’t write these, but you may see
them in Jazz definitions created from JSON or WSDL through the Web Services
Discovery process. Unlike most Jazz
keywords their name has been left in mixed case, because that’s the way that
they appear in JSON/WSDL.
If maxOccurs is present and is greater than 1,
then Jazz will create a dimensioned definition.
Thus
DEFINE Record SERVICE DATA(
Name VARCHAR(255) maxOccurs(5),
is similar to
DEFINE Record SERVICE DATA(
Name (5) VARCHAR (255),
If maxOccurs and minOccurs are different (including when one
of these options is present and the other isn’t) then Jazz will generate an INTEGER field to give the actual number of
occurrences. This will be named with
prefix “JZN-”, for example “JZN-Name”.
The data area will be created with the full number of occurrences
whatever the value of the JZN- field.
Thus
DEFINE Record SERVICE DATA(
Name VARCHAR (255) maxOccurs(5),
corresponds to a COBOL structure like this: -
001290 03
JZN-Name PIC S9(9) COMP-5 SYNC VALUE 1.
001300 03
Name OCCURS 5 INDEXED BY JZIX1-Name.
001310
49 JZL-Name PIC S9999
COMP-5 SYNC.
001320
49 JZD-Name PIC
X(255).
If MaxOccurs is absent or has value 1 then
there will be no OCCURS clause and you won’t need to use a subscript to refer
to values of Name.
Not valid
in SQL or SERVICE definitions. Valid in WORK, VSAM, ESDS, and Physical-Sequential (F, FB, V, VB, U)
definitions.
REDEFINES specifies that this item is to occupy the same
area of storage as a preceding item. For
example
DEFINE Wrk DATA(
Name CHAR(30),
Initial CHAR(1)
REDEFINES Wrk.Name,
NextField
???
Here WorkArea.Initial is the first character of WorkArea.Name. Any change to either field means
an immediate change to the value in the other field: -
WorkArea.Name
= ‘Robert’;
[WorkArea.Initial is now ‘R’]
WorkArea.Initial
= ‘BR’; [WorkArea.Initial is truncated to
“B” since it is only CHAR(1), WorkArea.Name is now
‘Bobert’
Redefinition
rules: -
·
A
redefinition defines a new name over the item that immediately precedes this
one at the same level. Thus Initial
redefines part of Name in the example above.
You can redefine a group: -
NameAndAddress GROUP,
Name
CHAR(30),
Address1
CHAR(30),
Address2
CHAR(30),
City CHAR(20),
State CHAR(20),
AreaCode CHAR(10),
END
GROUP,
NameAndAddressString CHAR(160) REDEFINES NameAndAddress,
…
Alternatively
you could have defined NameAndAddressString first and
used REDEFINE with the GROUP.
However if you had wanted to redefine the first character of Name, then
this redefinition would have been written within the group, immediately after
Name and before Address.
·
The
redefined item must not be longer than the base item. I.e. NameAndAddressString
must not be longer than NameAndAddress in the example
above.
·
If
another item follows the redefined item, then it is placed following the base
item. Thus with
DEFINE Wrk DATA(
Name CHAR(30),
Initial CHAR(1)
REDEFINES Wrk.Name,
NextField
???
WorkArea.NextField follows WorkArea.Name and so is at position 31. It is NOT
placed at position 2 following WorkArea.Initial.
·
The
base item and the redefining item should both be CHAR or PIC
variables, or a GROUP containing only these kinds
of items. Or
You can
redefine a VARCHAR field with another VARCHAR field, or a GROUP that starts with a SMALLINT field. For example
DEFINE W DATA(
VC VARCHAR(10),
C GROUP REDEFINES W.VC,
CL SMALLINT CONSTANT,
CD CHAR(10),
End GROUP);
It is strongly recommended that the length
field, CL in this example, be given the property CONSTANT so that
Jazz will produce messages if assignments are made to it. If W.CL is ever set to a value great than 10
then results will be unpredictable.
·
If
these last two rules are broken then you must understand the implementation
formats of the various data types. Jazz will continue to generate COBOL, and
the program might work correctly, but there are many error situations that Jazz
cannot protect you from. You may get different results should
you generate this program for running on another computer or operating
system.
In a
generic assignment: -
Record1.* = Record2.*;
fields are
assigned from Record2 to Record1 if their names match (including the names of
containing groups). Redefined fields may be assigned just like normal fields.
It is even possible that the same data is assigned more than once if both
records contain the same redefinition.
In a PRINT
statement using a generic reference redefined fields are omitted. Thus
DEFINE Record DATA(
Name CHAR(30),
Initial CHAR(1) REDEFINES Record.Name);
PRINT (Record.*);
This will
print Record.Name, but not Record.Initial. Of course you can always write
PRINT (Record.Name, Record.Initial);
if you want
both.
These properties can be applied to fields, but not to groups. They’re defined here as they don’t fit cleanly into “Format Properties”, “Display Properties” and “Validation Properties”,
This is generated by MANASYS into SCREEN and SERVICE definitions to relate a field in the message to a field within the COBOL program. ASSIGN may also be written explicitly with other definition types. For example, here is a typical container definition. For fields related to the Custf record ASSIGN relates a field in the SERVICE record to a field in the VSAM record.
COPY Custf;
…
DEFINE IWSPG1 SERVICE INPUT DATA(
Function CHAR(1) CAPS CODES(E:Enquiry,U:Update,A:Add,D:Delete)
VALUE Enquiry,
JZ-Custf-Skip SMALLINT VALUE 0,
Custf GROUP,
Account CHAR(6) ASSIGN CustF.Account,
Region CHAR(4) ASSIGN CustF.Region,
…
END GROUP,
…
DEFINE OWSPG1 SERVICE OUTPUT DATA(
…
Custf (1) GROUP,
Account LIKE CustF.Account ASSIGN CustF.Account,
Region LIKE CustF.Region ASSIGN CustF.Region,
…
END GROUP);
ASSIGN allows ACCEPT statements to relate input and target fields: for example
ACCEPT (IWSPG1.Custf.*) EXCEPT(CustF.Account) MESSAGE OWSPG1.ERROR;
#207 I Custf.Region,Custf.District,Custf.Name,Custf.SalesThisMonth,Custf.SalesYTD,Custf.Billingcycle,Custf.DateCommenced,
included in generic assignment
BOOLEAN is a field with only two possible values, True and False. BOOLEAN fields may be used whenever convenient for your program logic, but also they are automatically used automatically by Jazz in particular situations such as SQL and Web Service OPTIONAL fields (respectively NULL and IsNillable at SQL/Web Service level).
BOOLEAN fields follow these rules: -
1.
BOOLEAN
conflicts with CODES, CONDITION,
and VALID.
2. A field format may be given or omitted. When given, the format of a BOOLEAN field must be one of: TINYINT, SMALLINT, or CHAR(1). If omitted then data type CHAR(1) is assumed. Thus possible ways of defining a BOOLEAN field are: -
a. B1 BOOLEAN,
b. B2 BOOLEAN DISPLAY, [Equivalent to a
c.
B3 TINYINT BOOLEAN,
d.
B4 CHAR(1) BOOLEAN DISPLAY, [Equivalent
to a
e.
B5 SMALLINT BOOLEAN
3. Jazz assigns code defaults like this: -
Data formats |
Values |
Automatic use |
TINYINT BOOLEAN |
(1:True,0:False), |
Used for Web Service Nillable fields |
SMALLINT BOOLEAN |
(-1:True, 0:False) |
Used for SQL indicator fields |
BOOLEAN DISPLAY |
(Y:True,N:False) |
Used in general program logic |
With a BOOLEAN field Jazz tests for True and NOT True. The purpose of the False code value is only to provide a value for assignments like
IsNill = False;
For example
IF B2 = False;
tests that the value IS NOT Y, it does NOT test that the value IS N.
A BOOLEAN field is similar a field with a CODES definition: With IsNill defined
IsNill TINYINT BOOLEAN
it behaves almost like
IsNill2 TINYINT CODES (0:False,1:True),
There are differences however. With a BOOLEAN value the test is whether the value is True or not: -
IF IsNill = False
tests that the code value is not equal to 1, whereas
IF IsNill2 = False
tests that the code value is equal to 0.
Another difference: with CODES a code value of 0 is used to indicate “undefined”, so that the meaning of
IF IsNull2 = False
is ambiguous: there is no way of distinguishing an undefined value from a value that has explicitly been set to False. A BOOLEAN field does not have an undefined value, it is either True or not True (False).
4. Like a coded field you refer to the value, not the code, in conditions and assignments. Thus
IF IsNill = True …
not
IF IsNill = 1 …
and assignments are
IsNill = True;
not
IsNill = 1;
You initialise it with True or False, not the code values. Thus you’d write
HasValue BOOLEAN VALUE True
not
HasValue BOOLEAN VALUE 1
5. You can assign one BOOLEAN field to another even when the formats or code assignments of the two fields are different. For example, with definitions
HasValue TINYINT BOOLEAN,
Flag CHAR(1) BOOLEAN,
you may assign HasValue to Flag and the True/False value is assigned, with the code value of Flag becoming Y or N depending on HasValue’s code value being 1 or 0.
6. By default BOOLEAN variables are initialised to False. The default format (CHAR(1)) is initialized to SPACES, which is False but is not ‘N’. This allows DUPLICATE conditions to handle first-record situations reliably.
Specifies that a CHAR or VARCHAR value is capitals (M F) or lower case (m f). CAPITALS and UPPER are synonyms for CAPS.
This property may not be specified for types other than CHAR or VARCHAR. If present, it must follow the type, otherwise error message #165 is produced: -
PROJNO CAPS CHAR(6) REQUIRED KEY,
#165 E Case option (CAPS or LOWER) not valid except with types CHAR,
VARCHAR
#647 W CAPS/LOWER option recommended
Both messages disappear when the definitions is changed to
PROJNO CHAR(6) CAPS REQUIRED KEY,
It is strongly recommended that it be given when character values are used with CODES, or as record keys (KEY, UKEY, or DKEY property), as otherwise there may be unexpected “not found” conditions for code values or records. If present it should precede CODES and VALUE properties so that it can be checked, and can force values to the correct form. For example, when a definition was written
BC CHAR(8) CAPS VALUE 'Robert',
it was changed with a message: -
BC CHAR(8) CAPS VALUE 'ROBERT',
#644 W 'Robert' forced to 'ROBERT'
Both normal assignments and ACCEPT will force the input value into the correct format. Thus
W.Name = 'Robert';
R.BC = W.Name;
Result in R.BC = 'ROBERT';
Just as assigning one form of number to another
is not an error, similarly ACCEPT will ensure that the value has the correct case, but there are no
messages if an input value is not already in this case.
Synonyms: Enum, TValues. CODES conflicts with BOOLEAN and CONDITION
This combines validation, meaning, and display format, and provides an enumeration function. You use this for fields that are carried in the file as a code – perhaps a number, perhaps a character code – but you want displayed as the code’s value(meaning). The code is typically a number or a one or two character constant, as in
SEX CHAR(1) CODES('M':'Male', 'F':'Female'),
Region
DECIMAL(1) CODES (1:'
or may be implied as a TINYINT number as in
Qtrs CODES ('1st Qtr', ‘2nd Qtr’, ‘3rd Qtr’, ‘4th Qtr’),
The code must be compatible with the field’s data type – for example in this case the code values for SEX must be a single character, and for Region the codes must be numbers in the range 1-9. Character codes may be given as character strings, i.e. characters with surrounding quotes, or simply as characters. Codes must be unique. Values are given as a character string or word, and must also be unique. The surrounding quotes are necessary if the code or value contains a blank or quote.
For example, this is an equivalent definition of SEX, omitting the quotes around the values. Jazz has coloured the codes and values to indicate their usage: -
SEX CHAR(1) CODES(M:Male,F:Female),
You can mix the two
formats: here for example we have omitted the quotes around “
Region
DECIMAL(1) CODES (1:'
If the field has format TINYINT (or no type is given, in which case TINYINT is implied), then the codes can be omitted with just the values being given. Thus all three of these definitions are equivalent: -
Region
TINYINT CODES(1:'
Region
TINYINT CODES('
Region
CODES('New Zealand', '
Either all values must have the format Code:Value, or none of them. Thus a definition like this that attempts to mix the formats is invalid: -
Region
TINYINT CODES(1:'
Note that, in the
context of a code table, strings and word-values are coloured the “CodeTable colour”, not the normal “string colour”.
CODES means that
· The use of CODES forms a distinct data type. Thus SEX is not just a CHAR(1) field, it is a different data type to a normal CHAR(1) field and you cannot assign it to or from a normal CHAR(1) field without a message being produced by Jazz when the program is processed (checked). Similarly Region is not just a number. See Codes, Types, and Domains below for more explanation.
· The fields are carried in the record as a code, i.e. SEX will be carried in the record as a single character.
· You may give a data type, as in the examples above. However you can omit the data type, in which case Jazz will assume a data type of TINYINT, and expect the code values to be numbers in the range 1 to 255.
· When the fields are displayed on a report or screen they will be displayed in their extended form, i.e. as 'Male' or 'Female' and 'New Zealand',’Victoria’ etc.
· In screen generation the value pairs are used in menu programs: the user may select from a list (showing “New Zealand” etc) and the screen will return 1 (etc). The screen editor will provide various ways of displaying this.
· In your Jazz programs you refer to the values, not the code, e.g.
IF Record.Region = Victoria & Record.SEX = Male …
NOT
IF Record.Region = 3 & Record.Sex = ‘M’ …
This ensures that your code is more understandable and more likely to be correct. Just as Jazz expands references it will convert codes; thus although you write the IF statement in the first form, the generated COBOL program will test for the actual code, 3 and “M”, not its value (meaning).
· In data entry you’ll normally enter the values as codes rather than their extended values. Codes will be validated against the list, and reflected back as extended values.
· You cannot use coded fields in expressions, you’re only allowed to assign their value to/from a field of the same type. For example, an expression like Record.Region + 1 is invalid.
· You can iterate through all values of a coded field with the FOR statement: -
FOR EACH
Region;
…
· Code value or display value? Jazz will normally choose the appropriate form. For example, PRINT (Record.Sex) will print “Male” or “Female”, whereas Record2.Sex = Record.Sex; assigns the single character, “M” or “F”.
You should use CODES only for coded values where there is a very stable list of codes. Should the codes change or new codes be added then you will need to regenerate all programs using the definition, so if change is possible you should probably use a lookup file and GET. Thus CODES is a safe choice for SEX, but may be unwise for Region. You certainly wouldn’t use this for something like airline codes
AirlineCode
CHAR(2) CODES (QF:Qantas,
NZ:’Air
because the code list is too volatile, and every other month you’d be regenerating your program to include the latest code values.
The VALUE property must follow the CODES option, and refer to the code value, not the raw code. Thus
AirlineCode
CHAR(2) CODES (QF:Qantas,
NZ:’Air
not
AirlineCode
CHAR(2) CODES (QF:Qantas,
NZ:’Air
and not
AirlineCode
CHAR(2) VALUE ’Air New Zealand' CODES
(QF:Qantas, NZ:’Air
When you define a field with CODES you create a new data type that is different to the standard data types provided by Jazz. If you’ve written
SEX CHAR(1) CODES(M:Male, F:Female),
Region
DECIMAL(1) CODES (1:'
then you can think of these fields as having data type “SEX” and “Region”, not CHAR(1) and DECIMAL(1). You have created a new data type, or as some languages call it, a domain. This has several consequences: -
· You cannot assign data to or from these fields from “ordinary fields” – CHAR(1) and DECIMAL(1) in this example – without Jazz producing a message. You may choose to ignore this message – it will have severity code “E” not “S” – but if you do you should be careful that you haven’t introduced errors into your program. It is better to use an ACCEPT statement – see #4
· The message is avoided if you can use another field that shares the same list of codes because it is defined LIKE the first field, or LIKE a common field that defines the code table (see #3). Thus if you have definitions
SEX2 CHAR(1) LIKE SEX,
SEX3 CHAR(1),
there are no error messages from assignment SEX = SEX2; and SEX2 = SEX; but messages are produced with assignments to/from SEX3 and any other CHAR field.
· You may find it convenient to create a definition of your own data types as a SYSTEM definition, e.g.
DEFINE MyTypes SYSTEM DATA(
SEX CHAR(1) CODES(M:Male, F:Female),
Region DECIMAL(1) CODES (1:'
…
TYPE (SYSTEM) definitions are recognized by Jazz but don’t generate any COBOL and are used to define COBOL functions, CICS interface tables, and so on. You can use them yourself as here to create a list of your own types. Now, with any record definition you’d write
COPY MyTypes,
DEFINE Customer … DATA(
SEX LIKE MyTypes.Sex,
…
· If you need to assign a value to a coded field you should use ACCEPT. For example: -
DEFINE R… DATA(
Sex CHAR(1) CODES(M:Male, F:Female),
SexCode CHAR(1),
Writing R.Sex = R.SexCode; introduces a potential error into your program. It is better to write
ACCEPT (R.Sex = R.SexCode);
This validates the value as it is assigned, and will assign the “no valid code” value (“ ” in this case) if the value is neither M nor F. You can see if an error has been found by testing $Error, which qualifies to JZ.$Error:-
IF
JZ.$Error THEN;
Logic to handle invalid assignment
You’d
also use this to assign one coded field to another when the code tables are
different. For example, suppose that you
had a coded field States that had all
ACCEPT (R.NewEngland = R.State);
IF
JZ.$Error = False
THEN;
State is in New England
You can assign data directly to or from a coded field. MANASYS will work out whether you meant the code or the code value, and will produce a message telling you which option it’s applied: -
DEFINE R1 DATA(
A CHAR(2),
B CHAR(15));
DEFINE R2 DATA(
B CHAR(2) CAPS CODES (AL:Alabama, AK:Alaska, AZ:Arizona, AR:Arkansas));
R1.A = R2.B;
#319 W Actual Code is assigned
R1.B = R2.B;
#319 W Code Value is assigned
R2.B = R1.A;
#072 W Value directly assigned to a Coded field. It may be invalid
R2.B = R1.B;
#072 W Value directly assigned to a Coded field. It may be invalid
#539 W B is shorter than source: value may be truncated
MANASYS decides whether you want the actual code (AL, AK, etc) or the code value (Alabama, Alaska, etc) by these rules: -
1. In R1.A = R2.B; the fields have the same type and nbr-of-characters, so the actual code is assigned. R1.A is set to AL, AK, etc. Message #319 W Actual Code is assigned is produced.
2. If the target is a longer CHAR field then the code value is assigned. This is the case with R1.B = R2.B. There may be another message (320) if the field is not long enough for the converted code. Message #319 W Code Value is assigned is produced.
3. For the two assignments to R2.B a 2-character value is assigned. Message #72 is produced: there is no checking that the value assigned is one of the valid codes.
The same rules apply when CODES has single values, as in
DEFINE MTHTAB DATA(
DESC SMALLINT CODES('January','February','March','April','May','June','July',
'August','September','October','November','December'));
If the value is not valid: not a valid US State Code for R2.B, not a number in the range 1:12 for MTHTAB.DESC, then when an assignment uses the Value (and message #319 W Code value is assigned), a string of asterisks “*****” is assigned.
ValueList::= Value1 [TO Value2] [,ValueList]…
ConditionName follows the same rules as for a field name. Each condition name must be unique for the field, but the same name may be reused for other fields in this and other records.
Example: -
OVERLIMIT
PIC '9' CONDITIONS(1 TO 7:OVERLIMIT,1,3,5,7:OVLM-FEE-ASSESSED,
2,3,6,7:OVLM-LTR-SENT,4:OVLM-REPORTED),
Here there are four named conditions: -
OVERLIMIT True if the field OVERLIMIT has value 1, 2, 3, 4, 5, 6 or 7.
OVLM-FEE-ASSESSED True if the field OVERLIMIT has value 1, 3, 5, or 7.
OVLM-LTR-SENT True if the field OVERLIMIT has value 2, 3, 6, or 7
OVLM-REPORTED True if the field OVERLIMIT has value 4
Note that more than one of the conditions may be true.
CONDITIONS combines validation and meaning but unlike CODES it does not provide display format, nor provide an enumeration function. CONDITIONS conflicts with BOOLEAN and CODES
For those with COBOL knowledge, a condition is equivalent to a COBOL “Level 88”, and will be generated if you convert a COBOL record layout containing level 88 definitions to Jazz.
You may define fields with CONDITIONS like this (Jazz
has coloured the codes and values to indicate their usage): -
SEX CHAR(1) CONDITIONS(M:Male,F:Female),
Unlike CODES, condition names may not be written as strings with quotes. If you were to write
Regn DECIMAL(1)
CONDITIONS
(1:'
Jazz will change them to make the names valid, like this: -
Regn DECIMAL(1) CONDITIONS (1:New-Zealand, 2:
#558 E '
#558 E '
As with CODES you would write conditions like this: -
IF Record.Regn =
not
IF Record.Regn = 2
but unlike CODES you assign values directly: -
Record.Regn = 1;
not
Record.Regn = New-Zealand;
CONDITIONS differ from CODES as follows: -
1. Code ranges may be given, not just individual values, and codes may overlap. For example: -
Overlimit-Flag DECIMAL(1) CONDITIONS(1 TO 7:OVERLIMIT,1:OVLM-FEE-ASSESSED,
3:OVLM-FEE-ASSESSED,5:OVLM-FEE-ASSESSED,7:OVLM-FEE-ASSESSED,
2:OVLM-LTR-SENT,3:OVLM-LTR-SENT,6:OVLM-LTR-SENT,7:OVLM-LTR-SENT,
4:OVLM-REPORTED,5:OVLM-REPORTED,6:OVLM-REPORTED,7:OVLM-REPORTED),
Thus if the value of Record.Overlimit-Flag is 7 then
IF Record.Overlimit-Flag = OVERLIMIT THEN…
IF Record.Overlimit-Flag = OVLM-FEE-ASSESSED THEN…
IF Record.Overlimit-Flag = OVLM-LTR-SENT THEN…
IF
Record.Overlimit-Flag = OVLM-REPORTED THEN…
are all true.
If this were a CODES option then error messages would have been reported because there are several “interpretations” of value 7.
2. When the display-form (or “meaning”) of the field is required, as in PRINT (Record.Overlimit-Flag); then the first possible value is used. Thus any of the values 1 through 7 will cause PRINT (Record.Overlimit-Flag); to produce “OVERLIMIT”.
3. Assignments to the coded field result
in the corresponding value being assigned, or the lowest of a range in cases
where TO is used. Thus
Record.Overlimit-Flag
= OVERLIMIT;
sets the field to 1, while
Record.Overlimit-Flag = OVLM-REPORTED;
will set it to 7.
4. You cannot use CONDITIONS with TINYINT fields.
CODES are preferable to CONDITIONS. They are more precise, and allow assignment both ways.
By defining
a field with CONSTANT you create a named constant.
It is good
practice to define the constants in your system with a definition like: -
DEFINE Constants DATA
AccountLimit Money(7,2) Value (1000.00) Constant,
…
This makes
later changes easier because you can easily locate all references to AccountLimit, and there is a single place to change if you
want to change the constant’s value.
If you
define a field with Constant you may not assign a value to it:
this will result in an error message.
You can
also imply Constant for every item in a definition by using TYPE(CONSTANTS). This also has the advantage
that Jazz doesn’t generate anything for unused constants within a CONSTANTS definition. You can specify all
the constants that your system uses in a common COPY definition, and then Jazz will only
include those that you use in the generated COBOL program.
This
applies to BOOLEAN, DATE, DATETIME, and TIME data. It specifies that the data will be kept in
character format, as follows: -
BOOLEAN: The
field is CHAR(1), with ‘Y’
meaning True
Date and time fields: these are stored in the form in which DB2 provides them to COBOL programs, which is
DATE: The field is CHAR(10), with format yyyy-mm-dd
DATETIME: The field is CHAR(26), with format yyyy-mm-dd-hh.mm.ss.mmmmmm
TIME: The field is CHAR(8) with format hh.mm.ss
DISPLAY is assumed in SQL definitions, but is optional in other types.
This
applies to fields defined in SYSTEM or CONSTANT definitions. You are not normally allowed to assign values
to these fields: message #159 is produced and the assignment statement is
rejected. However the COBOL special
register RETURN-CODE is defined
DEFINE COBOL SYSTEM DATA(
…
RETURN-CODE SMALLINT DPIC ‘9999’ SET,
…
Now you can
set it with normal assignment statements: -
COBOL.RETURN-CODE = 9;
Message
#159 is not produced and the assignment is accepted and is valid even though,
because this is a COBOL special register, there is no reference to it in the
data division because COBOL has type SYSTEM.
Synonym:
Initial
VALUE specifies
an initial value for a field. For
example: -
DEFINE WD DATA(
B CHAR(5) VALUE 'ABCDE',
C
SMALLINT CONSTANT
VALUE 15,
…
The value must be a string-constant if the field is alphanumeric, or a numeric-constant if the field is numeric. It may be enclosed in brackets. It should be a value that is not used by any real value.
VALUE and Tables (Arrays).
For tables (arrays) a single initial-value may be specified,
and all elements of the table will be set to that initial-value. For example:
STATUS(3) CHAR(1) VALUE
'A',
STATUS(1), STATUS(2) and STATUS (3) are all initialised to 'A'. Alternatively values may be given for each
array member: -
STATUS(3) CHAR(1) VALUE ('A', 'B', 'C'),
If each array value is given, then there must be exactly the right number, 3 in this case, and the brackets around the VALUE set must be given.
For multi-dimensioned tables values are given in dimension order: for example with STATUS(3,2) values are given in order 1,1, 1,2, 2,1, 2,2, 3,1, 3,2: -
STATUS(3,2) CHAR(2) VALUE ('A1', 'A2', 'B1', 'B2', 'C1', 'C2'),
For tables within tables, VALUE gives values for the local table, not for the inherited dimensions: -
Grp (3) GROUP,
STATUS(2) CHAR(2) VALUE ('A', 'B'),
not
Grp (3) GROUP,
STATUS(2) CHAR(2) VALUE ('A1', 'A2', 'B1', 'B2', 'C1', 'C2'),
VALUE and KEY/DKEY/UKEY fields.
The values of key fields must not be the keys of any
existing record. Thus if you actually
want to have a record with key value 0 or blank you should explicitly use
another VALUE
that you never use, e.g.
DEFINE
Parts VSAM DATA(
Partnbr
INTEGER KEY VALUE -1,
…
A field with a default value is considered “Absent”. Thus
· If we write
Partnbr
INTEGER KEY REQUIRED,
then because there’s no VALUE property the default value of Partnbr is 0. ACCEPT (Parts.Partnbr) will report an error if the field has value 0.
·
EXISTS clauses are not checked if the field has default
value. Thus with
OrdPart LIKE parts.partnbr
DKEY 'ibmuser.vsam.Orders2'
EXISTS Parts.Partnbr,
if OrdPart has
value 0 then ACCEPT (Orders.OrdPart)
does not check to see if there is a record in Parts with Parts.Partnbr=0
· For fields in SQL for which OPTIONAL is specified or implied NULL is set to show “Not present”, whether VALUE is 0 or blank or any other value.
Defaults: if not specified, Jazz assumes REQUIRED for fields that are all or part of a Key (KEY, UKEY, or DKEY), otherwise OPTIONAL. NULL and NOTNULL are synonyms for OPTIONAL
and REQUIRED.
OPTIONAL means that the field may be absent: if so, then its value will be set as described for VALUE. REQUIRED means that the field is always present in every record. Typical usage is that key fields like AccountCode will use REQUIRED, while non-key data fields like Address will use OPTIONAL.
For most “Normal” fields – in working storage and VSAM and Sequential files – OPTIONAL and REQUIRED have little effect in most situations, but OPTIONAL/REQUIRED are useful with: -
a. On the behaviour of ACCEPT(Field). If Field is defined (explicitly or implicitly) with REQUIRED, then ACCEPT(Field) will report an error if there is no value returned from the data entry screen.
b. With PARAMETERS definitions. With
DEFINE Rtn PARAMETERS (PA SMALLINT, PB SMALLINT OPTIONAL, PC SMALLINT OPTIONAL);
CALL Rtn(W.A);
CALL Rtn(W.A, W.B);
CALL Rtn(W.A, W.B, W.C);
are all valid. For the missing arguments the CALL statements will use fields Rtn.PB and Rtn.PC after setting them to their default values (normally blank or zero)
c. Fields in WebService messages are often optional, and may be absent from an input message.
d. On the behaviour of fields stored in SQL tables. See SQL and OPTIONAL Fields for more information.
These are mostly field Properties, but CHECKR and EXISTS can also be given for groups.
See also BOOLEAN, CODES,
CONDITIONS,
REQUIRED
above.
CHECKR specifies a routine that will be called to validate a field or group. For example you might define a field: -
Phone CHAR(15) CHECKR CHKPHON,
This means that when Jazz validates the field in an ACCEPT statement, it will CALL CHKPHON
The following rules must be followed: -
1. The routine name, CHKPHON in this case, is an external name, and so must not exceed 8 characters, must not be a COBOL reserved word, and must not include hyphens.
2. There must be an interface definition for the routine, so that Jazz can check that it is called correctly. Refer to JazzLRM_Type
3. The routine’s parameters must be: -
· An INPUT or INOUT parameter with the type of the field to be checked, i.e. in this case CHAR(15). The CHECKR routine may reformat the field, for example expressing a Phone Number or Social Security Number in a standard way.
· A CHAR(*) OUTPUT parameter. This field is set to blanks if the field is valid, anything else indicates that the field is invalid. If this is CHAR(1) then it is assumed to be only a flag defined as BOOLEAN, and returned as True ('Y') if the field is valid, False ('N') if not. If longer than one character, the field will be blank if the field is valid, anything else will be treated as an error message.
· In classical (3270) CICS programs a non-blank output message will be put into the screen’s error message field if there is room. Note that error messages do not need to include the field name as this will be included in the error message field anyway, and would be duplicated if included in the returned value.
· In other programs you will need to handle the returned error message with your own logic
4. The routine may be written in Jazz, Assembler, COBOL, or PL/I (PL/I routines should use OPTIONS (COBOL)).
5. Routines should follow the rules for ANY type, not the rules for BATCH, CICS, or SOA. Otherwise they may include I/O statements which will be invalid if the routine is called in the wrong environment.
EXISTS Reference specifies that a value must be found in another file. For example, you might define an Order record like this: -
DEFINE
Orders VSAM DATA(
…
OrdPart LIKE Parts.PartNbr EXISTS Parts.PartNbr,
…
This means that the value of Orders.OrdPart must exist as a value of Parts.PartNbr. Thus if Orders.OrdPart has value 1234, then there must be a record in Parts for which Parts.PartNbr has value 1234. Here Parts.PartNbr is a “Foreign Key”:-
· The Foreign File (Parts) must be able to directly accessed (VSAM, SQL),
· The field named must be its primary key
· The two fields must have the same format. The use of LIKE, as here, is strongly recommended.
You can only give one of these options. They are only valid for numeric fields, and the values must be numeric constants, not field references.
RANGE specifies a minimum and maximum value, e.g.
AGE DECIMAL(3) RANGE(0:110)
A value will be invalid if it is less than the first value, or greater than the second value.
The first value must be lower than or equal to the second value. This definition: -
AGE DECIMAL(3) RANGE(110:0)
would mean that every value will be invalid.
MAX gives a maximum value, but there is no minimum
MIN gives the minimum value, but there is no maximum
You can
give a list of the valid values that this field can hold. For example: -
DEFINE CustF TYPE(VSAM) DATA(
Region
DECIMAL(3) VALID (1, 3, 5),
Code CHAR(1) VALID('E','U','A','D'),
….
Values may be individual constants, as in the example above, or may specify a range: -
Code SMALLINT VALID (1, 3, 7 TO 10, 23),
These values are checked when ACCEPT assigns data into these fields. For example, Region can only have a value of 1, 3, or 5, while Code can have one of the values 'E','U','A','D'. The constants must be compatible with the field: numeric constants with numeric fields, and string constants with CHAR or VARCHAR fields. TO implies “>= lower value & <= higher value”, so that the validation test implied by Code SMALLINT VALID (1, 3, 7 TO 10, 23) is: -
IF
Custf.Code = 1 | Custf.Code
= 3 | (Custf.Code >= 7 & Custf.Code
<= 10) | Custf.Code
= 23 THEN;
Thus when TO is used it is important to write the values in the correct order. If you were to write
Code SMALLINT VALID (1, 3, 10 TO 7, 23),
then there’s no value that could satisfy the condition (Custf.Code >= 10 & Custf.Code <= 7), so ACCEPT will always report an error.
Care is needed when TO is used with CHAR (or VARCHAR) values, especially when the target COBOL environment is z/OS where EBCDIC code is used instead of ASCII (or Unicode). With a CHAR field “Greater than” means “Comes after in the collating sequence”, which is the alphabetic sequence we used in dictionaries – A, B, C, D, …. Z. Thus 'A' < 'B' . But is 'A' < 'a'? Is 'A' < 'z'? And where do numbers fit? The answer depends on whether you’re in an ASCII or EBCDIC environment. In EBCDIC (z/OS) lower case letters come BEFORE upper case letters, so the answer is “No” for “is 'A' < 'a'?” and “is 'A' < 'z'?”, and any number, even '0', is greater than (comes after) any letter. In ASCII this order is reversed, with numbers coming first, then upper case letters, and then lower case letters, so in ASCII '0' < 'A', and 'A' < 'a'. A further curiosity with EBCDIC: between the codes assigned to “A” and “Z” are some codes that are not assigned to letters at all, so a test
Code CHAR(1) VALID('A' TO 'Z'));
will allow these values as well as the 26 values of upper case letters.
VALUE and VALID are different properties: VALUE gives the field’s
default (initial) value, while VALID gives a list of valid values. The default value does not have to be in the
list of valid values, indeed it usually isn’t and the default value is used as
a way of signalling “No value given”. In
the absence of VALUE a field’s default value is zero or spaces.
For validation, if a field has the default value it is regarded as absent, so that if Code were defined
Code CHAR(1) VALID ('E','U','A','D') REQUIRED,
the property REQUIRED requires that CODE has a value other than the default, SPACE.
With WHERE you give a condition that is checked: if false the field is invalid. You can write any condition that would be valid here, including references to fields or functions in other records that have already been defined, and to fields that have been defined earlier in this record. You cannot refer to following fields in this or following records: Jazz definitions are processed strictly top to bottom.
Within the condition you can use $Self to refer to the current field. Thus: -
DEFINE
R DATA(
F5 CHAR(1) WHERE (R.F5>='C'&R.F5<='G')|R.F5>'X',
F6 CHAR(1) WHERE R.F5 = R.F6,
F7 CHAR(1) WHERE($Self > R.F5),
F8 LIKE R.F5,
F9 LIKE R.F6);
#556 I Reference R.F5 treated as $SELF
#556 I Reference R.F5 treated as $SELF
#556 I Reference R.F5 treated as $SELF
#556 I Reference R.F6 treated as $SELF
DEFINE
Input DATA(Field CHAR(1));
DEFINE
W DATA(Message VARCHAR(40));
W.Message
= Spaces;
ACCEPT(R.F5
= Input.Field) MESSAGE W.Message;
ACCEPT(R.F6
= Input.Field) MESSAGE W.Message;
ACCEPT(R.F7
= Input.Field) MESSAGE W.Message;
ACCEPT(R.F8
= Input.Field) MESSAGE W.Message;
ACCEPT(R.F9
= Input.Field) MESSAGE W.Message;
or
DEFINE
R DATA(
F5 CHAR(1) WHERE ($Self>='C'&$Self<='G')|$Self>'X',
F6 CHAR(1) WHERE R.F5 = $Self,
F7 CHAR(1) WHERE($Self > R.F5),
F8 LIKE R.F5,
F9 LIKE R.F6);
(No #556 messages)
Changing
F5 CHAR(1) WHERE (R.F5>='C'&R.F5<='G')|R.F5>'X',
to
F5 CHAR(1) WHERE ($Self>='C'&$Self<='G')|$Self>'X',
makes no difference to the validation of F5, but is vital for F8 which is defined
F8 LIKE R.F5,
Without this change (which Jazz makes for you with message #556), the definition of F8 would imply that the validity of F8 depended on the value of F5!
F8 CHAR(1) WHERE (R.F5>='C'&R.F5<='G')|R.F5>'X',
These control the appearance of a field when it is displayed, either as a result of PRINT, or because it appears on a screen.
DPIC specifies an explicit display format, a PICTURE, for a numeric data item. It is written
DPIC ‘picture’
e.g.
TaxNbr Decimal(9)
DPIC '999-999-999',
For numeric fields DPIC follows the rules previously described for PIC.
For DATE fields, DPIC uses these symbols: -
dd Represents the Day number
ddd Represents the ordinal day, i.e. a value from 1 to 365 (or 366 if a leap year) representing 1st Jan to 31st December.
MM Represents the month, as a number, i.e. 02 = February
MMM Represents the month as an abbreviation, e.g. Feb
MMMM Represents the month as its name (eight characters)
yy Represents the year, without century, e.g. 2018 is displayed as 18
yyyy Represents the year including century
dd etc may be lower or upper case. Capital M is used for month to distinguish it from minutes and milliseconds in a TIME field.
blank, comma, period, / and - are separator characters, and may appear anywhere except within day, month, and year. Double hyphens, e.g. DPIC ‘dd--MM--yy', are not permitted.
The presence of “ddd” distinguishes an ordinal date DPIC from a Gregorian (normal) DPIC. They may contain only one separator between the year and day, and do not contain a month. Examples are yy.ddd and yyyy.ddd.
All other characters are invalid
The maximum length of a DATE DPIC is 12 characters, allowing a DPIC such as dd MMMM yyyy. The default DPIC is 'dd MMM yy'.
Thus for date 15th February 2018: -
dd
MM yy => 15 02 18
MM/dd/yyyy => 02/15/2018
dd
MMM yy => 17 Feb 18
dd.MMMM.yyyy => 17.February.2018
For TIME fields, DPIC uses these symbols
hh Represents the hour, using the 24 hour clock, e.g. 13 = 1 PM. Values 0 to 23.
mm Minutes. Values 0 to 59.
ss Seconds. Values 0 to 59.
mmm Milliseconds. Values 0 to 999. Depending on the system clock, this value may be approximate.
PM The time will be printed as AM or PM, with hour values 0 to 12. Hour values less than 10 will not have leading zeros.
mm and mmm must be lower case to distinguish them from Month values in DATE fields. hh and ss must also be lower case.
Blank (B or “ “),
period (.), and colon (:) are separator characters. The default DPIC
is ‘hh:mm:ss.mmm’
A DATETIME field is a DATE field combined with a TIME field. DPIC for a DATETIME field is a DATE DPIC, optionally a separator character (usually blank), followed by a TIME DPIC
Fields are printed under a heading on a report, and when you drop a field on to a screen a heading is used as a caption. The default heading is the field’s name, but
HEADING ‘string’
uses the string value instead of the field name. You can give multiple string values, with strings separated by one or more blanks. For example
DEFINE IN1 VB DATA(
Region DECIMAL(3) HEADING 'Region' 'Nbr' EXISTS FR.Region,
District DECIMAL(3) HEADING 'District' 'of' 'Prefecture',
…
produces report
output like this: -
1Printed
at 16 May 2022, 08:39:26 RepNbr1 Page 1
0Region *--------Region Name---------* *District*
*-----------------Name-----------------* *SalesThisMonth-*
*Nbr-* *---of---*
Prefecture
0 1 New Zealand 1 REEDE, Phillip $468.55
Subtotal
lines. Note that only the first heading
is used in subtotal lines: -
1 7 District Subtotal $7,103.77
Region
Subtotal
$83,215.58
Also the Report Designer, and the 3270 Screens Editor only
use the first heading.