/**********************************************************************
* FILENAME : ListProcedureColumns.c
*
* DESCRIPTION :
* Example uses SQLProcedures to return the list of input and
* output parameters, as well as the column details for the
* procedures visible to a datasource.
*
* ODBC USAGE :
* selectDSN() to get data source name
* SQLProcedures() - with statement handle and NULL for SchemaName,
* ProcName and ColumnName. This retrieves all procedure
* names.
* SQLProcedureColumns - for each procedure name returned by
* SQLProcedures, retrieved column names, types and data types.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sql.h>
#include <sqlext.h>
#include <string.h>
#include "util.c"
// Arbitary sizes for char buffs
#define BUFF_SIZE 255
// Arbitary sizes for number of procedures and
#define MAX_PROCS 100
// Declare buffers for result set data
SQLCHAR strProcedureName[BUFF_SIZE];
struct DataBinding {
SQLSMALLINT TargetType;
SQLPOINTER TargetValuePtr;
SQLINTEGER BufferLength;
SQLLEN StrLen_or_Ind;
};
//
// Fill an array of procedure names associated with a datasource
//
SQLRETURN getProcedures (SQLCHAR *procNames[], // procedure names array
SQLLEN *noProcNames, // no of procedures found
SQLCHAR *dsn) { // data source handle
SQLHENV henv = SQL_NULL_HENV; // Environment
SQLHDBC hdbc = SQL_NULL_HDBC; // Connection handle
SQLHSTMT hstmt = SQL_NULL_HSTMT; // Statement handle
SQLRETURN retcode;
SQLCHAR strProcName[BUFF_SIZE];
SQLLEN lenProcName;
char confirm='N';
char reply=' ';
int i;
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
CHECK_ERROR(retcode, "SQLAllocHandle (SQL_HANDLE_ENV)",
henv, SQL_HANDLE_ENV);
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,
(SQLPOINTER*)SQL_OV_ODBC3, 0);
CHECK_ERROR(retcode, "SQLSetEnvAttr (SQL_ATTR_ODBC_VERSION)",
henv, SQL_HANDLE_ENV);
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
CHECK_ERROR(retcode, "SQLAllocHandle (SQL_HANDLE_DBC)",
hdbc, SQL_HANDLE_DBC);
retcode = SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT,
(SQLPOINTER)5, 0);
CHECK_ERROR(retcode, "SQLSetConnectAttr (SQL_LOGIN_TIMEOUT)",
hdbc, SQL_HANDLE_DBC);
retcode = SQLConnect(hdbc, (SQLCHAR*) dsn, SQL_NTS,
(SQLCHAR*) NULL, 0, NULL, 0);
CHECK_ERROR(retcode, "SQLConnect (SQL_HANDLE_DBC)",
hdbc, SQL_HANDLE_DBC);
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
CHECK_ERROR(retcode, "SQLAllocHandle (SQL_HANDLE_STMT)",
hstmt, SQL_HANDLE_STMT);
// Request all procedures
retcode = SQLProcedures (hstmt,
NULL, 0,
NULL, 0,
NULL, 0);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
// Bind Procedure Name column of result set to buffers
retcode = SQLBindCol(hstmt, 3, SQL_C_CHAR, strProcName,
sizeof(strProcName), &lenProcName);
while (SQL_SUCCESS == retcode && i < MAX_PROCS) {
retcode = SQLFetch(hstmt);
CHECK_ERROR(retcode, "SQLFetch (Procedures)",
hstmt, SQL_HANDLE_STMT);
procNames[i]=(char *)malloc((strlen(strProcName)+1)*sizeof(char));
strcpy (procNames[i++], strProcName);
}
*noProcNames=i;
}
exit:
if (hstmt != SQL_NULL_HSTMT)
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
if (hdbc != SQL_NULL_HDBC) {
SQLDisconnect(hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
}
if (henv != SQL_NULL_HENV)
SQLFreeHandle(SQL_HANDLE_ENV, henv);
return retcode;
}
int main () {
SQLHENV henv = SQL_NULL_HENV; // Environment
SQLHDBC hdbc = SQL_NULL_HDBC; // Connection handle
SQLHSTMT hstmt = SQL_NULL_HSTMT; // Statement handle
SQLRETURN retcode;
SQLCHAR *procNames[MAX_PROCS];
SQLLEN noProcNames;
SQLCHAR colName[BUFF_SIZE];
// vars for full result set
SQLCHAR strProcedureCat[BUFF_SIZE];
SQLCHAR strProcedureSchem[BUFF_SIZE];
SQLCHAR strProcedureName[BUFF_SIZE];
SQLCHAR strColumnName[BUFF_SIZE];
SQLSMALLINT ColumnType;
SQLSMALLINT DataType;
SQLCHAR strTypeName[BUFF_SIZE];
SQLLEN ColumnSize;
SQLLEN BufferLength;
SQLLEN DecimalDigits;
SQLSMALLINT NumPrevRadix;
SQLSMALLINT Nullable;
SQLCHAR strRemarks[BUFF_SIZE];
SQLCHAR strColumnDef[BUFF_SIZE];
SQLSMALLINT SQLDataType;
SQLSMALLINT SQLDateTimeSub;
SQLLEN CharOctetLength;
SQLLEN OrdinalPosition;
SQLCHAR strIsNullable[BUFF_SIZE];
// ind/len vars for full result set
SQLLEN lenProcedureCat;
SQLLEN lenProcedureSchem;
SQLLEN lenProcedureName;
SQLLEN lenColumnName;
SQLLEN lenColumnType;
SQLLEN lenDataType;
SQLLEN lenTypeName;
SQLLEN lenColumnSize;
SQLLEN lenBufferLength;
SQLLEN lenDecimalDigits;
SQLLEN lenNumPrevRadix;
SQLLEN lenNullable;
SQLLEN lenRemarks;
SQLLEN lenColumnDef;
SQLLEN lenSQLDataType;
SQLLEN lenSQLDateTimeSub;
SQLLEN lenCharOctetLength;
SQLLEN lenOrdinalPosition;
SQLLEN lenIsNullable;
char procName[BUFF_SIZE];
char dsn[BUFF_SIZE];
char confirm='N';
char reply=' ';
int i, header;
// Allcoate environment handle
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
CHECK_ERROR(retcode, "SQLAllocHandle (SQL_HANDLE_ENV)",
henv, SQL_HANDLE_ENV);
// Set ODBC Version
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,
(SQLPOINTER*)SQL_OV_ODBC3, 0);
CHECK_ERROR(retcode, "SQLSetEnvAttr (SQL_HANDLE_ENV)",
henv, SQL_HANDLE_ENV);
// Prompt for DSN
retcode = selectDSN (henv, dsn, "Select DSN : ");
if (retcode != SQL_SUCCESS) {
printf ("DSN not selected, exiting.");
goto exit;
}
// Allocate connection handle
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
CHECK_ERROR(retcode, "SQLAllocHandle (SQL_HANDLE_DBC)",
hdbc, SQL_HANDLE_DBC);
// Set connection timeout
retcode = SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
CHECK_ERROR(retcode, "SQLSetConnectAttr (SQL_LOGIN_TIMEOUT)",
hdbc, SQL_HANDLE_DBC);
// Connect to DSN
retcode = SQLConnect(hdbc, (SQLCHAR*) dsn, SQL_NTS,
(SQLCHAR*) NULL, 0, NULL, 0);
CHECK_ERROR(retcode, "SQLConnect (dsn)", hdbc, SQL_HANDLE_DBC);
// Allocate statement handle
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
CHECK_ERROR(retcode, "SQLAllocHandle (SQL_HANDLE_STMT)",
hstmt, SQL_HANDLE_STMT);
// Get list of procedure names
retcode = getProcedures (procNames, &noProcNames, dsn);
if (retcode==SQL_SUCCESS) {
for (i=0;i<noProcNames;i++) {
// Get columns associated with each pocedure name
header=0;
retcode = SQLProcedureColumns (hstmt,
NULL, 0,
NULL, 0,
procNames[i], SQL_NTS,
NULL, 0);
CHECK_ERROR(retcode, "SQLProcedureColumns ()",
hstmt, SQL_HANDLE_STMT);
// Bind all 19 columns
SQLBindCol (hstmt, 1, SQL_C_CHAR, strProcedureCat,
sizeof(strProcedureCat), &lenProcedureCat);
SQLBindCol (hstmt, 2, SQL_C_CHAR, strProcedureSchem,
sizeof(strProcedureSchem),&lenProcedureSchem);
SQLBindCol (hstmt, 3, SQL_C_CHAR, strProcedureName,
sizeof(strProcedureName), &lenProcedureName);
SQLBindCol (hstmt, 4, SQL_C_CHAR, strColumnName,
sizeof(strColumnName), &lenColumnName);
SQLBindCol (hstmt, 5, SQL_C_SHORT, &ColumnType,
sizeof(ColumnType), &lenColumnType);
SQLBindCol (hstmt, 6, SQL_C_SHORT, &DataType,
sizeof(DataType), &lenDataType);
SQLBindCol (hstmt, 7, SQL_C_CHAR, strTypeName,
sizeof(strTypeName), &lenTypeName);
SQLBindCol (hstmt, 8, SQL_C_LONG, &ColumnSize,
sizeof(ColumnSize), &lenColumnSize);
SQLBindCol (hstmt, 9, SQL_C_LONG, &BufferLength,
sizeof(BufferLength), &lenBufferLength);
SQLBindCol (hstmt, 10, SQL_C_SHORT, &DecimalDigits,
sizeof(DecimalDigits), &lenDecimalDigits);
SQLBindCol (hstmt, 11, SQL_C_SHORT, &NumPrevRadix,
sizeof(NumPrevRadix), &lenNumPrevRadix);
SQLBindCol (hstmt, 12, SQL_C_SHORT, &Nullable,
sizeof(Nullable), &lenNullable);
SQLBindCol (hstmt, 13, SQL_C_CHAR, strRemarks,
sizeof(strRemarks), &lenRemarks);
SQLBindCol (hstmt, 14, SQL_C_CHAR, strColumnDef,
sizeof(strColumnDef), &lenColumnDef);
SQLBindCol (hstmt, 15, SQL_C_SHORT, &SQLDataType,
sizeof(SQLDataType), &lenSQLDataType);
SQLBindCol (hstmt, 16, SQL_C_SHORT, &SQLDateTimeSub,
sizeof(SQLDateTimeSub), &lenSQLDateTimeSub);
SQLBindCol (hstmt, 17, SQL_C_LONG, &CharOctetLength,
sizeof(CharOctetLength), &lenCharOctetLength);
SQLBindCol (hstmt, 18, SQL_C_LONG, &OrdinalPosition,
sizeof(OrdinalPosition), &lenOrdinalPosition);
SQLBindCol (hstmt, 19, SQL_C_CHAR, strIsNullable,
sizeof(strIsNullable), &lenIsNullable);
// Get column data.
while (retcode == SQL_SUCCESS) {
retcode = SQLFetch(hstmt);
CHECK_ERROR(retcode, "SQLFetch (ProcedureColumns)",
hstmt, SQL_HANDLE_STMT);
if (header++==0) {
printf ("\nProcedure Name : %s\n",strProcedureName);
}
printf (" Column Name : %s\n", strColumnName);
printf (" Column Type : %i\n", ColumnType);
printf (" Data Type : %i\n", DataType);
if (retcode==SQL_NO_DATA && header==1) {
printf ("(NO DATA)\n");
}
}
}
}
printf ("\nThe End.\n");
exit:
if (hstmt != SQL_NULL_HSTMT)
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
if (hdbc != SQL_NULL_HDBC) {
SQLDisconnect(hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
}
if (henv != SQL_NULL_HENV)
SQLFreeHandle(SQL_HANDLE_ENV, henv);
}
Further information