/*******************************************************************************
**                                                                        
** Source File Name = tbconstr.c                                       
**                                                                        
** Licensed Materials - Property of IBM                                   
**                                                                        
** (C) COPYRIGHT International Business Machines Corp. 1995, 2000
** All Rights Reserved.                                                   
**                                                                        
** US Government Users Restricted Rights - Use, duplication or            
** disclosure restricted by GSA ADP Schedule Contract with IBM Corp.      
**                                                                        
**                                                                        
**    PURPOSE :                                                           
**    Shows how to work with constraints associated with tables.
**                                                                        
** For more information about these samples see the README file.
**
** For more information on programming in CLI see the:
**     - "Building CLI Applications" section of the Application Building Guide, and the
**     - CLI Guide and Reference.
**
** For more information on the SQL language see the SQL Reference.
**
*******************************************************************************/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sqlcli1.h>
#include "utilcli.h"          /* Header file for CLI sample code */

int CnDefine( SQLHANDLE) ;
int CnListPrimaryKeys( SQLHANDLE) ;
int CnListForeignKeys( SQLHANDLE) ;
int CnListSpecialColumns( SQLHANDLE) ;
int CnListIndexColumns( SQLHANDLE) ;
int CnCleanUp( SQLHANDLE);

/*******************************************************************
** main
*******************************************************************/
int main( int argc, char * argv[] )
{   SQLRETURN   sqlrc = SQL_SUCCESS;
    int         rc = 0; 
    SQLHANDLE   henv;  /* environment handle */
    SQLHANDLE   hdbc;  /* connection handles */

    char       dbAlias[SQL_MAX_DSN_LENGTH + 1] ;
    char       user[MAX_UID_LENGTH + 1] ;
    char       pswd[MAX_PWD_LENGTH + 1] ;

    /* checks the command line arguments */
    rc = CmdLineArgsCheck1( argc, argv, dbAlias, user, pswd );
    if ( rc != 0 ) return( rc ) ;

    printf("\n\nTABLES: HOW TO WORK WITH CONSTRAINTS.\n");

    /* initialize the CLI application */
    rc = CLIAppInit( dbAlias, user, pswd, &henv, &hdbc, 
                     (SQLPOINTER)SQL_AUTOCOMMIT_ON);
    if ( rc != 0 ) return( rc ) ;

    rc = CnDefine( hdbc) ;
    rc = CnListPrimaryKeys( hdbc) ;    
    rc = CnListForeignKeys( hdbc) ;
    rc = CnListSpecialColumns( hdbc) ;
    rc = CnListIndexColumns( hdbc) ;
    rc = CnCleanUp( hdbc) ;    
    
    /* terminate the CLI application */
    rc = CLIAppTerm( &henv, &hdbc, dbAlias);
    return( rc ) ;
}                                  /* end main */
    
