Was this helpful?
Variable and Type Declarations
The following sections describe variable and type declarations.
EQUEL Variable Declarations Procedures
EQUEL statements use BASIC variables to transfer data from a database or a form into the program and conversely. You must declare BASIC variables to EQUEL before using them in EQUEL statements. The preprocessor does not allow implicit variable declarations. For this reason, the "%" and "$" suffixes cannot be used with variable names. BASIC variables are declared to EQUEL by preceding the declaration with the ## mark. The declaration must be in a position syntactically correct for the BASIC language.
In general, EQUEL variables can be referred to in the program or subprogram in which they are declared. The scope of variables is discussed in detail in a later section.
The Declare Ingres Statement
Prior to any EQUEL declarations or statements in your main program, you must issue the following statement:
##   declare ingres
This statement causes the preprocessor to generate code to include a file of declarations needed by EQUEL at runtime. You will not be able to successfully link an EQUEL program without this statement. The statement also serves to terminate the scope of variables declared earlier in the file. Therefore, any variables declared before the declare ingres statement will not be visible to the preprocessor. For this reason, it is an error to issue two declare ingres statements in a single program module.
You should not issue the declare ingres statement in subroutines and functions declared to EQUEL. After processing a sub or function statement, the preprocessor automatically generates the declare ingres statement and terminates the scope of previous subprograms. If you do issue the declare ingres statement in a subroutine or function known to EQUEL, the preprocessor will generate a warning and ignore the statement. On the other hand, if you do not define a subprogram to EQUEL (perhaps because it lists formal parameters of a type unavailable to EQUEL variables), you must specifically issue the declare ingres statement before any EQUEL declarations or statements in that subprogram.
Because a def function is local to the program or subprogram that defines it, the declare ingres statement is neither needed nor automatically generated for it. The def function inherits its program module's variables and definitions.
Reserved Words in Declarations
All EQUEL keywords are reserved: therefore, you cannot declare variables with the same names as EQUEL keywords. You can only use them in quoted string literals. These words are:
byte
decimal
double
functionend
real
subend
case
declare
dynamic
group
record
variant
com
def
external
integer
single
word
common
dim
fnend
long
string
constant
dimension
function
map
sub
The EQUEL preprocessor does not distinguish between uppercase and lowercase in keywords. In generating BASIC code, it converts any uppercase letters in keywords to lowercase.
Data Types
EQUEL/BASIC accepts elementary BASIC data types in variable declarations and maps them to their corresponding Ingres types as shown in the following table.
BASIC Data Types and Corresponding Ingres Type
BASIC Type
Ingres Type
string
character
integer
integer
long
integer
word
integer
byte
integer
real
float
single
float
double
float
EQUEL accepts the BASIC record type in variable declarations, providing the record has already been declared to EQUEL.
The following data types are illegal and will cause declaration errors:
     gfloat
     hfloat
