| Click here to support our advertisers

SOFTWARE FOR SALE
BOOKS FOR SALE
SEARCH CENTRAL
JOB BANK
CLASSIFIEDS
DIRECTORIES
REFERENCE Online Library
LEARNING CENTER
JOURNAL
NEWS CENTRAL
DOWNLOADS
COMMUNITY
CALENDAR
ABOUT US
Journal:
Get the weekly email highlights from the most popular journal for developers! Current issue
> developer.com developerdirect.com htmlgoodies.com javagoodies.com jars.com intranetjournal.com javascripts.com | All Categories : C/C++ vcg03.htm The SQL...() Functions SQLAllocConnect() SQLAllocEnv() SQLAllocStmt() SQLBindCol() SQLBindParameter() SQLBrowseConnect() SQLCancel() SQLColAttributes() SQLColumnPrivileges() SQLColumns() SQLConnect() SQLDataSources() SQLDescribeCol() SQLDescribeParam() SQLDisconnect() SQLDriverConnect() SQLDrivers() SQLError() SQLExecDirect() SQLExecute() SQLExtendedFetch() SQLFetch() SQLForeignKeys() SQLFreeConnect() SQLFreeEnv() SQLFreeStmt() SQLGetConnectOption() SQLGetCursorName() SQLGetData() SQLGetFunctions() SQLGetInfo() SQLGetStmtOption() SQLGetTypeInfo() SQLMoreResults() SQLNativeSql() SQLNumParams() SQLNumResultCols() SQLParamData() SQLParamOptions() SQLPrepare() SQLPrimaryKeys() SQLProcedureColumns() SQLProcedures() SQLPutData() SQLRowCount() SQLSetConnectOption() SQLSetCursorName() SQLSetPos() SQLSetScrollOptions() SQLSetStmtOption() SQLSpecialColumns() SQLStatistics() SQLTablePrivileges() SQLTables() SQLTransact() Using the SQL...() Functions Using a Datasource Handling Errors in SQL...() Statements Quoting Names Getting the Datasource from the User Summary # - 3 - Using Visual C++ Data Access Functions In Chapter 2, "Understanding MFC's ODBC Database Classes," you learned about the MFC data access objects. These C++ classes were built on the data access functions that are part of the SQL library that interfaces with ODBC. These functions offer a powerful interface to ODBC. The first part of this chapter is a reference to the SQL...() functions that make up the ODBC SDK 2.x interface. Those functions that were present in the ODBC SDK 1.0 version (such as SQLSetParam()) and that have been deleted in more recent versions of ODBC aren't covered in this chapter. The second part of this chapter presents a set of functions that you can use to access datasets. It generally is more difficult to use the SQL...() functions than to use the MFC database classes described in Chapter 2. However, these functions do offer more flexibility to the programmer who is writing an application that must access many different types of datasources, with differing tables and schema (layout and definitions). Not withstanding the existing functionality found in the MFC ODBC classes, there is no reason why you can't use both the MFC classes and the SQL...() functions in the same code. The MFC ODBC classes have all the necessary handles to allow usage of the SQL...() functions; in fact, the MFC ODBC classes use the SQL...() functions to perform most of their database manipulation tasks. ### The SQL...() Functions This reference to the SQL...() functions will show virtually everything you need to know in order to use most of these functions. However, some functions are complex and return a substantial amount of information. If you need more information, you can refer to the various help files available (including the MSDN CD set, the ODBC SDK, and Visual C++'s help facility). NOTE The SQL...() functions haven't changed substantially since their introduction. Minor changes to accommodate 32-bit programming (the original SQL...() functions were 16-bit) account for virtually all the changes found. When you use the SQL...() functions, remember that there is a fixed order of usage. The sample code in the second part of this chapter provides more information about how to use the functions. Each function is presented with a prototype, function arguments (if any), an explanation of the return value (if any), a description of what the function should do, and an explanation of possible failures that might occur when you use the function. Some functions will fail for a number of reasons. When you encounter a failure, use SQLError() to determine the cause of the failure. NOTE Using the SQL logging facility is often very useful in determining why an SQL function failed during development. Of course, you shouldn't expect your application's users to have SQL logging turned on. Don't forget that SQL logging will significantly affect ODBC performance because detailed information is written to the logging file for each and every SQL operation. Don't turn on SQL logging indiscriminately; use it when you need it and then turn it off. In all cases where the return value is shown as type RETCODE, you should create a variable defined as this type to hold the return code. You can then use either an if() or a switch() statement to check the return code for errors. NOTE There are two versions of the ODBC SDK 2.1: 2.10a and 2.10b. You should use 2.10b, which was released in August of 1995, if you're using Visual C++ 2.x. The version of ODBC that is included with Visual C++ 4.0 is 2.5. Version 2.5 is intended for use on both Windows 95 and on Windows NT versions 3.5 and 3.51. NOTE The current version of the ODBC SDK is 2.5, which is included with both Visual C++ 4 and Visual C++ 1.5x. Microsoft hasn't announced whether (or when) further updates to the ODBC SDK will occur. It can be assumed that new versions of Visual C++ may well include new versions of ODBC. #### SQLAllocConnect() Prototype:
>     RETCODE SQLAllocConnect(HENV henv, HDBC FAR * phdbc)
> Parameters:
> HENV henv | The environment handle from the call to SQLAllocEnv().
> HDBC FAR * phdbc | A pointer to the storage for the connection handle.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: The SQLAllocConnect() function is used to allocate the connection between the application and the datasource. It's called after a call to SQLAllocEnv(), and SQLAllocStmt() is called after a call to SQLAllocEnv(). You must call the SQLAllocConnect() function after getting an HENV handle from SQLAllocEnv(). Without a valid HENV handle, this function won't succeed. Always check the return code from this function for errors. Notes: The function's results are placed in the handle pointed to by the phdbc parameter. If the SQLAllocConnect() function fails, the phdbc handle will be set to SQL_NULL_HDBC. #### SQLAllocEnv() Prototype:
>     RETCODE SQLAllocEnv(HENV FAR * phenv)
> Parameter:
> HENV FAR * phenv | A pointer to an environment handle.
> \Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Often, this function is the first SQL...() function that is called. If it fails, there may be no recovery. Usage: Call the SQLAllocEnv() function to initialize the SQL environment. You should make a matching SQLFreeEnv() call when your calling function has finished accessing the datasource. Always check the return code from these functions for errors. Notes: This function places the HENV in the supplied handle. If SQLAllocEnv() fails, the resultant phenv parameter is set to SQL_NULL_HENV. #### SQLAllocStmt() Prototype:
>     RETCODE SQLAllocStmt(HDBC hdbc, HSTMT FAR * hstmt)
> Parameters:
> HDBC hdbc | A handle to an HDBC as returned by the call to the SQLAllocConnect() function.
> HSTMT FAR * hstmt | A pointer to a statement handle that will be filled in by this function.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful and more information is available.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: The SQLAllocStmt() function is used to allocate a statement handle. This statement handle is associated with the datasource to which the HDBC handle was connected. Notes: If this function fails, the returned HSTMT handle will be set to SQL_NULL_HSTMT. #### SQLBindCol() Prototype:
>     RETCODE SQLBindCol(HSTMT hstmt, UWORD icol, SWORD fCType,

>     PTR rbgValue, SDWORD cbValueMax, SDWORD FAR * pcbValue)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UWORD icol | The index to the column in the table to which the variable is being bound.
> SWORD fCType | The data type of the data variable that is being bound to column icol.
> PTR rgbValue | A pointer to the location in the application where the column's data is to be stored. The data type of rgbValue should be defined by fCType.
> SDWORD cbValueMax | The number of bytes in the storage location pointed to by rgbValue. Usually, the C sizeof() operator can be used for this parameter.
> SDWORD FAR * pcbValue | A pointer to an SDWORD variable that will receive the count of how many bytes in rgbValue were used.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLBindCol() function only for the columns in a table that you need. You don't have to bind to every column in a table. Columns that don't have a variable bound to them will be discarded without error. You make a call—usually in a loop—to SQLFetch() or SQLExtendedFetch() to actually get the data from a record. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. When a column hasn't been bound and later must be accessed, use SQLGetData(). #### SQLBindParameter() Prototype:
>     RETCODE SQLBindParameter(HSTMT hstmt, UWORD ipar, SWORD fParamType,

>     SWORD fCType, SWORD fSqlType, UDWORD cbColDef,

>     SWORD ibScale, PTR rgbValue, SDWORD cbValueMax, SDWORD pcbValue)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UWORD ipar | The parameter number, which is one-based (not zero-based) from left to right.
> SWORD fParamType | Parameter ipar's type.
> SWORD fCType | The C data type of the parameter.
> SWORD fSqlType | The SQL data type of the parameter.
> UDWORD cbColDef | The column's precision.
> SWORD ibScale | The column's scale.
> PTR rgbValue | A pointer to the location in the application where the column's data is to be stored. The data type of rgbValue should be defined by fCType.
> SDWORD cbValueMax | The number of bytes in the storage location pointed to by rgbValue. Usually the C sizeof() operator can be used for this parameter.
> SDWORD FAR * pcbValue | A pointer to an SDWORD variable that will receive the count of how many bytes in rgbValue were used.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLBindParameter() function to bind a buffer to a parameter marker in an SQL statement. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. This function replaces the SQLSetParam() function found in ODBC version 1.x. #### SQLBrowseConnect() Prototype:
>     RETCODE SQLBrowseConnect(HDBC hdbc, UCHAR FAR * szConnStrIn, SWORD cbConnStrIn,

>     UCHAR FAR * szConnStrOut, SWORD cbConnStrOutMax, SWORD FAR * pcbConnStrOut)
> Parameters:
> HDBC hdbc | A handle to an HDBC as returned by the call to the SQLAllocConnect() function.
> UCHAR FAR * szConnStrIn | The input connection string.
> SWORD cbConnStrIn | The number of bytes in szConnStrIn.
> UCHAR FAR * szConnStrOut | The output connection string.
> SWORD cbConnStrOutMax | The number of bytes available in szConnStrOut.
> SWORD FAR * pcbConnStrOut | The count of the number of bytes actually used in szConnStrOut.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_NEED_DATA | The function failed. More information in the input connect string was required than was supplied. Call SQLError() to get more information about the specific failure.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLBrowseConnect() function to enumerate the attributes of a specific datasource. Always check the return code from this function for errors, making additional calls as necessary to gather the desired information to establish the connection. Notes: When a return code of either SQL_SUCCESS or SQL_SUCCESS_WITH_INFO is returned, your application will know that the enumeration process has completed and the application is connected to the datasource. #### SQLCancel() Prototype:
>     RETCODE SQLCancel (HSTMT hstmt)
> Parameter:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLCancel() function to cancel an asynchronous operation pending on the parameter statement indicated by hstmt. Always check the return code from this function for errors. Notes: You can cancel functions running on hstmt that are running on other threads. You also can cancel functions on hstmt that require more data. #### SQLColAttributes() Prototype:
>     RETCODE SQLColAttributes (HSTMT hstmt, UWORD icol, UWORD fDescType,

>     PTR rgbDesc, SWORD cbDescMax, SWORD FAR * pcbDesc, SWORD FAR * pfDesc)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UWORD icol | The index to the column in the table that the variable is being bound to.
> UWORD fDescType | A valid descriptor.
> PTR rgbDesc | A pointer to the location in the application where the column's data is to be stored. The data type of rgbValue should be defined by fCDescType.
> SWORD cbDescMax | The number of bytes in the storage location pointed to by rgbDesc. Usually, the C sizeof() operator can be passed for this parameter.
> SWORD FAR * pcbDesc | A pointer to an SDWORD variable that will receive the count of how many bytes in rgbDesc were used.
> SWORD FAR * pfDesc | A pointer to an integer variable that will receive the results of a query which returns a numeric result.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLColAttributes() function to gather information about a column in a table. Always check the return code from this function for errors. Notes: Table 3.1 shows the information that will be returned for columns. Table 3.1. Column attributes returned by SQLColAttributes().
> Identifier | Minimum ODBC Version | Where Returned | Description
> SQL_COLUMN_AUTO_INCREMENT | 1.0 | pfDesc | Returns TRUE if the column is an auto-increment column and FALSE if it isn't. Only numeric columns can be auto increment. Values may be inserted into an auto-increment column, but the auto-increment column can't be updated.
> SQL_COLUMN_CASE_SENSITIVE | 1.0 | pfDesc | Returns TRUE if the column will be considered case-sensitive for sorts and comparisons. Columns that aren't character-based will return FALSE.
> SQL_COLUMN_COUNT | 1.0 | pfDesc | Number of columns that are in the result set. The icol argument will be ignored.
> SQL_COLUMN_DISPLAY_SIZE | 1.0 | pfDesc | Returns the maximum number of characters positions that will be necessary to display data from the column.
> SQL_COLUMN_LABEL | 2.0 | rgbDesc | The column's label or title. As an example, an Access database may have a column called ZipCodes that could be labeled (or titled) "5-Digit Zip Code." The column name is returned for columns that don't have specified labels or titles. For unnamed columns (such as those found in a text file datasource), an empty string is returned.
> SQL_COLUMN_LENGTH | 1.0 | pfDesc | The number of bytes of data that will be transferred on an SQLGetData() or SQLFetch() operation when the SQL_C_DEFAULT parameter is specified.
> SQL_COLUMN_MONEY | 1.0 | pfDesc | Returns TRUE if the column is a money data type.
> SQL_COLUMN_NAME | 1.0 | rgbDesc | Returns the column name. If the column is unnamed, an empty string is returned. See SQL_COLUMN_LABEL earlier in this table.
> SQL_COLUMN_NULLABLE | 1.0 | pfDesc | Returns SQL_NO_NULLS if the column doesn't accept null values, or returns SQL_NULLABLE if the column accepts null values. Will return SQL_NULLABLE_UNKNOWN if it can't be determined whether the column accepts null values.
> SQL_COLUMN_OWNER_NAME | 2.0 | rgbDesc | Returns the name of the owner of the table that contains the specified column. When the datasource doesn't support owners (such as for xBase files) or the owner name can't be determined, an empty string will be returned.
> SQL_COLUMN_PRECISION | 1.0 | pfDesc | Returns the precision of the column on the datasource.
> SQL_COLUMN_QUALIFIER_NAME | 2.0 | rgbDesc | Returns the table qualifier for the column. For datasources that don't support qualifiers or where the qualifier name can't be determined, an empty string will be returned.
> SQL_COLUMN_SCALE | 1.0 | pfDesc | Returns the scale of the column on the datasource.
> SQL_COLUMN_SEARCHABLE | 1.0 | pfDesc | Returns SQL_UNSEARCHABLE when the column can't be used in a WHERE clause.
> |  |  | Returns SQL_LIKE_ONLY if the column can be used in a WHERE clause only with the LIKE predicate. When the column is a type SQL_LONGVARCHAR or SQL_LONGVARBINARY this is the usual return.
> |  |  | Returns SQL_ALL_EXCEPT_LIKE if the column can be used in a WHERE clause with all comparison operators except LIKE.
> |  |  | Returns SQL_SEARCHABLE if the column can be used in a WHERE clause with any comparison operator.
> SQL_COLUMN_TABLE_NAME | 2.0 | rgbDesc | Returns the table name for the table that contains the column. When the table name can't be determined, an empty string is returned.
> SQL_COLUMN_TYPE | 1.0 | pfDesc | Returns the SQL data type for the column.
> SQL_COLUMN_TYPE_NAME | 1.0 | rgbDesc | A character string indicating the data type of the column: CHAR, VARCHAR, MONEY, LONG VARBINARY, or CHAR ( ) FOR BIT DATA. When the data type is unknown, an empty string is returned.
> SQL_COLUMN_UNSIGNED | 1.0 | pfDesc | Returns TRUE if the column is either nonnumeric or is an unsigned numeric value.
> SQL_COLUMN_UPDATABLE | 1.0 | pfDesc | The column will be described with one of the following constants: SQL_ATTR_READONLY, SQL_ATTR_WRITE, SQL_ATTR_READWRITE_UNKNOWN, SQL_COLUMN_UPDATABLE, which describe how the column may be updated. When it can't be determined whether the column may be updatable, SQL_ATTR_READWRITE_UNKNOWN is typically returned.
> #### SQLColumnPrivileges() Prototype:
>     RETCODE SQLColumnPrivileges(HSTMT hstmt, UCHAR FAR * szTableQualifier,

>     SWORD cbTableQualifier, UCHAR FAR * szTableOwner, SWORD cbTableOwner,

>     UCHAR FAR * szTableName, SWORD cbTableName, UCHAR FAR * szColumnName,

>     SWORD cbColumnName)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UCHAR FAR * szTableQualifier | The table qualifier. Use an empty string for tables that don't support table qualifiers.
> SWORD cbTableQualifier | The length of szTableQualifier.
> UCHAR FAR * szTableOwner | The table owner name. Use an empty string for tables that don't support table owners.
> SWORD cbTableOwner | The length of szTableOwner.
> UCHAR FAR * szTableName | The table name.
> SWORD cbTableName | The length of szTableName.
> UCHAR FAR * szColumnName | The search pattern string (used for column names).
> SWORD cbColumnName | The length of szColumnName.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_STILL_EXECUTING | An asynchronous event is still pending.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLColumnPrivileges() function to obtain a list of columns and privileges for the specified table. Always check the return code from this function for errors. Notes: The information is returned as a result set. #### SQLColumns() Prototype:
>     RETCODE SQLColumns(HSTMT hstmt, UCHAR FAR * szTableQualifier,

>     SWORD cbTableQualifier, UCHAR FAR * szTableOwner,

>     SWORD cbTableOwner, UCHAR FAR * szTableName, SWORD cbTableName,

>     UCHAR FAR * szColumnName, SWORD cbColumnName)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UCHAR FAR * szTableQualifier | The table qualifier. Use an empty string for tables that don't support table qualifiers.
> SWORD cbTableQualifier | The length of szTableQualifier.
> UCHAR FAR * szTableOwner | The table owner name. Use an empty string for tables that don't support table owners.
> SWORD cbTableOwner | The length of szTableOwner.
> UCHAR FAR * szTableName | The table name.
> SWORD cbTableName | The length of szTableName.
> UCHAR FAR * szColumnName | The search pattern string (used for column names).
> SWORD cbColumnName | The length of szColumnName.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLColumns() function obtain a list of the columns in a specified table. Always check the return code from this function for errors. Notes: The results are returned as a result set. The columns returned in the result set are shown in Table 3.2. Table 3.2. Columns in the SQLColumns() result set.
> Column Number | Data Type | Description
> 1 | SQL_C_CHAR | Qualifier
> 2 | SQL_C_CHAR | Owner
> 3 | SQL_C_CHAR | Table Name
> 4 | SQL_C_CHAR | Column Name
> 5 | SQL_C_SSHORT | Data Type
> 6 | SQL_C_CHAR | Type Name
> 7 | SQL_C_SLONG | Precision
> 8 | SQL_C_SLONG | Length
> 9 | SQL_C_SSHORT | Scale
> 10 | SQL_C_SSHORT | Radix
> 11 | SQL_C_SSHORT | Nullable
> 12 | SQL_C_CHAR | Remarks
> #### SQLConnect() Prototype:
>     RETCODE SQLConnect(HDBC hdbc, UCHAR FAR * szDSN, SWORD cbDSN,

>     UCHAR FAR * szUID, SWORD cbUID, UCHAR FAR * szAuthStr, SWORD cbAuthStr)
> Parameters:
> HDBC hdbc | A handle to an HDBC as returned by the call to the SQLAllocConnect() function.
> UCHAR FAR * szDSN | A pointer to a string containing the datasource name.
> SWORD cbDSN | The length of szDSN.
> UCHAR FAR * szUID | A pointer to the string that contains the user's identifier.
> SWORD cbUID | The length of szUID.
> UCHAR FAR * szAuthStr | The password or authentication string.
> SWORD cbAuthStr | The length of szAuthStr.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLConnect() function to establish a connection between the application and a specific datasource. Always check the return code from this function for errors. Notes: The SQLConnect() function tells ODBC to load the driver in preparation for using the datasource. #### SQLDataSources() Prototype:
>     RETCODE SQL (HENV henv, UWORD fDirection, UCHAR FAR * szDSN,

>     SWORD cbDSNMax, SWORD FAR * pcbDSN, UCHAR FAR * szDescription,

>     SWORD cbDescriptionMax, SWORD FAR * pcbDescription)
> Parameters:
> HENV henv | Environment handle.
> UWORD fDirection | This parameter is used to determine whether the driver manager will fetch the next datasource name in the list (use the SQL_FETCH_NEXT identifier) or whether the search starts from the beginning of the list (use the SQL_FETCH_FIRST identifier).
> UCHAR FAR * szDSN | A pointer to a storage buffer for the datasource name.
> SWORD cbDSNMax | Maximum length of the szDSN buffer. The maximum length supported by ODBC is SQL_MAX_DSN_LENGTH + 1.
> SWORD FAR * pcbDSN | The total number of bytes returned in szDSN. If the returned string won't fit in szDSN, the datasource name is truncated to cbDSNMax – 1 bytes.
> UCHAR FAR * szDescription | A pointer to storage buffer for the description string of the driver associated with the datasource. The szDescription buffer should be at least 255 bytes long. Driver descriptions might be dBASE or SQL Server.
> SWORD cbDescriptionMax | Maximum length of szDescription.
> SWORD FAR * pcbDescription | The total number of bytes returned in szDSN. If the returned string won't fit in szDescription, the description is truncated to cbDescriptionMax – 1 bytes.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_NO_DATA_FOUND | There were no datasources remaining.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLDataSources() function to enumerate a list of the currently installed datasources. Always check the return code from this function for errors. Notes: You should call the SQLDataSources() function in a loop while the application checks the return code. When the return code is SQL_NO_DATA_FOUND, then all the datasources have been enumerated. #### SQLDescribeCol() Prototype:
>     RETCODE SQL (HSTMT hstmt, UWORD icol, UCHAR FAR * szColName,

>     SWORD cbColNameMax, SWORD FAR * pcbColName,

>     SWORD FAR * pfSqlType, UDWORD FAR * pcbColDef,

>     SWORD FAR * pibScale, SWORD FAR * pfNullable)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UWORD icol | The index to the column in the table to which the variable is being bound.
> UCHAR FAR * szColName | A pointer to a string that will contain the column name. For columns that have no name, or when the name can't be determined, an empty string will be returned.
> SWORD cbColNameMax | The size of the szColName.
> SWORD FAR * pcbColName | The number of bytes returned in szColName. If the column name won't fit in szColName, the column name is truncated to cbColNameMax – 1 bytes.
> SWORD FAR * pfSqlType | The column's SQL data type. Use one of the constants shown in Table 3.3 for this parameter.
> UDWORD FAR * pcbColDef | The column's precision, or zero if the precision can't be determined.
> SWORD FAR * pibScale | The column's scale, or zero if the scale can't be determined.
> SWORD FAR * pfNullable | A constant that indicates whether this column supports null data values. Will be either SQL_NO_NULLS, SQL_NULLABLE, or SQL_NULLABLE_UNKNOWN.
> Table 3.3. Column types.
> Identifier | Description
> SQL_BIGINT | Integer data
> SQL_BINARY | Binary data
> SQL_BIT | Bit-field data
> SQL_CHAR | Character data
> SQL_DATE | Data field
> SQL_DECIMAL | Decimal data
> SQL_DOUBLE | Double data
> SQL_FLOAT | Floating-point data
> SQL_INTEGER | Integer data
> SQL_LONGVARBINARY | Binary data
> SQL_LONGVARCHAR | Variable-length character data
> SQL_NUMERIC | Numeric data
> SQL_REAL | Floating-point data
> SQL_SMALLINT | Integer data
> SQL_TIME | Time data
> SQL_TIMESTAMP | Timestamp data
> SQL_TINYINT | Integer data
> SQL_VARBINARY | Variable-length binary data
> SQL_VARCHAR | Variable-length character data
> Other | Driver-specific data
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_STILL_EXECUTING | An asynchronous operation is still pending.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLDescribeCol() function to get information about a specific column in a datasource. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLDescribeParam() Prototype:
>     RETCODE SQLDescribeParam(HSTMT hstmt, UWORD ipar,

>     SWORD FAR * pfSqlType, UWORD FAR * pcbColDef,

>     SWORD FAR * pibScale, SWORD FAR * pfNullable)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UWORD ipar | The parameter marker index, ordered sequentially left to right. This index is one-based, not zero-based.
> SWORD FAR * pfSqlType | A pointer to a variable that will be used to return the SQL type of the parameter. Valid SQL types are listed in Table 3.4.
> UDWORD FAR * pcbColDef | The column's precision.
> SWORD FAR * pibScale | The column's scale.
> SWORD FAR * pfNullable | A constant that indicates whether this column supports null data values. Will be either SQL_NO_NULLS, SQL_NULLABLE, or SQL_NULLABLE_UNKNOWN.
> Table 3.4. Column return types.
> Identifier | Description
> SQL_BIGINT | Integer data
> SQL_BINARY | Binary data
> SQL_BIT | Bit-field data
> SQL_CHAR | Character data
> SQL_DATE | Data field
> SQL_DECIMAL | Decimal data
> SQL_DOUBLE | Double data
> SQL_FLOAT | Floating-point data
> SQL_INTEGER | Integer data
> SQL_LONGVARBINARY | Binary data
> SQL_LONGVARCHAR | Variable-length character data
> SQL_NUMERIC | Numeric data
> SQL_REAL | Floating-point data
> SQL_SMALLINT | Integer data
> SQL_TIME | Time data
> SQL_TIMESTAMP | Timestamp data
> SQL_TINYINT | Integer data
> SQL_VARBINARY | Variable-length binary data
> SQL_VARCHAR | Variable-length character data
> Other | Driver-specific data
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_STILL_EXECUTING | An asynchronous operation is still pending.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLDescribeParam() function to obtain a description of the parameter marker in an SQL statement. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLDisconnect() Prototype:
>     RETCODE SQLDisconnect(HDBC hdbc)
> Parameter:
> HDBC hdbc | A handle to an HDBC as returned by the call to the SQLAllocConnect() function.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLDisconnect() function to disconnect from the currently connected datasource. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLDriverConnect() Prototype:
>     RETCODE SQLDriverConnect(HDBC hdbc, HWND hwnd, UCHAR FAR * szConnStrIn,

>     SWORD cbConnStrIn, UCHAR FAR * szConnStrOut, SWORD cbConnStrOutMax,

>     SWORD FAR * pcbConnStrOut, UWORD fDriverCompletion)
> Parameters:
> HDBC hdbc | A handle to an HDBC as returned by the call to the SQLAllocConnect() function.
> HWND hwnd | The window handle of the parent window. This is used if the SQLDriverConnect() function must display any dialog boxes to prompt the user for information (such as user ID or passwords). If a NULL pointer is specified, SQLDriverConnect() won't present any dialog boxes.
> UCHAR FAR * szConnStrIn | A pointer to a full connection string, a partial connection string, or an empty string. Don't pass a NULL pointer.
> SWORD cbConnStrIn | The length of szConnStrIn.
> UCHAR FAR * szConnStrOut | A pointer to a buffer that will receive the resulting string that is used to connect to the datasource. This buffer should be at least 255 bytes or longer.
> SWORD cbConnStrOutMax | The size of the szConnStrOut buffer.
> SWORD FAR * pcbConnStrOut | A pointer to the variable that will receive the number of bytes that have been stored in szConnStrOut. If the buffer was too small to contain the connect string, the connect string in szConnStrOut is truncated to cbConnStrOutMax – 1 bytes.
> UWORD fDriverCompletion | Contains a flag that tells whether the driver manager or driver must prompt for more connection information. See Table 3.5 for valid values for this string.
> Table 3.5. Driver completion values.
> Value | Description
> SQL_DRIVER_PROMPT | The driver manager will display the datasources dialog box for the user to select the datasource.
> SQL_DRIVER_COMPLETE | The driver will use the connection string specified by the application if the connection string contains the DSN keyword; otherwise, the same action as SQL_DRIVER_PROMPT is taken.
> SQL_DRIVER_COMPLETE_REQUIRED | The driver will use the connection string specified by the application if the connection string contains the DSN keyword; otherwise, the same action as SQL_DRIVER_PROMPT is taken.
> SQL_DRIVER_NOPROMPT | The driver manager uses the connection string specified by the application.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_NO_DATA_FOUND | The command didn't find the driver to connect to.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLDriverConnect() function to connect to a specific driver. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLDrivers() Prototype:
>     RETCODE SQLDrivers(HENV henv, UWORD fDirection, UCHAR FAR * szDriverDesc,

>     SWORD cbDriverDescMax, SWORD FAR * pcbDriverDesc,

>     UCHAR fAR * szDriverAttributes, SWORD cbDrvrAttrMax, SWORD FAR * pcbDrvrAttr)
> Parameters:
> HENV henv | An environment handle, as returned by a call to SQLAllocEnv().
> UWORD fDirection | This parameter is used to determine whether the driver manager fetches the next, or first, driver description in the list. Use SQL_FETCH_NEXT or SQL_FETCH_FIRST.
> UCHAR FAR * szDriverDesc | A pointer to a buffer for the driver description.
> SWORD cbDriverDescMax | The size of the szDriverDesc buffer.
> SWORD FAR * pcbDriverDesc | A pointer to a variable that will hold the number of bytes returned in szDriverDesc. If the size of the string returned is too large for szDriverDesc, the driver description in szDriverDesc will be truncated to cbDriverDescMax – 1 bytes.
> UCHAR FAR * szDriverAttributes | A pointer to a buffer that will hold the list of driver attribute value pairs.
> SWORD cbDrvrAttrMax | The size of the szDriverAttributes buffer.
> SWORD FAR * pcbDrvrAttr | A pointer to a variable that will hold the number of bytes placed in szDriverAttributes. If the size of the string returned is too large for szDriverAttributes, the list of attribute value pairs in szDriverAttributes will be truncated to cbDrvrAttrMax – 1 bytes.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLDrivers() function to list the drivers and driver attributes. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLError() Prototype:
>     RETCODE SQLError(HENV henv, HDBC hdbc, HSTMT hstmt,

>     UCHAR FAR * szSqlState, SDWORD FAR * pfNativeError,

>     UCHAR FAR * szErrorMsg, SWORD cbErrorMsgMax, SWORD FAR * pcbErrorMsg)
> Parameters:
> HENV henv | A handle to an HENV as returned by the call to the SQLAllocEnv() function, or SQL_NULL_HENV to query all open environments.
> HDBC hdbc | A handle to an HDBC as returned by the call to the SQLAllocConnect() function, or SQL_NULL_HDBC to query all open database connections.
> HSTMT hstmt | A handle to a HSTMT as returned by the call to the SQLAllocStmt() function, or SQL_NULL_HSTMT to query all open statements.
> UCHAR FAR * szSqlState | A buffer containing the SQLSTATE, formatted as a null-terminated string, will be returned.
> SDWORD FAR * pfNativeError | The returned native error code.
> UCHAR FAR * szErrorMsg | A buffer that will point to the error message text.
> SWORD cbErrorMsgMax | A variable that specifies the maximum length of the szErrorMsg buffer. This buffer's size must be less than or equal to SQL_MAX_MESSAGE_LENGTH – 1.
> SWORD FAR * pcbErrorMsg | A pointer to a variable that will contain the number of bytes in szErrorMsg. If the string is too large for szErrorMsg, the text in szErrorMsg will be truncated to cbErrorMsgMax – 1 bytes.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_NO_DATA_FOUND | The command didn't find any error conditions on which to report.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should try to recover—displaying or saving whatever diagnostic information is appropriate—or the error should be corrected and the function should be re-executed. Usage: Call the SQLError() function to obtain more information about the error condition. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLExecDirect() Prototype:
>     RETCODE SQLExecDirect(HSTMT hstmt, UCHAR FAR * szSqlStr, SDWORD cbSqlStr)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UCHAR FAR * szSqlStr | A pointer to an SQL statement to be executed.
> SDWORD cbSqlStr | The length of the string in szSqlStr.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_NEED_DATA | The function needs more information to process the request.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLExecDirect() function to execute (usually once) a preparable SQL statement. Always check the return code from this function for errors. Notes: This function is probably the fastest way to execute SQL statements when the statement needs to be executed only one time. If this function fails, use the SQLError() function to find out why. #### SQLExecute() Prototype:
>     RETCODE SQLExecute(HSTMT hstmt)
> Parameter:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_NEED_DATA | The function needs more information to process the request.
> SQL_STILL_EXECUTING | An asynchronous operation is still pending.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLExecute() function to execute a prepared statement using the parameter values contained in marker variables, if there are any. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLExtendedFetch() Prototype:
>     RETCODE SQLExtenedeFetch(HSTMT hstmt, UWORD fFetchType,

>     SDWORD irow, UDWORD FAR * pcrow, UWORD FAR * rgfRowStatus)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UWORD fFetchType | Specifies the type of fetch desired. Table 3.6 describes valid values for this parameter.
> SDWORD irow | Specifies the number of the row to be fetched.
> UDWORD FAR * pcrow | Returns the count of the number of rows that were actually fetched.
> UWORD FAR * rgfRowStatus | A pointer to an array of status values.
> Table 3.6. Valid fetch values.
> Identifier | Description
> SQL_FETCH_NEXT | Fetch the next row.
> SQL_FETCH_FIRST | Fetch the first row.
> SQL_FETCH_LAST | Fetch the last row.
> SQL_FETCH_PRIOR | Fetch the previous row.
> SQL_FETCH_ABSOLUTE | Fetch the row specified absolutely.
> SQL_FETCH_RELATIVE | Fetch the row specified relative to the current row.
> SQL_FETCH_BOOKMARK | Fetch the marked row.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_NO_DATA_FOUND | The command didn't find the driver to connect to.
> SQL_STILL_EXECUTING | An asynchronous operation is still pending.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLExtendedFetch() function to fetch one or more rows from a result set. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLFetch() Prototype:
>     RETCODE SQLFetch(HSTMT hstmt)
> Parameter:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_NO_DATA_FOUND | The command didn't find the driver to connect to.
> SQL_STILL_EXECUTING | An asynchronous operation is still pending.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLFetch() function to fetch a single row of data from the result set. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLForeignKeys() Prototype:
>     RETCODE SQLForeignKeys(HSTMT hstmt,

>     UCHAR FAR * szPkTableQualifier, SWORD cbPkTableQualifier,

>     UCHAR FAR * szPkTableOwner, SWORD cbPkTableOwner,

>     UCHAR FAR * szPkTableName, SWORD cbPkTableName,

>     UCHAR FAR * szFkTableQualifier, SWORD cbFkTableQualifier,

>     UCHAR FAR * szFkTableOwner, SWORD cbFkTableOwner,

>     UCHAR FAR * szFkTableName, SWORD cbFkTableName)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UCHAR FAR * szPkTableQualifier | A pointer to the primary key table qualifier.
> SWORD cbPkTableQualifier | The length of szPkTableQualifier.
> UCHAR FAR * szPkTableOwner | A pointer to the primary key owner name.
> SWORD cbPkTableOwner | The length of szPkTableOwner.
> UCHAR FAR * szPkTableName | A pointer to the primary key table name.
> SWORD cbPkTableName | The length of szPkTableName.
> UCHAR FAR * szFkTableQualifier | A pointer to the foreign key table qualifier.
> SWORD cbFkTableQualifier | The length of szFkTableQualifier.
> UCHAR FAR * szFkTableOwner | A pointer to the foreign key owner name.
> SWORD cbFkTableOwner | The length of szFkTableOwner.
> UCHAR FAR * szFkTableName | A pointer to the foreign key table name.
> SWORD cbFkTableName | The length of szFkTableName.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_STILL_EXECUTING | An asynchronous operation is still pending.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLForeignKeys() function to return either a list of foreign keys in the specified table or a list of foreign keys in other tables that refer to the primary key in the specified table. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLFreeConnect() Prototype:
>     RETCODE SQLFreeConnect(HDBC hdbc)
> Parameter:
> HDBC hdbc | A handle to an HDBC as returned by the call to the SQLAllocConnect() function.
> Return Value: This function will return one of the following values: SQL_SUCCESS The function was successful. SQL_SUCCESS_WITH_INFO The function was successful, and more information is available. SQL_ERROR The function failed. Call SQLError() to get more information about the specific failure. SLQ_INVALID_HANDLE The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle. If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLFreeConnect() function to release the connection established with the SQLAllocConnect() function. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLFreeEnv() Prototype:
>     RETCODE SQL (HENV henv)
> Parameter:
> HENV henv | A handle to an HENV as returned by the call to the SQLAllocEnv() function.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLFreeEnv() function to free the environment established by the SQLAllocEnv() function. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLFreeStmt() Prototype:
>     RETCODE SQLFreeStmt(HSTMT hstmt, UWORD fOption)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UWORD fOption | An option from the list shown in Table 3.7.
> Table 3.7. fOption values from SQLFreeStmt().
> Identifier | Description
> SQL_ CLOSE | Used to close the cursor associated with hstmt (if one was defined) and discard any pending results. Later, the application will be able to reopen the cursor by executing a SELECT statement again with the same or different parameter values.
> SQL_DROP | Used to release the hstmt, free all resources associated with it, close the cursor, and discard any rows that are pending. This option terminates all access to the hstmt. The hstmt may not be reused.
> SQL_UNBIND | Used to release any column buffers bound by SQLBindCol() for the given hstmt.
> SQL_RESET_PARAMS | Used to release all parameter buffers set by SQLBindParameter() for the given hstmt.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLFreeStmt() function to free the statement handle allocated by the SQLAllocStmt() function. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLGetConnectOption() Prototype:
>     RETCODE SQL (HDBC hdbc, UWORD fOption, PTR pvParam)
> Parameters:
> HDBC hdbc | A handle to an HDBC as returned by the call to the SQLAllocConnect() function.
> UWORD fOption | Specifies the option to retrieve.
> PTR pvParam | The buffer where the value associated with fOption will be placed. This variable will be either a 32-bit integer value or a pointer to a null-terminated character string.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_NO_DATA_FOUND | The command didn't find the driver to connect to.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLGetConnectOption() function to get the settings for the current connection. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLGetCursorName() Prototype:
>     RETCODE SQLCursorName(HSTMT hstmt, UCHAR FAR * szCursor,

>     SWORD cbCursorMax, SWORD FAR * pcbCursor)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UCHAR FAR * szCursor | A pointer to a buffer that will receive the cursor name.
> SWORD cbCursorMax | The length of szCursor.
> SWORD FAR * pcbCursor | A pointer to a variable that will have the length of szCursor stored in it. If the cursor name is too large for szCursor, the cursor name in szCursor is truncated to cbCursorMax – 1 bytes.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLGetCursorName() function to get the name for the cursor specified by the hstmt parameter. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLGetData() Prototype:
>     RETCODE SQLGetData(HSTMT hstmt, UWORD icol, SWORD fCType,

>     PTR rgbValue, SDWORD cbValueMax, SDWORD FAR * pcbValue)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UWORD icol | The column number starting at column 1. Specifying a column number of 0 will retrieve a bookmark for the row. Neither ODBC 1.0 drivers nor SQLFetch() support bookmarks.
> SWORD fCType | A constant that specifies the column's resultant C data type values. See Table 3.8 for valid values.
> PTR rgbValue | A pointer to location used to store the data.
> SDWORD cbValueMax | Specifies the length of the buffer rgbValue.
> SDWORD FAR * pcbValue | One of the values specified in Table 3.9.
> Table 3.8. SQL C data types for SQLGetData().
> Identifier | Description
> SQL_C_BINARY | Binary data.
> SQL_C_BIT | Bitmapped data.
> SQL_C_BOOKMARK | Bookmark data.
> SQL_C_CHAR | Character string data.
> SQL_C_DATE | Date data.
> SQL_C_DOUBLE | Floating-point data.
> SQL_C_FLOAT | Floating-point data.
> SQL_C_SLONG | Integer data.
> SQL_C_SSHORT | Integer data.
> SQL_C_STINYINT | Integer data.
> SQL_C_TIME | Time-formatted data.
> SQL_C_TIMESTAMP | Timestamp formatted data.
> SQL_C_ULONG | Integer data.
> SQL_C_USHORT | Integer data.
> SQL_C_UTINYINT | Integer data.
> SQL_C_DEFAULT | This identifier specifies that data be converted to its default C data type.
> SQL_C_LONG | Integer data.
> SQL_C_SHORT | Integer data.
> SQL_C_TINYINT | Integer data.
> Drivers must support the final three C data type values listed in Table 3.8 from ODBC 1.0. Applications must use these values, rather than the ODBC 2.0 values, when calling an ODBC 1.0 driver. Table 3.9. Values for the pcbValue parameter.
> Identifier | Description
> SQL_NULL_DATA | Specifies that the total number of bytes (excluding the null termination byte for character data) that was returned in the rgbValue parameter.
> SQL_NO_TOTAL | For character data, if pcbValue is greater than or equal to cbValueMax, the data in rgbValue is truncated to cbValueMax – 1 bytes and is null-terminated by the driver.
> SQL_NO_TOTAL | For binary data, if pcbValue is equal to or greater than cbValueMax, the data in rgbValue is truncated to cbValueMax bytes.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_NO_DATA_FOUND | The command didn't find the requested data.
> SQL_STILL_EXECUTING | An asynchronous operation is still pending.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLGetData() function to obtain information about a specific column in a datasource. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLGetFunctions() Prototype:
>     RETCODE SQLGetFunctions(HDBC hdbc, UWORD fFunction, UWORD FAR * pfExists)
> Parameters:
> HDBC hdbc | A handle to an HDBC as returned by the call to the SQLAllocConnect() function.
> UWORD fFunction | Either the constant SQL_API_ALL_FUNCTIONS or a #defined value that will identify the ODBC function for which information is desired.
> UWORD FAR * pfExists | A pointer to a variable that will contain either a pointer to an array (if fFunction is SQL_API_ALL_FUNCTIONS) or the information returned for a specific function.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLGetFunctions() function to obtain information about other SQL...() functions. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. The functions supported are shown in Table 3.10. Table 3.10. SQLGetFunctions() function index.
> Function | Notes
> SQLGetFunctions | Implemented in the driver manager.
> SQLDataSources | Implemented in the driver manager.
> SQLDrivers | Implemented in the driver manager.
> SQL_API_SQLALLOCCONNECT | ODBC core function.
> SQL_API_SQLFETCH | ODBC core function.
> SQL_API_SQLALLOCENV | ODBC core function.
> SQL_API_SQLFREECONNECT | ODBC core function.
> SQL_API_SQLALLOCSTMT | ODBC core function.
> SQL_API_SQLFREEENV | ODBC core function.
> SQL_API_SQLBINDCOL | ODBC core function.
> SQL_API_SQLFREESTMT | ODBC core function.
> SQL_API_SQLCANCEL | ODBC core function.
> SQL_API_SQLGETCURSORNAME | ODBC core function.
> SQL_API_SQLCOLATTRIBUTES | ODBC core function.
> SQL_API_SQLNUMRESULTCOLS | ODBC core function.
> SQL_API_SQLCONNECT | ODBC core function.
> SQL_API_SQLPREPARE | ODBC core function.
> SQL_API_SQLDESCRIBECOL | ODBC core function.
> SQL_API_SQLROWCOUNT | ODBC core function.
> SQL_API_SQLDISCONNECT | ODBC core function.
> SQL_API_SQLSETCURSORNAME | ODBC core function.
> SQL_API_SQLERROR | ODBC core function.
> SQL_API_SQLSETPARAM | ODBC core function.
> SQL_API_SQLEXECDIRECT | ODBC core function.
> SQL_API_SQLTRANSACT | ODBC core function.
> SQL_API_SQLEXECUTE | ODBC core function.
> SQL_API_SQLBINDPARAMETER | For ODBC 1.0 drivers, SQLGetFunctions() will return TRUE if the driver supports SQLSetParam().
> SQL_API_SQLSETPARAM | For ODBC 1.0 drivers, SQLGetFunctions() will return TRUE if the driver supports SQLSetParam().
> SQL_API_SQLSETPARAM | For ODBC 2.0 drivers, SQLGetFunctions() will return TRUE if the driver supports SQLBindParameter().
> SQL_API_SQLBINDPARAMETER | For ODBC 2.0 drivers, SQLGetFunctions() will return TRUE if the driver supports SQLBindParameter().
> SQL_API_SQLBINDPARAMETER | ODBC extension level 1 function.
> SQL_API_SQLGETTYPEINFO | ODBC extension level 1 function.
> SQL_API_SQLCOLUMNS | ODBC extension level 1 function.
> SQL_API_SQLPARAMDATA | ODBC extension level 1 function.
> SQL_API_SQLDRIVERCONNECT | ODBC extension level 1 function.
> SQL_API_SQLPUTDATA | ODBC extension level 1 function.
> SQL_API_SQLGETCONNECTOPTION | ODBC extension level 1 function.
> SQL_API_SQLSETCONNECTOPTION | ODBC extension level 1 function.
> SQL_API_SQLGETDATA | ODBC extension level 1 function.
> SQL_API_SQLSETSTMTOPTION | ODBC extension level 1 function.
> SQL_API_SQLGETFUNCTIONS | ODBC extension level 1 function.
> SQL_API_SQLSPECIALCOLUMNS | ODBC extension level 1 function.
> SQL_API_SQLGETINFO | ODBC extension level 1 function.
> SQL_API_SQLSTATISTICS | ODBC extension level 1 function.
> SQL_API_SQLGETSTMTOPTION | ODBC extension level 1 function.
> SQL_API_SQLTABLES | ODBC extension level 1 function.
> SQL_API_SQLBROWSECONNECT | ODBC extension level 2 function.
> SQL_API_SQLNUMPARAMS | ODBC extension level 2 function.
> SQL_API_SQLCOLUMNPRIVILEGES | ODBC extension level 2 function.
> SQL_API_SQLPARAMOPTIONS | ODBC extension level 2 function.
> SQL_API_SQLDATASOURCES | ODBC extension level 2 function.
> SQL_API_SQLPRIMARYKEYS | ODBC extension level 2 function.
> SQL_API_SQLDESCRIBEPARAM | ODBC extension level 2 function.
> SQL_API_SQLPROCEDURECOLUMNS | ODBC extension level 2 function.
> SQL_API_SQLDRIVERS | ODBC extension level 2 function.
> SQL_API_SQLPROCEDURES | ODBC extension level 2 function.
> SQL_API_SQLEXTENDEDFETCH | ODBC extension level 2 function.
> SQL_API_SQLSETPOS | ODBC extension level 2 function.
> SQL_API_SQLFOREIGNKEYS | ODBC extension level 2 function.
> SQL_API_SQLSETSCROLLOPTIONS | ODBC extension level 2 function.
> SQL_API_SQLMORERESULTS | ODBC extension level 2 function.
> SQL_API_SQLTABLEPRIVILEGES | ODBC extension level 2 function.
> SQL_API_SQLNATIVESQL | ODBC extension level 2 function.
> #### SQLGetInfo() Prototype:
>     RETCODE SQLGetInfo(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,

>     SWORD cbInfoValueMax, SWORD FAR * pcbInfoValue)
> Parameters:
> HDBC hdbc | A handle to an HDBC as returned by the call to the SQLAllocConnect() function.
> UWORD fInfoType | The type of information that is desired. See the ODBC documentation for more information about this parameter.
> PTR rgbInfoValue | A pointer to a buffer used to store the information.
> SWORD cbInfoValueMax | The size of the buffer rgbInfoValue.
> SWORD FAR * pcbInfoValue | A pointer to a variable that will receive the count of the number of bytes stored in rgbInfoValue.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: The SQLGetInfo() function returns a vast array of information about ODBC. Always check the return code from this function for errors. Notes: Refer to the documentation supplied with ODBC and Visual C++ for more information about this function. If this function fails, use the SQLError() function to find out why. #### SQLGetStmtOption() Prototype:
>     RETCODE SQLGetStmtOption(HSTMT hstmt, UWORD fOption, PTR pvParam)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UWORD fOption | Value that indicates which option to retrieve.
> PTR pvParam | A pointer to a buffer that will receive the option's value.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLGetStmtOption() function to retrieve information about the specified statement. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLGetTypeInfo() Prototype:
>     RETCODE SQLGetTypeInfo(HSTMT hstmt, SWORD fSqlType)
> Parameters:
> HSTMT hstmt | Statement handle for the result set.
> SWORD fSqlType | The SQL data type. This must be one of the identifiers from Table 3.11.
> Table 3.11. Valid values for fSqlType parameter.
> Identifier | Description
> SQL_BIGINT | Integer data
> SQL_BINARY | Binary data
> SQL_BIT | Bit-field data
> SQL_CHAR | Character data
> SQL_DATE | Data field
> SQL_DECIMAL | Decimal data
> SQL_DOUBLE | Double data
> SQL_FLOAT | Floating-point data
> SQL_INTEGER | Integer data
> SQL_LONGVARBINARY | Binary data
> SQL_LONGVARCHAR | Variable-length character data
> SQL_NUMERIC | Numeric data
> SQL_REAL | Floating-point data
> SQL_SMALLINT | Integer data
> SQL_TIME | Time data
> SQL_TIMESTAMP | Timestamp data
> SQL_TINYINT | Integer data
> SQL_VARBINARY | Variable-length binary data
> SQL_VARCHAR | Variable-length character data
> SQL_ALL_TYPES | Returns information about all types
> Other | Driver-specific data
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_STILL_EXECUTING | An asynchronous operation is still pending.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLGetTypeInfo() function to return information about a specific data type. Always check the return code from this function for errors. Notes: This functions returns the results as a result set. If this function fails, use the SQLError() function to find out why. #### SQLMoreResults() Prototype:
>     RETCODE SQLMoreResults(HSTMT hstmt)
> Parameter:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_NO_DATA_FOUND | The command didn't find the driver to connect to.
> SQL_STILL_EXECUTING | An asynchronous operation is still pending.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLMoreResults() function to determine whether there are more results available from the SELECT, UPDATE, INSERT, or DELETE SQL statements. If there are more results, SQLMoreResults() will initiate processing for the additional results. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLNativeSql() Prototype:
>     RETCODE SQLNativeSql(HDBC hdbc, UCHAR FAR * szSqlStrIn,

>     SDWORD cbSqlStrIn, UCHAR FAR * szSqlStr, SDWORD cbSqlStrMax,

>     SDWORD FAR * pcbSqlStr)
> Parameters:
> HDBC hdbc | A handle to an HDBC as returned by the SQLAllocConnect() function.
> UCHAR FAR * szSqlStrIn | A pointer to the buffer holding the SQL statement that is to be translated.
> SDWORD cbSqlStrIn | The length of the szSqlStrIn text string.
> UCHAR FAR * szSqlStr | A pointer to a buffer that will hold the translated SQL string.
> SDWORD cbSqlStrMax | The sizeof the szSqlStr buffer.
> SDWORD FAR * pcbSqlStr | The number of bytes stored in szSqlStr. If the translated SQL string is too long to fit in szSqlStr, the translated SQL string in szSqlStr is truncated to cbSqlStrMax – 1 bytes.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLNativeSql() function to translate an SQL string for a native ODBC driver. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLNumParams() Prototype:
>     RETCODE SQLNumParams(HSTMT hstmt, SWORD FAR * pcpar)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> SWORD FAR * pcpar | A pointer to a variable that will hold the number of parameters in the statement.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_STILL_EXECUTING | An asynchronous operation is still pending.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLNumParams() function to get the number of parameters in the SQL statement. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLNumResultCols() Prototype:
>     RETCODE SQLNumResultCols(HSTMT hstmt, SWORD FAR * pccol)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> SWORD FAR * pccol | A pointer to a variable that will hold the number of columns in the result set.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_STILL_EXECUTING | An asynchronous operation is still pending.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLNumResultCols() function to find out how many columns are in the result set. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLParamData() Prototype:
>     RETCODE SQLParamData(HSTMT hstmt, PTR FAR * prgbValue)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> PTR FAR * prgbValue | A pointer to a buffer used to store the results returned by the SQLParamData() function.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_NEED_DATA | The function needs more information to process the request.
> SQL_STILL_EXECUTING | An asynchronous operation is still pending.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLParamData() function with SQLPutData() to supply parameter data at statement execution time. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLParamOptions() Prototype:
>     RETCODE SQLParamOptions(HSTMT hstmt, UWORD crow, UWORD FAR * pirow)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UDWORD crow | The number of values for the parameter. If crow is greater than 1, the rgbValue argument in SQLBindParameter() points to an array of parameter values, and pcbValue points to an array of lengths.
> UDWORD FAR * pirow | A pointer to a buffer used to store the current row number.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLParamOptions() function to specify values for parameters created with SQLBindParameter(). Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLPrepare() Prototype:
>     RETCODE SQLPrepare(HSTMT hstmt, UCHAR FAR * szSqlStr, SDWORD cbSqlStr)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UCHAR FAR * szSqlStr | A pointer to the buffer containing the SQL text string.
> SDWORD cbSqlStr | The length of the string in szSqlStr.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_STILL_EXECUTING | An asynchronous operation is still pending.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLPrepare() function to prepare an SQL string for execution. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLPrimaryKeys() Prototype:
>     RETCODE SQLPrimaryKeys(HSTMT hstmt, UCHAR FAR * szTableQualifier,

>     SWORD cbTableQualifier, UCHAR FAR * szTableOwner, SWORD cbTableOwner,

>     UCHAR FAR * szTableName, SWORD cbTableName)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UCHAR FAR * szTableQualifier | A pointer to a buffer containing the qualifier name.
> SWORD cbTableQualifier | The length of the string in szTableQualifier.
> UCHAR FAR * szTableOwner | A pointer to a buffer containing the table owner.
> SWORD cbTableOwner | The length of the string in szTableOwner.
> UCHAR FAR * szTableName | A pointer to a buffer containing the table name.
> SWORD cbTableName | The length of the string in szTableName.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_STILL_EXECUTING | An asynchronous operation is still pending.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLPrimaryKeys() function to retrieve the column names that comprise the primary key for the specified table. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLProcedureColumns() Prototype:
>     RETCODE SQLProcedureColumns(HSTMT hstmt, UCHAR FAR * szProcQualifier,

>     SWORD cbProcQualifier, UCHAR FAR * szProcOwner, SWORD cbProcOwner,

>     UCHAR FAR * szProcName, SWORD cbProcName, UCHAR FAR * szColumnName,

>     SWORD cbColumnName)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UCHAR FAR * szProcQualifier | A pointer to a buffer containing the procedure qualifier name.
> SWORD cbProcQualifier | The length of the string contained in szProcQualifier.
> UCHAR FAR * szProcOwner | A pointer to a buffer containing the string search pattern for procedure owner names.
> SWORD cbProcOwner | The length of the string contained in szProcOwner.
> UCHAR FAR * szProcName | A pointer to a buffer containing the string search pattern for procedure names.
> SWORD cbProcName | The length of the string in szProcName.
> UCHAR FAR * szColumnName | A pointer to a buffer containing the string search pattern for column names.
> SWORD cbColumnName | The length of the string in szColumnName.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_STILL_EXECUTING | An asynchronous operation is still pending.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLProcedureColumns() function to obtain a list of input and output parameters for the specified procedure. This function will also retrieve the columns that make up the result set for this procedure. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLProcedures() Prototype:
>     RETCODE SQLProcedures(HSTMT hstmt, UCHAR FAR * szProcQualifier,

>     SWORD cbProcQualifier, UCHAR FAR * szProcOwner, SWORD cbProcOwner,

>     UCHAR FAR * szProcName, SWORD cbProcName)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UCHAR FAR * szProcQualifier | A pointer to the buffer that contains the procedure qualifier.
> SWORD cbProcQualifier | The length of the string in szProcQualifier.
> UCHAR FAR * szProcOwner | A pointer to the buffer containing the string search pattern for procedure owner names.
> SWORD cbProcOwner | The length of the string in szProcOwner.
> UCHAR FAR * szProcName | A pointer to the buffer containing the string search pattern for procedure names.
> SWORD cbProcName | The length of the string in szProcName.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_STILL_EXECUTING | An asynchronous operation is still pending.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLProcedures() function to retrieve a list of all the procedure names stored in the specified datasource. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLPutData() Prototype:
>     RETCODE SQLPutData(HSTMT hstmt, PTR rgbValue, SDWORD cbValue)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> PTR rgbValue | A pointer to a buffer used to store the actual data for the parameter or column. The data's type must be a C data type as specified in the SQLBindParameter() or SQLBindCol().
> SDWORD cbValue | The length of the data in rgbValue.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_STILL_EXECUTING | An asynchronous operation is still pending.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLPutData() function to send data for a parameter or column to the driver at execution time. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLRowCount() Prototype:
>     RETCODE SQLRowCount(HSTMT hstmt, SDWORD FAR * pcrow)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> SDWORD FAR * pcrow | A pointer to a variable that will typically hold the number of rows affected by the request, or – 1 if the number of affected rows isn't available.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLRowCount() function to determine how many rows were affected by an UPDATE, DELETE, or INSERT, or by an SQL_UPDATE, SQL_DELETE, or SQL_ADD operation. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLSetConnectOption() Prototype:
>     RETCODE SQLSetConnectOption(HDBC hdbc, UWORD fOption, UDWORD vParam)
> Parameters:
> HDBC hdbc | A handle to an HDBC as returned by the call to the SQLAllocConnect() function.
> UWORD fOption | The option to set. See the ODBC documentation for more details.
> UDWORD vParam | The value to be associated with the option specified in foption.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLSetConnectOption() function to set connection options. Always check the return code from this function for errors. Notes: The SQLSetConnectOption() has many valid parameter values, which are detailed in the ODBC documentation. If this function fails, use the SQLError() function to find out why. #### SQLSetCursorName() Prototype:
>     RETCODE SQLSetCursorName(HSTMT hstmt, UCHAR FAR * szCursor, SWORD cbCursor)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UCHAR FAR * szCursor | A pointer to a buffer containing the cursor name.
> SWORD cbCursor | The length of the string contained in szCursor.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLSetCursorName() function to associate a name with the specified hstmt. Always check the return code from this function for errors. Notes: If your application doesn't set cursor names, the driver will automatically generate default cursor names. If this function fails, use the SQLError() function to find out why. #### SQLSetPos() Prototype:
>     RETCODE SQLSetPos(HSTMT hstmt, UWORD irow, UWORD fOption, UWORD fLock)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UWORD irow | Indicates the position of the row in the rowset on which to perform the operation specified. If 0, the operation is applied to every row in the rowset.
> UWORD fOption | The operation to perform: SQL_POSITION, SQL_REFRESH, SQL_UPDATE, SQL_DELETE, or SQL_ADD.
> UWORD fLock | Tells how the row is to be locked after the operation has been performed. Values include SQL_LOCK_NO_CHANGE, SQL_LOCK_EXCLUSIVE, and SQL_LOCK_UNLOCK.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_NEED_DATA | The function needs more information to process the request.
> SQL_STILL_EXECUTING | An asynchronous operation is still pending.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLSetPos() function to set the cursor position in a result set. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLSetScrollOptions() Prototype:
>     RETCODE SQLSetScrollOptions(HSTMT hstmt, UWORD fConcurrency,

>     UWORD crowKeyset, UWORD crowRowset)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UWORD fConcurrency | Parameter to specify the cursor's concurrence. Valid values are listed in Table 3.12.
> UWORD crowKeyset | Specifies the number of rows for which to buffer keys. Either greater than or equal to crowRowset, or must be one of the following: SQL_SCROLL_FORWARD_ONLY, SQL_SCROLL_STATIC, SQL_SCROLL_KEYSET_DRIVEN, or SQL_SCROLL_DYNAMIC.
> UWORD crowRowset | Specifies the number of rows in a rowset. The crowRowset parameter defines the number of rows that will be fetched by each call to SQLExtendedFetch() and the number of rows that the application buffers.
> Table 3.12. fConcurrency values.
> Identifier | Description
> SQL_CONCUR_READ_ONLY | The cursor is read-only.
> SQL_CONCUR_LOCK | The cursor uses the lowest level of locking sufficient to ensure that the row can be updated.
> SQL_CONCUR_ROWVER | The cursor uses optimistic concurrency control.
> SQL_CONCUR_VALUES | The cursor uses optimistic concurrency control.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: The SQLSetScrollOptions() function should be used only with ODBC 1.x drivers. For ODBC 2, use SQLSetStmtOption(). Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLSetStmtOption() Prototype:
>     RETCODE SQLSetStmtOption(HSTMT hstmt, UWORD fOption, UDWORD vParam)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UWORD fOption | Specifies the option that is to be set. Valid options include SQL_ASYNC_ENABLE, SQL_BIND_TYPE, SQL_CONCURENCY, SQL_CURSOR_TYPE, SQL_KEYSET_SIZE, SQL_MAX_LENGTH, SQL_MAX_ROWS, SQL_NOSCAN, SQL_QUERY_TIMEOUT, SQL_RETRIEVE_DATA, SQL_ROWSET_SIZE, SQL_SIMULATE_CURSOR, and SQL_USE_BOOKMARKS.
> UDWORD vParam | The value to which the option is to be set.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLSetStmtOption() function to set statement options. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLSpecialColumns() Prototype:
>     RETCODE SQLSpecialColumns(HSTMT hstmt, UWORD fColType,

>     UCHAR FAR * szTableQualifier, SWORD cbTableQualifier,

>     UCHAR FAR * szTableOwner, SWORD cbTableOwner,

>     UCHAR FAR * szTableName, SWORD cbTableName,

>     UWORD fScope, UWORD fNullable)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UWORD fColType | Specifies the type of column to return. Must be either SQL_BEST_ROWID or SQL_ROWVER.
> UCHAR FAR * szTableQualifier | A pointer to a buffer containing the qualifier name for the table.
> SWORD cbTableQualifier | The length of the string in szTableQualifier.
> UCHAR FAR * szTableOwner | A pointer to a buffer containing the owner name for the table.
> SWORD cbTableOwner | The length of the string in szTableOwner.
> UCHAR FAR * szTableName | A pointer to a buffer containing the table name.
> SWORD cbTableName | The length of the string in szTableName.
> UWORD fScope | The minimum required scope of the row ID.
> UWORD fNullable | Specifies when to return special columns that can have a NULL value.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_STILL_EXECUTING | An asynchronous operation is still pending.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLSpecialColumns() function to retrieve information about the optimal set of columns that will uniquely identify a row in a table, or columns that are automatically updated when a value in the row has been updated by transactions. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLStatistics() Prototype:
>     RETCODE SQLStatistics(HSTMT hstmt, UCHAR FAR * szTableQualifier,

>     SWORD cbTableQualifier, UCHAR FAR * szTableOwner, SWORD cbTableOwner,

>     UCHAR FAR * szTableName, SWORD cbTableName, UWORD fUnique, UWORD fAccuracy)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UCHAR FAR * szTableQualifier | A pointer to a buffer containing the qualifier name.
> SWORD cbTableQualifier | The length of the string in szTableQualifier.
> UCHAR FAR * szTableOwner | A pointer to a buffer containing the owner name.
> SWORD cbTableOwner | The length of the string in szTableOwner.
> UCHAR FAR * szTableName | A pointer to a buffer containing the table name.
> SWORD cbTableName | The length of the string in szTableName.
> UWORD fUnique | Indicates the index type; either SQL_INDEX_UNIQUE or SQL_INDEX_ALL.
> UWORD fAccuracy | Specifies the importance of the CARDINALITY and PAGES columns in the result set. Use SQL_ENSURE to request that the driver retrieve the statistics unconditionally. Use SQL_QUICK to request that the driver retrieve results only if they are readily available from the server.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_STILL_EXECUTING | An asynchronous operation is still pending.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLStatistics() function to retrieve a list of statistics regarding a specified single table. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLTablePrivileges() Prototype:
>     RETCODE SQLTablePrivileges(HSTMT hstmt,

>     UCHAR FAR * szTableQualifier, SWORD cbTableQualifier,

>     UCHAR FAR * szTableOwner, SWORD cbTableOwner,

>     UCHAR FAR * szTableName, SWORD cbTableName)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UCHAR FAR * szTableQualifier | A pointer to a buffer containing the table qualifier.
> SWORD cbTableQualifier | The length of the string in szTableQualifier.
> UCHAR FAR * szTableOwner | A pointer to a buffer containing the string search pattern for owner names.
> SWORD cbTableOwner | The length of the string in szTableOwner.
> UCHAR FAR * szTableName | A pointer to a string search pattern for table names.
> SWORD cbTableName | The length of the string in szTableName.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_STILL_EXECUTING | An asynchronous operation is still pending.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLTablePrivileges() function to return a list of tables and privileges for each table in the list. Always check the return code from this function for errors. Notes: The SQLTablePrivileges() function returns the results in the form of a result set. If this function fails, use the SQLError() function to find out why. #### SQLTables() Prototype:
>     RETCODE SQLTables(HSTMT hstmt,

>     UCHAR FAR * szTableQualifier, SWORD cbTableQualifier,

>     UCHAR FAR * szTableOwner, SWORD cbTableOwner,

>     UCHAR FAR * szTableName, SWORD cbTableName,

>     UCHAR FAR * szTableType, SWORD cbTableType)
> Parameters:
> HSTMT hstmt | A statement handle returned by the call to SQLAllocStmt().
> UCHAR FAR * szTableQualifier | A pointer to a buffer containing the qualifier name.
> SWORD cbTableQualifier | The length of the string in szTableQualifier.
> UCHAR FAR * szTableOwner | A pointer to a buffer containing the string search pattern for owner names.
> SWORD cbTableOwner | The length of the string in szTableOwner.
> UCHAR FAR * szTableName | A pointer to a buffer containing the string search pattern for table names.
> SWORD cbTableName | The length of the string in szTableName.
> UCHAR FAR * szTableType | A pointer to a buffer containing a list of table types to match.
> SWORD cbTableType | The length of the string in szTableType.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_STILL_EXECUTING | An asynchronous operation is still pending.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLTables() function to obtain a list of tables in the datasource. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. #### SQLTransact() Prototype:
>     RETCODE SQLTransact(HENV henv, HDBC hdbc, UWORD fType)
> Parameters:
> HENV henv | A handle to an HENV as returned by the call to the SQLAllocEnv() function.
> HDBC hdbc | A handle to an HDBC as returned by the call to the SQLAllocConnect() function.
> UWORD fType | Either SQL_COMMIT or SQL_ROLLBACK.
> Return Value: This function will return one of the following values:
> SQL_SUCCESS | The function was successful.
> SQL_SUCCESS_WITH_INFO | The function was successful, and more information is available.
> SQL_ERROR | The function failed. Call SQLError() to get more information about the specific failure.
> SLQ_INVALID_HANDLE | The function failed. The handle that was passed wasn't a valid handle. Possibly, the function that created the handle had failed and didn't return a valid handle.
> If this function fails, your SQL function should end or the error should be corrected; the function should then be re-executed. Usage: Call the SQLTransact() function to commit or rollback the transaction. Always check the return code from this function for errors. Notes: If this function fails, use the SQLError() function to find out why. ### Using the SQL...() Functions In the first part of this chapter, you learned about the library of SQL...() functions. These functions are usable in both C and C++ applications. However, it's possible to write a set of wrapper functions around some of the more commonly used sets of SQL...() commands. The second part of this chapter shows how to use the SQL...() functions and presents a few useful functions (which t can be called from both C and C++ programs) that use these functions. #### Using a Datasource The first example is a simple function that accesses a table, determines what columns are in the accessed table, and then fetches data from the datasource. Although this routine is a simple implementation, it can form the basis of a number of useful applications. First, look at the sequence of operation in accessing an SQL datasource. Unlike most other statements, the SQL...() statements require a rather fixed sequence of execution. You simply can't call the SQLExecute() function without first setting up the SQL environment. The most basic part of any data access application is the initialization of the SQL environment. Listing 3.1 shows a simple function that initializes the ODBC SQL environment. This function gets the names of the columns in the datasource that the user selects and then fetches the first four columns in this datasource. The routine would be better if it were to check to make sure that there were more than four columns in the datasource. I also have coded checks for errors, but I didn't call error handlers in this example. A later example shows a simple error handler routine that can be used by most ODBC functions to display information to the developer and the user. Listing 3.1. INITODBC.C: A simple function that initializes the ODBC SQL environment.
>     //  INITODBC.C

