Fortran data types in ODBC

 

The original ODBC defines the C data types that are used by application variables and their corresponding type identifiers. These data types are used by the buffers bound to result set columns and statement parameters. For example, suppose an application wants to retrieve data from a result set column in character format. It declares a variable with the SQLCHAR* data type and binds this variable to the result set column with a type identifier of SQL_C_CHAR. ODBC also defines a default mapping from each SQL data type to a C data type. For example, a 2-byte integer in the data source is mapped to a 2-byte integer in the application. To use the default mapping, an application specifies the SQL_C_DEFAULT type identifier. However, use of this identifier is discouraged for interoperability reasons.

 

Fortran and C data types do not always have a direct correspondence relationship. For example, unsigned integers do not exist in Fortran. f90SQL has mapped all ODBC-defined C data types into the Fortran types that match them more closely. Although f90SQL allows the use of C data type identifiers, as a general rule you should not use them in your applications to avoid conflicts and mistakes, which  may be very difficult to track. Fortran data types are identified in the same fashion that ODBC C data types, but instead of the letter C, they use the letter F. For example, the C type identifier for short signed integers is SQL_C_SSHORT. The type identifier for the corresponding data type in Fortran is SQL_F_SSHORT.

 

C has a richer data-type set than Fortran does. In C integers can be declared as signed or unsigned. Most Fortran compilers do not allow for this distinction. Because of this, many Fortran ODBC data types map to the same Fortran data type. For example, SQL_F_SSHORT and SQL_F_USHORT, map to the same Fortran type (usually integer*2).

 

When declaring variables, Fortran programs should used the kinds provided by f90SQL. A kind indicates to the Fortran compiler the number of bytes a given Fortran data type will use. For example, the following declaration tells the compiler that variable i is a 2-byte integer:

 

integer(kind=2)::i

 

The ODBC Fortran type identifier for variable i would be SQL_F_SSHORT. f90SQL defines kind-values using named-constants, which make it easier to relate the declaration of variables to their corresponding data type identifier. For example, instead of declaring i as previously showed, you can use the following declaration:

 

integer(SQLSMALLINT_KIND)::i

 

You do not have to worry about how many bytes variable i has. You know it is a small signed integer, and as such, it can be identified to ODBC using the identifier SQL_F_SSHORT.

 

The following table shows the f90SQL data types, their identifiers, and Fortran type they represent. It also includes the corresponding C identifiers for reference.

 

Table 4.3. ODBC Fortran data type identifiers

 

