Variable Usage
Pascal variables declared to EQUEL can substitute for most elements of EQUEL statements that are not keywords. Of course, the variable and its data type must make sense in the context of the element. To use a Pascal variable in an EQUEL statement, just use its name. To refer to an element, such as a database column, with the same name as a variable, dereference the element by using the EQUEL dereferencing indicator (#). As an example of variable usage, the following retrieve statement uses the variables "namevar" and "numvar" to receive data, and the variable "idnovar" as an expression in the where clause:
## retrieve (namevar = e.name, numvar = e.num)
## where e.idno = idnovar;
You should not use the Pascal type-cast operator (::) in EQUEL statements. The preprocessor ignores it and does not change the type of the variable.
If, in retrieving from Ingres into a program variable, no value is returned for some reason (for example, no rows qualified in a query), the variable will not be modified.
Various rules and restrictions apply to the use of Pascal variables in EQUEL statements. The sections below describe the usage syntax of different categories of variables and provide examples of such use.
Simple Variables
A simple scalar-valued variable (integer, floating-point or character string) is referred to by the syntax:
simplename
Syntax Notes:
1. If the variable is used to send data to Ingres, it can be any scalar-valued variable, constant or enumerated literal.
2. If the variable is used to receive data from Ingres, it cannot be a constant or an enumerated literal.
3. Packed or varying arrays of characters (for example, character
strings) are referenced as simple variables.
The following program fragment demonstrates a typical message-handling routine that uses two scalar-valued variables, "buffer" and "seconds":
## var
## buffer : packed array[1..80] of Char;
## seconds : Integer;
...
## message buffer
## sleep seconds
A special case of a scalar type is the enumerated type. As mentioned in the section describing declarations, EQUEL treats all enumerated literals and any variables declared with an enumerated type as integers. When used in an EQUEL statement, only the ordinal position of the value in relation to the original enumerated list is relevant. When assigning into an enumerated variable, EQUEL will pass the object by address and assume that the value being assigned into the variable will not raise a runtime error. For example, the following enumerated type declares the states of a table field row, and the variable of that type will always receive one of those values:
## type
## Table_Field_States =
## (UNDEFINED, NEWROW, UNCHANGED, CHANGED, DELETED);
## var
## tbstate: Table_Field_States;
## ename: varying[20] of Char;
...
tbstate := undefined;
## getrow empform employee (ename = name,
## tbstate = _state)
case tbstate of
undefined:
...
deleted:
...
end;
Another example retrieves the value TRUE (an enumerated literal of type boolean) into a variable when a database qualification is successful:
## var
## found: Boolean;
## qual: varying[100] of Char;
...
found := FALSE;
## retrieve (found = TRUE) WHERE qual
if not found then
begin
...
end;
Array Variables
An array variable is referred to by the syntax:
arrayname[subscript{,subscript}] {[subscript{,subscript}]}
Syntax Notes:
1. The variable must be subscripted, because only scalar-valued elements (integers, floating-point and character strings) are legal EQUEL values.
2. When the array is declared, the array bounds specification is not parsed by the EQUEL preprocessor. Consequently, illegal bounds values will be accepted. Also, when an array is referenced, the subscript is not parsed, allowing illegal subscripts to be used. The preprocessor only confirms that an array subscript is used for an array variable. You must make sure that the subscript is legal and that the correct number of indices is used.
3. An array of characters is not a string unless it is packed or varying.
4. A packed or varying array of characters is considered a simple variable, not an array variable, in its usage. It therefore cannot be subscripted in order to reference a single character. For example, assuming the following variable declaration and subsequent assignment:
## var
## abc : packed array[1..3] of Char
...
abc := 'abc';
you could not reference
abc[1]
to access the character "a". To perform such a task, you should declare the variable as a plain (not packed or varying) array, as, for example:
## var
## abc : array[1..3] of Char
...
abc := ('a', 'b', 'c');
Record Components
The syntax EQUEL uses to refer to a record component is:
record_name{^ | [subscript]}.component{^ | [subscript]}{.component{^ | [subscript]}}
that is, the name of the record, followed by any number of pointer dereference operators or array subscripts, followed by one or more field names (with any number of pointer dereference operators or array subscripts attached).
Syntax Notes:
1. The last record component denoted by the above reference must be a scalar value (integer, floating-point or character string). There can be any combination of arrays and records, but the last object referenced must be a scalar value. Thus, the following references are all legal:
{Assume correct declarations for "employee",}
{ "person" and other records.}
employee.sal {Component of a record}
person[3].name {Component of an element of an array}
rec1.mem1.mem2.age {Deeply nested component}
2. All record components must be fully qualified when referenced. You can shorten the qualification by using the Pascal with statement (see below).
3. Any array subscripts or pointer references referred to in the record reference, and not at the very end of the reference, are not checked by the preprocessor. Consequently, both of the following references are accepted, even though one must be wrong, depending on whether "person" is an array:
person[1].age
person.age
The following example uses the array of records "emprec" to load values into the table field "emptable" in form "empform."
## type
## EmployeeRec = record
## ename: packed array[1..20] of Char;
## eage: [word] -32768 .. 32767;
## eidno: Integer;
## ehired: packed array[1..25] of Char;
## edept: packed array[1..10] of Char;
## esalary: Real;
## end;
## var
## emprec: array[1..100] of EmployeeRec;
## i: Integer;
...
for i := 1 to 100 do
begin
## loadtable empform emptable
## (name = emprec[i].ename, age = emprec[i].eage,
## idno = emprec[i].eidno, hired = emprec[i].ehired,
## dept = emprec[i].edept, salary = emprec[i].esalary)
end;
The With Statement
You can use the with statement to shorten a reference to a record. The syntax of the with statement is:
with record_reference do
begin
statements
end [;]
where record_reference is
record_name{^ | [subscript]}{.component{^ | [subscript]}}
that is, the name of a record, followed by any number of pointer dereference operators or array subscripts, followed by zero or more field names (with any number of pointer dereference operators or array subscripts attached).
Following the rules of Pascal,
## with rec_a, rec_b do
## begin
## ...
## end;
is exactly equivalent to
## with rec_a do
## begin
## with rec_b do
## begin
## ...
## end;
## end;
Syntax Notes:
1. The with statement, along with its begin and end clauses, must be preceded by the EQUEL ## mark in order to be used with EQUEL statements.
2. The record_reference must denote a record variable, not a scalar variable.Note that the with statement opens the scope of the record so that the member names can stand alone. This creates the possibility that a member name could conflict with the name of an Ingres object. For example, assume that there is an Ingres form called "rname":
## var
## rec : record
## rname : packed array[1..12] of char;
## ri : integer;
## end;
...
## with rec do
## begin
## forminit rname
## sleep ri;
## end;
In the forminit statement, "rname" refers to "rec.rname," not to the form called "rname," even though outside the scope of the with statement it would unambiguously refer to the form. To refer to the form, you must either dereference the name:
## forminit #rname
or enclose it in quotes:
## forminit 'rname'
The following example uses the array of records "emprec," declared in previous example , to load values into the emptable table field in form "empform."
for i := 1 to 100 do
begin
## with emprec[i] do
## begin
## loadtable empform emptable
## (name = ename, age = eage,
## idno = eidno, hired = ehired,
## dept = edept, salary = esalary)
## end;
end;
Pointer Variables
A pointer variable references an object in the same way as in Pascal—the name of the pointer is followed by a caret (^):
pointer_name^
Any further referencing required to fully qualify an object, such as a member of a pointed-to record, follows the usual Pascal syntax.
Syntax Notes:
1. The final object denoted by the pointer reference must be a scalar value (integer, floating-point or character string). There can be any combination of arrays, records or pointer variables, as long as the last object referenced has a scalar valuThe pointer reference is also used with file type variables.
In the following example, a pointer to an employee record is used to load a linked list of values into the Employee database table:
## type
## EmpLink = ^EmployeeRec;
## EmployeeRec = record
## ename: packed array [1..20] of Char;
## eage: Integer;
## eidno: Integer;
## enext: EmpLink;
## end;
## elist: EmpLink;
...
while (elist <> nil) do
begin
## repeat append to employee
## (name = @elist^.ename, age = @elist^.eage,
## idno = @elist^.eidno)
elist := elist^.enext;
end;
Indicator Variables
The syntax for referring to an indicator variable is the same as for a simple variable, except that an indicator variable is always associated with a host variable:
host_variable:indicator_variable
Syntax Note:
The indicator variable can be a simple variable, an array element or a record component that yields a 2-byte integer. The type indicator has already been declared by the preprocessor. For example:
## var
## ind_var, ind_arr[5] : Indicator;
var_1:ind_var
var_2:ind_arr[2]