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 and DeptSet. The compiler assumes references to the current set are to EmpSet until the second FIND command, after which references apply to DeptSet.

Technical Insight:

  • Compiler Behavior: The compiler processes commands sequentially. After the first FIND command, any reference to the current set points to EmpSet. After the second FIND, references switch to DeptSet.

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 the CHANGE command is understood by the compiler to refer to the result set created by the second FIND command, causing unexpected behavior.

Technical Insight:

  • Implicit Result Set: The CHANGE command operates on the current set, which is determined by the last FIND 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 compiling test2.

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 all FIND commands producing set1 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 all FIND 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 the LET command because it is not a field in the current set (DeptSet). It treats LastName 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 finding EmpSet.

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 for DeptSet 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 make EmpSet the current set inside the second IF 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

$addyears

$addmonths

$addminutes

$addhours

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

About Arithmetic Expressions

Arithmetic with Dates

Decimals and Rounding

Rules of Precedence for Operators

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:

  1. Character handling
    • definition of non-English characters
    • uppercase/lowercase translation
    • collating sequence for sorting, indexing, and comparing
  1. Zim errors file
    • errors produced by Zim itself
  2. Internal messages and strings
    • errors and processing messages produced for the application’s forms
    • day and month names
  3. 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

$mask

How To Use Data Masks

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.

pt_BRPortuguese