>     #include "windows.h"

>     #include "odbcmisc.h"

>     #include "sql.h"

>     #include "sqlext.h"

>     #include <stdio.h>

>     #include <stdlib.h>

>     #include <string.h>

>     #include <ctype.h>

>     /******************************************************************************

>     **

>     **      TITLE: ODBC1.c

>     **

>     **   FUNCTION: Open DataBase Connectivity interface code

>     **

>     **     INPUTS: VARIOUS

>     **

>     **    OUTPUTS: VARIOUS

>     **

>     **    RETURNS: YES

>     **

>     **      CALLS: ODBC routines: SQL...()

>     **

>     **     AUTHOR: Peter D. Hipson

>     **

>     **   COPYRIGHT 1995 BY PETER D. HIPSON, All rights reserved.

>     **

>     ******************************************************************************/

>     // Static, for this module only:

>     // Routines:

>     void SimpleODBC(HWND hWnd)

>     {

>     #define STR_LEN 128+1

>     #define REM_LEN 254+1

>     /* Declare storage locations for result set data */

>     UCHAR  szQualifier[STR_LEN], szOwner[STR_LEN];

>     UCHAR  szTableName[STR_LEN], szColName[STR_LEN];

>     UCHAR  szTypeName[STR_LEN], szRemarks[REM_LEN];

>     SDWORD Precision, Length;

>     SWORD  DataType, Scale, Radix, Nullable;

>     /* Declare storage locations for bytes available to return */

>     SDWORD cbQualifier, cbOwner, cbTableName, cbColName;

>     SDWORD cbTypeName, cbRemarks, cbDataType, cbPrecision;

>     SDWORD cbLength, cbScale, cbRadix, cbNullable;

>     char    szSource[60];

>     char    szDirectory[132];

>     char    szTable[60];

>     //      Keep above, delete below...

>     char    szDSN[256];

>     char    szConStrOut[256];

>     char    szBuffer[513];

>     char    szColumn1[128];

>     char    szColumn2[128];

>     char    szColumn3[128];

>     char    szColumn4[128];

>     int             i;

>     int        j;

>     HENV    henv;

>     HDBC    hdbc;

>     HSTMT    hstmt = SQL_NULL_HSTMT;

>     RETCODE RC;

>     int             nConStrOut;

>     SDWORD  sdReturn;

>     SWORD    swReturn;

>     //  Keep this line:

>         szSource[0] = '\0';

>         szTable[0] = '\0';

>         szDirectory[0] = '\0';

>     //  The GetODBC() function returns the ODBC source

>     //  table and directory that the user selects.

>         GetODBC(

>             szSource, sizeof(szSource),

>             szTable, sizeof(szTable),

>             szDirectory, sizeof(szDirectory));

>         SQLAllocEnv(&henv);

>         SQLAllocConnect(henv, &hdbc);

>         RC = SQLDriverConnect(hdbc, hWnd,

>             (unsigned char far *)szDSN, SQL_NTS,

>             (unsigned char far *)szConStrOut, sizeof(szConStrOut),

>             (short far *)&nConStrOut, SQL_DRIVER_COMPLETE);

>         if (RC != SQL_SUCCESS && RC != SQL_SUCCESS_WITH_INFO)

>         {// Call whatever error handler your application uses

>         }

>         else

>         {// Connect was successful. Just continue in most cases

>         }

>         RC = SQLAllocStmt(hdbc, &hstmt);

>         if (RC != SQL_SUCCESS && RC != SQL_SUCCESS_WITH_INFO)

>         {// Could not allocate the statement! Call an error handler:

>         }

>     //  Get the DBMS version string. Just for our information, it is not used.

>         SQLGetInfo(hdbc, SQL_DBMS_VER, szConStrOut,

>             sizeof(szConStrOut), &swReturn);

>     //  Get the columns in the specified table:

>         RC = SQLColumns(hstmt,

>             NULL, 0,    // All qualifiers

>             NULL, 0,    // All owners

>             szTable, SQL_NTS,       // The table!

>             NULL, 0);       // All columns

>         if (RC != SQL_SUCCESS && RC != SQL_SUCCESS_WITH_INFO)

>         {// Could not determine columns! Call an error handler:

>         }

>     //    Now bind variables to columns!

>         SQLBindCol(hstmt, 1,  SQL_C_CHAR,   szQualifier, STR_LEN,&cbQualifier);

>         SQLBindCol(hstmt, 2,  SQL_C_CHAR,   szOwner, STR_LEN, &cbOwner);

>         SQLBindCol(hstmt, 3,  SQL_C_CHAR,   szTableName, STR_LEN,&cbTableName);

>         SQLBindCol(hstmt, 4,  SQL_C_CHAR,   szColName, STR_LEN, &cbColName);

>         SQLBindCol(hstmt, 5,  SQL_C_SSHORT, &DataType, 0, &cbDataType);

>         SQLBindCol(hstmt, 6,  SQL_C_CHAR,   szTypeName, STR_LEN, &cbTypeName);

>         SQLBindCol(hstmt, 7,  SQL_C_SLONG,  &Precision, 0, &cbPrecision);

>         SQLBindCol(hstmt, 8,  SQL_C_SLONG,  &Length, 0, &cbLength);

>         SQLBindCol(hstmt, 9,  SQL_C_SSHORT, &Scale, 0, &cbScale);

>         SQLBindCol(hstmt, 10, SQL_C_SSHORT, &Radix, 0, &cbRadix);

>         SQLBindCol(hstmt, 11, SQL_C_SSHORT, &Nullable, 0, &cbNullable);

>         SQLBindCol(hstmt, 12, SQL_C_CHAR,   szRemarks, REM_LEN, &cbRemarks);

>     // Then get the column names:

>         while(TRUE)

>         {// Do till we break out:

>             RC = SQLFetch(hstmt);

>             if (RC == SQL_NO_DATA_FOUND)

>             {// Fetch done; got last column...

>                     break;

>             }

>             if (RC != SQL_SUCCESS && RC != SQL_SUCCESS_WITH_INFO)

>             {// Fetch failed; may (or may not) be fatal!

>                     break;

>             }

>             if (RC == SQL_SUCCESS || RC == SQL_SUCCESS_WITH_INFO)

>             {// Fetch was OK; display the results:

>                 sprintf(szBuffer,

>                     "%20.20s %10.10s %15.15s %15.15s %10.10s %10.10s \n",

>                     szQualifier,

>                     szOwner,

>                     szColName,

>                     szTableName,

>                     szTypeName,

>                     szRemarks);

>                 OutputDebugString(szBuffer);

>             }

>         }

>         SQLFreeStmt(hstmt, SQL_CLOSE);

>         SQLFreeStmt(hstmt, SQL_UNBIND);

>     //  END: Get the columns in the specified table:

>     //  Get data from the table:

>         strcpy(szConStrOut,

>             "SELECT * FROM \"");

>         strcat(szConStrOut, szTable);

>         strcat(szConStrOut, "\" ");

>         RC = SQLExecDirect(hstmt, (unsigned char far *)szConStrOut, SQL_NTS);

>         if (RC != SQL_SUCCESS && RC != SQL_SUCCESS_WITH_INFO)

>         {// Something is wrong; error message, and then DIE!

>         }

>         else

>         {// Bind to whichever columns in result set are needed:

>             SQLBindCol(hstmt, 1, SQL_C_CHAR, (unsigned char far *)szColumn1,

>                 sizeof(szColumn1), &sdReturn);

>             SQLBindCol(hstmt, 2, SQL_C_CHAR, (unsigned char far *)szColumn2,

>                 sizeof(szColumn2), &sdReturn);

>             SQLBindCol(hstmt, 3, SQL_C_CHAR, (unsigned char far *)szColumn3,

>                 sizeof(szColumn3), &sdReturn);

>             SQLBindCol(hstmt, 4, SQL_C_CHAR, (unsigned char far *)szColumn4,

>                 sizeof(szColumn4), &sdReturn);

>     //      In our example, we will simply get up to 100 rows from the dataset:

>             i = 0;

>             j = 0;

>             while(++j < 100)

>             {// j is the number of rows

>                 RC = SQLFetch(hstmt);

>                 if (RC == SQL_ERROR || RC == SQL_SUCCESS_WITH_INFO)

>                 {// There was a problem!

>                 }

>                 if (RC == SQL_SUCCESS || RC == SQL_SUCCESS_WITH_INFO)

>                 {// Now we have our row's data! Use it (like write a report?)

>                     sprintf(szBuffer, "1 '%15.15s' 2 '%15.15s' "

>                         "3 '%15.15s' 4 '%15.15s' 5 '%d' \n",

>                         szQualifier, szOwner, szColName, szTypeName, i);

>                     OutputDebugString(szBuffer);

>                 }

>                 else

>                 {// That's all, folks... No more data here!

>                     break;

>                 }

>             }

>         }

>         SQLFreeStmt(hstmt, SQL_DROP);

>         SQLDisconnect(hdbc);

>         SQLFreeConnect(hdbc);

>         SQLFreeEnv(henv);

>     }
> Take a look at the SimpleODBC() function. First, the following code fragment shows what is necessary to initialize the ODBC system.
>         SQLAllocEnv(&henv);