f90SQL type identifier f90SQL declaration Fortran type
SQL_F_CHAR character(len=*) character(len=*)
SQL_F_SSHORT [j] integer (SQLSMALLINT_KIND) integer(kind=2)
SQL_F_USHORT [j] integer (SQLUSMALLINT_KIND) integer(kind=2)
SQL_F_SLONG [j] integer (SQLINTEGER_KIND) integer(kind=4)
SQL_F_ULONG [j] integer (SQLUINTEGER_KIND) integer(kind=4)
SQL_F_FLOAT real(SQLREAL_KIND) real(kind=4)
SQL_F_DOUBLE real(SQLDOUBLE_KIND),
real(SQLFLOAT_KIND)
real(kind=8)
SQL_F_BIT integer (SQLCHAR_KIND) integer(kind=1)
SQL_F_STINYINT [j] integer (SQLCHAR _KIND) integer(kind=1)
SQL_F_UTINYINT [j] integer (SQLCHAR _KIND) integer(kind=1)
SQL_F_SBIGINT integer (SQLBIGINT _KIND) integer(kind=8) [h]
SQL_F_UBIGINT integer (SQLUBIGINT _KIND) integer(kind=8) [h]
SQL_F_BINARY integer (SQLPOINTER_KIND) [l] integer(kind=4) [l]
SQL_F_BOOKMARK [i] integer (BOOKMARK_KIND) integer(kind=4) [d]
SQL_F_VAR_BOOKMARK character(len=*)
[l]
character(len=*) [l]
SQL_F_TYPE_DATE [c] type(SQL_DATE_STRUCT)
Type DATE_STRUCT
integer(SQLSMALLINT_KIND):: Year
integer(SQLUSMALLINT_KIND)::Month
integer(SQLUSMALLINT_KIND)::Day
End Type DATE_STRUCT [a]
SQL_F_TYPE_TIME [c] type(SQL_TIME_STRUCT)
Type TIME_STRUCT
integer(SQLUSMALLINT_KIND)::Hour
integer(SQLUSMALLINT_KIND)::Minute
integer(SQLUSMALLINT_KIND)::Second
End Type TIME_STRUCT [a,b]
SQL_F_TYPE_TIMESTAMP [c] type(SQL_TIMESTAMP_STRUCT)
Type TIMESTAMP_STRUCT
integer(SQLSMALLINT_KIND):: Year
integer(SQLUSMALLINT_KIND)::Month
integer(SQLUSMALLINT_KIND)::Day
integer(SQLUSMALLINT_KIND)::Hour
integer(SQLUSMALLINT_KIND)::Minute
integer(SQLUSMALLINT_KIND)::Second
integer(SQLUINTEGER_KIND):: Fraction
End Type TIMESTAMP_STRUCT [a,b]
SQL_F_NUMERIC type(SQL_NUMERIC_STRUCT)
Type SQL_NUMERIC_STRUCT
integer(SQLCHAR_KIND):: precision
integer(SQLSCHAR_KIND):: scale
integer(SQLCHAR_KIND):: sign
integer(SQLCHAR_KIND)::value(SQL_MAX_NUMERIC_LEN)
End Type SQL_NUMERIC_STRUCT [e, g, f]
SQL_F_GUID type(SQLGUID)
Type SQLGUID_STRUCT
integer(kind=4) Data1
integer(kind=2) Data2
integer(kind=2) Data3
integer(kind=1) Data4(8)
End Type SQLGUID_STRUCT [k]
All Fortran interval data types type(SQL_INTERVAL_STRUCT) See interval data types in Appendix 4

 

 

Table 4.3 (continuation)

 

f90SQL type identifier C type identifier ODBC C typedef C type
SQL_F_CHAR SQL_C_CHAR SQLCHAR * unsigned char *
SQL_F_SSHORT [j] SQL_C_SSHORT [j] SQLSMALLINT short int
SQL_F_USHORT [j] SQL_C_USHORT [j] SQLUSMALLINT unsigned short int
SQL_F_SLONG [j] SQL_C_SLONG [j] SQLINTEGER long int
SQL_F_ULONG [j] SQL_C_ULONG [j] SQLUINTEGER unsigned long int
SQL_F_FLOAT SQL_C_FLOAT SQLREAL float
SQL_F_DOUBLE SQL_C_DOUBLE SQLDOUBLE,
SQLFLOAT
double
SQL_F_BIT SQL_C_BIT SQLCHAR unsigned char
SQL_F_STINYINT [j] SQL_C_STINYINT [j] SQLSCHAR signed char
SQL_F_UTINYINT [j] SQL_C_UTINYINT [j] SQLCHAR unsigned char
SQL_F_SBIGINT SQL_C_SBIGINT SQLBIGINT _int64 [h]
SQL_F_UBIGINT SQL_C_UBIGINT SQLUBIGINT unsigned _int64 [h]
SQL_F_BINARY SQL_C_BINARY SQLCHAR * unsigned char *
SQL_F_BOOKMARK [i] SQL_C_BOOKMARK [i] BOOKMARK unsigned long int [d]
SQL_F_VAR_BOOKMARK SQL_C_VAR_BOOKMARK SQLCHAR * unsigned char *
SQL_F_TYPE_DATE [c] SQL_C_TYPE_DATE [c] SQL_DATE_STRUCT
struct tagDATE_STRUCT {
SQLSMALLINT year;
SQLUSMALLINT month;
SQLUSMALLINT day;
} DATE_STRUCT; [a]
SQL_F_TYPE_TIME [c] SQL_C_TYPE_TIME [c] SQL_TIME_STRUCT
struct tagTIME_STRUCT {
SQLUSMALLINT hour;
SQLUSMALLINT minute;
SQLUSMALLINT second;
} TIME_STRUCT; [a]
SQL_F_TYPE_TIMESTAMP [c] SQL_C_TYPE_TIMESTAMP [c] SQL_TIMESTAMP_STRUCT
struct tagTIMESTAMP_STRUCT {
SQLSMALLINT year;
SQLUSMALLINT month;
SQLUSMALLINT day;
SQLUSMALLINT hour;
SQLUSMALLINT minute;
SQLUSMALLINT second;
SQLUINTEGER fraction; [b]
} TIMESTAMP_STRUCT; [a]
SQL_F_NUMERIC SQL_C_NUMERIC SQL_NUMERIC_STRUCT
struct tagSQL_NUMERIC_STRUCT {
SQLCHAR precision;
SQLSCHAR scale;
SQLCHAR sign [g];
SQLCHAR val[SQL_MAX_NUMERIC_LEN]; [e,f]
} SQL_NUMERIC_STRUCT;
SQL_F_GUID SQL_C_GUID SQLGUID
struct tagSQLGUID {
DWORD Data1;
WORD Data2;
WORD Data3;
BYTE Data4[8];
} SQLGUID; [k]

