Previous PageTop Of PageTable Of ContentsNext Page


6. Error Handling and Catalog Functions

6.1 Retrieving Error Information

6.2 Catalog Functions

6.3 Getting System Information


6. Error Handling and Catalog Functions

After reading the previous chapters, you can construct an ODBC program. But what do you do when problems occur while calling ODBC functions? In this chapter you will learn how to get error information when an error occurs. This chapter also introduces some ODBC catalog functions which allow you to get information from the system catalog (system tables). Some other ODBC functions are also covered here, including functions which are used to get system information about the data source, such as supported data types, supported built-in functions, and supported ODBC functions. In this chapter you will learn how to:

get detailed error information when a call to an ODBC function fails by using the SQLError function.

retrieve catalog information such as table schemas and statistics information by using catalog functions such as SQLTables, SQLColumns, SQLStatistics and SQLSpecialColumns.

obtain system information about the data source by using the SQLGetTypeInfo, SQLGetInfo and SQLGetFunctions functions.

Note: You retrieve error information differently using DBMaker 3.5 (ODBC 3.0) from what is described in this chapter. Refer to Appendix E, What's New in DBMaker 3.5 for more information.

6.1 Retrieving Error Information

When an application executes an ODBC function and an error code is returned, it needs detailed error information to determine what caused the error. This section explains how to use the SQLError function to retrieve error information.

Common Error Codes Defined in ODBC

After calling an ODBC function, you may get one of the following return codes:

SQL_SUCCESS - the ODBC function executed successfully.

SQL_SUCCESS_WITH_INFO - the ODBC function executed successfully, but some warning information is being returned.

SQL_NO_DATA_FOUND - no more data can be fetched.

SQL_ERROR - some error has occurred and the function failed.

SQL_INVALID_HANDLE - an invalid handle was detected and the function failed.

SQL_NEED_DATA - the driver found the application must send parameter data values.

If an application calls any ODBC function (except SQLError itself) and the return code is SQL_ERROR or SQL_SUCCESS_WITH_INFO, it can call SQLError to get additional error information.

How to Use SQLError

SQLError is used to get the error information in the input handle, including the error message, error state and the driver's native error code. The driver's native error code is the error code is defined by each driver itself. This may be different for different drivers. (For the native DBMaker error codes, see Appendix C.)

Generally speaking, an application calls SQLError when the error code returned by the previous ODBC function is SQL_ERROR or SQL_SUCCESS_WITH_INFO.

The prototype for SQLError is:

RETCODE  SQLError(
                  HENV        henv,
                  HDBC        hdbc,
                  HSTMT       hstmt,
                  UCHAR  FAR *szSqlState,
                  SDWORD FAR *pfNativeError,
                  UCHAR  FAR *szErrorMsg,
                  SWORD       cbErrorMsgMax,
                  SWORD  FAR *pcbErrorMsg
                 );

Note that the three handles in the argument list of SQLError are not all necessarily passed to SQLError. The ODBC driver will find the associated return code from the rightmost non-null handle, for example, if you pass handles like this:

SQLError(henv, hdbc, hstmt, ....)

then the returned error information is in hstmt. In the following case,

SQLError(SQL_NULL_ENV, hdbc, SQL_NULL_STMT, ...)

the driver will return the error information associated with hdbc. You should ensure the applications pass the proper handles to SQLError so that the error information they need can be retrieved successfully.

If there is no error information to be retrieved, SQLError will return SQL_NO_DATA_FOUND. Each time after SQLError is called and error information is returned, the error information in that handle will be cleared. This means the error information for one ODBC function call can be retrieved only once.

The SQLSTATE values returned from SQLError are defined by the SQL Access Group SQL CAE specification (1992) and X/Open. The values are 5-character strings with a two character class value followed by a three character subclass value. For example, the class value 01 is a warning and the corresponding return code is SQL_SUCCESS_WITH_INFO. To get more detailed information about SQLSTATE values defined in ODBC, refer to the Microsoft ODBC Programmer's Reference .

Here is an example to illustrate the usage of SQLError:

#define  MSG_LEN  256           /* error message buffer length        */