>         SQLAllocConnect(henv, &hdbc);

>         RC = SQLDriverConnect(hdbc, hWnd,

>             (unsigned char far *)szDSN, SQL_NTS,

>             (unsigned char far *)szConStrOut, sizeof(szConStrOut),

>             (short far *)&nConStrOut, SQL_DRIVER_COMPLETE);

>         if (RC != SQL_SUCCESS && RC != SQL_SUCCESS_WITH_INFO)

>         {// Call whatever error handler your application uses

>         }

>         else

>         {// Connect was successful. Just continue in most cases

>         }

>         RC = SQLAllocStmt(hdbc, &hstmt);
> Notice how a call is made to SQLAllocEnv() and then a call is made to SQLAllocConnect(). These two calls (which must be made in the order shown) initialize the ODBC environment and allocate the memory necessary for the connection handle. After this setup is performed, it's then possible to connect the actual database to the application. This is done with a call to the SQLDriverConnect() function. This function takes, as arguments, information to let ODBC locate the datasource and the HDBC handle to connect to. After the database has been connected, you need to open a statement handle. This statement handle is used to let the application issue SQL commands to the datasource. At this point, the datasource is truly connected to the application, and the application is able to obtain both information about the datasource and information from the datasource. In the sample program, the next step performed is to obtain information about the table that was opened. SQLColumns() is called to obtain information about each column in the datasource. SQLColumns() returned results are part of a result set. A result set is simply a set of "records" that the application is able to retrieve, either one at a time or in blocks.
>         RC = SQLColumns(hstmt,

>             NULL, 0,    // All qualifiers

>             NULL, 0,    // All owners

>             szTable, SQL_NTS,       // The table!

>             NULL, 0);       // All columns

