Back to Contents


Variables

Summary:

See also: Records, Arrays, Data Types, Constants.


Definition

A variable is a program element that can hold volatile data. The following list summarizes variables usage:


DEFINE

Purpose:

A variable contains volatile information of a specific data type.

Syntax:

DEFINE identifier [,...] { type | LIKE [dbname:]tabname.colname }

Notes:

  1. identifier is the name of the variable to be defined.
  2. type can be any data type supported by the language, a record definition, an array definition, or a built-in class.
  3. When using the LIKE clause, the data type is taken from the schema file. Columns defined as SERIAL are converted to INTEGER.
  4. dbname identifies a specific database schema file.
  5. tabname.colname can be any column reference defined in the database schema file.
  6. Variables can be global to the program, local to a module, or local to a function.

Tips:

  1. To write well-structured programs, it is recommended that you not use global variables. If you need persistent data storage during a program's execution, use variables local to the module and give access to them with functions.

Warnings:

  1. When defining variables with the LIKE clause, the data types are taken from the schema file during compilation. Make sure that the schema file of the development database corresponds to the production database; otherwise the variables defined in the compiled version of your modules will not match the table structures of the production database.

Usage

A variable is a named location in memory that can store a single value, or an ordered set of values. You cannot reference any program variable before it has been declared by the DEFINE statement.


Declaration Context

The DEFINE statement declares the identifier of one or more variables. There are two important things to know about these identifiers:

The context of its declaration in the source module determines where a variable can be referenced by other language statements, and when storage is allocated for the variable in memory. The DEFINE statement can appear in three contexts:

  1. Within a FUNCTION, MAIN, or REPORT program block, DEFINE declares local variables, and causes memory to be allocated for them. These DEFINE declarations of local variables must precede any executable statements within the same program block.
  2. Outside any FUNCTION, REPORT, or MAIN program block, the DEFINE statement declares names and data types of module variables, and causes storage to be allocated for them. These declarations must appear before any program blocks.
  3. Inside a GLOBALS block, the DEFINE statement declares global variables.

A compile-time error occurs if you declare the same name for two variables that have the same scope. You can, however, declare the same name for variables that differ in their scope. For example, you can use the same identifier to reference different local variables in different program blocks.

You can also declare the same name for two or more variables whose scopes of reference are different but overlapping. Within their intersection, the compiler interprets the identifier as referencing the variable whose scope is smaller, and therefore the variable whose scope is a superset of the other is not visible.

If a local variable has the same identifier as a global variable, then the local variable takes precedence inside the program block in which it is declared. Elsewhere in the program, the identifier references the global variable.

A module variable can have the same name as a global variable that is declared in a different module. Within the module where the module variable is declared, the module variable takes precedence over the global variable. Statements in that module cannot reference the global variable.

A module variable cannot have the same name as a global variable that is declared in the same module.

If a local variable has the same identifier as a module variable, then the local identifier takes precedence inside the program block in which it is declared. Elsewhere in the same source-code module, the name references the module variable.


Structured Types

You can use the RECORD or ARRAY keywords to declare a structured variable.

For example:

01 MAIN
02   DEFINE myarr ARRAY[100] OF RECORD
03      id INTEGER,
04      name VARCHAR(100)
05   END RECORD
06   LET myarr[2].id = 52
07 END MAIN

For more detail, refer to Arrays and Records.


Indirect Typing

You can use the LIKE keyword to declare a variable that has the same data type as a specified column in a database schema, for example:

01 DATABASE stores
02 DEFINE cname LIKE customer.cust_name
03 MAIN
05   DEFINE cr RECORD LIKE customer.*
06 END MAIN

The following rules apply when using the LIKE keyword:

To understand how to generate database schema files, refer to Database Schema Files.


Default Values

After a variable is defined, it is automatically initialized by the runtime system to a default value based on the data type. The following table shows all possible default values that variables can take:

Data Type Default Value
CHAR NULL
VARCHAR NULL
STRING NULL
INTEGER Zero
SMALLINT Zero
FLOAT Zero
SMALLFLOAT Zero
DECIMAL NULL
MONEY NULL
DATE 1899-12-31 (=Zero in number of days)
DATETIME NULL
INTERVAL NULL
TEXT NULL, See LOCATE
BYTE NULL, See LOCATE

INITIALIZE

Purpose:

The INITIALIZE instruction assigns initial NULL or default values to variables.

Syntax:

INITIALIZE target [,...] { TO NULL | LIKE {table.*|table.column} }

Notes:

  1. target is the name of the variable to be initialized.
  2. target can be a simple variable, a record or an array element.
  3. If target is a record, you can use the star to reference all record members in the initialization. 
  4. The TO NULL clause initializes the variable to NULL.
  5. The LIKE clause initializes the variable to the default value defined in the database schema attributes file.
  6. table.column can be any column reference defined in the database schema file.

Tips:

  1. To initialize a complete record, use the star to reference all members:
      INITIALIZE record.* LIKE table.*

Warnings:

  1. The LIKE clause requires the IBM Informix upscol utility to populate the syscolatt table. See  the database schema files for more details. Informix only!
  2. You cannot initialize variables defined with a complex data type (like TEXT or BYTE) to a non-NULL value.

Example:

01 DATABASE stores
02 MAIN
03   DEFINE cr RECORD LIKE customer.*
04   INITIALIZE cr.cust_name TO NULL
05   INITIALIZE cr.* LIKE customer.*
06 END MAIN