HENV   henv;                    /* environment handle                 */
HDBC   hdbc;                    /* connection handle                  */
HSTMT  hstmt;                   /* statement handle                   */
SDWORD retcode, retcode1;       /* return code                        */
UCHAR  sqlState[6];             /* buffer to store SQLSTATE           */
SDWORD nativeErr;               /* native error code                  */
UCHAR  errMsg[MSG_LEN];         /* buffer to store error message      */
SWORD  realMsgLen;              /* real length of error message       */
retcode = SQLAllocEnv(&henv);
retcode = SQLAllocConnect(&hdbc);
/* Use specified DB_NAME(data source name), uid (user id),            */
/* pwd (password) to connect to a data source.  If any warnings or    */
/* errors are detected, call SQLError and pass hdbc to retrieve       */
/* error information from the connection handle with other handles    */
/* set to NULL.  Then print the error information and return.         */
retcode = SQLConnect(hdbc, DB_NAME, SQL_NTS, uid, SQL_NTS, pwd,
                     SQL_NTS);
if (retcode != SQL_SUCCESS)     /* warning or error returned          */
   {
   retcode1 = SQLError(SQL_NULL_HDBC, hdbc, SQL_NULL_HSTMT, sqlState,
                       &nativeErr, errMsg, MSG_LEN, &realMsgLen);

   print_err(sqlState, nativeErr, errMsg, realMsgLen);

   return;
   }
/* Get SQL command string and execute it.  If any warnings or errors  */
/* are detected, call SQLError and pass hstmt to retrieve error       */
/* information from the statement handle, then print the error        */
/* information and return.                                            */
retcode = execute_cmd(hstmt);   /* execute a SQL command              */
if (retcode != SQL_SUCCESS)     /* warning or error returned          */
   {
   retcode1 = SQLError(SQL_NULL_HDBC, SQL_NULL_HDBC, hstmt, sqlState,
                       &nativeErr, errMsg, MSG_LEN, &realMsgLen);
   print_err(sqlState, nativeErr, errMsg, realMsgLen);
   return;
   }

Example 6-1: Getting error information with SQLError

Error Queues

ODBC allows multiple error codes to be stored in an error queue and associated with one handle. SQLError can be called multiple times to retrieve the error codes one by one. Currently DBMaker will only return multiple errors for DataBase Consistency Checking (DBCC) operations. These errors are stored in the error queue.

An application can call SQLError many times until all the errors in error queue are fetched. Once all errors have been fetched SQLError will return SQL_NO_DATA_FOUND. For example, if an application wants to check the consistency of the account table, the code may look like this:

#define  MSG_LEN  256           /* error message buffer length        */
UCHAR   sqlState[6];            /* buffer to store SQLSTATE           */
SDWORD  nativeErr;              /* native error code                  */
UCHAR   errMsg[MSG_LEN];        /* buffer to store error message      */
SWORD   realMsgLen;             /* real length of error message       */
SWORD   count;
SWORD   retcode;
retcode = SQLExecute(hstmt, "check table account", SQL_NTS);
do
   {
   retcode = SQLError(SQL_NULL_HDBC, hdbc, SQL_NULL_HSTMT, sqlState,
                      &nativeErr, errMsg, MSG_LEN, &realMsgLen);
   if (retcode == SQL_NO_DATA_FOUND)
       {
       printf("check error queue finish \n\n");
       break;
       }
   count++;
   printf("-->Error %d :\n", count);
   printf("   SQLSTATE = %s \n", sqlState);
   printf("   native error = %ld \n", nativeErr);
   printf("   error message = %s \n", errMsg);
   printf("   error message length = %d \n", realMsgLen);
   }

while ((retcode == SQL_SUCCESS) || (retcode == SQL_SUCCESS_WITH_INFO));

Example 6-2: Retrieving error codes from an error queue

6.2 Catalog Functions

There are several system tables in a relational database which record information about tables, columns, privileges on tables, etc. We call these system tables catalogs. When you want to know the schema of tables and indexes in a database, you can look at the catalogs to get the information.

ODBC provides many functions to retrieve catalog information. These functions are called catalog functions. In this section, four commonly used catalog functions: SQLTables, SQLColumns, SQLStatistics, and SQLSpecialColumns will be introduced.

SQLTables - gets a list of table or view names in a database.

SQLColumns - gets column information about specified tables.

SQLStatistics - gets statistics information about tables and the indexes associated with those tables.

SQLSpecialColumns - gets the optimal set of columns that uniquely identifies a row in a table.