>         if (RC != SQL_SUCCESS && RC != SQL_SUCCESS_WITH_INFO)

>         {// Could not determine columns! Call an error handler:

>         }

>     //    Now bind variables to columns!

>         SQLBindCol(hstmt, 1,  SQL_C_CHAR,   szQualifier, STR_LEN,&cbQualifier);

>         SQLBindCol(hstmt, 2,  SQL_C_CHAR,   szOwner, STR_LEN, &cbOwner);

>         SQLBindCol(hstmt, 3,  SQL_C_CHAR,   szTableName, STR_LEN,&cbTableName);

>         SQLBindCol(hstmt, 4,  SQL_C_CHAR,   szColName, STR_LEN, &cbColName);

>         SQLBindCol(hstmt, 5,  SQL_C_SSHORT, &DataType, 0, &cbDataType);

>         SQLBindCol(hstmt, 6,  SQL_C_CHAR,   szTypeName, STR_LEN, &cbTypeName);

>         SQLBindCol(hstmt, 7,  SQL_C_SLONG,  &Precision, 0, &cbPrecision);

>         SQLBindCol(hstmt, 8,  SQL_C_SLONG,  &Length, 0, &cbLength);

>         SQLBindCol(hstmt, 9,  SQL_C_SSHORT, &Scale, 0, &cbScale);

