/*******************************************************************************
**                                                                        
** Source File Name = tbinfo.c  1.4                                      
**                                                                        
** 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 get/set info about 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 TbListTables( SQLHANDLE) ;
int TbListColumns( SQLHANDLE) ;
int TbListRowsAndPages( SQLHANDLE) ;
int TbListTablePrivileges( SQLHANDLE) ;
int TbListColumnPrivileges( 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 GET INFO ABOUT TABLES.\n");

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

    rc = TbListTables( hdbc) ;
    rc = TbListColumns( hdbc) ;
    rc = TbListRowsAndPages( hdbc) ;
    rc = TbListTablePrivileges( hdbc) ;
    rc = TbListColumnPrivileges( hdbc) ;
    
    /* terminate the CLI application */
    rc = CLIAppTerm( &henv, &hdbc, dbAlias);
    return( rc ) ;
}                                  /* end main */
    


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

    struct
    {   SQLINTEGER ind ;
        SQLCHAR    val[129] ;
    } tbQualifier, tbSchema, tbName, tbType;   

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

    SQLCHAR tbSchemaPattern[] = "%";  
    SQLCHAR tbNamePattern[] = "ST%";  /* all the tables starting with ST */     

    printf("\nUSE THE CLI FUNCTIONS\n");
    printf("-SQLSetConnectAttr\n-SQLAllocHandle\n");
    printf("-SQLTables\n-SQLBindCol\n");    
    printf("-SQLFetch\n-SQLFreeHandle\n");    
    printf("TO SHOW HOW TO LIST SOME TABLES:\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 SQLTables */ 
    printf("\n    Call SQLTables for:\n");
    printf("        schemaPattern = %s\n", tbSchemaPattern);    
    printf("        namePattern = %s\n", tbNamePattern);    
    sqlrc = SQLTables( hstmt, NULL, 0,
                       tbSchemaPattern, SQL_NTS,
                       tbNamePattern, SQL_NTS,
                       NULL, 0); 
    STMT_HANDLE_CHECK( hstmt, sqlrc);

    /* bind columns to variables */
    sqlrc = SQLBindCol( hstmt, 1, SQL_C_CHAR, tbQualifier.val, 129,
                        &tbQualifier.ind ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc);
    sqlrc = SQLBindCol( hstmt, 2, SQL_C_CHAR, tbSchema.val, 129,
                        &tbSchema.ind ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc);
    sqlrc = SQLBindCol( hstmt, 3, SQL_C_CHAR, tbName.val, 129,
                        &tbName.ind ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc);    
    sqlrc = SQLBindCol( hstmt, 4, SQL_C_CHAR, tbType.val, 129,
                        &tbType.ind ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc); 
    sqlrc = SQLBindCol( hstmt, 5, SQL_C_CHAR, tbRemarks.val, 255, 
                        &tbRemarks.ind ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc);    

    /* fetch each row, and display */ 
    printf("    Fetch each row and dispaly.\n");
    printf("        TABLE SCHEMA   TABLE_NAME     TABLE_TYPE\n");
    printf("        -------------- -------------- ----------\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("        %-14s %-14s %-11s\n", 
               tbSchema.val, tbName.val, tbType.val);
        if (tbRemarks.ind > 0)
        {   printf("        (Remarks ) %s\n", tbRemarks.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);    
}

/******************************************************************************
**   TbListColumns 
******************************************************************************/
int TbListColumns( 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; 
    } colLength;             
    
    struct 
    {   SQLINTEGER ind ;
        SQLSMALLINT val; 
    } colScale, colNullable;       
    
    SQLCHAR tbSchemaPattern[] = "%";  
    SQLCHAR tbNamePattern[] = "STAFF";  
    SQLCHAR colNamePattern[] = "%";  
    
    printf("\nUSE THE CLI FUNCTIONS\n");
    printf("-SQLSetConnectAttr\n-SQLAllocHandle\n");
    printf("-SQLColumns\n-SQLBindCol\n");    
    printf("-SQLFetch\n-SQLFreeHandle\n");    
    printf("TO SHOW HOW TO LIST SOME COLUMNS:\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 SQLColumns */ 
    printf("\n    Call SQLColumns for:\n");
    printf("        tbSchemaPattern = %s\n", tbSchemaPattern);    
    printf("        tbNamePattern = %s\n", tbNamePattern); 
    printf("        colNamePattern = %s\n", colNamePattern);    
    sqlrc = SQLColumns( hstmt, NULL, 0,
                        tbSchemaPattern, SQL_NTS,
                        tbNamePattern, SQL_NTS,
                        colNamePattern, SQL_NTS); 
    STMT_HANDLE_CHECK( hstmt, sqlrc);

    /* bind columns to variables */
    sqlrc = SQLBindCol( hstmt, 4, SQL_C_CHAR, colName.val, 129,
                        &colName.ind ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc);
    sqlrc = SQLBindCol( hstmt, 6, SQL_C_CHAR, colType.val, 129,
                        &colType.ind ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc);
    sqlrc = SQLBindCol( hstmt, 7, SQL_C_LONG, (SQLPOINTER)&colLength.val,
                        sizeof(colLength.val), &colLength.ind ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc); 
    sqlrc = SQLBindCol( hstmt, 9, SQL_C_SHORT, (SQLPOINTER)&colScale.val,
                        sizeof(colScale.val), &colScale.ind ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc); 
    sqlrc = SQLBindCol( hstmt, 11, SQL_C_SHORT, (SQLPOINTER)&colNullable.val,
                        sizeof(colNullable.val), &colNullable.ind ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc); 
    sqlrc = SQLBindCol( hstmt, 12, SQL_C_CHAR, colRemarks.val, 255, 
                        &colRemarks.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);
        if ( colNullable.val == SQL_NULLABLE)
        {   printf(",     NULLABLE");
        } 
        else
        {   printf(", NOT NULLABLE");
        }

        printf(", %s", colType.val);
	
        if ( colLength.ind != SQL_NULL_DATA)
        {   printf(" (%ld", colLength.val);
        }
        else
        {   printf("(");
        }
	
        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);    
}

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

    struct
    {   SQLINTEGER ind ;
        SQLINTEGER val ;
    } tbCardinality, tbPages;   

    struct
    {   SQLINTEGER ind ;
        SQLSMALLINT val ;
    } infoType;  
    
    SQLCHAR tbSchema[] = "SYSCAT";  
    SQLCHAR tbName[] = "TABLES";      

    printf("\nUSE THE CLI FUNCTIONS\n");
    printf("-SQLSetConnectAttr\n-SQLAllocHandle\n");
    printf("-SQLStatistics\n-SQLBindCol\n");    
    printf("-SQLFetch\n-SQLFreeHandle\n");    
    printf("TO SHOW HOW TO GET THE NUMBER OF ROWS AND PAGES:\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:\n");
    printf("        tbSchema = %s\n", tbSchema);    
    printf("        tbName = %s\n", 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, 7, SQL_C_SHORT, (SQLPOINTER)&infoType.val,
                        sizeof(infoType.val), &infoType.ind ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc);     
    sqlrc = SQLBindCol( hstmt, 11, SQL_C_LONG, (SQLPOINTER)&tbCardinality.val,
                        sizeof(tbCardinality.val), &tbCardinality.ind ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc); 
    sqlrc = SQLBindCol( hstmt, 12, SQL_C_LONG, (SQLPOINTER)&tbPages.val,
                        sizeof(tbPages.val), &tbPages.ind) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc);     

    /* fetch each row, and display */ 
    printf("    Display the number of rows and pages.\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)     
    {   if( infoType.val == SQL_TABLE_STAT)
        {   if ( tbCardinality.ind == SQL_NULL_DATA)
	    {   printf("        Number of rows = (Unavailable)\n");	
            }		
            else
            {   printf("        Number of rows = %u\n", tbCardinality.val);
            }	
            if ( tbPages.ind == SQL_NULL_DATA)
	    {   printf("        Number of pages used to store the table =");
                printf("(Unavailable)\n");	
            }		
            else
            {   printf("        Number of pages used to store the table = %u\n",
                        tbCardinality.val);
            }		    
            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);    
}

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

    struct 
    {   SQLINTEGER ind;  
        SQLCHAR    val[129]; 
    } tbSchema, tbName, grantor, grantee, privilege; 

    struct
    {   SQLINTEGER  ind;
        SQLCHAR     val[4];
    } is_grantable;
    
    SQLCHAR tbSchemaPattern[] = "%";  
    SQLCHAR tbNamePattern[] = "ORG";      

    printf("\nUSE THE CLI FUNCTIONS\n");
    printf("-SQLSetConnectAttr\n-SQLAllocHandle\n");
    printf("-SQLTablePrivileges\n-SQLBindCol\n");    
    printf("-SQLFetch\n-SQLFreeHandle\n");    
    printf("TO GET TABLE PRIVILEGES:\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 SQLTablePrivileges */ 
    printf("\n    Call SQLTablePrivileges for:\n");
    printf("        tbSchemaPattern = %s\n", tbSchemaPattern);    
    printf("        tbNamePattern = %s\n", tbNamePattern);    
    sqlrc = SQLTablePrivileges( hstmt, NULL, 0,
                                tbSchemaPattern, SQL_NTS,
                                tbNamePattern, SQL_NTS); 
    STMT_HANDLE_CHECK( hstmt, sqlrc);

    /* bind columns to variables */
    sqlrc = SQLBindCol( hstmt, 2, SQL_C_CHAR, tbSchema.val, 129,
                        &tbSchema.ind ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc);
    sqlrc = SQLBindCol( hstmt, 3, SQL_C_CHAR, tbName.val, 129,
                        &tbName.ind ) ;    
    sqlrc = SQLBindCol(hstmt, 4, SQL_C_CHAR, (SQLPOINTER) grantor.val, 129,
                    &grantor.ind);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;
    sqlrc = SQLBindCol(hstmt, 5, SQL_C_CHAR, (SQLPOINTER) grantee.val, 129,
                    &grantee.ind);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;
    sqlrc = SQLBindCol(hstmt, 6, SQL_C_CHAR, (SQLPOINTER) privilege.val, 129,
                    &privilege.ind);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;
    sqlrc = SQLBindCol(hstmt, 7, SQL_C_CHAR, (SQLPOINTER) is_grantable.val, 4,
                    &is_grantable.ind);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;

    /* Fetch each row, and display */
    printf("\n    Current User's Privileges \n");
    printf("        Table Grantor  Grantee      Privilege  Grantable\n");
    printf("        ----- -------- ------------ ---------- ---------\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 )  
    {   printf("        %-5s", tbName.val);
        printf(" %-8s", grantor.val);
        printf(" %-12s", grantee.val);
        printf(" %-10s", privilege.val);
        printf(" %-3s\n", is_grantable.val);
	
        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);    
}

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

    struct 
    {   SQLINTEGER ind;  
        SQLCHAR    val[129]; 
    } colName, grantor, grantee, privilege; 

    struct
    {   SQLINTEGER  ind;
        SQLCHAR     val[4];
    } is_grantable;
    
    SQLCHAR tbSchema[] = "SCHEMA";  
    SQLCHAR tbName[] = "TABLE_NAME"; 
    SQLCHAR colNamePattern[] = "%";    

    SQLCHAR stmt[100];    
    
    printf("\nUSE THE CLI FUNCTIONS\n");
    printf("-SQLSetConnectAttr\n-SQLAllocHandle\n");
    printf("-SQLTablePrivileges\n-SQLBindCol\n");    
    printf("-SQLFetch\n-SQLFreeHandle\n");    
    printf("TO GET COLUMN PRIVILEGES:\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, &hstmtTable ) ;
    DBC_HANDLE_CHECK( hdbc, sqlrc);

    /* create a test table */ 
    sprintf( (char *)stmt, "CREATE TABLE %s.%s ( COL1 CHAR(10))", tbSchema, tbName );    
    printf("\n    Execute directly\n");
    printf("        %s\n", stmt);    
    sqlrc = SQLExecDirect( hstmtTable, stmt, SQL_NTS ) ;
    STMT_HANDLE_CHECK( hstmtTable, sqlrc);

    /* allocate a statement handle */
    sqlrc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ;
    DBC_HANDLE_CHECK( hdbc, sqlrc);
    
    /* call SQLColumnPrivileges */ 
    printf("\n    Call SQLColumnPrivileges for:\n");
    printf("        tbSchema = %s\n", tbSchema);    
    printf("        tbName = %s\n", tbName);    
    sqlrc = SQLColumnPrivileges( hstmt, NULL, 0,
                                 tbSchema, SQL_NTS,
                                 tbName, SQL_NTS,
                                 colNamePattern, SQL_NTS); 
    STMT_HANDLE_CHECK( hstmt, sqlrc);

    /* bind columns to variables */
    sqlrc = SQLBindCol( hstmt, 4, SQL_C_CHAR, colName.val, 129,
                        &colName.ind ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc);
    sqlrc = SQLBindCol(hstmt, 5, SQL_C_CHAR, (SQLPOINTER) grantor.val, 129,
                    &grantor.ind);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;
    sqlrc = SQLBindCol(hstmt, 6, SQL_C_CHAR, (SQLPOINTER) grantee.val, 129,
                    &grantee.ind);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;
    sqlrc = SQLBindCol(hstmt, 7, SQL_C_CHAR, (SQLPOINTER) privilege.val, 129,
                    &privilege.ind);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;
    sqlrc = SQLBindCol(hstmt, 8, SQL_C_CHAR, (SQLPOINTER) is_grantable.val, 4,
                    &is_grantable.ind);
    STMT_HANDLE_CHECK( hstmt, sqlrc ) ;

    /* Fetch each row, and display */
    printf("\n    Current User's Privileges for table %s.%s\n", tbSchema, tbName);
    printf("        Column  Grantor  Grantee      Privilege  Grantable\n");
    printf("        ------- -------- ------------ ---------- ---------\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 )  
    {   printf("        %-7s", colName.val);
        printf(" %-8s", grantor.val);
        printf(" %-12s", grantee.val);
        printf(" %-10s", privilege.val);
        printf(" %-3s\n", is_grantable.val);
	
        sqlrc = SQLFetch( hstmt );
        STMT_HANDLE_CHECK( hstmt, sqlrc );
    }   /* endwhile */

    /* free the statement handle */
    sqlrc = SQLFreeHandle( SQL_HANDLE_STMT, hstmt ) ;
    STMT_HANDLE_CHECK( hstmt, sqlrc);
    
    /* drop the test table */ 
    sprintf((char*) stmt, "DROP TABLE %s.%s", tbSchema, tbName );    
    printf("\n    Execute directly\n");
    printf("        %s\n", stmt);    
    sqlrc = SQLExecDirect( hstmtTable, stmt, SQL_NTS ) ;
    STMT_HANDLE_CHECK( hstmtTable, sqlrc);
    
    /* free the statement handle */
    sqlrc = SQLFreeHandle( SQL_HANDLE_STMT, hstmtTable ) ;
    STMT_HANDLE_CHECK( hstmtTable, sqlrc);

    return(rc);    
}