/**********************************************************************
* FILENAME : ListDBTables.c
*
* DESCRIPTION :
* Example illustrates use of SQLTables to show Catalogs, Schemas,
* and Tables
*
* ODBC USAGE :
* SQLGetInfo to get SQL_DATABASE_NAME e.g msdb
* SQL_DBMS_NAME e.g Microsoft SQL Server
* SQL_DBMS_VER e.g 12.00.2000
* SQL_USER_NAME e.g dbo
* SQLTables to get Catalogs
* SQLTables to get Schemas
* SQLTables to get Tables
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <sql.h>
#include <sqlext.h>
#include <string.h>
#include "util.c"
#define NUMCOLS 5
#define BUFFERSIZE 1024
struct DataBinding {
SQLSMALLINT TargetType;
SQLPOINTER TargetValuePtr;
SQLINTEGER BufferLength;
SQLLEN StrLen_or_Ind;
};
int MySQLSuccess(SQLRETURN rc) {
return (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO);
}
void printCatalog(const struct DataBinding* catalogResult) {
// index 0 - Catalog e.g. master, msdb, etc
// index 1 - empty
// index 2 - empty
// index 3 - empty
if (catalogResult[0].StrLen_or_Ind != SQL_NULL_DATA)
printf("Catalog = %s\n", (char *)catalogResult[0].TargetValuePtr);
}
void printSchema(const struct DataBinding* schemaResult) {
// index 0 - empty
// index 1 - Schema Name e.g dbo, sys
// index 2 - empty
// index 3 - empty
if (schemaResult[1].StrLen_or_Ind != SQL_NULL_DATA)
printf("Schema = %s\n", (char *)schemaResult[1].TargetValuePtr);
}
void printTable(const struct DataBinding* tableResult) {
// index 0 - catalog e.q. msdb
// index 1 - schema e.g dbo
// index 2 - table name e.g. TestTBL1
// index 3 - type - e.g. TABLE
if (tableResult[2].StrLen_or_Ind != SQL_NULL_DATA)
printf("Table (%s) = %s\n", (char *)tableResult[1].TargetValuePtr,
(char *)tableResult[2].TargetValuePtr);
}
int main () {
struct DataBinding* catalogResult = (struct DataBinding*)
malloc( NUMCOLS * sizeof(struct DataBinding) );
struct DataBinding* schemaResult = (struct DataBinding*)
malloc( NUMCOLS * sizeof(struct DataBinding) );
struct DataBinding* tableResult = (struct DataBinding*)
malloc( NUMCOLS * sizeof(struct DataBinding) );
SQLCHAR* dbName = (SQLCHAR *)malloc( sizeof(SQLCHAR)*BUFFERSIZE );
SQLCHAR* dbmsName = (SQLCHAR *)malloc( sizeof(SQLCHAR)*BUFFERSIZE );
SQLCHAR* dbmsVerName = (SQLCHAR *)malloc( sizeof(SQLCHAR)*BUFFERSIZE );
SQLCHAR* userName = (SQLCHAR *)malloc( sizeof(SQLCHAR)*BUFFERSIZE );
// Declare and initialise the environment, connection, statement handles
SQLHENV henv = SQL_NULL_HENV; // Environment
SQLHDBC hdbc = SQL_NULL_HDBC; // Connection handle
SQLHSTMT hstmt = SQL_NULL_HSTMT; // Statement handle
SQLRETURN retcode;
SQLCHAR connStrbuffer[1024];
SQLSMALLINT connStrBufferLen, buffSize;
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,
(void*)SQL_OV_ODBC3, -1);
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)10, 0);
CHECK_ERROR(retcode, "SQLSetConnectAttr(SQL_LOGIN_TIMEOUT)",
hdbc, SQL_HANDLE_DBC);
retcode = SQLConnect(hdbc, (SQLCHAR*) "DATASOURCE", SQL_NTS,
(SQLCHAR*) NULL, 0, NULL, 0);
CHECK_ERROR(retcode, "SQLConnect(DATASOURCE)",
hdbc, SQL_HANDLE_DBC);
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
CHECK_ERROR(retcode, "SQLAllocHandle(SQL_HANDLE_STMT)",
hstmt, SQL_HANDLE_STMT);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
// Get database name and user name
retcode = SQLGetInfo(hdbc, SQL_DATABASE_NAME,
dbName, (SQLSMALLINT)1024,
(SQLSMALLINT *)&buffSize);
CHECK_ERROR(retcode, "SQLGetInfo(SQL_DATABASE_NAME)",
hstmt, SQL_HANDLE_STMT);
retcode = SQLGetInfo(hdbc, SQL_DBMS_NAME,
dbmsName, (SQLSMALLINT)1024,
(SQLSMALLINT *)&buffSize);
CHECK_ERROR(retcode, "SQLGetInfo(SQL_DBMS_NAME)",
hstmt, SQL_HANDLE_STMT);
retcode = SQLGetInfo(hdbc, SQL_DBMS_VER,
dbmsVerName, (SQLSMALLINT)1024,
(SQLSMALLINT *)&buffSize);
CHECK_ERROR(retcode, "SQLGetInfo(SQL_DBMS_VER)",
hstmt, SQL_HANDLE_STMT);
retcode = SQLGetInfo(hdbc, SQL_USER_NAME,
userName, (SQLSMALLINT)1024,
(SQLSMALLINT *)&buffSize);
CHECK_ERROR(retcode, "SQLGetInfo(SQL_USER_NAME)",
hstmt, SQL_HANDLE_STMT);
printf ("\nSQL_DATABASE_NAME : %s\n", dbName);
printf ("SQL_DBMS_NAME : %s\n", dbmsName);
printf ("SQL_DBMS_VER : %s\n", dbmsVerName);
printf ("SQL_USER_NAME : %s\n\n", userName);
// Allocate memory for the binding
// Catalogues
for ( i = 0 ; i < NUMCOLS ; i++ ) {
catalogResult[i].TargetType = SQL_C_CHAR;
catalogResult[i].BufferLength = (BUFFERSIZE + 1);
catalogResult[i].TargetValuePtr =
malloc( sizeof(unsigned char)*catalogResult[i].BufferLength );
}
// Schemas
for ( i = 0 ; i < NUMCOLS ; i++ ) {
schemaResult[i].TargetType = SQL_C_CHAR;
schemaResult[i].BufferLength = (BUFFERSIZE + 1);
schemaResult[i].TargetValuePtr =
malloc( sizeof(unsigned char)*schemaResult[i].BufferLength );
}
// Tables
for ( i = 0 ; i < NUMCOLS ; i++ ) {
tableResult[i].TargetType = SQL_C_CHAR;
tableResult[i].BufferLength = (BUFFERSIZE + 1);
tableResult[i].TargetValuePtr =
malloc( sizeof(unsigned char)*tableResult[i].BufferLength );
}
// Setup the binding for catalog
for ( i = 0 ; i < NUMCOLS ; i++ )
retcode = SQLBindCol(hstmt, (SQLUSMALLINT)i + 1,
catalogResult[i].TargetType,
catalogResult[i].TargetValuePtr,
catalogResult[i].BufferLength,
&(catalogResult[i].StrLen_or_Ind));
// All catalogs query
printf( "A list Catalogs : \n" );
retcode = SQLTables( hstmt, (SQLCHAR*)SQL_ALL_CATALOGS,
SQL_NTS, (SQLCHAR*)"", SQL_NTS, (SQLCHAR*)"",
SQL_NTS, (SQLCHAR*)"", SQL_NTS );
for ( retcode = SQLFetch(hstmt) ;
MySQLSuccess(retcode) ;
retcode = SQLFetch(hstmt) ) {
printCatalog( catalogResult );
}
// Set up the binding for schemas
for ( i = 0 ; i < NUMCOLS ; i++ )
retcode = SQLBindCol(hstmt, (SQLUSMALLINT)i + 1,
schemaResult[i].TargetType,
schemaResult[i].TargetValuePtr,
schemaResult[i].BufferLength,
&(schemaResult[i].StrLen_or_Ind));
printf( "A list of Schemas : \n" );
retcode = SQLTables( hstmt, (SQLCHAR*)"", SQL_NTS,
(SQLCHAR*)SQL_ALL_SCHEMAS, SQL_NTS, (SQLCHAR*)"",
SQL_NTS, (SQLCHAR*)"", SQL_NTS );
for ( retcode = SQLFetch(hstmt) ;
MySQLSuccess(retcode) ;
retcode = SQLFetch(hstmt) ) {
printSchema( schemaResult );
}
// Setup the binding for tables
for ( i = 0 ; i < NUMCOLS ; i++ )
retcode = SQLBindCol(hstmt, (SQLUSMALLINT)i + 1,
tableResult[i].TargetType,
tableResult[i].TargetValuePtr,
tableResult[i].BufferLength,
&(tableResult[i].StrLen_or_Ind));
// Ideally, we could loop around to get tables within schemas
// within catalogs, but uses msdb and dbo to illustrate the point...
printf( "A list of Tables : \n" );
retcode = SQLTables( hstmt, (SQLCHAR*)"msdb",
SQL_NTS, (SQLCHAR*)"dbo",
SQL_NTS, (SQLCHAR*)SQL_ALL_TABLE_TYPES,
SQL_NTS, (SQLCHAR*)"'TABLE'", SQL_NTS );
for ( retcode = SQLFetch(hstmt) ;
MySQLSuccess(retcode) ;
retcode = SQLFetch(hstmt) ) {
printTable( tableResult );
}
}
printf ("\nThe End.\n");
exit:
// Free memory
for ( i = 0 ; i < NUMCOLS ; i++ ) {
free (catalogResult[i].TargetValuePtr); // Catalogues
free (schemaResult[i].TargetValuePtr); // Schemas
free (tableResult[i].TargetValuePtr); // Tables
}
printf ("\nComplete.\n");
// Free handles
// Statement
if (hstmt != SQL_NULL_HSTMT)
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
// Connection
if (hdbc != SQL_NULL_HDBC) {
SQLDisconnect(hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
}
// Environment
if (henv != SQL_NULL_HENV)
SQLFreeHandle(SQL_HANDLE_ENV, henv);
return 0;
}
Further information