>         SQLBindCol(hstmt, 10, SQL_C_SSHORT, &Radix, 0, &cbRadix);

>         SQLBindCol(hstmt, 11, SQL_C_SSHORT, &Nullable, 0, &cbNullable);

>         SQLBindCol(hstmt, 12, SQL_C_CHAR,   szRemarks, REM_LEN, &cbRemarks);
> In the preceding code fragment, first the SQLColumns() function is called. Then you must bind variables in the application to the columns in the result set that SQLColumns() returns. In this example, you will look at all the columns; however, many applications may need to use only a few of the result set columns (such as getting the name of the column and the column's data type).
>     // Then get the column names:

>         while(TRUE)

>         {// Do till we break out:

>             RC = SQLFetch(hstmt);

>             if (RC == SQL_SUCCESS || RC == SQL_SUCCESS_WITH_INFO)

>             {// Fetch was OK; display the results:

>                 sprintf(szBuffer,

>                     "%20.20s %10.10s %15.15s %15.15s %10.10s %10.10s \n",

>                     szQualifier,

>                     szOwner,

>                     szColName,

>                     szTableName,

>                     szTypeName,

>                     szRemarks);

>                 OutputDebugString(szBuffer);

>             }

>         }

>         SQLFreeStmt(hstmt, SQL_CLOSE);

>         SQLFreeStmt(hstmt, SQL_UNBIND);
> This code fragment shows how to get the actual records from the result set. The process, done in a while() loop, is simple and easy to program. A call to SQLFetch() at the beginning of the loop is followed by whatever code is necessary to process the information that SQLFetch() returns. The column names could be added to a list box to let the user select a specific column. After the records from the result set have been processed, you need to discard the result set. You do this by using calls to SQLFreeStmt(), as the following code fragment shows. Notice that you needed to call SQLFreeStmt() two times with different arguments:
>     SQLFreeStmt(hstmt, SQL_CLOSE);

>     SQLFreeStmt(hstmt, SQL_UNBIND);
> The first call to SQLFreeStmt() closed the statement handle. The second call was used to actually tell ODBC to discard the result set's contents and release the memory that the result set occupied. To obtain information from a table in a datasource, you must actually issue an SQL command to fetch the desired records. This chapter won't try to detail SQL commands; SQL commands are covered in Chapter 5, "Learning Structured Query Language."
>     //  Get data from the table:

>         strcpy(szConStrOut,

>             "SELECT * FROM \"");

>         strcat(szConStrOut, szTable);

>         strcat(szConStrOut, "\" ");

>         RC = SQLExecDirect(hstmt, (unsigned char far *)szConStrOut, SQL_NTS);
> This example simply creates an SQL statement SELECT * FROM and appends the table name. You need to make sure that the table name is quoted in this example; however, the rules on quoting a name are based on whether the name contains embedded spaces or not. Later in this chapter, you will see an example of a function that quotes names when quotes are needed. Like SQLColumns(), SQLExecDirect() returns the results of the SQL statement as a result set. This result set contains the records from the datasource that the SQL statement has selected (usually limited using a WHERE clause). Because the example simply gets all columns in the datasource, you must either know in advance (perhaps a database was created) or determine (using a call to SQLColumns()) what columns have been included in the result set. Whenever a result set has been returned by an SQL...() function, you must bind variables in your application to the columns in the result set. The SQLFetch() function will place in these variables the data from the current row.
>             SQLBindCol(hstmt, 1, SQL_C_CHAR, (unsigned char far *)szColumn1,

>                 sizeof(szColumn1), &sdReturn);

>             SQLBindCol(hstmt, 2, SQL_C_CHAR, (unsigned char far *)szColumn2,

>                 sizeof(szColumn2), &sdReturn);

>             SQLBindCol(hstmt, 3, SQL_C_CHAR, (unsigned char far *)szColumn3,

>                 sizeof(szColumn3), &sdReturn);

>             SQLBindCol(hstmt, 4, SQL_C_CHAR, (unsigned char far *)szColumn4,

>                 sizeof(szColumn4), &sdReturn);
> In this example, four columns are bound in the result set. If there are columns in the result set that your application doesn't need, you don't have to bind variables to any columns that you don't want. You can always bind a character variable to a column, and the SQL...() routines will convert the column's data to a character-based format. However, the default conversion for numeric data might not be formatted the way you want. After variables have been bound to columns, the next step is to actually fetch the rows from the result set. These rows are fetched with either SQLFetch() or SQLExtendedFetch(). In the following example, SQLFetch() is called to get the data from the result set.
>             while(TRUE)

>             {

>                 RC = SQLFetch(hstmt);

>                 if (RC == SQL_ERROR || RC == SQL_SUCCESS_WITH_INFO)

>                 {// There was a problem!

>                 }

>                 if (RC == SQL_SUCCESS || RC == SQL_SUCCESS_WITH_INFO)

>                 {// Now we have our row's data! Use it (like write a report?)

>                 }

>                 else

>                 {// That's all, folks... No more data here!

>                     break;

>                 }

>             }

>         }
> The preceding code shows a simple while() loop; the first line in the loop is a call to SQLFetch(). After SQLFetch() completes successfully, you can use the data (which in this example is stored in the variables szBuffer1, szBuffer2, szBuffer3, and szBuffer4). After the results of the result set have been processed by the application and the application is finished with the entire datasource, the statement handle should be discarded, as shown next. It's also necessary to disconnect from the datasource, free the connection handle, and then free the environment handle. These calls are done in the opposite order than when they were created, at the beginning of the sample function.
>         SQLFreeStmt(hstmt, SQL_DROP);