Neither the preprocessor nor the runtime support routines support gfloat or hfloat floating-point arithmetic. You should not compile the BASIC source code with the command line qualifiers gfloat or hfloat if you intend to pass those floating-point values to or from Ingres objects.
The String Data Type
EQUEL accepts both fixed-length and dynamic string declarations. Strings can be declared to EQUEL using any of the declarations listed later. Note that you can indicate string length only for non-dynamic strings; that is, for string declarations appearing in common, map or record declarations. For example,
##   common (globals) string ename = 30
is acceptable, but
##   declare string bad_str_var = 30 ! length is illegal
will generate an error.
The reference to an uninitialized BASIC dynamic string variable in an embedded statement that assigns the value of that string to Ingres results in a runtime error because an uninitialized dynamic string points at a zero address. This restriction does not apply to the retrieval of data into an uninitialized dynamic string variable.
The Integer Data Type
All BASIC integer data type sizes are accepted by the preprocessor. It is important that the preprocessor knows about integer size, because it generates code to load data in and out of program variables. EQUEL assumes that integer size is four bytes by default. However, you may inform EQUEL of a non-default integer size by using the -i flag on the preprocessor command line. (For more information, see Precompiling, Compiling, and Linking an EQUEL Program.)
For example, the preprocessor command:
$ eqb -i2 myfile.qb
causes the preprocessor to treat all variables of type integer as two-byte quantities. If you use the -i flag, be sure to inform the BASIC compiler of the integer size, either by means of an option to the basic command or, in the program, by means of the BASIC options statement.
You can explicitly override the default or the preprocessor -i size by using the BASIC subtype words byte, word or long in the variable declaration, as these examples illustrate:
##   declare byte one_byte_int
##   common (globals) word two_byte_int
##   external long four_byte_int
These declarations create EQUEL integer variables of one, two, and four bytes, respectively, regardless of the default setting.
An integer variable can be used with any numeric-valued object to assign or receive numeric data. For example, such a variable can be used to set a field in a form or to retrieve a column from a database table.
The Real Data Type
As with the integer data type, EQUEL must know the size of real data to manipulate variables of type real. Two sizes of real data are acceptable to EQUEL: four-byte variables (the default) and eight-byte variables. Again, you can change the default size with a flag on the preprocessor command line—in this case, the -r flag. For example:
$ eqb -r8 myfile.qb
instructs EQUEL to treat all real variables as eight-byte quantities. You can explicitly override the default or the -r size by using the BASIC subtype words single or double in a variable declaration. For example, the following two declarations
##   declare single four_byte_real
##   map (myarea) double eight_byte_real
create EQUEL real variables of four and eight bytes, respectively, regardless of the default setting.
A real variable can be used in EQUEL statements to assign or receive numeric data (both real and integer) to and from database columns, form fields and table field columns. It cannot be used to specify numeric objects, such as table field row numbers.
The Record Data Type
You can declare EQUEL variables with type record if you have already defined the record to EQUEL. Later sections discuss the syntax of EQUEL record definitions. You can also declare formal parameters of type record to subprograms. In that case, the EQUEL record definition must follow the EQUEL subprogram statement. Later sections discuss record type formal parameters.
Variable and Constant Declaration Syntax
EQUEL/BASIC variables and constants can be declared in a variety of ways when those statements are made known to EQUEL with the ## mark. The following sections describe these declaration statements and their syntax.
The Declare Statement
The declare statement for an EQUEL/BASIC variable has the following syntax:
declare type identifier [(dimensions)] {[typeidentifier [(dimensions)]}
The declare statement for an EQUEL/BASIC constant has the syntax:
declare type constant identifier = literal {identifier = literal}
Syntax Notes:
1. If the word constant is specified, the declared constants cannot be targets of Ingres retrievals.
2. The type must be a BASIC type acceptable to EQUEL or, in the case of variables only, a record type already defined to EQUEL. Note that the type is mandatory for EQUEL declarations, because EQUEL has no notion of a default type. The type need only be specified once when declaring a list of variables of the same type.
3. The dimensions of an array specification are not parsed by the EQUEL preprocessor. Consequently, the preprocessor does not check bounds. Note also that an illegal dimension, such as a non-numeric value, will be accepted by the preprocessor, but will later cause BASIC compiler errors.
4. You cannot use the declare statement to declare def functions to EQUEL.
The following example illustrates the use of the declare statement:
##   declare integer enum, eage, string ename
##   declare single constant minsal = 12496.62
##   declare real esal(100)
##   declare word null_ind     ! Null indicator
The Dimension Statement
The dimension statement can be used to declare arrays to EQUEL. Its syntax is:
dimension dim type identifier(dimensions{[typeidentifier (dimensions)}
Syntax Notes:
1. The type must be a BASIC type acceptable to EQUEL or a record already defined to EQUEL. Note that the type is mandatory for EQUEL declarations, because EQUEL has no notion of a default type. The type need only be specified once when declaring a list of variables of the same type.
2. The dimensions of an array specification are not parsed by the EQUEL preprocessor. Consequently, the preprocessor does not check bounds. Note also that an illegal dimension, such as a non-numeric value, will be accepted by the preprocessor, but will later cause BASIC compiler errors. Furthermore, EQUEL does not distinguish between executable and declarative dimension statements. If you have used the dimension statement to declare an executable array to EQUEL, using the EQUEL ## mark with subsequent executable dimension statements of the same array will cause a redeclaration error.
The following example illustrates the use of the dimension statement:
##  dim string employee_names(100,20)  ! declarative DIM statement
##  dimension long emp_id(100,2,2)
##  dimension double expenses(numdepts) ! executable DIM statement
Static Storage Variable Declarations
EQUEL supports the BASIC common and map variable declarations. The syntax for a common variable declaration is as follows:
common com [(com_name)]
              type identifier [(dimensions)] [str_length]
              {[typeidentifier [(dimensions)] [str_length]}
The syntax for a map variable declaration is as follows:
map map dynamic (map_name) 
              type identifier [(dimensions)] [str_length]
              {[typeidentifier [(dimensions)] [str_length]}
Syntax Notes:
1. The type must be a BASIC type acceptable to EQUEL or a record type already defined to EQUEL. Note that the type is mandatory for EQUEL declarations, because EQUEL has no notion of a default type. The type need only be specified once when declaring a list of variables of the same type.
2. The dimensions of an array specification are not parsed by the EQUEL preprocessor. Consequently, the preprocessor does not check bounds. Note also that an illegal dimension, such as a non-numeric value, will be accepted by the preprocessor, but will later cause BASIC compiler errors.
3. The string length, if present, must be a simple integer literal.
4. The com_name or map_name clause is not parsed by the EQUEL preprocessor. Consequently, the preprocessor will accept common and map areas of the same name in a single program module. It will also accept a map dynamic statement whose com_name has not appeared in another map statement. Either of these situations will later cause BASIC compiler errors.
The following example uses common and map variable declarations:
##   common (globals) string address = 30, integer zip
##   map (ebuf) byte eage, string ename = 20,     single
##             emp_num
##   common (globals) integer empid (200)
The External Statement
You can inform EQUEL of variables and constants declared in an external module. The syntax for a variable is as follows:
external type identifier {identifier}
The syntax for a constant is as follows:
external type constant identifier {identifier}
Syntax Notes:
1. EQUEL applies the same restrictions on type as VMS BASIC.
2. You cannot declare external functions or subroutines to EQUEL. EQUEL understands only function and subroutine definitions.
The following example illustrates the use of the external statement:
##   external integer empform, infoform     !Compiled forms
##   external single constant emp_minsal
Parameter Variables
Variables can be declared by listing them as formal parameters to a subroutine or function definition, providing the sub, function, or def statement is preceded by the EQUEL ## mark. The syntax for a function statement is:
function type identifier [pass_mech
                   [(type identifier [(dimensions)] [str_length] [pass_mech]
                   {, [typeidentifier [(dimensions)] [str_length] [pass_mech]})]
The sub statement has the syntax:
sub identifier [pass_mech
     [(type identifier [(dimensions)] [str_length] [pass_mech]
     {, [typeidentifier [(dimensions)] [str_length] [pass_mech]})]
The def statement has the syntax:
def type identifier 
     [(type identifier {, [typeidentifier})]
Syntax Notes:
1. The type must be a BASIC type acceptable to EQUEL or a BASIC record. Unlike the rules for other EQUEL variable declarations, you can define the record to EQUEL after it appears in the parameter list. For example:
##   sub process_info (emp_rec emp)
##        record emp_rec
##             ...
##        end record emp_rec
2. The type is mandatory for EQUEL parameter declarations because EQUEL has no notion of a default type. The type need only be specified once when declaring a list of parameters of the same type.
3. The pass_mech (allowed on sub and function statements) may be by desc or by ref. However, the preprocessor does not verify that the formal parameter declaration is consistent with the passing mechanism. You should follow the VMS BASIC rules for parameter passing mechanisms.
4. The dimensions of an array specification are not parsed by the EQUEL preprocessor. Consequently, the preprocessor does not check bounds. Note also that an illegal dimension, such as a non-numeric value, will be accepted by the preprocessor, but will later cause BASIC compiler errors.
The following example illustrates the use of parameter variables:
##   def real newsal (integer grade, real oldsal, single      percent)
##   function string get_addr by ref (string ename = 20,      integer eno)
##   sub new_emps (integer deptno, string emplist (100) = 20 by ref)
Record Type Definitions
EQUEL accepts BASIC record definitions. The syntax of a record definition is:
record identifier
               record_component
              {record_component}
end record [identifier]
where record_component can be any of the following:
type identifier [(dimensions)] [str_length
              {[typeidentifier [(dimensions)] [str_length]}
group_clause
variant_clause
host_code
In turn, the syntax of a group_clause is:
group identifier [(dimensions)]
               record_component
              {record_component}
              end group [identifier]
The syntax of a variant_clause is:
variant
              
 case_clause
              {case_clause}
end variant
where case_clause consists of:
case
              
record_component
Syntax Notes:
1. The type must be a BASIC type acceptable to EQUEL or a record type already defined to EQUEL. Note that the type is mandatory for EQUEL declarations because EQUEL has no notion of a default type. The type need only be specified once when declaring a list of variables of the same type.
2. The string length clause is allowed only for record components of type string.
3. The host code record component allows you to declare components of records without informing EQUEL of their existence. For instance, you may want to declare fill items or components whose type is not allowed in an EQUEL declaration. For example, the following record definition is acceptable to EQUEL:
##   record dept_rec
##        double net_profit
          gfloat gross_sales  ! Not for use with EQUEL statements
##   end record
4. Record definitions must appear before declarations using that record type. An exception occurs where a parameter to an EQUEL subroutine or function is of the record type. In that case, you may define the record to EQUEL after declaring it in the parameter list.
The following example illustrates the use of record type definitions:
##  record emp_history
##             string ename = 30
##             group prev_employers(10)
##                  string comp_name = 30
##                  real salary
##                  integer num_years
##  end group prev_employers
##  end record emp_history

##  record emp_sports
##               string ename = 30
##               variant
##                    case
##                         group golf
##                              integer handicap
##                              string club_name
##                         end group golf
##                    case
##                         group baseball
##                              integer batting_avg
##                              string team_name
##                         end group baseball
##                    case
##                         group tennis
##                              integer seed
##                              string club_name
##                         end group tennis
##               end variant
##  end record emp_hobbies
The Indicator Variable
An indicator variable is a 2-byte integer variable. There are three possible ways to use these in an application:
In a statement that retrieves data from Ingres, you can use an indicator variable to determine if its associated host variable was assigned a null.
In a statement that sets data to Ingres, you can use an indicator variable to assign a null to the database column, form field, or table field column.
In a statement that retrieves character data from Ingres, you can use the indicator variable as a check that the associated host variable is large enough to hold the full length of the returned character string.
An indicator variable can be declared using the integer word subtype, or, if the -i2 preprocessor command line flag was used, can be declared as an integer. The following example declares two indicator variables, one a single variable and the other an array of indicators:
##   declare word ind, ind_arr(10)
Assembling and Declaring External Compiled Forms
You can pre-compile your forms in the Visual Forms Editor (VIFRED). This saves time that would otherwise be required at runtime to extract the form's definition from the database forms catalogs. When you compile a form in VIFRED, VIFRED creates a file in your directory describing the form in the VAX-11 MACRO language. VIFRED prompts you for the name of the file with the MACRO. After the file is created, you can use the following VMS command to assemble it into a linkable object module:
macro filename
This command produces an object file containing a global symbol with the same name as your form. Before the Embedded SQL/FORMS statement addform can refer to this global object, you must declare it in an Embedded SQL declaration section, using the following syntax:
external integer formname
Syntax Notes:
1. The formname is the actual name of the form. VIFRED gives this name to the address of the global object. The formname is also used as the title of the form in other EQUEL/FORMS statements. In all statements that use the formname as an argument, except for addform, you must dereference the name with the # sign.
2. The external statement associates the object with the external form definition.
The example below shows a typical form declaration and illustrates the difference between using the form's object definition and the form's name.
##   external integer empform
##   addform empform          ! The global object
##   display #empform         ! The name of the form
Concluding Example
The following example demonstrates some simple EQUEL/BASIC declarations:
##   declare ingres
##   declare byte      d_byte ! Variables of each data type
##   declare word      d_integer2
##   declare long      d_integer4
##   declare integer      d_integer_def
##   declare single      d_real4
##   declare double      d_real8
##   declare real      d_real_def
##   declare decimal(6,2) d_decimal
##   declare string d_string
##   declare integer constant num_depts = 10 ! Constant

##   common(globs) real e_raise ! Static storage variables
##   map (ebuf) string ename = 20
##   dim string emp_names(100,30) ! Array declarations
##   declare integer dept_id(10)
##   common(globs) string e_address(40) = 30
##   record person ! Variant record
##         byte age
##         long flags
##         variant
##             case
##                  group emp_list
##                        string full_name = 30
##                  end group
##             case
##                     group emp_directory
##                          string firstname = 12
##                          string lastname = 8
##                    end group
##        end variant
##   end record

##   declare person p_table(100)      ! Array of records
##   external integer empform, deptform     ! Compiled forms
##   dim word indicators(10)          ! Array of null indicators
Last modified date: 08/28/2024