[a] The values of the year, month, day, hour, minute, and second fields in the datetime C data types must conform to the constraints of the Gregorian calendar.
[b] The value of the fraction field is the number of billionths of a second and ranges from 0 to 999,999,999 (1 less than 1 billion). For example, the value of the fraction field for a half-second is 500,000,000. For a thousandth of a second (one millisecond) it is 1,000,000. For a millionth of a second (one microsecond) it is 1,000, and for a billionth of a second (one nanosecond) it is 1.
[c] In ODBC 2.x, the C date, time, and timestamp data types are SQL_C_DATE, SQL_C_TIME, and SQL_C_TIMESTAMP.
[d] ODBC 3.5 applications should use SQL_C_VARBOOKMARK, not SQL_C_BOOKMARK. When an ODBC 3.5 application works with an ODBC 2.x driver, the ODBC 3.5 Driver Manager will map SQL_C_VARBOOKMARK to SQL_C_BOOKMARK.
[e] A number is stored in the val (or value for f90SQL) field of the SQL_NUMERIC_STRUCT structure as a scaled integer, in little endian mode (the leftmost byte being the least-significant byte). For example, the number 10.001 base 10, with a scale of 4, is scaled to an integer of 100010. Because this is 186AA in hexadecimal format, the value in SQL_NUMERIC_STRUCT would be "AA 86 01 00 00 … 00", with the number of bytes defined by the SQL_MAX_NUMERIC_LEN.
[f] The precision and scale fields of the SQL_C_NUMERIC or SQL_F_NUMERIC data type are never used for input from an application, only for output from the driver to the application. When the driver writes a numeric value into the SQL_NUMERIC_STRUCT, it will use its own driver-specific default as the value for the precision field. It will also use the value in the SQL_DESC_SCALE field of the application descriptor (which defaults to 0) for the scale field. An application can provide its own values for precision and scale by setting the SQL_DESC_PRECISION and SQL_DESC_SCALE fields of the application descriptor.
[g] The sign field is 1 if positive, 0 if negative.
[h]_int64 or int(kind=8) may not be supplied by some compilers.
[i] _SQL_C_BOOKMARK has been deprecated in ODBC 3.x.
[j] _SQL_C_SHORT, SQL_C_LONG, and SQL_C_TINYINT have been replaced in ODBC by signed and unsigned types: SQL_C_SSHORT and SQL_C_USHORT, SQL_C_SLONG and SQL_C_ULONG, and SQL_C_STINYINT and SQL_C_UTINYINT.
[k] SQL_C_GUID may only be converted to SQL_CHAR or SQL_WCHAR.
[l] SQL_F_VAR_BOOKMARK and SQL_F_BINARY are defined as pointers to arrays of type SQLCHAR_KIND.