>         SQLDisconnect(hdbc);

>         SQLFreeConnect(hdbc);

>         SQLFreeEnv(henv);
> #### Handling Errors in SQL...() Statements When calls to SQL...() statements are made, the function will return a return code that should always be examined by the application to determine whether the function was successful or not. When a function fails, the application must determine what failed and, if possible, correct this failure with a minimum amount of interruption to the user's workflow. Except for the most disastrous failures, the application should try to recover without user interaction if possible. When the error problem is so serious that recovery is impossible, the application must notify the user and explain the problem. Don't put a message like Error 0x1003 occurred, program ending in your application. This type of message went out with the 8088. Make sure that the error message provides as much information as possible to assist the user in correcting the problem. For example, Could not open database C:\MSOffice\Access\Samples\NorthWind.MDB, please check and make sure that the database is in this directory is a better message to give to the user. Regardless of how your application "talks" to the user, the SQLError() function will let your application obtain information about the failure. The function shown in Listing 3.2 is an error function that will use the SQLError() function's return values to format an error message. Listing 3.2. SQLERROR.C: An error handler.
>     //  SQLError.C

>     #include "windows.h"

>     #include "resource.h"

>     #include "odbcmisc.h"

>     #include "sql.h"

>     #include "sqlext.h"

>     #include <stdio.h>

>     #include <stdlib.h>

>     #include <string.h>

>     #include <ctype.h>