/******************************************************************************
**    CnDefine
******************************************************************************/
int CnDefine( SQLHANDLE hdbc)
{   SQLRETURN   sqlrc = SQL_SUCCESS;
    int         rc = 0; 
    SQLHANDLE   hstmt ;  /* statement handle */

    SQLCHAR *   stmt1 = ( SQLCHAR *) "CREATE TABLE sch.dept ( "
        "deptno   CHAR(3) NOT NULL PRIMARY KEY, "
        "deptname VARCHAR(32)    )" ;	

    SQLCHAR *   stmt2 = ( SQLCHAR *) "CREATE TABLE sch.emp ( "
        "empno    CHAR(7) NOT NULL PRIMARY KEY, "
        "deptno   CHAR(3) NOT NULL,"
        "sex      CHAR(1) WITH DEFAULT 'M', "	
        "salary   DECIMAL(7,2) WITH DEFAULT, "
	"CONSTRAINT check1 "
        "    CHECK( sex IN ( 'M', 'F')), "	
        "CONSTRAINT check2"	
        "    CHECK( salary < 70000.00), "	
        "CONSTRAINT fk1"	
        "    FOREIGN KEY (deptno) REFERENCES sch.dept(deptno)   )" ;	
    
    printf("\nUSE THE CLI FUNCTIONS\n");
    
    printf("-SQLSetConnectAttr\n-SQLAllocHandle\n");
    printf("-SQLExecDirect\n-SQLFreeHandle\n");

    printf("TO CREATE TABLES WITH CONSTRAINTS:\n");   

    /* set AUTOCOMMIT on */
    sqlrc = SQLSetConnectAttr( hdbc,
                               SQL_ATTR_AUTOCOMMIT,
                               (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_NTS) ;
    DBC_HANDLE_CHECK( hdbc, sqlrc);
    
    /* allocate a statement handle */
    sqlrc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ;
    DBC_HANDLE_CHECK( hdbc, sqlrc);

    /* create first table */ 
    printf("\n    Execute directly the statement\n");
    printf("        CREATE TABLE sch.dept ( \n");    
    printf("          deptno   CHAR(3) NOT NULL PRIMARY KEY, \n"); 
    printf("          deptname VARCHAR(32)    )\n"); 
    sqlrc = SQLExecDirect( hstmt, stmt1, SQL_NTS ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc);

    /* create second table */ 
    printf("    Execute directly the statement\n");
    printf("        CREATE TABLE sch.emp ( \n");    
    printf("          empno    CHAR(7) NOT NULL PRIMARY KEY,\n"); 
    printf("          deptno   CHAR(3) NOT NULL,\n"); 
    printf("          sex      CHAR(1) WITH DEFAULT 'M', \n"); 
    printf("          salary   DECIMAL(7,2) WITH DEFAULT, \n"); 
    printf("          CONSTRAINT check1 \n"); 
    printf("            CHECK( sex IN ( 'M', 'F')), \n"); 
    printf("          CONSTRAINT check2\n");     
    printf("            CHECK( salary < 70000.00), \n"); 
    printf("          CONSTRAINT fk1\n"); 
    printf("            FOREIGN KEY (deptno) REFERENCES sch.dept(deptno))\n");     
    sqlrc = SQLExecDirect( hstmt, stmt2, SQL_NTS ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc);
    
    /* free the statement handle */
    sqlrc = SQLFreeHandle( SQL_HANDLE_STMT, hstmt ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc);    
    
    return(rc);  
}    

/******************************************************************************
**   CnCleanUp - drop the tables created in CnDefine
******************************************************************************/
int CnCleanUp( SQLHANDLE hdbc)
{   SQLRETURN   sqlrc = SQL_SUCCESS;
    int         rc = 0; 
    SQLHANDLE   hstmt ;  /* statement handle */

    SQLCHAR *   stmt1 = ( SQLCHAR *) "DROP TABLE sch.dept" ;	
    SQLCHAR *   stmt2 = ( SQLCHAR *) "DROP TABLE sch.emp" ;


    printf("\nDrop the tables created in CnDefine.\n");
    
    /* set AUTOCOMMIT on */
    sqlrc = SQLSetConnectAttr( hdbc,
                               SQL_ATTR_AUTOCOMMIT,
                               (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_NTS) ;
    DBC_HANDLE_CHECK( hdbc, sqlrc);
    
    /* allocate a statement handle */
    sqlrc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ;
    DBC_HANDLE_CHECK( hdbc, sqlrc);

    /* drop the first table */ 
    sqlrc = SQLExecDirect( hstmt, stmt1, SQL_NTS ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc);

    /* drop the second table */ 
    sqlrc = SQLExecDirect( hstmt, stmt2, SQL_NTS ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc);
    
    /* free the statement handle */
    sqlrc = SQLFreeHandle( SQL_HANDLE_STMT, hstmt ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc);    
    
    return(rc);  
}    

/******************************************************************************
**   CnListPrimaryKeys 
******************************************************************************/
int CnListPrimaryKeys( SQLHANDLE hdbc)
{   SQLRETURN   sqlrc = SQL_SUCCESS;
    int         rc = 0; 
    SQLHANDLE   hstmt ;  /* statement handle */

    SQLCHAR tbSchema[] = "SCH";  
    SQLCHAR tbName[] = "DEPT";  

    struct
    {   SQLINTEGER ind;
        SQLCHAR    val[129];
    } pkColumnName, pkName;

    struct
    {   SQLINTEGER  ind;
        SQLSMALLINT val;	    
    } pkColumnPos ;

    SQLINTEGER rowNb = 0;    
    
    printf("\nUSE THE CLI FUNCTIONS\n");
    printf("-SQLSetConnectAttr\n-SQLAllocHandle\n");
    printf("-SQLPrimaryKeys\n-SQLBindCol\n");    
    printf("-SQLFetch\n-SQLFreeHandle\n");    
    printf("TO LIST THE PRIMARY KEYS FOR A SPECIFIED TABLE:\n");   


    /* set AUTOCOMMIT on */
    sqlrc = SQLSetConnectAttr( hdbc,
                               SQL_ATTR_AUTOCOMMIT,
                               (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_NTS) ;
    DBC_HANDLE_CHECK( hdbc, sqlrc);
    
    /* allocate a statement handle */
    sqlrc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ;
    DBC_HANDLE_CHECK( hdbc, sqlrc);

    
    /*--> 00003366.snippet */
    /* call SQLPrimaryKeys */
    printf("\n    Call SQLPrimaryKeys for the table %s.%s\n", 
            tbSchema, tbName); 
    sqlrc = SQLPrimaryKeys(hstmt, NULL, 0,
                        tbSchema, SQL_NTS, tbName, SQL_NTS);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;
    /* 00003366.snippet <--*/

    /* bind columns to variables */    
    sqlrc = SQLBindCol(hstmt, 4, SQL_C_CHAR, (SQLPOINTER) pkColumnName.val, 129,
                    &pkColumnName.ind);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;

    sqlrc = SQLBindCol(hstmt, 5, SQL_C_SHORT, (SQLPOINTER) &pkColumnPos.val,
                    0, &pkColumnPos.ind);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;

    sqlrc = SQLBindCol(hstmt, 6, SQL_C_CHAR, (SQLPOINTER) pkName.val, 129,
                    &pkName.ind);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;

    /*-->00000595.snippet */
    /* fetch each row, and display */
    printf("    Fetch each row and display.\n");   
    sqlrc = SQLFetch( hstmt );
    /* 00000595.snippet <--*/
    STMT_HANDLE_CHECK( hstmt, sqlrc );     
    if (sqlrc == SQL_NO_DATA_FOUND)
    {   printf("\nData not found.\n");
    }    
    while( sqlrc != SQL_NO_DATA_FOUND ) 
    {   rowNb = rowNb + 1;         	    
        printf("        -------row nb. %lu --------\n", rowNb);
        printf("            Primary Key Name: %s\n", pkName.val);
        printf("            Primary Key Column Name: %s\n",
               pkColumnName.val);
        printf("            Primary Key Column Position: %d\n", 
               pkColumnPos.val);	

        sqlrc = SQLFetch( hstmt );
        STMT_HANDLE_CHECK( hstmt, sqlrc );         	
    }

    /* free the statement handle */
    sqlrc = SQLFreeHandle( SQL_HANDLE_STMT, hstmt ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc);

    return(rc);    
}


/******************************************************************************
**   CnListForeignKeys 
******************************************************************************/
int CnListForeignKeys( SQLHANDLE hdbc)
{   SQLRETURN   sqlrc = SQL_SUCCESS;
    int         rc = 0; 
    SQLHANDLE   hstmt ;  /* statement handle */

    SQLCHAR tbSchema[] = "SCH";  
    SQLCHAR tbName[] = "DEPT";  

    struct
    {   SQLINTEGER ind;
        SQLCHAR    val[129];
    } pkTableSch, pkTableName, pkColumnName, pkName;

    struct 
    {   SQLINTEGER ind;
        SQLCHAR    val[129];
    } fkTableSch, fkTableName, fkColumnName, fkName;

    struct
    {   SQLINTEGER  ind;
        SQLSMALLINT val;	    
    } deleteRule, updateRule ;

    SQLINTEGER rowNb = 0;    
    
    printf("\nUSE THE CLI FUNCTIONS\n");
    printf("-SQLSetConnectAttr\n-SQLAllocHandle\n");
    printf("-SQLForeignKeys\n-SQLBindCol\n");    
    printf("-SQLFetch\n-SQLFreeHandle\n");    
    printf("TO LIST THE FOREIGN KEYS FOR A SPECIFIED TABLE:\n");   


    /* set AUTOCOMMIT on */
    sqlrc = SQLSetConnectAttr( hdbc,
                               SQL_ATTR_AUTOCOMMIT,
                               (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_NTS) ;
    DBC_HANDLE_CHECK( hdbc, sqlrc);
    
    /* allocate a statement handle */
    sqlrc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ;
    DBC_HANDLE_CHECK( hdbc, sqlrc);

    
    /* call SQLForeignKeys */
    printf("\n    Call SQLForeignKeys for the table %s.%s\n", 
            tbSchema, tbName); 
    sqlrc = SQLForeignKeys(hstmt, NULL, 0,
                        tbSchema, SQL_NTS, tbName, SQL_NTS,
                        NULL, 0,
                        NULL, SQL_NTS, NULL, SQL_NTS);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;

    /* bind columns to variables */    
    sqlrc = SQLBindCol(hstmt, 2, SQL_C_CHAR, (SQLPOINTER) pkTableSch.val, 129,
                    &pkTableSch.ind);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;

    sqlrc = SQLBindCol(hstmt, 3, SQL_C_CHAR, (SQLPOINTER) pkTableName.val, 129,
                    &pkTableName.ind);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;

    sqlrc = SQLBindCol(hstmt, 4, SQL_C_CHAR, (SQLPOINTER) pkColumnName.val, 129,
                    &pkColumnName.ind);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;

    sqlrc = SQLBindCol(hstmt, 6, SQL_C_CHAR, (SQLPOINTER) fkTableSch.val, 129,
                    &fkTableSch.ind);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;

    sqlrc = SQLBindCol(hstmt, 7, SQL_C_CHAR, (SQLPOINTER) fkTableName.val, 129,
                    &fkTableName.ind);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;

    sqlrc = SQLBindCol(hstmt, 8, SQL_C_CHAR, (SQLPOINTER) fkColumnName.val, 129,
                    &fkColumnName.ind);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;

    sqlrc = SQLBindCol(hstmt, 10, SQL_C_SHORT, (SQLPOINTER) &updateRule.val,
                    0, &updateRule.ind);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;

    sqlrc = SQLBindCol(hstmt, 11, SQL_C_SHORT, (SQLPOINTER) &deleteRule.val,
                    0, &deleteRule.ind);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;

    sqlrc = SQLBindCol(hstmt, 12, SQL_C_CHAR, (SQLPOINTER) fkName.val, 129,
                    &fkName.ind);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;

    sqlrc = SQLBindCol(hstmt, 13, SQL_C_CHAR, (SQLPOINTER) pkName.val, 129,
                    &pkName.ind);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;

    /* fetch each row, and display */
    printf("    Fetch each row and dispaly.\n");   
    sqlrc = SQLFetch( hstmt );
    STMT_HANDLE_CHECK( hstmt, sqlrc );     
    if (sqlrc == SQL_NO_DATA_FOUND)
    {   printf("\nData not found.\n");
    }    
    while( sqlrc != SQL_NO_DATA_FOUND ) 
    {   rowNb = rowNb + 1;       	    
        printf("        -------row nb. %lu --------\n", rowNb);
        printf("            Foreign Key Name: %s\n", fkName.val);
        printf("            Primary Key Name: %s\n", pkName.val);
        printf("            Foreign Key Column: %s.%s.%s\n",
               fkTableSch.val, fkTableName.val, fkColumnName.val);
        printf("            Primary Key Column: %s.%s.%s\n",
               pkTableSch.val, pkTableName.val, pkColumnName.val);

        printf("            Update Rule: ");	
        switch( updateRule.val)
        {   case SQL_RESTRICT:
                printf("RESTRICT\n");  /* always for IBM DBMSs */
                break;
            case SQL_CASCADE:
                printf("CASCADE\n");  /* non-IBM only */
                break;
            default:		
                printf("SET NULL\n");
                break;		
        }
	
        printf("            Delete Rule: ");
        switch( deleteRule.val)
        {   case SQL_RESTRICT:
                printf("RESTRICT\n");  /* always for IBM DBMSs */
                break;
            case SQL_CASCADE:
                printf("CASCADE\n");  /* non-IBM only */
                break;
            case SQL_NO_ACTION:
                printf("NO ACTION\n"); 	/* non-IBM only */
                break;		
            default:		
                printf("SET NULL\n");
                break;		
        }	

        sqlrc = SQLFetch( hstmt );
        STMT_HANDLE_CHECK( hstmt, sqlrc );         	
    }

    /* free the statement handle */
    sqlrc = SQLFreeHandle( SQL_HANDLE_STMT, hstmt ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc);

    return(rc);    
}



/******************************************************************************
**   CnListSpecialColumns - list the columns included in 
**                          Foreign Key or Unique Indexes 
******************************************************************************/
int CnListSpecialColumns( SQLHANDLE hdbc)
{   SQLRETURN   sqlrc = SQL_SUCCESS;
    int         rc = 0; 
    SQLHANDLE   hstmt ;  /* statement handle */

    struct
    {   SQLINTEGER ind ;
        SQLCHAR    val[129] ;
    } colName, colType;   

    struct 
    {   SQLINTEGER ind ;
        SQLCHAR val[255] ;
    } colRemarks;         

    struct 
    {   SQLINTEGER ind ;
        SQLINTEGER val; 
    } colPrecision;             
    
    struct 
    {   SQLINTEGER ind ;
        SQLSMALLINT val; 
    } colScale;       
    
    SQLCHAR tbSchema[] = "SCH";  
    SQLCHAR tbName[] = "DEPT";  
    
    printf("\nUSE THE CLI FUNCTIONS\n");
    printf("-SQLSetConnectAttr\n-SQLAllocHandle\n");
    printf("-SQLSpecialColumns\n-SQLBindCol\n");    
    printf("-SQLFetch\n-SQLFreeHandle\n");    
    printf("TO LIST SPECIAL COLUMNS FOR A SPECIFIED TABLE:\n");   

    /* set AUTOCOMMIT on */
    sqlrc = SQLSetConnectAttr( hdbc,
                               SQL_ATTR_AUTOCOMMIT,
                               (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_NTS) ;
    DBC_HANDLE_CHECK( hdbc, sqlrc);
    
    /* allocate a statement handle */
    sqlrc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ;
    DBC_HANDLE_CHECK( hdbc, sqlrc);

    /*--> 00000660.snippet */
    /* call SQLSpecialColumns */ 
    printf("\n    Call SQLSpecialColumns for the table %s.%s\n",
           tbSchema, tbName); 
    sqlrc = SQLSpecialColumns(hstmt, SQL_BEST_ROWID, NULL, 0,
                              tbSchema, SQL_NTS, tbName, SQL_NTS,
                              SQL_SCOPE_CURROW, SQL_NULLABLE);
    /* 00000660.snippet <--*/
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;

    /* bind columns to variables */
    sqlrc = SQLBindCol( hstmt, 2, SQL_C_CHAR, colName.val, 129,
                        &colName.ind ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc);
    sqlrc = SQLBindCol( hstmt, 4, SQL_C_CHAR, colType.val, 129,
                        &colType.ind ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc);
    sqlrc = SQLBindCol( hstmt, 5, SQL_C_LONG, (SQLPOINTER)&colPrecision.val,
                        sizeof(colPrecision.val), &colPrecision.ind ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc); 
    sqlrc = SQLBindCol( hstmt, 7, SQL_C_SHORT, (SQLPOINTER)&colScale.val,
                        sizeof(colScale.ind), &colScale.ind ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc); 


    /* fetch each row, and display */ 
    printf("    Fetch each row and dispaly.\n");
    sqlrc = SQLFetch( hstmt );
    STMT_HANDLE_CHECK( hstmt, sqlrc);
    if (sqlrc == SQL_NO_DATA_FOUND)
    {   printf("\n    Data not found.\n");
    }
    while( sqlrc != SQL_NO_DATA_FOUND )  
    {   printf("        %-10.10s", colName.val);

        printf(", %s", colType.val);
	
        if ( colPrecision.ind != SQL_NULL_DATA)
        {   printf(" (%ld", colPrecision.val);
        }
        else
        {   printf("(\n");
        }
	
        if (colScale.ind != SQL_NULL_DATA)
        {   printf(", %d)\n", colScale.val);
        } 
        else
        {   printf(")\n");
        }
	
        sqlrc = SQLFetch( hstmt );
        STMT_HANDLE_CHECK( hstmt, sqlrc );	
    }         /* endwhile */  

    /* free the statement handle */
    sqlrc = SQLFreeHandle( SQL_HANDLE_STMT, hstmt ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc);

    return(rc);    
}

/******************************************************************************
**   CnListIndexColumns 
******************************************************************************/
int CnListIndexColumns( SQLHANDLE hdbc)
{   SQLRETURN   sqlrc = SQL_SUCCESS;
    int         rc = 0; 
    SQLHANDLE   hstmt ;  /* statement handle */

    SQLCHAR tbSchema[] = "SCH";  
    SQLCHAR tbName[] = "DEPT";  

    struct
    {   SQLINTEGER ind;
        SQLCHAR    val[129];
    } columnName, indexName;

    struct
    {   SQLINTEGER  ind;
        SQLSMALLINT val;	    
    } type ;

    printf("\nUSE THE CLI FUNCTIONS\n");
    printf("-SQLSetConnectAttr\n-SQLAllocHandle\n");
    printf("-SQLStatistics\n-SQLBindCol\n");    
    printf("-SQLFetch\n-SQLFreeHandle\n");    
    printf("TO LIST INDEX COLUMNS FOR A SPECIFIED TABLE:\n");   


    /* set AUTOCOMMIT on */
    sqlrc = SQLSetConnectAttr( hdbc,
                               SQL_ATTR_AUTOCOMMIT,
                               (SQLPOINTER)SQL_AUTOCOMMIT_ON, SQL_NTS) ;
    DBC_HANDLE_CHECK( hdbc, sqlrc);
    
    /* allocate a statement handle */
    sqlrc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ;
    DBC_HANDLE_CHECK( hdbc, sqlrc);

    
    /* call SQLStatistics */
    printf("\n    Call SQLStatistics for the table %s.%s\n", 
            tbSchema, tbName); 
    sqlrc = SQLStatistics(hstmt, NULL, 0, tbSchema, SQL_NTS,
                          tbName, SQL_NTS, SQL_INDEX_UNIQUE, SQL_QUICK);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;

    /* bind columns to variables */    
    sqlrc = SQLBindCol(hstmt, 6, SQL_C_CHAR, (SQLPOINTER) indexName.val, 129,
                    &indexName.ind);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;

    sqlrc = SQLBindCol(hstmt, 7, SQL_C_SHORT, (SQLPOINTER) &type.val,
                    0, &type.ind);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;

    sqlrc = SQLBindCol(hstmt, 9, SQL_C_CHAR, (SQLPOINTER) columnName.val, 129,
                    &columnName.ind);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;

    /* fetch each row, and display */
    printf("    Fetch each row and dispaly.\n");   
    sqlrc = SQLFetch( hstmt );
    STMT_HANDLE_CHECK( hstmt, sqlrc );     
    if (sqlrc == SQL_NO_DATA_FOUND)
    {   printf("\nData not found.\n");
    }    
    while( sqlrc != SQL_NO_DATA_FOUND ) 
    {   if ( type.val != SQL_TABLE_STAT)
        {   printf("        Column: %-10s Index Name: %s\n",
                   columnName.val, indexName.val);
        }	

        sqlrc = SQLFetch( hstmt );
        STMT_HANDLE_CHECK( hstmt, sqlrc );         	
    }

    /* free the statement handle */
    sqlrc = SQLFreeHandle( SQL_HANDLE_STMT, hstmt ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc);

    return(rc);    
}