All of the catalog functions work in the same manner. You specify what information you want in parameters when calling the catalog functions, and a result set will be returned. Then you can fetch data from the result set.

Search Patterns

Some arguments of the catalog functions accepts search patterns to select the desired object. The simplest search pattern is a character string which is used to match exactly the item you are looking for. In addition you can use wild card metacharacters in a search pattern to do more powerful searches. DBMaker supports the following metacharacters: underscore(_), percent (%) and the escape character (\).

The underscore character (_) is used to match any one character.

The percent character (%) is used to match zero or more characters.

The escape character (\) permits the metacharacters % or _ to be used as literal characters in search patterns. To use the escape character \ as a literal character in search pattern, just include it twice (\\).

For example, if the search pattern for a table name is %A%, the function will return all tables with names that contain the character A. If the search pattern for a table name is _A_, the function will return all tables with names that are three character long with A as the middle character. If the search pattern for a table name is %, the function will return all tables.

If you want to retrieve the information for a table named TAB_TEST, and you use TAB_TEST as the search pattern, then you will also get the information for the tables TAB1TEST, TAB2TEST, etc. in the result set. This is not what you want. To solve this problem put an escape character in front of the metacharacter: TAB\_TEST.

Note: When passing this string through a C compiler, you must specify TAB\\_TEST instead of TAB\_TEST. This is because the C compiler also treats "\" as an escape character. See the following example for SQLTables.

SQLTables: Retrieving Information About Tables or Views

When you connect to a database and want to determine information about all or a particular set of tables, calling SQLTables with the specified criteria will get the answer.

The prototype for SQLTables is:

RETCODE SQLTables (
                   HSTMT  hstmt,
                   UCHAR *szTableQualifier,
                   SWORD  cbTableQualifier,
                   UCHAR *szTableOwner,
                   SWORD  cbTableOwner,
                   UCHAR *szTableName,
                   SWORD  cbTableName,
                   UCHAR *szTableType,
                   SWORD  cbTableType
                  );

The arguments for SQLTables are:

hstmt - a valid statement handle for retrieved results.

szTableQualifier - not supported by DBMaker, and should be NULL or an empty string.

cbTableQualifier - the length of szTableQualifier, and should be zero.

szTableOwner - points to the owner name. The owner is the person who created the table or view. It can be a string to be used as a search pattern or a NULL value. Use a NULL value to indicate all owners.

cbTableOwner - the length of szTableOwner or SQL_NTS.

szTableName - points to the name of tables or views. It can be a string to be used as a search pattern or a NULL value. Use a NULL value to indicate all names.

cbTableName - the length of szTableName or SQL_NTS.

szTableType - the list of table types (TABLE or VIEW or both)

cbTableType - the length of szTableType.

Note: A string to be used as a search pattern can exist in szTableQualifier, szTableOwner and szTableName. These three arguments and their corresponding string length arguments, cbTableQualifier, cbTableOwner and cbTableName also appear in the other three catalog functions: SQLColumns, SQLStatistics and SQLSpecialColumns. (These three functions will be introduced later).

SQLTables returns a result set consisting of the following columns:

Column No.

Column Name

Data Type

1

TABLE_QUALIFIER

VARCHAR(128)

2

TABLE_OWNER

VARCHAR(128)

3

TABLE_NAME

VARCHAR(128)

4

TABLE_TYPE

VARCHAR(128)

5

REMARKS

VARCHAR(254)

Table 6-1: Columns returned in SQLTables result set

SQLTables returns a result set according to the user's criteria. For example, when szTableName is %A% and szTableOwner is _A_, the result set will contain all tables whose names contain the character A and that have owners whose names are three characters long with A as the middle character. If you want to find the names of all tables in the database, you only need to set szTableQualifier, szTableOwner and szTableName to NULL.

In fact, you can regard SQLTables as a form of executing a query by SQLExecDirect. This means you need to use SQLFetch to get the result set. Of course before using SQLFetch, you should use SQLBindCol to bind the columns in the result set.

The following code gives an example for SQLTables. Suppose there are two tables named TAB_TEST1 and TAB_TEST2. After calling SQLTables, you will get information for TAB_TEST1 and TAB_TEST2, ordered by TABLE_TYPE, TABLE_QUALIFIER, TABLE_OWNER and TABLE_NAME:

HDBC  hdbc;
HSTMT hstmt;
UCHAR tabQualifier[255], tabOwner[255], tabName[255],
UCHAR tabType[255], remarks[255];
SDWORD lenTabQualifier, lenTabOwner, lenTableName;
SDWORD lenTableType, lenRemarks;
SDWORD retcode;
...
retcode = SQLAllocStmt(hdbc,&hstmt);
retcode = SQLTables(hstmt,
                   (UCHAR FAR *)NULL, 0,             /* tabQualifier  */
                   (UCHAR FAR *)NULL, 0,             /* tabOwners     */
                   (UCHAR FAR *)"DB\\_%", SQL_NTS,   /* table name    */
                   (UCHAR FAR *)"TABLE", SQL_NTS);   /* table type    */
/* Bind columns in result set to storage locations                    */
retcode = SQLBindCol(hstmt, 1, SQL_C_CHAR, tabQualifier, 255,
                     &lenTabQualifier);
retcode = SQLBindCol(hstmt, 2, SQL_C_CHAR, tabOwner, 255, &lenTabOwner);
retcode = SQLBindCol(hstmt, 3, SQL_C_CHAR, tabName, 255, &lenTableName);
retcode = SQLBindCol(hstmt, 4, SQL_C_CHAR, tabType, 255, &lenTableType);
retcode = SQLBindCol(hstmt, 5, SQL_C_CHAR, remarks, 255, &lenremarks);
/* print out the records in the result set                            */


while ((retcode = SQLFetch(hstmt)) == SQL_SUCCESS)
      {                        
       printf("column 1 : table qualifier = %s\n", tabQualifier);
       printf("column 2 : table owner = %s\n", tabOwner);
       printf("column 3 : table name = %s\n", tabName);
       printf("column 4 : table type = %s\n", tabType);
       printf("column 5 : remarks = %s\n", remarks);
      }
...

Example 6-3: Retrieving table/view information using SQLTables

Note: When a function returns a result set, the user should use SQLBindCol and SQLFetch to get the rows in the result set. SQLTables, SQLColumns, SQLStatistics and SQLSpecialColumns are all such functions.

SQLColumns: Retrieving Information About Columns in Specified Tables

You can use SQLTables to get the names of tables that are in a database. Similarly, you can use the SQLColumns function to get information on the columns found in a particular table.

The prototype for SQLColumns is:

RETCODE SQLColumns (
                    HSTMT  hstmt,
                    UCHAR *szTableQualifier,
                    SWORD  cbTableQualifier,
                    UCHAR *szTableOwner,
                    SWORD  cbTableOwner,
                    UCHAR *szTableName,
                    SWORD  cbTableName,
                    UCHAR *szColumnName,
                    SWORD  cbColumnName
                   );

where szTableQualifier, cbTableQualifier, szTableOwner, cbTableOwner, szTableName and cbTableName are defined the same as for SQLTables. szColumnName points to the search pattern string of the column name. The cbColumnName is the length of szColumnName.

Like the SQLTables function, a result set that matches the criteria in the arguments given above is returned containing the column information. The following table lists the columns of the result set:

Column No.

Column Name

Data Type

Comments

1

TABLE_QUALIFIER

VARCHAR(128)

 

2

TABLE_OWNER

VARCHAR(128)

 

3

TABLE_NAME

VARCHAR(128)

NOT NULL

4

COLUMN_NAME

VARCHAR(128)

NOT NULL

5

DATA_TYPE

SMALLINT

NOT NULL

6

TYPE_NAME

VARCHAR(128)

NOT NULL

7

PRECISION

INTEGER

 

8

LENGTH

INTEGER

 

9

SCALE

SMALLINT

 

10

RADIX

SMALLINT

 

11

NULLABLE

SMALLINT

NOT NULL

12

REMARKS

VARCHAR(254)

 

Table 6-2: Columns returned in SQLColumns result set

The result set is ordered by TABLE_QUALIFIER, TABLE_OWNER and TABLE_NAME. You should use SQLBindCol to bind the columns in the result set and then use SQLFetch to fetch the results.

SQLStatistics

SQLStatistics retrieves a list of statistics about specified table(s) and the indexes associated with those table(s).

The prototype for SQLStatistics is:

RETCODE SQLStatistics (
                       HSTMT  hstmt,
                       UCHAR *szTableQualifier,
                       SWORD  cbTableQualifier,
                       UCHAR *szTableOwner,
                       SWORD  cbTableOwner,
                       UCHAR *szTableName,
                       SWORD  cbTableName,
                       UWORD  fUnique,
                       UWORD  fAccuracy
                      );

where szTableQualifier, cbTableQualifier, szTableOwner, cbTableOwner, szTableName and cbTableName are defined the same as for SQLTables and SQLColumns. fUnique is used to specify the type of index to be returned and fAccuracy is used to specify the importance of the CARDINALITY and PAGES columns in the result set.

Note: fUnique has two options: SQL_INDEX_UNIQUE or SQL_INDEX_ALL. fAccuracy also has two options: SQL_ENSURE or SQL_QUICK.

The following table lists the columns in the result set:

Column No.

Column Name

Data Type

Comments

1

TABLE_QUALIFIER

VARCHAR(128)

 

2

TABLE_OWNER

VARCHAR(128)

 

3

TABLE_NAME

VARCHAR(128)

NOT NULL

4

NON_UNIQUE

SMALLINT

 

5

INDEX_QUALIFIER

VARCHAR(128)

 

6

INDEX_NAME

VARCHAR(128)

 

7

TYPE

SMALLINT

NOT NULL

8

SEQ_IN_INDEX

SMALLINT

 

9

COLUMN_NAME

VARCHAR(128)

 

10

COLLATION

CHAR(1)

 

11

CARDINALITY

INTEGER

 

12

PAGES

INTEGER

 

13

FILTER_CONDITION

VARCHAR(128)

 

Table 6-3: Columns returned in SQLStatistics result set

The TYPE column either has the value SQL_TABLE_STAT or SQL_INDEX_OTHER. SQL_TABLE_STAT indicates the row contains statistics for a table and the NON_UNIQUE, INDEX_QUALIFIER, INDEX_NAME, SEQ_IN_INDEX, COLUMN_NAME, COLLATION and FILTER_CONDITION columns (used for indexes) will be NULL. On the other hand, SQL_INDEX_OTHER indicates the row contains statistics for an index.

Similar to SQLTables and SQLColumns, you need SQLBindCol and SQLFetch to retrieve the data in the result set. The order of the columns in the result set is NON_UNIQUE, TYPE, INDEX_QUALIFIER, INDEX_NAME and SEQ_IN_INDEX. For a code example of a similar function, please refer to the SQLTables code example.

SQLSpecialColumns

As the function name implies, SQLSpecialColumns returns the special columns which could uniquely specify rows in a table.

The prototype for SQLSpecialColumns is:

RETCODE SQLSpecialColumns (
                           HSTMT  hstmt,
                           UWORD  fColType,
                           UCHAR *szTableQualifier,
                           SWORD  cbTableQualifier,
                           UCHAR *szTableOwner,
                           SWORD  cbTableOwner,
                           UCHAR *szTableName,
                           SWORD  cbTableName,
                           UWORD  fScope,
                           UWORD  fNullable
                          );

hstmt is a valid statement handle, szTableQualifier, cbTableQualifier, szTableOwner, cbTableOwner, szTableName, cbTableName are all defined the same as for SQLTables. fColType specifies the type of column to return. fScope is the minimum required scope of the special column. fNullable determines whether to return special columns that can have a NULL value.

Note: fColType has two options: SQL_BEST_ROWID and SQL_ROWVER. fScope has three options: SQL_SCOPE_CURROW, SQL_SCOPE_TRANSACTION and SQL_SCOPE_SESSION. fNullable has two options: SQL_NO_NULLS and SQL_NULLABLE.

The following table lists the columns in the result set:

Column No.

Column Name

Data Type

Comments

1

SCOPE

SMALLINT

 

2

COLLUMN_NAME

VARCHAR(128)

NOT NULL

3

DATA_TYPE

SMALLINT

NOT NULL

4

TYPE_NAME

VARCHAR(128)

NOT NULL

5

PRECISION

INTEGER

 

6

LENGTH

INTEGER

 

7

SCALE

SMALLINT

 

8

PSEUDO_COLUMN

SMALLINT

 

Table 6-4: Columns returned SQLSpecialColumns result set

