Refer to the description of CASE.
Category: Building an Application
Working with Sets in ZIM
Understanding Result Set References in Zim
Introduction: Result set references in Zim are crucial for managing and manipulating data efficiently. This guide provides detailed examples to illustrate how result set references are compiled and highlights situations to avoid for optimal performance.
Example 1: Basic Result Set Creation
procedure test()
find all Employees -> EmpSet
... other non-FIND commands ...
find all Departments -> DeptSet
... other non-FIND commands ...
endprocedure
- Explanation: This procedure creates two result sets,
EmpSet
andDeptSet
. The compiler assumes references to the current set are toEmpSet
until the secondFIND
command, after which references apply toDeptSet
.
Technical Insight:
- Compiler Behavior: The compiler processes commands sequentially. After the first
FIND
command, any reference to the current set points toEmpSet
. After the secondFIND
, references switch toDeptSet
.
Example 2: Conditional Result Set Creation
procedure GetEmps (DeptNo, NewDeptNo)
if DeptNo = 'D01'
find all Employees where DeptNum = DeptNo
else
find all Departments where DeptNum = DeptNo
endif
change all CurrentSet let DeptNum = NewDeptNo
endprocedure
- Explanation: The
DeptNum
reference in theCHANGE
command is understood by the compiler to refer to the result set created by the secondFIND
command, causing unexpected behavior.
Technical Insight:
- Implicit Result Set: The
CHANGE
command operates on the current set, which is determined by the lastFIND
command executed. This can lead to ambiguity if not managed carefully.
Example 3: Using External Result Sets
procedure test2()
form open MyForm
change MyForm from EmpSet
form display
endprocedure
- Explanation:
EmpSet
must be a set object in the application database or created by a set-processing command before compilingtest2
.
Technical Insight:
- Set Object Requirement: Ensure that
EmpSet
exists and has the expected structure before using it in procedures. This can be achieved by creating a “dummy” set during compilation.
Example 4: Context-Sensitive Result Sets
procedure GetSet1 (a,b)
if a=b
find all Employees WorkIn Departments -> set1
else
find all Employees -> set1
endif
list set1
bottom set1
list set1
endprocedure
- Explanation: Using
set1
with different structures causes the compiled program to not work as expected. Ensure allFIND
commands producingset1
have the same structure.
Technical Insight:
- Consistent Structure: Maintain a consistent structure for result sets to avoid compilation issues. Use
SET CHECKSETS ON
to enforce continuity of structure.
Example 5: Consistent Result Set Structure
procedure GetSet1 (a,b)
if a=b
find all Employees WorkIn Departments -> set1
else
find all Employees WorkIn Departments where LastName = 'Smith' -> set1
endif
list set1
bottom set1
list set1
endprocedure
- Explanation: Ensuring
set1
has the same structure in allFIND
commands avoids issues.
Technical Insight:
- Compiler Consistency: The compiler can resolve references correctly when the structure of the result set remains consistent across different
FIND
commands.
Example 6: Resolving Field References
procedure test3 (a,b)
if a=b
find Employees -> EmpSet
else
find Departments -> DeptSet
endif
if a=b
let a = LastName
endif
endprocedure
- Explanation: The compiler cannot resolve
LastName
in theLET
command because it is not a field in the current set (DeptSet
). It treatsLastName
as a character literal.
Technical Insight:
- Field Resolution: The
LET
command can only refer to fields in the current set. Ensure the correct set is active when referencing fields.
Solutions to Example 6
Example 7: Save LastName in a Variable
procedure test3 (a, b, SavedLastName)
if a=b
find Employees -> EmpSet
let SavedLastName = LastName
else
find Departments -> DeptSet
endif
if a=b
let a = SavedLastName
endif
endprocedure
- Explanation: Save
LastName
in a variable immediately after findingEmpSet
.
Technical Insight:
- Variable Storage: Storing field values in variables ensures they are accessible even if the current set changes.
Example 8: Remove FIND to Another Procedure
procedure test3 (out a, b)
if a=b
find Employees -> EmpSet
else
findDeptSet % Call a program to find DeptSet.
endif
if a=b
let a = LastName
endif
endprocedure
- Explanation: Remove the
FIND
command forDeptSet
to another procedure.
Technical Insight:
- Procedure Separation: Separating
FIND
commands into different procedures can prevent conflicts and ensure correct field references.
Example 9: Use SET CURRENTSET
procedure test3 (a, b)
if a=b
find Employees -> EmpSet
else
find Departments -> DeptSet
endif
if a=b
set currentset EmpSet
let a = LastName
endif
endprocedure
- Explanation: Use
SET CURRENTSET
to makeEmpSet
the current set inside the secondIF
statement.
Technical Insight:
- Current Set Management: Explicitly setting the current set ensures the correct fields are referenced, avoiding ambiguity.
Conclusion: Understanding how result set references are compiled and managed in Zim is essential for developing robust applications. By following these examples and technical insights, developers can avoid common pitfalls and ensure their programs work as expected.
Decimals and Rounding
The result of an arithmetic expression contains as many decimal places as are found in the operands of the expression.
If the expression contains several operands with varying numbers of decimal places, the result takes on the number of decimal places found in the operand with the most decimal places.
If the result of the expression is assigned to an object with a numeric data type, the value takes on the number of decimal places defined for that object. If the object has fewer rounded decimal places than the expression’s result, the final value is rounded as shown in the following example:
5/2 | Evaluates to 3 |
5/2.0 | Evaluates to 2.5 |
1+1.01 | Evaluates to 2.01 |
1.01+(5/2) | Evaluates to 3.51 |
Rounding occurs only after the entire expression has been evaluated. Therefore, in 1.01+(5/2), the fractional part of 5/2 is kept during the addition of 1.01. Because 1.01 has two decimal places, the result also has two decimal places.
Arithmetic with Dates
ZIM-X provides a number of built-in functions to perform date and time arithmetic. If an arithmetic expression subtracts one date from another (i.e., both operands are of data type DATE), the result is a number representing the number of days between the two dates.
Example
Consider the Date Type values: Date1 = 19990923 (23SEP1999) and Date2 = 19980923 (23SEP1998). We can now apply arithmetic to the dates by simply doing the following:
Date1 – Date2 evaluates to 365. Because the numbers are Date Types, ZIM equates to Date1 to 19990923 and Date2 to 19980923. If the same calculation was performed with INT Data Types the result would be 10,000.
If you add (subtract) a value that is not a date to (from) a date, the result is a date equal to the date operand plus (minus) the number of DAYS indicated by the non-date operand.
Date1 - 100 equates to 19990923 - 100, but evaluates to 19990615 (15Jun1999 - not 19990823) Date1 + 100 equates to 19990923 + 100, but evaluates to 20000101 (1Jan2000- not 19991023)
Comments
You can covert a Number Type value to do a Date Type value by using $todate().
If you use dates in any other type of operation, the dates are treated as numbers:
Date1/100 equates to 19990923/100, and evaluates to 199909.
See Also
How To Construct Arithmetic Expressions
Writing Expressions
Arithmetic operators and parentheses can be combined to create long, complex expressions. Arithmetic expressions are evaluated based on the standard rules of precedence. Parentheses alter the order of evaluation.
Spaces between operands and operators can be used for clarity, but are not required.
For example, Salary * 1.1 and Salary*1.1 are equivalent.
Data Types
Arithmetic expressions yield a numeric result (if possible).
Operands should preferably be of a numeric data type, but character types are converted into an equivalent number as shown in the following example:
” ” (a space) is 0.
“-2″+5 is 3.
“2”*”-4″ is -8.
If a character value cannot be converted to a number (e.g., “abcd”), an error message is returned and the value is treated as 0.
Decimals and Rounding
The result of an arithmetic expression has as many decimal places as are found in the operand with the most decimal places in the expression. If the result is assigned to a field, variable, or form field that has fewer decimal places than the result, the result takes on the number of decimal places in the field, variable, or form field. Results are rounded as required. Rounding occurs only after the entire expression has been evaluated as shown in the following examples:
5/2 is 3
5/2.0 is 2.5
1+1.01 is 2.01
1.01+(5/2) is 3.51
How To Use Arithmetic Expressions
An arithmetic expression is a complex value expression that consists of two or more value expressions and associated arithmetic operators.
The arithmetic operators are
- + (Add)
- – (Subtract)
- ^(Exponentiation)
- * (Multiply)
- / (Divide)
Examples of Arithmetic Expressions
For clarity, spaces can be used between operands and operators, but they are not required.
Salary * 1.1
or
Salary*1.1
Salary + (Salary * 0.1)
(1 + InterestRate)^Years
TotalPrice/Items
SellingPrice – (SellingPrice * BulkDiscount)
See Also
Rules of Precedence for Arithmetic Operators
Operator | Rule of Precedence |
Unary + and – | Positive (+) and negative (-) signs are evaluated first, e.g., +2 or -Salary. |
^ | Exponentiation (^) is performed next, e.g., x^y, that is x raised to the power of y. Note: If x is negative, y must be an integer. |
* and / | Multiplication (*) and division (/) are performed following exponentiation. |
+ and – | Addition (+) and subtraction (-) are performed last. |
Notes:
- Operators of equal precedence are evaluated from left to right in the expression.
- Parentheses can be used to explicitly determine the order of evaluation, overriding the order described above. Each pair of parentheses can contain only one arithmetic expression. Use parentheses extensively in arithmetic expressions.
Arithmetic Expressions
Arithmetic expressions use arithmetic operators to combine operands (typically value expressions). When evaluated, these arithmetic expression yield a numeric result, if possible.
Operator | Meaning |
+ | Positive sign (unary +); addition |
– | Negative sign (unary -); subtraction |
^ | Exponentiation |
* | Multiplication |
/ | Division |
Note: If the ^ character is unavailable, you can substitute **.
The standard rules of precedence for arithmetic evaluation are used.
Examples of arithmetic expressions follow:
Salary * 1.1
Salary + (Salary*0.1)
(! + InterestRate)^Years
The data types (CHAR, NUMERIC, INT, and so on) of the operands used in an arithmetic expression can be mixed. Operands that are character strings are translated (if possible) into an equivalent number, as shown below:
‘/’ evaluates to 0
‘-2’ + 5 evaluates to 3
‘2’ * ‘-4’ evaluates to -8
If a character string cannot be translated into a number (e.g., abcd), then an error message is returned, or the operand is treated as if it were zero.
Multi-Language Support
Customizing applications for languages other than English
In Zim applications, some information that appears in the user interface, such as data masks, and error and processing messages, is language dependent. Zim provides tools to handle these dependencies and to make the application appear to the application user in languages other than English. A single application can be designed to handle several different languages simultaneously.
Language dependencies occur in four major areas of any application:
- Character handling
- definition of non-English characters
- uppercase/lowercase translation
- collating sequence for sorting, indexing, and comparing
- Zim errors file
- errors produced by Zim itself
- Internal messages and strings
- errors and processing messages produced for the application’s forms
- day and month names
- Data masking
- numeric masks
- alphanumeric masks
- date masks
Tools used for adaptation
Zim provides three tools specifically geared to language adaptation:
- the developer-defined collating table
- the ability to translate error messages
- the ZIMLANG utility to alter masks, day names, and so on
The collating table is stored in the database. The collating table defines, internally to the system, how characters are represented and how they are to be sorted.
You can provide your own collating tables. For applications in languages other than English, the collating table enables you to properly handle special characters, such as accented characters.
Messages, strings, and mask characters can be customized for the desired language by translating the error message file or calling up the ZIMLANG utility.
Restrictions
Although Zim’s language-independence features solve a number of language adaptation problems, keep in mind these restrictions:
- Applications are developed in English
- You must ensure that output from an application is properly translated into the required language(s)
Numeric input/output can be adapted to another language only if it is controlled by a mask or numeric form field. Numeric values input from documents, including the terminal, or output without masks, appear in the original English format.
Zim does not recognize multi-character currency symbols.
Character Handling
Some languages use more characters than the twenty-six found in the English alphabet. These extra characters must be defined to ZIM in the collating table.
Collating Information
Zim uses a collating sequence that the database initialization program ZIMINIT reads from a collating table stored in an operating system file. The name of the collating file is operating system dependent. If the collating table is not found, Zim uses the standard collating sequence for your operating system.
Applications that have a requirement to define a collating sequence other than the standard ASCII collating sequence (i.e. programs that use accented characters) should rename the appropriate collating file in the Zim software directory to ” COLLATE.ZIM”. Renaming the file ensures that it is read by the Database Initialization program. In Zim for Windows, ZCOLLATE.DOS defines a collating sequence for all the OEM-accented characters while ZCOLLATE.WIN provides a collating sequence for the ANSI-accented characters.
The collating file is a text file that can be modified with any text editor that can handle ASCII characters. The file contains one entry per line. Each entry consists of the following information:
- character representation (the internal value that represents the character)
- collating value (the sorting value assigned by to the character by the developer)
- lowercase representation (the lower case equivalent of the character)
- uppercase representation (the upper case equivalent of the character)
Each field in an entry is separated from the next by a space. The characters can be entered as single characters that exist in your hardware’s character set or as a hexadecimal value. Hex values are entered in the format
hh
where hh is a pair of valid hex characters (0 to 9, a to f, A to F).
Entries in the collating table are governed by the following rules:
- A character is known as a letter if either its uppercase representation or lowercase representation differs from the value placed in the character representation field of the collating table.
- A character is upper case if it is a letter and if the character’s uppercase representation (the entry in the “uppercase representation” field) is the same as the character representation.
- Some characters, such as $, #, @ are the same regardless of case. Therefore the entry in either the “uppercase representation” field or the “lowercase representation” field is irrelevant.
Accented Characters
A developer can treat a series of similar characters in the same way. For example, the characters
- á
- â
- Ã
- a
can all be assigned the same collating value. For sorting purposes, à and á would be treated the same way as a. This situation simplifies the data entry responsibilities of an application user. The user does not have to remember if a customer’s name, for example, contains an accent. On the other hand, record searches become more inefficient by having a wider scope (searches for records that contain a also return records that contain á and a).
The developer must decide if it is better for the application to differentiate between accented characters or to treat all similar characters in the same way. To differentiate accented characters, the developer can assign them collating values that correspond to user-defined locations in the normal collating sequence.
Zim error message translation
Error messages are produced from templates stored in the ZIM errors file. This file is described in Customizing Error Messages.
Error message prefixes ( eg *** Error***) and internally generated form messages can be modified using the ZIMLANG utility.
Using ZIMLANG
When customizing an application for a different language, internal strings (processing messages, day names, and so on) and mask characters must be taken into account. Strings and mask characters are customized through the ZIMLANG utility. For information on the use of the command, see ZIMLANG.
Internal strings
ZIMLANG can be used to modify the following types of strings:
- error message prefixes ( eg *** Error***)
- day and month names
- form error messages
- processing messages
When ZIMLANG is used to translate processing messages, formatting characters (such as / n, / r, / d) must not be changed, as they are the codes used to properly format the display of the messages.
Masks
Masks are used in reports and forms to precisely define how data is to be displayed. ZIMLANG can be used to replace the following mask characters with different characters:
- Date
- day (D)
- month ( M)
- year ( Y)
- numeric
- currency ($)
- comma (,)
- decimal point (.)
- alphanumeric
- various characters (?)
Several rules must be followed when translating mask characters with ZIMLANG:
- The mask characters for day, month, and year must be unique (i.e. the mask for day c
annot be the same as the mask for month). - The mask characters for the decimal point, the comma, and the currency symbol must be unique (i.e. the mask for the decimal point cannot be the same as the mask for the comma).
- ZIM developers can specify masks in a report, in the $mask function, and for a form field. Masks are always specified in English (the default format). ZIMLANG affects only how application users see masks in form fields and how they see masked values in form fields, reports, and the $mask function.
In reports and in the $mask function,
- only numeric masks are affected by ZIMLANG
- when a numeric mask indicates the presence of a decimal point, comma, or currency symbol, the newly defined character is used.
- application users never see the masks themselves, just the masked data.
In forms, all three classes of masks (date, numeric and alphanumeric) are altered by ZIMLANG, with the following results:
- In date masks, the new characters for day, month, and year replace the English characters
- In numeric masks, commas and decimal points in displayed values are replaced by the appropriate alternate language characters.
- In alphanumeric masks, mask characters (such as ?) are replaced with an appropriately defined alternate language character.
See Also
Number Literals
A number literal is composed using the digits 0 to 9 and a decimal point (if desired). The number literal is automatically assigned the data type VASTINT, with a number of decimal places equal to the number of places shown in the expression.
The following numbers are examples of valid number literals:
5 234 0.5 468.55
The following groups of digits are not number literals
56,789 1 23
because the software does not enable commas or spaces to be used inside numbers.