>     /******************************************************************************

>     **

>     **      TITLE: SQLError.c

>     **

>     **   FUNCTION: Open DataBase Connectivity interface code

>     **

>     **     INPUTS: VARIOUS

>     **

>     **    OUTPUTS: VARIOUS

>     **

>     **    RETURNS: YES

>     **

>     **      CALLS: ODBC routines: SQL...()

>     **

>     **     AUTHOR: Peter D. Hipson

>     **

>     **   COPYRIGHT 1995 BY PETER D. HIPSON, All rights reserved.

>     **

>     ******************************************************************************/

>     // Static, for this module only:

>     // Routines:

>     // A typical SQL type query:

>     void    SQLPrintError(HENV henv, HDBC hdbc, HSTMT hstmt)

>     {

>     RETCODE RC;

>     char    szSqlState[256];

>     char    szErrorMsg[256];

>     char    szMessage[256];

>     SDWORD     pfNativeError;

>     SWORD    pcbErrorMsg;

>         RC = SQLError(henv, hdbc, hstmt,

>             szSqlState,

>             &pfNativeError,

>             szErrorMsg,

>             sizeof(szErrorMsg),

>             &pcbErrorMsg);

>         if (RC == SQL_SUCCESS || RC == SQL_SUCCESS_WITH_INFO)

>         {

>             sprintf(szMessage, "SQL State = '%s', \nMessage = '%s'",

>                 szSqlState, szErrorMsg);

>             MessageBox(NULL, szMessage, "ODBC Error...", MB_OK);

>         }

>         else

>         {

>             MessageBox(NULL, "SQLError() returned an error!!!",

>                 "ODBC Error...", MB_OK);

>         }

>     }
> The SQLPrintError() function shown in Listing 3.2 really isn't that user-friendly. It displays a cryptic message about SQL states and messages without telling the user exactly what went wrong and what to do about the failure. A better example of an SQLPrintError() function would be a function that actually parsed the error condition returned by SQLError() and then offered both the reason and possible corrective actions. A hot link to WinHelp with a help file that contained more detailed information about both the failure and possible corrective action wouldn't be out of order. Of course, adding a help button would require writing a custom replacement for MessageBox(); however, that wouldn't be too difficult if you used the Visual C++ resource editor. #### Quoting Names When an SQL statement is built in a string, it's necessary to quote some names. Any name that contains embedded blanks must be quoted (column names often have embedded blanks, as in 'Zip Code'). The function QuoteName() shown in Listing 3.3 is a function that will quote a string if the string contains a character that isn't a letter, number, or an underscore. This function takes two parameters: a pointer to a buffer containing the string and the size of the buffer. This size parameter isn't the length of the string but the size of the memory allocated to the buffer. The size is needed so that the function can determine whether there is enough room to add the two quote characters to the string. Listing 3.3. QUOTES.C: Puts quotes around a string.
>     //  QUOTES.C

>     #include "windows.h"

>     #include "resource.h"

>     #include "odbcmisc.h"

>     #include "sql.h"

>     #include "sqlext.h"

>     #include <stdio.h>

>     #include <stdlib.h>

>     #include <string.h>

>     #include <ctype.h>

>     /******************************************************************************

>     **

>     **      TITLE: Quotes.c

>     **

>     **   FUNCTION: Open DataBase Connectivity interface code

>     **

>     **     INPUTS: VARIOUS

>     **

>     **    OUTPUTS: VARIOUS

>     **

>     **    RETURNS: YES

>     **

>     **      CALLS: ODBC routines: SQL...()

>     **

>     **     AUTHOR: Peter D. Hipson

>     **

>     **   COPYRIGHT 1995 BY PETER D. HIPSON, All rights reserved.

>     **

>     ******************************************************************************/

>     // Static, for this module only:

>     // Routines:

>     BOOL QuoteName(

>      char * szName,

>      int    nMaxLength)

>     {

>     // This function will enclose, in quotes, an SQL name if it contains

>     // a character that is not alphabetic, numeric, or an underscore

>     int i;

>     BOOL bMustQuote = FALSE;

>         for (i = 0; i < (int)strlen(szName); i++)

>         {

>             if(!__iscsym(szName[i]))

>             {

>                  bMustQuote = TRUE;

>             }

>         }

>         if (bMustQuote)

>         {//     Had a special character!

>              if((int)strlen(szName) + 2 > nMaxLength)

>               {//     Error: No room for quotes!

>                    bMustQuote = FALSE;

>               }

>               else

>               {//     Quote this string...

>                    memmove(&szName[1], &szName[0], strlen(szName) + 1);

>                    szName[0] = '"';

>                    strcat(szName, "\"");

>               }

>         }

>         return(bMustQuote);

>     }
> Calling QuoteName() makes it easy to pass correct SQL commands because if a name that must be quoted doesn't have quotes, the SQL command will fail. #### Getting the Datasource from the User It's necessary to get the datasource name from the user. You can do this by using a simple set of C++ functions (which are callable from C code). The final part of this section shows the GetODBC() function that is called to get the datasource and table names. This code is written in two parts. The first part is the main calling routine, GetODBC(), which is in the file GETODBC.CPP. This file is shown in Listing 3.4. Listing 3.4. GETODBC.CPP: The GetODBC() function.
>     //  GETODBC.CPP

>     #include "stdafx.h"

>     #include <afxdb.h>

>     // Include *YOUR* application header here (instead of application.h):

>     #include "application.h"

>     #include "odbcmisc.h"

>     #include "sql.h"

>     #include "sqlext.h"

>     #include <stdio.h>

>     #include <stdlib.h>

>     #include <string.h>

>     #include <commdlg.h>

>     #include "odbctabl.h"

>     #include "odbcinfo.h"

>     /******************************************************************************

>     **

>     **      TITLE: GETODBC.CPP - Database Developer's Guide with Visual C++

>     **

>     **   FUNCTION: Open DataBase Connectivity interface code

>     **

>     **     INPUTS: VARIOUS

>     **

>     **    OUTPUTS: VARIOUS

>     **

>     **    RETURNS: YES

>     **

>     **    WRITTEN: 1 February 1995

>     **

>     **      CALLS: ODBC routines: SQL...()

>     **

>     **  CALLED BY: Things that need data from databases

>     **

>     **     AUTHOR: Peter D. Hipson

>     **

>     **   COPYRIGHT 1995 BY PETER D. HIPSON, All rights reserved.

>     **

>     ******************************************************************************/

>     // Static, for this module only:

>     // Functions (may be shared):

>     // Shared data objects, not otherwise allocated:

>     // Routines:

>     BOOL GetODBC(

>         char * szDataSource,

>         int    nDataSourceSize,

>         char * szDataTable,

>         int    nDataTableSize,

>         char * szDataDir,

>         int    nDataDirSize)

>     {

>     BOOL        bReturnCode = TRUE;

>         ODBCInfo    COdbcInfo;

>         if (szDataSource)

>             szDataSource[0] = '\0';

>         if (szDataTable)

>             szDataTable[0] = '\0';

>         if (szDataDir)

>             szDataDir[0] = '\0';

>         bReturnCode = COdbcInfo.GetInfo();

>     //    A little debugging output for the programmer!

>         TRACE("At the GetODBC() end: return %d Datasource "

>         "'%s' table '%s' datadir '%s'\n",

>             bReturnCode,

>             (const char *)COdbcInfo.m_DataSourceName,

>             (const char *)COdbcInfo.m_DataTableName,

>             (const char *)COdbcInfo.m_DataTableDir);

>         if (bReturnCode && szDataSource != NULL)

>         {// User wants the datasource name

>             if (COdbcInfo.m_DataSourceName.GetLength() < nDataSourceSize)

>             {

>                 strcpy(szDataSource, COdbcInfo.m_DataSourceName);

>             }

>             else

>             {

>                 szDataSource[0] = '\0';

>                 bReturnCode = FALSE;

>             }

>         }

>         if (bReturnCode && szDataTable != NULL)

>         {// User wants the datatable name

>             if (COdbcInfo.m_DataTableName.GetLength() < nDataTableSize)

>             {

>                 strcpy(szDataTable, COdbcInfo.m_DataTableName);

>             }

>             else

>             {

>                 szDataTable[0] = '\0';

>                 bReturnCode = FALSE;

>             }

>         }

>         if (bReturnCode && szDataDir != NULL)

>         {// User wants the datatable directory name

>             if (COdbcInfo.m_DataTableDir.GetLength() < nDataTableSize)

>             {

>                 strcpy(szDataDir, COdbcInfo.m_DataTableDir);

>             }

>             else

>             {

>                 szDataDir[0] = '\0';

>                 bReturnCode = FALSE;

>             }

>         }

>     //  Finally, return either success or failure.

>         return(bReturnCode);

>     }
> The GetODBC() function creates an object of class ODBCInfo. This class is in the file ODBCINFO.CPP, which is shown in Listing 3.5. Notice that even though a C++ class is used, the CDatabase class is used in this function. This is because CDatabase offers integrated functionality to the program. This functionality could also have been incorporated by using the SQL...() functions if desired. Listing 3.5. ODBCINFO.CPP: Get ODBC datasource information.
>     //  ODBCINFO.CPP

>     #include "stdafx.h"

>     // After stdafx.h, include the application's main .H file.

>     // The application's resources must have the IDD_SELECT_ODBC_TABLE dialog

>     // defined! (save ODBC.RC, and copy using the resource editor and clipboard)

>     #include "APPLICATION.h"

>     #include <afxdb.h>

>     #include "sql.h"

>     #include "sqlext.h"

>     #include "odbcinfo.h"

>     #include <stdio.h>

>     #include <stdlib.h>

>     #include <string.h>

>     #include <commdlg.h>

>     #include "odbctabl.h"

>     /******************************************************************************

>     **

>     **      TITLE: ODBCINFO.CPP

>     **

>     **   FUNCTION: Open DataBase Connectivity interface code

>     **

>     **     INPUTS: VARIOUS

>     **

>     **    OUTPUTS: VARIOUS

>     **

>     **    RETURNS: YES

>     **

>     **    WRITTEN: 1 February 1995

>     **

>     **      CALLS: ODBC routines: SQL...()

>     **

>     **  CALLED BY: Things that need data from databases

>     **

>     **     AUTHOR: Peter D. Hipson

>     **

>     **      NOTES: Win 3.11 & later.

>     **

>     **   COPYRIGHT 1995 BY PETER D. HIPSON, All rights reserved.

>     **

>     ******************************************************************************/

>     // Static, for this module only:

>     // Shared data objects, not otherwise allocated:

>     // Routines:

>     // Construction

>     ODBCInfo::ODBCInfo()

>     {// Initialize variables, etc.

>     //  This sets the default table types that

>     //  will be displayed. To not display a table type at

>     //  startup time, change the appropriate variable to FALSE.

>         m_Synonyms = TRUE;

>         m_SystemTables = TRUE;

>         m_Tables = TRUE;

>         m_Views = TRUE;

>     }

>     BOOL ODBCInfo::GetInfo()

>     {

>     HSTMT        hstmt = SQL_NULL_HSTMT;

>     char        szConStrOut[256];

>     SWORD        swReturn;

>     CString        CDBType;

>     RETCODE        RC;

>     int            nReturnCode = TRUE;

>         TRY

>         {

>             if (!m_CDodbc.Open(m_TableInfo))

>             {//    User selected Cancel. Go home. No more playing for 'im.

>                 return(FALSE);

>             }

>         }

>         CATCH(CDBException, e)

>         {// User probably hit Return w/o selecting datasource! Msg and return!

>             return FALSE;

>         }

>         END_CATCH

>         m_DatabaseName = m_CDodbc.GetDatabaseName();

>         m_Connect = m_CDodbc.GetConnect();

>         m_CanUpdate = m_CDodbc.CanUpdate();

>         m_CanTransact = m_CDodbc.CanTransact();

>     //    C++'s MFC CRecordSet() class is a bit too unflexible to

>     //        really work well with an undefined database.

>     //        Therefore, we simply break into the older API (SQL...()) calls

>         RC = SQLGetInfo(m_CDodbc.m_hdbc, SQL_DATA_SOURCE_NAME, szConStrOut,

>             sizeof(szConStrOut), &swReturn);

>         m_DataSourceName = szConStrOut;

>     // Lines below are simply for debugging (nice to see what happened):

>     //

>     //      TRACE("Datasoure: '%s'\n", m_DataSourceName);

>     //

>     //      SQLGetInfo(m_CDodbc.m_hdbc, SQL_DRIVER_NAME, szConStrOut,

>     //             sizeof(szConStrOut), &swReturn);

>     //      TRACE("Driver Name %s\n", szConStrOut);

>     //

>     //      SQLGetInfo(m_CDodbc.m_hdbc, SQL_DRIVER_VER, szConStrOut,

>     //             sizeof(szConStrOut), &swReturn);

>     //      TRACE("Driver Version %s\n", szConStrOut);

>     //

>     //      SQLGetInfo(m_CDodbc.m_hdbc, SQL_ODBC_VER, szConStrOut,

>     //             sizeof(szConStrOut), &swReturn);

>     //      TRACE("ODBC Version %s\n", szConStrOut);

>     //

>     //      SQLGetInfo(m_CDodbc.m_hdbc, SQL_SERVER_NAME, szConStrOut,

>     //             sizeof(szConStrOut), &swReturn);

>     //      TRACE("Server Name %s\n", szConStrOut);

>     //

>     //      SQLGetInfo(m_CDodbc.m_hdbc, SQL_DATABASE_NAME, szConStrOut,

>     //             sizeof(szConStrOut), &swReturn);

>     //      TRACE("Database Name %s\n", szConStrOut);

>     //

>     //      SQLGetInfo(m_CDodbc.m_hdbc, SQL_DBMS_VER, szConStrOut,

>     //          sizeof(szConStrOut), &swReturn);

>     //      TRACE("DBMS Version %s\n", szConStrOut);

>     //    Once a datasource is provided, we need to get the TABLE that

>     //    the user will want. If the datasource is a text file,

>     //    we use a CFileDialog object (with modifications...)

>         SQLGetInfo(m_CDodbc.m_hdbc, SQL_DBMS_NAME, szConStrOut,

>             sizeof(szConStrOut), &swReturn);

>         CDBType = szConStrOut;

>         if (CDBType == "TEXT")

>         {// Data type is text. Use common dialog support to open file.

>         //  This code will break under Windows 95's new Explorer system,

>         //  which does not support common dialog template modifications

>         //  in the same manner as Windows 3.x and Windows NT! It forces

>         //  usage of "old style" dialog box!

>             CString Filter;

>             Filter =

>                 "CSV Files (*.csv)|*.csv|"

>                 "TAB Files (*.tab)|*.tab|"

>                 "Text Files (*.txt)|*.txt|"

>                 "Data Files (*.dat)|*.dat||";

>             CFileDialog dlg(TRUE, "txt", NULL, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY,

>                 (const char *)Filter);

>     //        Patch to use our dialog box template:

>             dlg.m_ofn.hInstance = AfxGetInstanceHandle();

>             dlg.m_ofn.lpTemplateName = MAKEINTRESOURCE(TABLESELECT);

>             dlg.m_ofn.Flags |= OFN_ENABLETEMPLATE;

>             if (dlg.DoModal() == IDOK)

>             {

>                 m_DataTableName = dlg.GetPathName();

>                 int nPosition = m_DataTableName.ReverseFind('\\');

>                 if (nPosition > 0)

>                 {

>                     m_DataTableDir = m_DataTableName.Left(nPosition);

>                     m_DataTableName = m_DataTableName.Mid(nPosition + 1);

>                 }

>             }

>             else

>             {

>                 nReturnCode = FALSE;

>             }

>         }

>         else

>         {// Data type is not text; possibly Access, dBASE, or FoxPro

>         //  (but could be others)

>             OdbcTabl OTDlg;

>             OTDlg.m_Synonyms = m_Synonyms;

>             OTDlg.m_SystemTables = m_SystemTables;

>             OTDlg.m_Tables = m_Tables;

>             OTDlg.m_Views = m_Views;

>             OTDlg.m_CDB = &m_CDodbc;

>             if (OTDlg.DoModal() == IDOK)

>             {

>                 m_DataTableName = OTDlg.m_TableName;

>             }

>             else

>             {

>                 nReturnCode = FALSE;

>             }

>         }

>     //    Finally, a successful return

>         return(nReturnCode);

>     }

