Was this helpful?
Data Type Conversion
A C variable declaration must be compatible with the Ingres value it represents. Numeric Ingres values can be set by and retrieved into numeric variables, and Ingres character values can be set by and retrieved into character variables.
Data type conversion occurs automatically for different numeric types such as from floating-point database column values into integer C variables, and for character strings, such as from varying-length Ingres character fields into fixed-length C character string buffers.
Ingres does not automatically convert between numeric and character types. You must use the Ingres type conversion operators, the Ingres ascii function, or a C conversion routine for this purpose.
The following table shows the default type compatibility for each Ingres data type.
Ingres Type
C Type
char(N)
char [N+1]
varchar(N)
char [N+1]
char(N)(with embedded nulls)
varchar
varchar(N)(with embedded nulls)
varchar
integer1
short
integer2
short
smallint
short
integer
int
integer
long
float4
float
bigint
long (64-bit); long long (32-bit)
float
double
date or ingresdate
char [26]
ansidate
char [11]
time without time zone
char [22]
time with time zone
char [32]
time with local time zone
char [32]
timestamp without time zone
char [40]
timestamp with time zone
char [50]
timestamp with local time zone
char [50]
interval year to month
char [16]
interval day to second
char [46]
money
double
table_key
char[8 ]
object_key
char[16]
decimal
double
long varchar
char[ ]
long varchar (with embedded nulls)
char[ ]
byte
char[ ]
varbyte
char[ ]
long byte
char[ ]
nchar(N)
wchar_t[N+1]
nvarchar(N)
wchar_t[N+1]
long nvarchar (with embedded nulls)
nvarchar
Runtime Numeric Type Conversion
The Ingres runtime system provides automatic data type conversion between numeric-type values in the database and the forms system and numeric C variables. It follows the standard type conversion rules (according to standard C numeric conversion rules). For example, if you assign a float variable to an integer-valued field, the digits after the decimal point of the variable's value are truncated. Runtime errors are generated for overflow on conversion.
Unsigned integers can be assigned to and retrieved from the database wherever plain integers are used. However, take care when using an unsigned integer whose positive value is large enough to cause the high order bit to be set. Integers such as these are treated as negative numbers in Ingres arithmetic expressions and are displayed as negative numbers by the Forms Runtime system.
The Ingres money type is represented as an 8-byte floating-point value compatible with a C double.
Runtime Character Type Conversion
Automatic conversion occurs between Ingres character string values and C character string variables. The string-valued Ingres objects that can interact with character string variables are:
Ingres names, such as form and column names
Database columns of type character
Database columns of type varchar
Form fields of type character
Database columns of type long varchar
Several considerations apply when dealing with character string conversions, both to and from Ingres.
References in this section to character string variables do not refer to single byte integers declared with the char type, but to the character string pointer:
char *character_string_pointer;
or to the character string buffer:
char character_string_buffer[length];
Character string pointers are always assumed to be pointing at legal string values. Any pointer that has not been initialized to point at a string value causes a runtime error, resulting in program failure or the overwriting of space in memory.
The conversion of C character string variables used to represent Ingres names is simple: trailing blanks are truncated from the variables, because the blanks make no sense in that context. For example, the string literals empform and empform refer to the same form.
The conversion of other Ingres objects is a bit more complicated. First, the storage of character data in Ingres differs according to whether the medium of storage is a database column of type character, a database column of type varchar, or a character form field. Ingres pads columns of type character with blanks to their declared length. Conversely, it does not add blanks to the data in columns of type varchar or long varchar, or in form fields.
Second, the C convention is to null terminate character strings, and the Ingres runtime system assumes that all strings are null-terminated. For example, the character string abc is stored as the string literal abc followed by the C null character, \0, requiring four bytes.
Fixed length character string variables cannot contain embedded nulls, because the runtime system cannot differentiate between embedded nulls and the trailing null terminator. For a complete description of variables that contain embedded nulls and the C varchar storage class, see Varying Length String Type in this chapter.
When retrieving character data from an Ingres database column or form field into a C character string variable, be sure to always supply enough room in the variable to accommodate the maximum size of the particular object, plus one byte for the C null character. (Consider the maximum size to be the length of the database column or the form field.) If the character string buffer is too small to contain the complete string value together with the null character, the runtime system may overwrite other space in memory.
If the length of a character string variable is known to the preprocessor, as in the declaration:
char character_string_buffer[fixed_length];
then the runtime system copies at most the specified number of characters including the trailing null character. In cases where the fixed length of the variable (less one for the null) is smaller than the data to be copied, the data is truncated. The specified length must be at least 2, because one character and the terminating null are retrieved. If the length is exactly 1, the data is overwritten by the terminating null.
Furthermore, take note of the following conventions:
Data stored in a database column of type character is padded with blanks to the length of the column. The variable receiving such data will contain those blanks, followed by the null character. If the receiving variable was declared with a fixed length known to the preprocessor, such as:
char myvar[25]
and the data retrieved is longer than the buffer, the variable will receive only as many characters as will fit (including the terminating null). If the data received is shorter than the variable, the behavior is determined by the setting of the -blank_pad preprocessor flag. By default, the terminating null is placed at the end of the retrieved data, without padding out any space remaining in the variable. But if a module is preprocessed with the ‑blank_pad flag then receiving variables are blank padded to their full defined length (less one space reserved for the terminating null). The ‑blank_pad behavior is specified by the ANSI SQL92 standard.
Data stored in a database column of type varchar is not padded with blanks. The character string variable receives only the actual characters in the column, plus the terminating null character.
Data stored in a character form field contains no trailing blanks. The character string variable receives only the actual characters in the field, plus the terminating null character.
When inserting character data into an Ingres database column or form field from a C variable, the following conventions are in effect:
When data is inserted from a C variable into a database column of type character and the column is longer than the variable, the column is padded with blanks. If the column is shorter than the variable, the data is truncated to the length of the column.
When data is inserted from a C variable into a database column of type varchar or long varchar and the column is longer than the variable, no padding of the column takes place. However, all characters in the variable, including trailing blanks, are inserted. Therefore, you may want to truncate any trailing blanks in character string variables before storing them in varchar columns. If the column is shorter than the variable, the data is truncated to the length of the column.
When data is inserted from a C variable into a character form field and the field is longer than the variable, no padding of the field takes place. In addition, all trailing blanks in the data are truncated before the data is inserted into the field. If the field is shorter than the data (even after all trailing blanks have been truncated), the data is truncated to the length of the field.
When comparing data in character or varchar database columns with data in a character variable, all trailing blanks are ignored. Initial and embedded blanks are significant.
For a more complete discussion of the significance of blanks in string comparisons, see the SQL Reference Guide.
IMPORTANT!  As just described, the conversion of character string data between Ingres objects and C variables often involves the trimming or padding of trailing blanks, with resultant change to the data. If trailing blanks have significance in your application, give careful consideration to the effect of any data conversion. Take care not to use the standard strcmp function to test for a change in character data, since blanks are significant.
The Ingres date data type is represented as 25-byte character string. Your program should allow 26 characters to accommodate the C null.
How Varchar is Used to Receive and Set Character Data
You can also use the C varchar storage class to retrieve and set character data. Typically, varchar variables are used when simple C char variables are not sufficient, as when null bytes are embedded in the character data. In those cases the runtime system cannot differentiate between embedded nulls and the null terminator of the string.
When using varchar variables, the 2-byte length specifier indicates how many bytes are used in the fixed length character array. The runtime system sets this length after a data retrieval, or the program sets it before assigning data to Ingres. This length does not include a null terminator, as the null terminator is not copied or included in the data. The runtime system copies, at most, the size of the fixed length data buffer into the variable.
You can also use varchar variables to retrieve character data that does not contain embedded nulls. Here too, the null terminator is not included in the data.
Because varchar variables never include a null terminator, the program should avoid sending the data member of varchar variables to C functions that assume null-terminated strings (such as strlen and strcmp).
The following program fragment demonstrates the use of the varchar storage class for C variables.
Example: Varchar storage class usage
exec sql begin declare section;
    exec sql declare vch table
        (row integer,
        data varchar(10));       /* Note the VARCHAR type */
        static varchar struct vch_ {
            short vch_length;
            char vch_data[10];
 } vch_store[3] = {
               /* Statically initialized data with nulls */
          {3, {'1', '2', '3'}},
          {6, {'1', '2', '3', '\0', '5', '6'}},
          {8, {'\0', '2', '3', '4', '\0', '6', '7', '8'}}
};
        varchar struct vch_ vch_res;
        int i, j;
 exec sql end declare section;
exec sql whenever sqlerror call sqlprint;
/*
** Add all three rows of data from table above (including mulls).
** Note that the members of the varchar structure are not mentioned.
*/
for (i = 0; i < 3; i++)
{
exec sql insert into vch
values (:i+1, :vch_store[i]);
}
/*
** Now SELECT the data back. Note that the runtime system implicitly
** assigns to the length field the size of the data.
*/
exec sql select *
into :i, :vch_res
from vch;
exec sql begin;
/*
** Print the values of each row. Before printing the values,
** convert all embedded nulls to the '?' character for printing.
** The results are:
** [1] '123'
** [2] '123?56'
** [3] '?234?678'
*/
for (j = 0; j < vch_res.vch_length; j++)
{
if (vch_res.vch_data[j] == '\0')
vch_res.vch_data[j] = '?';
}
printf("[%d] '%.*s'\n", i, vch_res.vch_length,
vch_res.vch_data);
/*
** Note the printf format used here is %.*s rather than %s
** because Ingres does not null terminate varchar data.
*/
 
exec sql end;
 
Last modified date: 01/30/2023