VALIDATE

Purpose:

The VALIDATE statement tests whether the value of a variable is within the range of values for a corresponding column in database schema files.

Syntax:

VALIDATE target [,...] LIKE {table.*|table.column}

Notes:

  1. target is the name of the variable to be validated.
  2. target can be a simple variable, a record, or an array element.
  3. If target is a record, you can use the star to reference all record members in the validation.
  4. Values are compared to the value defined in the database schema validation file.
  5. table.column can be any column reference defined in the database schema file.

Errors:

  1. If the value does not match any value defined in the INCLUDE attribute of the corresponding column, the runtime system raises an exception with error code -1321.

Warnings:

  1. The LIKE clause requires the IBM Informix upscol utility to populate the syscolval table. See  the database schema files for more details. Informix only!
  2. You cannot initialize variables defined with a complex data type (like TEXT or BYTE) to a non-NULL value.

Example:

01 DATABASE stores
02 MAIN
03   DEFINE cname LIKE customer.cust_name
04   LET cname = "aaa"
05   VALIDATE cname LIKE customer.cust_name
06 END MAIN

LET

Purpose:

The LET statement assigns a value to a variable, or a set of values to a record.

Syntax:

LET target = expression

Notes:

  1. target is the name of the variable to be assigned.
  2. target can be a simple variable, a record, or an array element.
  3. expression is any valid expression supported by the language
  4. The runtime system applies data type conversion rules if the data type of expression does not correspond to the data type of target.
  5. If target is a record, you can use the star to reference all record members in the validation, and expressions can also use this notation (record.*).

Warnings:

  1. Variables defined with a complex data type (like TEXT or BYTE) can only be assigned to NULL.
  2. For more detail, refer to the assignment operator.

Example:

01 DATABASE stores
02 MAIN
03   DEFINE c1, c2 RECORD LIKE customer.*
04   LET c1.* = c2.*
05 END MAIN

LOCATE

Purpose:

The LOCATE statement specifies where to store data of TEXT and BYTE variables.

Syntax:

LOCATE target [,...] IN { MEMORY | FILE filename }

Notes:

  1. Defining the location of large object data is mandatory before usage.
  2. target is the name of a TEXT or BYTE variable to be located.
  3. target can be a simple variable, a record member, or an array element.
  4. filename is a string expression defining the name of a file.
  5. The IN MEMORY clause specifies that the large object data must be located in memory.
  6. The IN FILE clause specifies that the large object data must be located in a file.
  7. After defining the data storage, the variable can be used as a parameter or as a fetch buffer in SQL statements.
  8. You can free the resources allocated to the large object variable with the FREE instruction.

Warnings:

  1. You cannot use a large object variable if the data storage location is not defined.

Example:

01 MAIN
02   DEFINE ctext1, ctext2 TEXT
03   DATABASE stock
04   LOCATE ctext1 IN MEMORY
05   LOCATE ctext2 IN FILE "/tmp/data1.txt"
06   CREATE TABLE lobtab ( key INTEGER, col1 TEXT, col2 TEXT )
06   INSERT INTO lobtab VALUES ( 123, ctext1, ctext2 )
07 END MAIN

FREE

Purpose:

The FREE statement releases resources allocated to store the data of TEXT and BYTE variables.

Syntax:

FREE target

Notes:

  1. target is the name of a TEXT or BYTE variable to be freed.
  2. target can be a simple variable, a record member, or an array element.
  3. If the variable was located in memory, the runtime system releases the memory.
  4. If the variable was located in a file, the runtime system deletes the named file.
  5. For variables declared in a local scope of reference, the resources are automatically freed by the runtime system when returning from the function or MAIN block.

Warnings:

  1. After freeing a large object, you must LOCATE the variable again before usage.

Example:

01 MAIN
02   DEFINE ctext TEXT
03   DATABASE stock
03   LOCATE ctext IN FILE "/tmp/data1.txt"
04   SELECT col1 INTO ctext FROM lobtab WHERE key=123
05   FREE ctext
06 END MAIN

Examples

Example 1: Function variables

01 FUNCTION myfunc( )
02   DEFINE i INTEGER
03   FOR i=1 TO 10
04       DISPLAY i
05   END FOR
06 END FUNCTION

Example 2: Module variables

01 DEFINE s VARCHAR(100)
02 
03 FUNCTION myfunc( )
04   DEFINE i INTEGER
05   FOR i=1 TO 10
06       LET s = "item #" || i
07   END FOR
08 END FUNCTION

Example 3: Global variables

File "myglobs.4gl":

01 GLOBALS
02   DEFINE userid CHAR(20)
03   DEFINE extime DATETIME YEAR TO SECOND
04 END GLOBALS

File "mylib.4gl":

01 GLOBALS "myglobs.4gl"
02 
03 DEFINE s VARCHAR(100)
04 
05 FUNCTION myfunc( )
06   DEFINE i INTEGER
07   DISPLAY "User Id = " || userid
08   FOR i=1 TO10
09       LET s = "item #" || i
10   END FOR
11 END FUNCTION

File "mymain.4gl":

01 GLOBALS "myglobs.4gl"
02 
03 MAIN
04   LET userid = fgl_getenv("LOGNAME")
05   LET extime = CURRENT YEAR TO SECOND
06   CALL myfunc()
07 END MAIN