Data buffers are described by three pieces of information: their type, address, and byte length. ODBC functions that need these pieces of information always provide the necessary arguments in their calls. This is useful for languages like C, but in Fortran, these three pieces of information are already included in variable definitions. f90SQL takes advantage of this, and in many cases lets you pass a variable name instead of the three parameters that define the buffer. Because f90SQL was designed with flexibility in mind, it also allows you to pass a buffer in the same format defined by the ODBC-API. For example, subroutine f90SQLExecDirect submits a SQL statement for execution to the ODBC driver. The original ODBC-API definition of this statement is as follows (from the ODBC-SDK):
| SQLRETURN SQLExecDirect | (SQLHSTMT StatementHandle, SQLCHAR* StatementText, SQLINTEGER TextLength); |
The function expects a pointer to a buffer that contains the SQL statement to execute (*StatementText). It also expects an integer indicating the length of the data in this buffer (TextLength). The f90SQL version of this function is subroutine f90SQLExecDirect. It can be called in two different ways:
| call f90SQLExecDirect | (StatementHandle,loc(StatementTextStr), TextLength, iRet) |
or
| call f90SQLExecDirect | (StatementHandle, StatementTextStr, iRet) |
Note that the first form is basically a direct translation of the definition in the ODBC-API. You call the subroutine passing a pointer to the buffer (the Fortran function loc(variable) returns the address of its argument) and the size of the data in the buffer (Argument TextLength could, for example, have the result of len_trim(StatementTextStr)). All f90SQL subroutines allow this format, called f90SQL Pointer-Format. f90SQL Pointer-Format subroutines attempt to offer maximum flexibility and close resemblance to the original ODBC-API functions they call. However, they can be harder to use for traditional Fortran programmers.
In the second form, argument StatementTextStr contains the buffer itself (i.e. the variable passed in StatementTextStr is a character variable). The size of the data in the buffer is computed by f90SQL before it calls the corresponding ODBC-API function.
Some ODBC functions expect a specific type of buffer. In the previous example, the ODBC function SQLExecDirect expects a character string buffer and will not work properly with any other type of data. The same applies to f90SQL subroutines. When you call the second form of f90SQLExecDirect, you do not need to indicate that StatementTextStr is a character buffer. The function expects this buffer to be of character type and will not work with any other type. One of the advantages of f90SQL over the original ODBC API, is it will perform type checking for buffers during compilation. Thus, if by mistake you call the second form of subroutine f90SQLExecDirect with an integer argument in StatementTextStr, your compiler will give you an error message.
Note: Type-checking in f90SQL is not available when you call subroutines using Pointer-Format.
Some ODBC functions can receive different types of buffers, the type being indicated when the function is called. Buffers used to transfer parameter values and recordset data, such as the buffer bound with TargetValue in f90SQLBindCol, usually have an associated type argument. For example, the TargetType argument in f90SQLBindCol. In this argument, the application passes the Fortran type identifier corresponding to the type of the buffer. For example, in the following call to f90SQLBindCol, the value SQL_F_TYPE_DATE tells the driver that the Date buffer is an SQL_DATE_STRUCT:
| call f90SQLBindCol | (StmtHndl,Column, SQL_F_TYPE_DATE, Date, f90SQL_NULL_PTR, iRet) |