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 Ingres 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 variables.
Ingres does not automatically convert between numeric and character types. You must use one of the Ingres type conversion functions or a C conversion routine for this purpose.
The following table shows the specific type correspondences for each Ingres data type.
Ingres and C Data Type Compatibility
The previous table shows a choice of two possible correspondences for the char and varchar Ingres types. If there is any possibility that database columns of these types will hold ASCII null bytes, you should use the varchar type in C to represent this data.
Runtime Numeric 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. 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 display 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 Conversion
Automatic conversion occurs between Ingres character string values and C character string variables. The string-valued objects that can interact with character string variables, are:
• Names, such as form and column names
• Database columns of type c
• Database columns of type text
• Form fields of type c
In this context, character string variables are not single byte integers declared with the char type. They are character string pointers:
char *character_string_pointer;
or references to the character string buffer:
char character_string_buffer[length];
Character string pointers are always assumed to be pointing at legal string values or variables. As in any C program, any pointer that has not been initialized to point at a string value will cause either a runtime error, resulting in program failure, or an insidious problem resulting from the overwriting of space in memory.
Also, database columns of type char and varchar may optionally be handled as strings in EQUEL/C. Several considerations apply when dealing with character string conversions, both to and from Ingres. If your char or varchar database columns contain ASCII null bytes as data, you should use the C varchar storage class rather than C character strings to represent this data.
The following notes apply to data represented in C string variables or constants. For analogous information regarding the
varchar storage class, see
The Varying Length String Type.
The conversion of C character string variables used to represent Ingres object 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 and "employees " and "employees" refer to the same database table.
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 c or char, a database column of type text or varchar, or a character-type form field. Ingres pads columns of type c and char with blanks to their declared length. Conversely, it does not add blanks to the data in columns of type text or 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 in a C variable as the string literal "abc" followed by the C null character, "\0" requiring four bytes.
Character string variables cannot contain embedded nulls because the runtime system cannot differentiate between embedded nulls and the trailing null terminator. For a description of variables that contain embedded nulls and the C
varchar storage class, see
The Varying Length String Type.
When retrieving character data from a 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 string terminator. (Consider the maximum size to be the length of the database column or the form field.) If the character string variable is too small to contain the complete string value together with the null character, the runtime system may overwrite other space in memory.
However, 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.
Furthermore, take note of the following conventions:
• Data stored in a database column of type c or char 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 variable is declared with a fixed length known to the preprocessor, the variable receives that many characters, including the terminating null.
• Data stored in a database column of type text or varchar is not padded with blanks. The character string variable receives only the actual characters in the column, plus the terminating null character. Remember that if char or varchar database columns contain null characters as data, you should represent them with C variables of the varchar storage class, thus avoiding this normal string-handling behavior.
• 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, note the following conventions:
• When data is moved from a C variable into a database column of type c or char 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 moved from a C variable into a database column of type text or 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 columns of these types. 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 character data in an Ingres database column with character data in a C variable, note the following convention:
• When comparing data in c, character, or varchar database columns with data in a character variable, all trailing blanks are ignored. Trailing blanks are significant in text. Initial and embedded blanks are significant in character, text, and varachar; they are ignored in c.
Caution! 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. Care should be taken if using the standard strcmp function to test for a change in character data, because blanks are significant in that function.
The Ingres date data type is represented as 25-byte character string. Your program should allow 26 characters to accommodate the C null byte at the end.
Using Varchar to Receive and Set Character Data
You can use the C varchar storage class to retrieve and set character data. Normally 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 data retrieval or by the program 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 retrieve character data that does not contain embedded nulls. Here too, no null terminator is 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:
## static varchar struct vch_ {
## short vch_length;
## char vch_data[10]; /* Statically initialized */
## } vch_store[3] = { /* 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;
/*
** Add all three rows of data from table above
** (including nulls). Note that the members of
** the varchar structure are not mentioned.
*/
for (i = 0; i > 3; i++)
{
## append vch (row = i+1; data = vch_store[i])
}
/*
** Now RETRIEVE the data back. Note that the runtime
** system implicitly assigns to the length field the
** size of the data.
*/
## retrieve (i = vch.row, vch.res = vch.data)
## {
/*
** 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] = '?';
}
/* Note the use of '%/.*s' format here.
** This is because varchar data doesn't
** contain a null terminator so length is used.
*/
printf("[%d] '%.*s'\n", i,
vch_res.vch_length, vch_res.vch_data);
## }