Type Declaration Syntax
Embedded SQL/Ada supports a subset of Ada type declarations. In a declaration, the Embedded SQL preprocessor only notes semantic information relevant to the use of the variable in Embedded SQL statements at runtime. The preprocessor ignores other semantic information. Refer to the syntax notes in this section and its subsections for details.
Type Definition
An Embedded SQL/Ada full type declaration has the following syntax:
type identifier [discriminant_part] is type_definition;
Note:
• The discriminant_part has the syntax:
(discriminant_specifications)
and is not processed by Embedded SQL. As with variable declarations, Embedded SQL always accepts a discriminant specification, even if Ada does not allow it. For example, Embedded SQL accepts the following declaration but later generates an Ada compiler error because the discriminant type is not a discrete type, and the discriminant part is not allowed in a non-record declaration:
type shapes(name: String := "BOX")
is array(1..10) of String(1..3);
From this point on, discriminant parts are not included in the syntax descriptions or notes.
• The legal type_definitions allowed in type declarations are described below.
Subtype Definition
An Embedded SQL/Ada subtype declaration has the following syntax:
subtype identifier is type_name [type_constraint];
Note:
• The type_constraint has the same rules as the type constraint of a variable declaration. The range, discriminant and index constraints are all allowed and are not processed against the type_name being used. For more details about these constraints, see the section above on variable type constraints. The floating-point constraint and the digits clause, which are allowed in subtype declarations, are discussed later.
Integer Type Definitions
The syntax of an Embedded SQL/Ada integer type definition is:
range lower_bound .. upper_bound
In the context of an integer type declaration, the syntax is:
type identifier is range lower_bound .. upper_bound;
In the context of an integer subtype declaration, the syntax is:
subtype identifier is integer_type_name
range lower_bound .. upper_bound;
Note:
• In an integer type declaration (not a subtype declaration), Embedded SQL processes the range constraint of an integer type definition to evaluate storage size information. Both lower_bound and upper_bound must be integer literals. Based on the specified range and the actual values of the bounds, Embedded SQL treats the type as a byte-size, a word-size or a longword-size integer. For example:
type Table_Num is range 1..200;
• In an integer subtype declaration, the range constraint is treated as a variable range constraint and is not processed. Consequently, the same rules that apply to range constraints for variable declarations apply to integer range constraints for integer subtype declarations. The base type and storage size information is determined from the integer_type_name used. For example:
subtype Ingres_I1 is Integer range -128..127;
subtype Ingres_I2 is Integer range -32768..32767;
subtype Table_Low is Table_Num range 1..10;
subtype Null_Ind is Short_Integer range -1..0;
-- Null Indicator
Floating-point Type Definitions
The syntax of an Embedded SQL/Ada floating-point type definition is:
digits digit_specification [range_constraint]
In the context of a floating-point type declaration, the syntax is:
type identifier is digits digit_specification [range_constraint];
The syntax of a floating-point subtype declaration is:
subtype identifier is floating_type_name
[digits digit_specification]
[range_constraint];
Note:
• The value of digit_specification must be an integer literal. Based on the value of the specification, Embedded SQL determines whether to treat a variable of that type as a 4-byte float or an 8-byte float. The following rules apply:
Note that if the digits specified are out of range, the type is unusable. Recall that Embedded SQL does not accept either the
long_long_float or the
h_float type. For detailed information on the internal storage format for 8-byte floating-point variables, see
Long Float Storage Format in this chapter.
• The range_constraint for floating-point types and subtypes is treated as a variable range constraint and is not processed. Although Embedded SQL allows any range constraint, you should not specify a range constraint that alters the size needed to store the declared type. Embedded SQL obtains its type information from the digits clause, and altering this type information by a range clause, which may require more precision, results in runtime errors.
• The digits clause in a subtype declaration does not have any effect on the Embedded SQL type information. This information is obtained from floating_type_name.
type Emp_Salary is digits 8 range 0.00..500000.00;
subtype Directors_Sal
is Emp_Salary 100500.00..500000.00;
subtype Raise_Percent
is Float range 1.05..1.20;
Enumerated Type Definitions
The syntax of an Embedded SQL/Ada enumerated type definition is:
(enumerated_literal {, enumerated_literal})
In the context of a type declaration, the syntax is:
type identifier is (enumerated_literal {, enumerated_literal});
In the context of a subtype declaration, the syntax is:
subtype identifier is enumerated_type_name [range_constraint];
• An enumerated type declaration can contain no more than 1000 enumerated literals. The preprocessor treats all literals and variables declared with this type as integers. Enumerated literals are treated as though they were declared with the constant clause, and therefore cannot be the targets of Ingres assignments. When using an enumerated literal with Embedded SQL statements, only the ordinal position of the value in relation to the original enumerated list is relevant. When assigning from an enumerated literal, Embedded SQL generates:
enumerated_type_name'pos(enumerated_variable_or_literal)
When assigning from or into an enumerated variable, Embedded SQL passes the object by address and assumes that the value being assigned from or into the variable will not raise a runtime constraint error.
• An enumerated literal can be an identifier or a character literal. Embedded SQL does not store or process enumerated literals that are character literals.
• Enumerated literal identifiers must be unique in their scope. Embedded SQL does not allow the overloading of variables or constants.
• The range_constraint for enumerated subtypes is treated as a variable range constraint and is not processed. The type information is determined from enumerated_type_name.
type Table_Field_States is
(UNDEFINED, NEWROW, UNCHANGED,CHANGED, DELETED);
subtype Updated_States is
Table_Field_States range CHANGED..DELETED;
tbstate: Table_Field_States := UNDEFINED;
• ESQL accepts the predefined enumeration type name Boolean, which contains the two literals FALSE and TRUE. You can use a representation clause for enumerated types. When you do so, however, you should not reference any enumerated literals of that type in embedded statements, though you can reference the variables.
Enumerated literals are interpreted into their integer relative position (pos) and representation clauses invalidate the effect of the pos attribute that the preprocessor generates. The representation clause must be outside of the declare section.
• You can only use enumerated variables and literals to assign to or from Ingres. You cannot use these objects to specify simple numeric objects, such as table field row numbers or sleep statement seconds.
Array Type Definitions
The syntax of an Embedded SQL/Ada array type definition is:
array (dimensions) of type_name;
In the context of a type declaration, the syntax is:
type identifier is array (dimensions) of
type_name [type_constraint];
• The dimensions of an array specification are not parsed by the Embedded SQL preprocessor. Consequently, the preprocessor accepts unconstrained array bounds and multi-dimensional array bounds. However, an illegal dimension (such as a non-numeric expression) is also accepted but later causes Ada compiler errors. For example, both of the following type declarations are accepted, even though only the first is legal in Ada:
type Square is array(1..10, 1..10) of Integer;
type What is array("dimensions") of Float;
Because the preprocessor does not store the array dimensions, it only checks to determine that when you use the array variable, it is followed by a subscript in parentheses.
• The type_constraint for array types is treated as a variable type constraint and is not processed. The type information is determined from type_name.
• Any array built from the base type character (not string) must be exactly one-dimensional. Embedded SQL treats the whole array as though you declared it as type string. If you declare more dimensions for a variable of type character, Embedded SQL still treats it as a one-dimensional array.
• The type string is the only array type.
Record Type Definitions
The syntax of an Embedded SQL/Ada record type definition is:
record
record_component {record_component}
end record;
where record_component is:
component_declaration ; | variant_part; | null;
where component_declaration is:
identifier {, identifier} :
type_name [type_constraint] [:= initial_value]
In the context of a type declaration, the syntax of a record type definition is:
type identifier is
record
record_component { record_component}
end record;
Note that the SQL Reference Guide refers to records as structures and record components as structure members.
Note:
• In a component_declaration, all clauses have the same rules and restrictions as they do in a regular type declaration. For example, as in regular declarations, the preprocessor does not check initial values for correctness.
• The variant_part accepts the Ada syntax for variant records: if specified, it must be the last component of the record. The variant discriminant name, choice names, and choice ranges are all accepted. There is no syntactic or semantic checking on those variant objects. Embedded SQL uses only the final component names of the variant part and not any of the variant object names.
• You can specify the null record.
The following example illustrates the use of record type definitions:
type Address_Rec is
record
street: String(1..30);
town: String(1..10);
zip: Positive;
end record;
type Employee_Rec is
record
name: String(1..20);
age: Short_Short_Integer;
salary: Float := 0.0;
address: Address_Rec;
end record;
Incomplete Type Declarations and Access Types
The incomplete type declaration should be used with an access type. The syntax for an incomplete type declaration is:
type identifier [discriminant_part];
Note:
• As with other type declarations, the discriminant_part is ignored.
• You must fully define an incomplete type before using any object declared with it.
The syntax for an access type declaration is:
type identifier is access type_name [type_constraint];
• The type_name must be an Embedded SQL/Ada type or a type name already declared to Embedded SQL, whether it is a full type declaration or an incomplete type declaration.
• The type_constraint has the same rules as other type declarations.
type Employee_Rec; -- Incomplete declaration
type Employee is access Employee_Rec;
-- Access to above
type Employee_Rec is -- Real definition
record
name: String(1..20);
age: Short_Short_Integer;
salary: Float := 0.0;
link: Employee;
end record;
Derived Types
The syntax for a derived type is:
type identifier is new type_name [type_constraint];
Note:
• The type_name must be an embedded SQL/Ada type or a type name already declared to Embedded SQL, whether it is a full type declaration or an incomplete type declaration.
• Embedded SQL assigns the type being declared the same properties as the type_name specified. The preprocessor makes sure that any variables of a derived type are cast into the original base type when used with the runtime routines.
• The type_constraint has the same rules as other type declarations.
type Dbase_Integer is new Integer;
Private Types
The syntax for a private type is:
type identifier is [limited] private;
This type declaration is treated as an incomplete type declaration. You must fully define a private type before using any object declared with it.
Representation Clauses
With one exception, you must not use representation clauses for any types or objects you have declared to Embedded SQL and intend to use with the Embedded SQL runtime system. Any such clauses causes runtime errors. These clauses include the Ada statement:
for type_or_attribute use expression;
and the Ada pragma:
pragma pack(type_name);
The exception is that you can use a representation clause to specify internal values for enumerated literals. When you do so, however, you should not reference any enumerated literals of the modified enumerated type in embedded statements. The representation clause invalidates the effect of the pos attribute that the preprocessor generates. If the application context is one that requires the assignment from the enumerated type, then you should deposit the literal into a variable of the same enumerated type and assign that variable to Ingres. In all cases, do not include the representation clause in a declare section. For example:
exec sql begin declare section;
type opcode is (opadd, opsub, opmul);
exec sql end declare section;
...
for opcode use (opadd => 1, opsub => 2, opmul => 4);
...
opcode_var := opsub;
exec sql insert into codes values (:opcode_var);