Assignment compatibility in EGL
- Your code assigns one value type (non-reference) variable to another.
- EGL transfers data between an argument and the related parameter in a function invocation, but only if the parameter in the receiving function has the in modifier (in which case the argument is the source) or the out modifier (in which case the parameter is the source).
- A parameter has the inOut modifier.
- A parameter is in the function referenced by the onConstructionFunction property of a JSF handler.
- You are assigning, passing, or returning a reference variable.
For more information about those cases, including assigning a reference variable to a value variable (and the other way around), see Reference compatibility in EGL.
In the following tables, the types in the leftmost column represent the left hand side (the target) of the assignment statement, and all other columns represent the right hand side (source). The letter Y indicates compatible types. A blank means the types are not compatible. A number refers to notes that follow the third table, detailing the circumstances under which the types are compatible.
The first table deals with text types as the source of the assignment.
| Target | Source | |||
|---|---|---|---|---|
| CHAR | MBCHAR | STRING, UNICODE | DBCHAR | |
| CHAR | Y | Y | Y | |
| MBCHAR | Y | Y | Y | |
| STRING, UNICODE | Y | Y | Y | Y |
| DBCHAR | Y | Y | ||
| BIN | 1 | 1 | 1 | |
| INT, BIGINT, SMALLINT | 1 | 1 | 1 | |
| DECIMAL | 1 | 1 | 1 | |
| NUM | 1 | 1 | 1 | |
| NUMBER | 1 | 1 | 1 | |
| FLOAT, SMALLFLOAT | 1 | 1 | 1 | |
| MONEY | 1 | 1 | 1 | |
| NUMC | 1 | 1 | 1 | |
| PACF | 1 | 1 | 1 | |
| DATE | 2 | 2 | 2 | |
| INTERVAL (months) | 2 | 2 | 2 | |
| INTERVAL (seconds) | 2 | 2 | 2 | |
| TIME | 2 | 2 | 2 | |
| TIMESTAMP | 2 | 2 | 2 | |
| HEX | Y | Y | ||
| BOOLEAN | ||||
The second table deals with numeric types as the source of the assignment.
| Target | Source | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| BIN | INT, |
DECI- |
NUM | NUM- |
FLOAT, |
MONEY | NUMC | PACF | |
| CHAR | Y | Y | Y | Y | Y | Y | 3 | Y | Y |
| MBCHAR | Y | Y | Y | Y | Y | Y | 3 | Y | Y |
| STRING | 4 | 4 | 4 | 4 | 4 | 4 | 3, 4 | 4 | 4 |
| UNICODE | Y | Y | Y | Y | Y | Y | 3 | Y | Y |
| DBCHAR | Y | Y | Y | Y | Y | Y | Y | Y | Y |
| BIN | Y | Y | Y | Y | Y | Y | Y | Y | Y |
| INT, BIGINT, SMALLINT | Y | Y | Y | Y | Y | Y | Y | Y | Y |
| DECIMAL | Y | Y | Y | Y | Y | Y | Y | Y | Y |
| NUM | Y | Y | Y | Y | Y | Y | Y | Y | Y |
| NUMBER | Y | Y | Y | Y | Y | Y | Y | Y | Y |
FLOAT, |
Y | Y | Y | Y | Y | Y | Y | Y | Y |
| MONEY | Y | Y | Y | Y | Y | Y | Y | Y | Y |
| NUMC | Y | Y | Y | Y | Y | Y | Y | Y | Y |
| PACF | Y | Y | Y | Y | Y | Y | Y | Y | Y |
| DATE | 5 | 5 | 5 | 5 | 5 | 5 | 5 | 5 | 5 |
| INTERVAL (months) | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 |
| INTERVAL (seconds) | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 |
| TIME | |||||||||
| TIMESTAMP | |||||||||
| HEX | 7 | ||||||||
| BOOLEAN | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 |
The third table deals with date/time, hex, and Boolean types as the source of the assignment.
| Target | Source | ||||||
|---|---|---|---|---|---|---|---|
| DATE | INTERVAL (months) | INTERVAL (seconds) | TIME | TIME- |
HEX | BOOLEAN | |
| CHAR | 9 | 9 | 9 | 9 | 9 | Y | |
| MBCHAR | 9 | 9 | 9 | 9 | 9 | ||
| STRING, UNICODE | 9 | 9 | 9 | 9 | 9 | Y | |
| DBCHAR | |||||||
| BIN | 10 | Y | Y | 11 | |||
| INT, BIGINT, SMALLINT | 10 | Y | Y | 11 | |||
| DECIMAL | 10 | 12 | 12 | 11 | |||
| NUM | 10 | 12 | 12 | 11 | |||
| NUMBER | 10 | 12 | 12 | 11 | |||
| FLOAT, SMALLFLOAT | 10 | Y | 11 | ||||
| MONEY | 10 | 12 | 12 | 11 | |||
| NUMC | 10 | 12 | 12 | 11 | |||
| PACF | 10 | 12 | 12 | 11 | |||
| DATE | Y | Y | |||||
| INTERVAL (months) | Y | ||||||
| INTERVAL (seconds) | Y | ||||||
| TIME | Y | Y | |||||
| TIMESTAMP | Y | Y | Y | ||||
| HEX | Y | ||||||
| BOOLEAN | Y | ||||||
- The text must depict a literal of the receiving data type. It can include the exponent notation, a leading sign, decimal separator other than period (depending on the language settings) and the currency symbol (when being assigned to a money type). It can have any number of leading or trailing spaces, but none in between.
- See Converting text to date/time types.
- A locale-dependent currency symbol is automatically added to the beginning of the target on assignment. In a comparison, the first character of a text value is ignored if it is a currency symbol. The strings "$10.20" and "10.20" are both equal to a MONEY variable with the value 10.20.
- EGL uses strLib.formatNumber() with no pattern argument whenever it converts a numeric type to a STRING. This includes assignments and string concatenations. See formatNumber().
- If the numeric type contains decimals, EGL truncates them; the
number is assumed to be the number of days since December 31, 1899.
Thus the following code prints "03/21/2006" on the console:
Function main() testBin BIN(9,3) = 38796.999; testDate DATE; StrLib.defaultDateFormat = "MM/dd/yyyy"; testDate = testBin; writeStdout (testDate); end - This is valid only if the numeric value has no decimal digits.
The number is interpreted according to the format of the interval.
Consider the following example:
Here EGL interprets the number 1208 as twelve years and eight months. The following rules apply:myInterval INTERVAL("yyMM") = 1208;- If the number has more digits than the interval can hold, disregarding leading zeros, the extra digits on the right are ignored.
- If the number has fewer digits than the interval can hold, leading zeros are added.
- The interval's sign is set to the sign of the number.
- If the number specifies an out-of-range value for a field of the
interval, EGL carries the excess to the next field. Consider this
example:
EGL assigns the interval 83 years and 4 months. There are only 12 months in a year, so the "16" is treated as four months and another year is added to the original 82.myInterval INTERVAL("yyMM") = 8216; - If a value must be carried from the leftmost field of the interval,
it is not an error. The extra digits are simply discarded. Here's
another example:
EGL assigns the interval 1 year and 1 month. 25 months = 2 years and 1 month, so months = 01. The years value is 99, plus 2 carried from the months = 101, which is truncated to 01.myInterval INTERVAL("yyMM") = 9925;
- To assign a value other than a FLOAT, SMALLFLOAT, or another HEX (including a literal), cast the value using the as operator.
- If the numeric variable has any non-zero value, positive or negative, EGL assigns the value TRUE to the BOOLEAN variable; only a numeric 0 results in a FALSE BOOLEAN value.
- See Converting date/time types to text.
- When you assign a DATE to a numeric type, the value is the number of days since December 31, 1899.
- If the BOOLEAN variable is TRUE, EGL assigns the value 1 to the numeric type; if FALSE, it assigns 0.
- Valid only if the target variable has no decimal places.
Rounding and truncation between numeric types
A value of any of the numeric types (including NUMC and PACF) can be assigned to a variable of any numeric type and size, and EGL does the conversions necessary to retain the value in the target format.
Non-significant zeros are added or truncated as needed. (Initial zeros in the integer part of a value are non-significant, as are trailing digits in the fraction part of a value.)
If you use V6 exception mode and set vgVar.handleOverflow accordingly, you can use the sysVar.overflowIndicator system variable to test whether an assignment or arithmetic calculation resulted in an overflow. For more information, see handleOverflow. If you do not use V6 exception mode, or do not handle overflows, an overflow will cause EGL to throw a RuntimeException.
- If the target variable allows seven digits with one decimal place, the target variable receives the value 000108.3, and an overflow is not detected. (A loss of precision in a fractional value is not considered an overflow.)
- If the target variable allows four digits with two decimal places, an overflow is detected.
In an assignment statement, extra decimal digits are truncated when the truncateExtraDecimals build descriptor option is YES (the default; for more information see the EGL Generation Guide), unless the source is a FLOAT or SMALLFLOAT and the target has a fixed number of decimals. Extra decimal digits are rounded when truncateExtraDecimlas is set to NO or the source is a FLOAT or SMALLFLOAT and the target has a fixed number of decimals.
In version 6 and previous versions of EGL, the truncateExtraDecimals option did not exist, so extra decimals were always truncated unless the source was a FLOAT or SMALLFLOAT and the target had a fixed number of decimals. An additional rule prevented truncation if the source of the assignment was one of the MathLib functions. If you need to maintain this V6 style rounding, use the MathLib.assign() function (see assign()).
Padding and truncation with character types
- Single-byte blanks pad a target of type CHAR or MBCHAR.
- Double-byte blanks pad a target of type DBCHAR.
- Unicode double-byte blanks pad a target of type UNICODE.
- Binary zeros pad a target of type HEX, which means (for example) that a source value "0A" is stored in a two-byte target as "0A00" rather than as "000A".
EGL truncates values on the right if the target of a character type has insufficient space to store the source value. No error is signaled.
- If more characters are in the source than are valid in the target, EGL runtime truncates the copied content to fit the available length.
- If fewer characters are in the source than are valid in the target, EGL runtime pads the copied content with blanks, to the length of the target string. However, any trailing blanks in a limited-length string are ignored in a comparison.
- The runtime platform supports the EBCDIC character set
- The assignment statement copies a literal of type MBCHAR or a variable of type MBCHAR to a shorter variable of type MBCHAR
- A byte-by-byte truncation would remove a final shift-in character or split a double-byte character
In this situation, EGL truncates characters as needed to ensure that the target variable contains a valid string of type MBCHAR, then adds (if necessary) terminating single-byte blanks.
Assignment to or from nullable types
- If the source is currently null and the target is a character variable, the target variable is set to blank.
- If the source is currently null and the target variable is numeric, the target variable is set to 0.
- If the source is not null, the assignment follows the normal assignment rules.
Nullable variables are reference compatible only with other nullable variables that have the exact same base type. The assignment follows the rules described in Reference compatibility in EGL.
Assignment between timestamps
- If the mask of the source variable is missing relatively high-level
entries that are required by the target variable, those target entries
are assigned in accordance with the clock on the machine at the time
of the assignment, as the following examples show:
sourceTimeStamp timestamp ("MMdd"); targetTimeStamp timestamp ("yyyyMMdd"); sourceTimeStamp = "1201"; // if this code runs in 2004, the next statement // assigns 20041201 to targetTimeStamp targetTimeStamp = sourceTimeStamp;sourceTimeStamp02 timestamp ("ssff"); targetTimeStamp02 timestamp ("mmssff"); sourceTimeStamp02 = "3201"; // the next assignment includes the minute // that is current when the assignment statement runs targetTimeStamp02 = sourceTimeStamp02;- If the mask of the source variable is missing relatively low-level
entries that are required by the target variable, those target entries
are assigned the lowest valid values, as the following examples show:
sourceTimeStamp timestamp ("yyyyMM"); targetTimeStamp timestamp ("yyyyMMdd"); sourceTimeStamp = "200412"; // regardless of the day, the next statement // assigns 20041201 to targetTimeStamp targetTimeStamp = sourceTimeStamp;sourceTimeStamp02 timestamp ("hh"); targetTimeStamp02 timestamp ("hhmm"); sourceTimeStamp02 = "11"; // regardless of the minute, the next statement // assigns 1100 to targetTimeStamp02 targetTimeStamp02 = sourceTimeStamp02;
Assignment to or from fields in structured records
You can assign a substructure field to a non-substructure field
or the reverse, and you can assign values between two substructure
fields. Assume, for example, that variables named myNum and myRecord are
based on the following parts:
DataItem Num12
NUM(12)
end
Record ExampleRecord type basicRecord
10 topMost CHAR(4);
20 next01 HEX(4);
20 next02 HEX(4);
end
The assignment of a value of type HEX to a variable of type NUM
is not valid outside of the mathematical system variables; but an
assignment of the form myNum = topMost is valid because topMost is
of type CHAR. In general terms, the primitive types of the fields
in the assignment statement guide the assignment, and the primitive
types of subordinate fields are not taken into account.
By default, the primitive type of a substructure field is CHAR. If you assign data to or from a substructure field and do not specify a different primitive type at declaration time, the rules described earlier for fields of type CHAR are in effect during the assignment.
Assignment of a structured record
An assignment of one structured record variable to another is equivalent to assigning one substructure field of type CHAR to another. A mismatch in length adds single-byte blanks to the right of the received value or removes single-byte characters from the right of the received value. The assignment does not consider the primitive types of subordinate structure fields.
- The content of a record can be assigned to a record variable or to a variable of type CHAR, HEX, STRING, or MBCHAR, but not to a variable of any other type
- A record can receive data from any of the following sources:
- another record
- a string literal (but not a numeric literal)
- a CHAR, HEX, STRING, or MBCHAR variable (no other type is permitted)
Finally, if you assign a structured SQL record variable to or from a structured record variable of a different type, you must ensure that the non-SQL record has space for the four-byte area that precedes each structure field (for more information, see Structured records).
Assignment between records
Non-structured record variables are assignment compatible only with other non-structured record variables of exactly the same type.
Achieving consistent results across environments
Due to truncation of intermediate results, COBOL programs might have different results than Java™ or Rich UI programs for the same arithmetic statements. To ensure consistent results across environments, use only one binary operator per statement. Multiple addition and subtraction operators can be safely combined if the number of decimal places defined for the result item is greater than or equal to the number of decimal places in any of the operands.
quotient = dividend / divisor;
remainder = dividend - (quotient * divisor);Compatibility
| Platform | Issue |
|---|---|
| COBOL generation | EGL is unable to convert text to SMALLFLOAT or FLOAT, though it can convert in the other direction. |