DATA (Data List)

DATA (Data List) 1

Item Names. 1

Dimension. 1

Format Properties. 1

BIGINT. 1

BOOLEAN – as a data type. 1

CHAR(length), VARCHAR(length) 1

CODES – as a data type. 1

DATE, TIME, DATETIME.. 1

DECIMAL(total-digits[,precision]), MONEY(total-digits[,precision]) 1

REAL, DOUBLE (synonyms FLOAT, LONG) 1

GROUP.. 1

GUID.. 1

INTEGER.. 1

INDEX.. 1

LIKE.. 1

PIC 'picture specification' 1

SMALLINT. 1

TINYINT. 1

USPCKD.. 1

VARCHAR(length) 1

Options (Properties) 1

Common Properties. 1

Key options: {KEY [PART n] | UKEY [dsname] | DKEY [dsname]}  [WILDCARD character] | GENERIC | FULL} FKEY.. 1

maxOccurs and minOccurs. 1

REDEFINES.. 1

General Field Properties. 1

ASSIGN.. 1

BOOLEAN.. 1

CAPS | LOWER.. 1

CODES (Code1:value1[, Code2:value2]…)  or CODES (value1[, value2]…) 1

CONDITIONS (ValueList]:ConditionName  [,ValueList]:ConditionName ]…) 1

Constant 1

DISPLAY.. 1

VALUE.. 1

OPTIONAL (NULL) or REQUIRED (NOTNULL) 1

Validation Properties. 1

CHECKR.. 1

EXISTS Reference. 1

RANGE, MAX, MIN.. 1

VALID (value1[, value2] …) 1

WHERE condition. 1

Display Properties. 1

DPIC.. 1

HEADING.. 1

 

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.

Item Names

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.

Dimension

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

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, INTEGERBIGINT

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',Victoria

 

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;

BIGINT

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.

BOOLEAN – as a data type

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.

CHAR(length), VARCHAR(length)

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.

CODES – as a data type

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, TIME, DATETIME

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.

DECIMAL(total-digits[,precision]), MONEY(total-digits[,precision])

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.

REAL, DOUBLE (synonyms FLOAT, LONG)

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.

GROUP

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  (not implemented yet)

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.

INTEGER

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

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. 

LIKE

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,

    CurrentBalance Money)

 

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;

statements.

PIC 'picture specification'

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).

SMALLINT

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.

TINYINT

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:'New Zealand', 3:Victoria, 5:South Australia),

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.

USPCKD

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(length)

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: -

  1. If the value is longer than the maximum length, it is truncated
  2. If the value is shorter, then it is extended with blanks

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'.

Options (Properties)

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: -

Common Properties

These may be given both for GROUP items and for individual fields.

Field Properties

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”.

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.

Display Properties

Properties Heading and DPIC affect how a field appears when it is displayed on a screen or a report.

Common Properties

These may be given both for GROUP items and for individual fields

 

CHECKR and EXISTS are described below in Validation Properties

Key options: {KEY [PART n] | UKEY [dsname] | DKEY [dsname]}  [WILDCARD character] | GENERIC | FULL} FKEY

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.

SQL Compound Keys and KEY PART n

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.

VSAM and UKEY or DKEY Options

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

DKEY and UKEY without DSNAME

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

WILDCARD [character] | GENERIC | FULL

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, Nancy

 

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 = 'JACKSON');

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 (Foreign Key)

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.

maxOccurs and minOccurs

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.

REDEFINES

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),

            County 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.  

Redefines and Generic References

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.

General Field Properties

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”,

ASSIGN

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

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.

CAPS | LOWER

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.

CODES (Code1:value1[, Code2:value2]…)  or CODES (value1[, value2]…)

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:'New Zealand', 3:Victoria, 5:South Australia),

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 “Victoria”. However we can’t do this with the other two values, as they contain a blank: -

            Region DECIMAL(1) CODES (1:'New Zealand', 3:Victoria, 5:South Australia),

 

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:'New Zealand', 2:'New South Wales',3:Victoria), 

        Region TINYINT CODES('New Zealand', 'New South Wales', Victoria), 

        Region CODES('New Zealand', 'New South Wales',Victoria), 

 

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:'New Zealand', 'New South Wales', Victoria),   <=  This is invalid!

 

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 New Zealand', ….)

because the code list is too volatile, and every other month you’d be regenerating your program to include the latest code values.

Initialising Coded Fields

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 New Zealand', ….) VALUE ’Air New Zealand'

not

            AirlineCode CHAR(2) CODES (QF:Qantas, NZ:’Air New Zealand', ….) VALUE NZ

and not

            AirlineCode CHAR(2) VALUE ’Air New Zealand' CODES (QF:Qantas, NZ:’Air New Zealand', ….)

Codes, Types, and Domains

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:'New Zealand', 3:Victoria, 5:South Australia),

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:'New Zealand', 3:Victoria, 5:South Australia),

   

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 U.S. states, and another NewEngland that had the subset of U.S. states that make up the New England region.  You might write

      ACCEPT (R.NewEngland = R.State);

          IF JZ.$Error = False THEN;

    State is in New England

Direct Assignment to/from a field with CODES

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.

CONDITIONS (ValueList]:ConditionName  [,ValueList]:ConditionName ]…)  

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:'New Zealand', 3:Victoria, 5:South Australia),

Jazz will change them to make the names valid, like this: -

    Regn DECIMAL(1) CONDITIONS (1:New-Zealand, 2:Victoria, 3:New-South-Wales),

#558 E 'New Zealand' changed to New-Zealand

#558 E 'New South Wales' changed to New-South-Wales

 

As with CODES you would write conditions like this: -

            IF Record.Regn = Victoria THEN

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.

Constant

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.

DISPLAY

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.

SET

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.

VALUE

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.

OPTIONAL (NULL) or REQUIRED (NOTNULL)

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.

Validation Properties

These are mostly field Properties, but CHECKR and EXISTS can also be given for groups.

 

See also BOOLEAN, CODES, CONDITIONS, REQUIRED above.

CHECKR

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

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.

RANGE, MAX, MIN

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

VALID (value1[, value2] …)

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

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.

 

See also CODES above.

WHERE condition

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',

Display Properties

These control the appearance of a field when it is displayed, either as a result of PRINT, or because it appears on a screen.

 

See also CODES above.

DPIC

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

HEADING

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.