DBMaker provides a specific row identifier, OID, which is similar to ROWID in Oracle or TID in Ingres. OID is treated as a pseudo-column in a table because a query like SELECT * FROM ACCOUNT will not return such a column name, but you can still use OID in a select list or WHERE clause to fetch the records you want by explicitly specifying it.

Once you specify SQL_BEST_ROWID in fColType, the result set returned by SQLSpecialColumns simply contains a row whose column name is OID. You can use this special column to re-select that row within the defined scope in fScope. And the result of the SELECT statement is guaranteed to have either no rows or one row. For a code example of a similar function, please reference SQLTables.

Note: If the fColType, fScope, or fNullable arguments specify characteristics that are not supported by DBMaker, SQLSpecialColumns returns a rowset with no rows. A subsequent call to SQLFetch or SQLExtendedFetch on the hstmt will return SQL_NO_DATA_FOUND.

6.3 Getting System Information

You can use SQLGetTypeInfo, SQLGetInfo, SQLGetFunctions to get system information about the data source. These ODBC functions are illustrated by examples in the following sections.

SQLGetTypeInfo

You can use SQLGetTypeInfo to get information about data types supported by the data source. The prototype for SQLGetTypeInfo is:

RETCODE SQLGetTypeInfo (
                        HSTMT hstmt,
                        SWORD fSqlType
                       );

When given a value for fSqlType, SQLGetTypeInfo returns the related type information in the result set. You can use SQLBindCol to bind output storage for the result set and use SQLFetch to fetch the results into the output storage. fSqlType can be any SQL data type - SQL_CHAR, SQL_DECIMAL, SQL_INTEGER, etc.

The result set is shown below:

Column No.

Column Name

Data Type

Comments

1

TYPE_NAME

VARCHAR(128)

NOT NULL

2

DATA_TYPE

SMALLINT

NOT NULL

3

PRECISION

INTEGER

 

4

LITERAL_PREFIX

VARCHAR(128)

 

5

LITERAL_SUFFIX

VARCHAR(128)

 

6

CREATE_PARAMS

VARCHAR(128)

 

7

NULLABLE

SMALLINT

NOT NULL

8

CASE_SENSITIVE

SMALLINT

NOT NULL

9

SEARCHABLE

SMALLINT

NOT NULL

10

UNSIGNED_ATTRIBUTE

SMALLINT

 

11

MONEY

SMALLINT

NOT NULL

12

AUTO_INCREMENT

SMALLINT

 

13

LOCAL_TYPE_NAME

VARCHAR(128)

 

14

MINIMUM_SCALE

SMALLINT

 

15

MAXIMUM_SCALE

SMALLINT

 

Table 6-5: Columns returned in SQLGetTypeInfo result set

This example uses SQLGetTypeInfo with SQL_ALL_TYPES as the value of fSqlType to fetch all data types supported by the data source.

