Summary:
See also: Records, Arrays, Data Types, Constants, User Types.
A variable is a program element that can hold volatile data. The following list summarizes variables usage:
A variable contains volatile information of a specific data type.
[PUBLIC|PRIVATE] DEFINE variable-definition [,...]
where variable-definition is:
identifier [,...] { datatype | LIKE
[dbname:]tabname.colname }
A variable is a named location in memory that can store a single value, or an ordered set of values. Variables can be global to the program, module-specific, or local to a function.
You cannot reference any program variable before it has been declared by the DEFINE statement.
By default, module-specific variables are private; They cannot be used by an other module of the program. In order to improve code reusability by data encapsulation, we recommend you to keep module variables private, except if you want to share large data (like arrays) between modules. To make a module variable public, add the PUBLIC keyword before DEFINE. When a module variable is declared as public, it can be referenced by another module by using the IMPORT instruction.
Note that 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.
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.
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:
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.
You can use the RECORD or ARRAY keywords to declare a structured variable.
For example:
01
MAIN02
DEFINE myarr ARRAY[100] OF RECORD03
id INTEGER,04
name VARCHAR(100)05
END RECORD06
LET myarr[2].id = 5207
END MAIN
For more detail, refer to Arrays and Records.
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
SCHEMA stores02
DEFINE cname LIKE customer.cust_name03
MAIN05
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 with the schema extractor tool, refer to Database Schema Files
Variables can be defined with a user type:
01
TYPE custlist DYNAMIC ARRAY OF RECORD LIKE customer.*02
MAIN03
DEFINE cl custlist04
END MAIN
The scope of a user type can be global, local to a module or local to a function. Variables can be defined with a user type defined in the same scope, or in a higher level of scope.
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 |
The INITIALIZE instruction assigns NULL or default values to variables.
INITIALIZE target [,...] { TO NULL | LIKE {table.*|table.column} }
The TO NULL clause initializes the variable to NULL.
When initializing a static array TO NULL, all elements will be initialized to NULL. When initializing a dynamic array TO NULL, all elements will be removed (i.e. the dynamic array is cleared).
The LIKE clause initializes the variable to the default value defined in the database schema validation file. This clause works only by specifying the table.column schema entry corresponding to the variable.
To initialize a complete record, you can use the star to reference all members:
01
INITIALIZE record.* LIKE table.*
You cannot initialize variables defined with a complex data type (like TEXT
or BYTE) to a non-NULL value.
01
DATABASE stores02
MAIN03
DEFINE cr RECORD LIKE customer.*04
DEFINE a1 ARRAY[100] OF INTEGER05
INITIALIZE cr.cust_name TO NULL06
INITIALIZE cr.cust_name THRU cr.cust_address TO NULL07
INITIALIZE cr.* LIKE customer.*08
INITIALIZE a1 TO NULL09
INITIALIZE a1[10] TO NULL10
END MAIN
The VALIDATE instructions checks a variable value according to schema validation rules.
VALIDATE target [,...] LIKE {table.*|table.column}
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.
The LIKE clause requires the IBM Informix upscol utility to populate the syscolval table. See the database schema files for more details. Informix only!You cannot initialize variables defined with a complex data type (like TEXT or BYTE) to a non-NULL value.
01
DATABASE stores02
MAIN03
DEFINE cname LIKE customer.cust_name04
LET cname = "aaa"05
VALIDATE cname LIKE customer.cust_name06
END MAIN
The THRU keyword can be used to specify a range of members of a record.
record.first-member [ THRU | THROUGH ] record.last-member
The THRU keyword can be used in several instructions such as INITIALIZE, VALIDATE, LOCATE.
01
DATABASE stores02
MAIN03
DEFINE cust LIKE customer.*04
INITIALIZE cust.cust_name THRU customer.cust_address TO NULL05
END MAIN
The LET statement assigns a value to a variable, or a set of values to a record.
LET target = expression [,...]
When specifying a comma-separated list of expressions for the right operand, the LET statement concatenates all expressions together. Unlike the || operator, if an expression in the comma-separated list evaluates to NULL, the concatenation result will not be null, except if all expressions to the right of the equal sign are null.
The runtime system applies data type conversion rules if the data type of expression does not correspond to the data type of target.
You can use most of the built-in functions and character string operators like CLIPPED or USING within the LET statement.
target can be record followed by dot + star (record.*) to reference all record members of the record. In this case, the right operand must also be a record using this notation (see example below).Note that variables defined with a complex data type (like TEXT or BYTE) can only be assigned to NULL.
For more details, refer to the assignment operator.
01
DATABASE stores02
MAIN03
DEFINE c1, c2 RECORD LIKE customer.*04
LET c1.* = c2.*05
END MAIN
The LOCATE statement specifies where to store data of TEXT and BYTE variables.
LOCATE target [,...] IN MEMORY
LOCATE target [,...] IN FILE filename
LOCATE target [,...] IN FILE
Note that you cannot use a large object variable if the data storage location is not defined.
The first syntax using the IN MEMORY clause specifies that the large object data must be located in memory. The second syntax using the IN FILE filename clause specifies that the large object data must be located in a specific file. The third syntax using the IN FILE clause specifies that the large object data must be located in a temporary file.
When using a temporary file, the location of the temporary file can be defined with the DBTEMP environment variable. By default, the runtime system will use /tmp on UNIX and %TMP% or %TEMP% on Windows. The temporary files are automatically dropped by the runtime system when the program terminates.
On UNIX systems, the permission on the temporary file can be controlled by umask.
You can free the resources allocated to the large object variable with the FREE instruction.01
MAIN02
DEFINE ctext1, ctext2 TEXT03
DATABASE stock04
LOCATE ctext1 IN MEMORY05
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
The FREE statement releases resources allocated to the specified variable.
FREE target
If the TEXT/BYTE variable was located in memory, the runtime system releases the memory. If the variable was located in a file, the runtime system deletes the file.
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.
After freeing a large object, you must LOCATE the variable again before usage.
01
MAIN02
DEFINE ctext TEXT03
DATABASE stock03
LOCATE ctext IN FILE "/tmp/data1.txt"04
SELECT col1 INTO ctext FROM lobtab WHERE key=12305
FREE ctext06
END MAIN
01
FUNCTION myfunc( )02
DEFINE i INTEGER03
FOR i=1 TO 1004
DISPLAY i05
END FOR06
END FUNCTION
01
DEFINE s VARCHAR(100)02
03
FUNCTION myfunc( )04
DEFINE i INTEGER05
FOR i=1 TO 1006
LET s = "item #" || i07
END FOR08
END FUNCTION
File "myglobs.4gl":
01
GLOBALS02
DEFINE userid CHAR(20)03
DEFINE extime DATETIME YEAR TO SECOND04
END GLOBALS
File "mylib.4gl":
01
GLOBALS "myglobs.4gl"02
03
DEFINE s VARCHAR(100)04
05
FUNCTION myfunc( )06
DEFINE i INTEGER07
DISPLAY "User Id = " || userid08
FOR i=1 TO1009
LET s = "item #" || i10
END FOR11
END FUNCTION
File "mymain.4gl":
01
GLOBALS "myglobs.4gl"02
03
MAIN04
LET userid = fgl_getenv("LOGNAME")05
LET extime = CURRENT YEAR TO SECOND06
CALL myfunc()07
END MAIN