>     void    ODBCInfo::PrintError(HENV henv, HDBC hdbc, HSTMT hstmt)

>     {// Private, programmer's error handler. Outputs to the debugging

>     //  terminal and doesn't use a message box!

>     RETCODE RC;

>     char    szSqlState[256];

>     char    szErrorMsg[256];

>     SDWORD     pfNativeError;

>     SWORD    pcbErrorMsg;

>         RC = SQLError(

>             henv,

>             hdbc,

>             hstmt,

>             (UCHAR FAR*)szSqlState,

>             &pfNativeError,

>             (UCHAR FAR*)szErrorMsg,

>             sizeof(szErrorMsg),

>             &pcbErrorMsg);

>         TRACE("SQL ERROR:\n");

>         if (RC == SQL_SUCCESS || RC == SQL_SUCCESS_WITH_INFO)

>         {

>             TRACE("%s\n", szSqlState);

>             TRACE("%s\n", szErrorMsg);

>         }

>         else

>         {

>             TRACE("%s\n", "SQLError() returned an error!!!");

>         }

>     }
> The ODBCInfo class shows a number of features. First, there is a call to the CDatabase::Open() function to open a datasource. Then you must prompt the user to select a table in the datasource. The call to the CDatabase::Open() function is followed by a number of other CDatabase member function calls, as the following edited code fragment shows:
>         m_CDodbc.Open(m_TableInfo

>         m_DatabaseName = m_CDodbc.GetDatabaseName();

>         m_Connect = m_CDodbc.GetConnect();

>         m_CanUpdate = m_CDodbc.CanUpdate();

>         m_CanTransact = m_CDodbc.CanTransact();

>         RC = SQLGetInfo(m_CDodbc.m_hdbc, SQL_DATA_SOURCE_NAME, szConStrOut,

>             sizeof(szConStrOut), &swReturn);

>         m_DataSourceName = szConStrOut

>         SQLGetInfo(m_CDodbc.m_hdbc, SQL_DBMS_NAME, szConStrOut,

>             sizeof(szConStrOut), &swReturn);

>     ;
> This example shows the call to Open() and then calls to get the database name and the connect string and finds out whether the database can be updated (not all datasources are updatable) and whether the database supports transactions. You also get the datasource name and the DBMS name. After you have the database, you must determine which table in the database the user is working with. Again, this type of information is individual to each application: perhaps there will be a number of predefined tables that will be used, or perhaps the user may have to be prompted to supply information about the table. In my example, I present either a custom dialog box of class OdbcTabl (for databases that aren't text-based) or I use the CFileDialog MFC class, with a custom template, to select which text file the user will be using for the table. The sample function actually has two dialog box templates (see ODBC.RC, included on this book's CD, and Figure 3.1). The ODBCTABL.CPP file is shown in Listing 3.6. This class uses calls to the SQL...() functions to manage the gathering of information about tables in the specified datasource. Figure 3.1. Dialog boxes for ODBCTABL. Listing 3.6. ODBCTABL.CPP: Dialog box allowing users to select a table.
>     // odbctabl.cpp : implementation file

>     //

>     #include "stdafx.h"

>     #include <afxdb.h>

>     // After stdafx.h, include the application's main .H file.

>     // The application's resources must have the IDD_SELECT_ODBC_TABLE dialog

>     // defined! (save ODBC.RC, and copy using the editor)

>     #include "sql.h"

>     #include "sqlext.h"

>     #include "odbctabl.h"

>     #ifdef _DEBUG

>     #undef THIS_FILE

>     static char BASED_CODE THIS_FILE[] = __FILE__;

>     #endif

>     /////////////////////////////////////////////////////////////////////////////

>     // OdbcTabl dialog

>     OdbcTabl::OdbcTabl(CWnd* pParent /*=NULL*/)

>         : CDialog(OdbcTabl::IDD, pParent)

>     {

>         //{{AFX_DATA_INIT(OdbcTabl)

>         m_Synonyms = FALSE;

>         m_SystemTables = FALSE;

>         m_Tables = FALSE;

>         m_Views = FALSE;

>         //}}AFX_DATA_INIT

>     }

>     void OdbcTabl::DoDataExchange(CDataExchange* pDX)

>     {

>         CDialog::DoDataExchange(pDX);

>         //{{AFX_DATA_MAP(OdbcTabl)

>         DDX_Control(pDX, IDC_SYNONYMS, m_CSynonyms);

>         DDX_Control(pDX, IDC_VIEWS, m_CViews);

>         DDX_Control(pDX, IDC_TABLES, m_CTables);

>         DDX_Control(pDX, IDC_SYSTEM_TABLES, m_CSystemTables);

>         DDX_Control(pDX, IDC_LIST1, m_TableList);

>         DDX_Check(pDX, IDC_SYNONYMS, m_Synonyms);

>         DDX_Check(pDX, IDC_SYSTEM_TABLES, m_SystemTables);

>         DDX_Check(pDX, IDC_TABLES, m_Tables);

>         DDX_Check(pDX, IDC_VIEWS, m_Views);

>         //}}AFX_DATA_MAP

>     }

>     BEGIN_MESSAGE_MAP(OdbcTabl, CDialog)

>         //{{AFX_MSG_MAP(OdbcTabl)

>         ON_BN_CLICKED(IDC_SYNONYMS, OnSynonyms)

>         ON_BN_CLICKED(IDC_SYSTEM_TABLES, OnSystemTables)

>         ON_BN_CLICKED(IDC_TABLES, OnTables)

>         ON_BN_CLICKED(IDC_VIEWS, OnViews)

>         //}}AFX_MSG_MAP

>     END_MESSAGE_MAP()

>     /////////////////////////////////////////////////////////////////////////////

>     // OdbcTabl message handlers

>     BOOL OdbcTabl::OnInitDialog()

>     {

>         CDialog::OnInitDialog();

>         m_TableList.SetTabStops(75);

>          LoadTableList();

>         return TRUE;  // Return TRUE  unless you set the focus to a control

>     }

>     void OdbcTabl::LoadTableList()

>     {

>     HSTMT    hstmt = SQL_NULL_HSTMT;

>     long    lReturnLength;

>     int        i;

>     SWORD    swReturn;

>     RETCODE    RC;

>     char    szQualifier[128];

>     char    szOwner[128];

>     char    szName[128];

>     char    szType[128];

>     char    szConStrOut[256];

>     char    szRemarks[254];

>         RC = SQLAllocStmt(m_CDB->m_hdbc, &hstmt);

>         if (RC != SQL_SUCCESS && RC != SQL_SUCCESS_WITH_INFO)

>         {

>             TRACE("SQLAllocStmt() FAILED!!!!\n");

>             PrintError(SQL_NULL_HENV, m_CDB->m_hdbc, hstmt);

>         }

>         RC = SQLTables (hstmt,

>             (unsigned char far *)"%", SQL_NTS, (unsigned char far *)"", 0,

>             (unsigned char far *)"", 0, (unsigned char far *)"", 0);

>         SQLFreeStmt(hstmt, SQL_CLOSE);

>         SQLFreeStmt(hstmt, SQL_UNBIND);

>         SQLGetInfo(m_CDB->m_hdbc, SQL_MAX_OWNER_NAME_LEN,

>            &i, sizeof(int), &swReturn);

>         szRemarks[0] = '\0';

>         if (m_CTables.GetCheck() == 1)

>         {

>             strcat(szRemarks, "'TABLE'");

>         }

>         if (m_CSystemTables.GetCheck() == 1)

>         {

>             if (strlen(szRemarks) > 0)

>                 strcat(szRemarks, ", ");

>             strcat(szRemarks, "'SYSTEM TABLE'");

>         }

>         if (m_CViews.GetCheck() == 1)

>         {

>             if (strlen(szRemarks) > 0)

>                 strcat(szRemarks, ", ");

>             strcat(szRemarks, "'VIEW'");

>         }

>         if (m_CSynonyms.GetCheck() == 1)

>         {

>             if (strlen(szRemarks) > 0)

>                 strcat(szRemarks, ", ");

>             strcat(szRemarks, "'SYNONYM'");

>         }

>         RC = SQLTables(hstmt,

>             NULL, SQL_NTS,    // Table qualifier

>             NULL, SQL_NTS,    // Table owner

>             NULL, SQL_NTS,    // Table name

>             (unsigned char far *)szRemarks, strlen(szRemarks));

>         if (RC != SQL_SUCCESS && RC != SQL_SUCCESS_WITH_INFO)

>         {

>             PrintError(SQL_NULL_HENV, m_CDB->m_hdbc, hstmt);

>         }

>         SQLGetInfo(m_CDB->m_hdbc, SQL_DBMS_VER, szConStrOut,

>            sizeof(szConStrOut), &swReturn);

>         TRACE("%s\n", szConStrOut);

>     //    Now bind variables to columns!

>         RC = SQLBindCol(hstmt, 1, SQL_C_CHAR,

>             szQualifier, sizeof(szQualifier), &lReturnLength);

>         RC = SQLBindCol(hstmt, 2, SQL_C_CHAR,

>             szOwner, sizeof(szOwner), &lReturnLength);

>         RC = SQLBindCol(hstmt, 3, SQL_C_CHAR,

>             szName, sizeof(szName), &lReturnLength);

>         RC = SQLBindCol(hstmt, 4, SQL_C_CHAR,

>             szType, sizeof(szType), &lReturnLength);

>         RC = SQLBindCol(hstmt, 5, SQL_C_CHAR,

>             szRemarks, sizeof(szRemarks), &lReturnLength);

>     // Then get the table names:

>         m_TableList.ResetContent();

>         while(TRUE)

>         {

>              RC = SQLFetch(hstmt);

>             if (RC == SQL_ERROR || RC == SQL_SUCCESS_WITH_INFO)

>             {

>                 TRACE("SQLFetch() FAILED!!!!\n");

>                 PrintError(SQL_NULL_HENV, m_CDB->m_hdbc, hstmt);

>             }

>             if (RC == SQL_SUCCESS || RC == SQL_SUCCESS_WITH_INFO)

>             {

>     //             Must set tab stops for this list to look good!

>                 sprintf(szRemarks, "%s\t%s", szType, szName);

>                 m_TableList.AddString(szRemarks);

>             }

>              else

>             {// That's all, folks...

>                 break;

>             }

>         }

>         m_TableList.SetCurSel(0);

>          SQLFreeStmt(hstmt, SQL_CLOSE);

>         SQLFreeStmt(hstmt, SQL_UNBIND);

>         SQLFreeStmt(hstmt, SQL_DROP);

>     }

>     void OdbcTabl::OnSynonyms()

>     {

>         // TODO: Add your control notification handler code here

>          LoadTableList();

>     }

>     void OdbcTabl::OnSystemTables()

>     {

>         // TODO: Add your control notification handler code here

>          LoadTableList();

>     }

>     void OdbcTabl::OnTables()

>     {

>         // TODO: Add your control notification handler code here

>          LoadTableList();

>     }

>     void OdbcTabl::OnViews()

>     {

>         // TODO: Add your control notification handler code here

>          LoadTableList();

>     }

>     void OdbcTabl::OnOK()

>     {

>     CString        TempString;

>         // TODO: Add extra validation here

>         m_TableList.GetText(m_TableList.GetCurSel(), TempString);

>     //    Get everything after the tab...

>         m_TableName    = TempString.Mid(TempString.Find('\t') + 1);

>         CDialog::OnOK();

>     }

>     void    OdbcTabl::PrintError(HENV henv, HDBC hdbc, HSTMT hstmt)

>     {// Private, programmer's error handler. Outputs to the debugging

>     //     terminal and doesn't use a message box!

>     RETCODE RC;

>     char    szSqlState[256];

>     char    szErrorMsg[256];

>     SDWORD     pfNativeError;

>     SWORD    pcbErrorMsg;

>         RC = SQLError(henv, hdbc, hstmt,

>             (UCHAR FAR*)szSqlState,

>             &pfNativeError,

>             (UCHAR FAR*)szErrorMsg,

>             sizeof(szErrorMsg),

>             &pcbErrorMsg);

>         TRACE("SQL ERROR:\n");

>         if (RC == SQL_SUCCESS || RC == SQL_SUCCESS_WITH_INFO)

>         {

>             TRACE("%s\n", szSqlState);

>             TRACE("%s\n", szErrorMsg);

>         }

>         else

>         {

>             TRACE("%s\n", "SQLError() returned an error!!!");

>         }

>     }
### Summary This chapter introduced you to the ODBC SQL...() functions and provided a reference section. A set of sample routines provided practical examples of how to use the SQL...() functions and also showed examples of how to use the MFC database objects that were covered in Chapter 2. This chapter completes Part I of this book. You will create more sophisticated examples of decision support and transaction processing applications when you reach Part III, "An Introduction to Database Front-End Design," and Part IV, "Advanced Programming with Visual C++." The next chapter, "Optimizing the Design of Relational Databases," introduces you to database design methodology and shows you some of the CASE design tools that are available for Access and client-server databases. Contact reference@earthweb.com with questions or comments. Copyright 1998 EarthWeb Inc., All rights reserved. PLEASE READ THE ACCEPTABLE USAGE STATEMENT. Copyright 1998 Macmillan Computer Publishing. All rights reserved. |