UCHAR  name[30, prefix[30], suffix[30], params[30], local_name[30];
SWORD  type, nullable, case_sen, searchable, unsign, money, auto_inc;
SWORD  min_scale, max_scale;
UDWORD prec;
SDWORD len[15], retcode;
/* bind all columns                                                   */
retcode = SQLBindCol(hstmt,  1, SQL_C_CHAR,  name,       30, &len[1]);
retcode = SQLBindCol(hstmt,  2, SQL_C_SHORT, &type,       0, &len[2]);
retcode = SQLBindCol(hstmt,  3, SQL_C_LONG,  &prec,       0, &len[3]);
retcode = SQLBindCol(hstmt,  4, SQL_C_CHAR,  prefix,     30, &len[4]);
retcode = SQLBindCol(hstmt,  5, SQL_C_CHAR,  suffix,     30, &len[5]);
retcode = SQLBindCol(hstmt,  6, SQL_C_CHAR,  params,     30, &len[6]);
retcode = SQLBindCol(hstmt,  7, SQL_C_SHORT, &nullable,   0, &len[7]);
retcode = SQLBindCol(hstmt,  8, SQL_C_SHORT, &case_sen,   0, &len[8]);
retcode = SQLBindCol(hstmt,  9, SQL_C_SHORT, &searchable, 0, &len[9]);
retcode = SQLBindCol(hstmt, 10, SQL_C_SHORT, &unsign,     0, &len[10]);
retcode = SQLBindCol(hstmt, 11, SQL_C_SHORT, &money,      0, &len[11]);
retcode = SQLBindCol(hstmt, 12, SQL_C_SHORT, &auto_inc,   0, &len[12]);
retcode = SQLBindCol(hstmt, 13, SQL_C_CHAR,  local_name, 30, &len[13]);
retcode = SQLBindCol(hstmt, 14, SQL_C_SHORT, &min_scale,  0, &len[14]);
retcode = SQLBindCol(hstmt, 15, SQL_C_SHORT, &max_scale,  0, &len[15]);
/* tell odbc driver to get all type information                       */
printf("tell odbc driver to get all SQL type information \n");
SQLGetTypeInfo(hstmt,SQL_ALL_TYPES);
/ fetch all type information                                          */
do
   {
   retcode = SQLFetch(hstmt);
   switch (retcode)
       {
       case SQL_SUCCESS_WITH_INFO:


       case SQL_SUCCESS:
           print_type_info();   /* print type info such as name,type, */
           break;               /* prec, prefix, ...                  */


       case SQL_NO_DATA_FOUND:
           break;
           default:
               print error
       }
   }
while (retcode != SQL_NO_DATA_FOUND);

Example 6-4: Determining supported data types using SQLGetTypeInfo

SQLGetInfo

You can use SQLGetInfo to get general information about the data source.

The prototype for SQLGetInfo is:

RETCODE SQLGetInfo (
                    HDBC       hdbc,
                    UWORD      fInfoType,
                    PTR        rgbInfoValue,
                    SWORD      cbInfoValueMax,
                    SWORD FAR *pcbInfoValue
                    );

Given a value in fInfoType representing the type of information you want to know, and given the output storage rgbInfoValue and its storage size cbInfoValueMax, SQLGetInfo will return the fetched information in rgbInfoValue and will return the size of the fetched information in pcbInfoValue.

Example

You can use the following codes to decide whether the data source supports the string function CONCAT.

UDWORD  bitmask;
SDWORD  retcode;
retcode = SQLGetInfo(hdbc, SQL_STRING_FUNCTIONS, (PTR) &bitmask,
                     sizeof(bitmask), NULL);
if (bitmask & SQL_FN_STR_CONCAT)
    printf ("the data source supports CONCAT\n");
else
    printf ("the data source does not support CONCAT\n");

Example

If you want to know the maximum number of columns allowed in a table, you can try the following code:

UWORD  maxNCol;
SDWORD retcode;
retcode = SQLGetInfo(hdbc, SQL_MAX_COLUMNS_IN_TABLE, (PTR) &maxNCol,
                     sizeof(maxNCol));
printf ("In this data source, a table can have %d columns at most\n",
        (int) maxNCol );

SQLGetFunctions

You can use SQLGetFunctions to check what ODBC functions the data source supports. The prototype for SQLGetFunctions is:

RETCODE  SQLGetFunctions (
                          HDBC       hdbc,
                          UWORD      fFunction,
                          UWORD FAR *pfExists
                         );

The input argument fFunction specifies the kind of ODBC function. The value of fFunction can be SQL_API_SQLCANCEL, SQL_API_SQLFETCH, SQL_PUTDATA, etc. - SQLCancel, SQLFetch, SQLPutData are all ODBC functions.

For example, you can give SQL_API_SQLCANCEL in fFunction to check whether the data source supports SQLCancel.

After submitting SQLGetFunctions, in order to determine the existence of the ODBC function you can check the Boolean value(s) in pfExists, which is a pointer to a single Boolean value or a list of Boolean values.

Example

You can use the following code to check whether the data source supports SQLExecDirect.

UWORD  fExecDirect;
SDWORD retcode;
retcode = SQLGetFunctions (hdbc, SQL_API_SQLEXECDIRECT, &fExecDirect);
if (fExecDirect)
   printf ("the data source supports SQLExecDirect\n");
else
   printf ("the data source does not support SQLExecDirect\n");

Example

You can use the following code to check whether the data source supports SQLTables.

UWORD  fExecDirect;
SDWORD retcode;
retcode = SQLGetFunctions (hdbc, SQL_API_SQLTABLES, &fExecDirect);
if (fExecDirect)
   printf ("the data source supports SQLExecDirect\n");
else
   printf ("the data source does not support SQLExecDirect\n");

Previous PageTop Of PageTable Of ContentsNext Page

Copyright 2002 SYSCOM Computer Engineering Co. All rights reserved.