/****************************************************************************
** (c) Copyright IBM Corp. 2007 All rights reserved.
** 
** The following sample of source code ("Sample") is owned by International 
** Business Machines Corporation or one of its subsidiaries ("IBM") and is 
** copyrighted and licensed, not sold. You may use, copy, modify, and 
** distribute the Sample in any form without payment to IBM, for the purpose of 
** assisting you in the development of your applications.
** 
** The Sample code is provided to you on an "AS IS" basis, without warranty of 
** any kind. IBM HEREBY EXPRESSLY DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR 
** IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Some jurisdictions do 
** not allow for the exclusion or limitation of implied warranties, so the above 
** limitations or exclusions may not apply to you. IBM shall not be liable for 
** any damages you suffer as a result of using, copying, modifying or 
** distributing the Sample, even if IBM has been advised of the possibility of 
** such damages.
*****************************************************************************
**
** SOURCE FILE NAME: dbuse.c
**
** SAMPLE: How to use a database
**
**         This sample demonstrates how to execute different types of SQL
**         statements in various ways, including executing compound SQL and
**         binding parameters.  It also shows numerous ways descriptors
**         can be used.
**
** CLI FUNCTIONS USED:
**         SQLAllocHandle -- Allocate Handle
**         SQLBindCol -- Bind a Column to an Application Variable or
**                       LOB locator
**         SQLBindParameter -- Bind a Parameter Marker to a Buffer or
**                             LOB locator
**         SQLCopyDesc -- Copy Descriptor Information Between Handles
**         SQLEndTran -- End Transactions of a Connection
**         SQLExecDirect -- Execute a Statement Directly
**         SQLExecute -- Execute a Statement
**         SQLFetch -- Fetch Next Row
**         SQLFreeHandle -- Free Handle Resources
**         SQLGetDescField -- Get Single Field Settings of Descriptor Record
**         SQLGetDescRec -- Get Mulitple Field Settings of Descriptor Record
**         SQLGetStmtAttr -- Get Current Setting of a Statement Attribute
**         SQLNumResultCols -- Get Number of Result Columns
**         SQLPrepare -- Prepare a Statement
**         SQLSetConnectAttr -- Set Connection Attributes
**         SQLSetDescField -- Set a Single Field of a Descriptor Record
**         SQLSetDescRec -- Set Multiple Descriptor Fields for a Column
**                          or Parameter Data
**         SQLSetStmtAttr -- Set Options Related to a Statement
**
**                           
*****************************************************************************
**
** For more information on the sample programs, see the README file.
**
** For information on developing CLI applications, see the CLI Guide
** and Reference.
**
** For information on using SQL statements, see the SQL Reference.
**
** For the latest information on programming, building, and running DB2 
** applications, visit the DB2 Information Center: 
**     http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/index.jsp
****************************************************************************/

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

int StmtExecDirect(SQLHANDLE);
int ConnExecTransact(SQLHANDLE);
int StmtBindParam(SQLHANDLE);
int StmtExecute(SQLHANDLE);
int StmtExecCompound(SQLHANDLE);
int DescSetGetRec(SQLHANDLE);
int DescSetGetField(SQLHANDLE);
int DescCopy(SQLHANDLE);
int DropTempTables(SQLHANDLE);

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

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

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

  printf("\nTHIS SAMPLE SHOWS HOW TO USE A DATABASE.\n");

  /* initialize the CLI application by calling a helper
     utility function defined in utilcli.c */
  rc = CLIAppInit(dbAlias,
                  user,
                  pswd,
                  &henv,
                  &hdbc,
                  (SQLPOINTER)SQL_AUTOCOMMIT_ON);
  if (rc != 0)
  {
    return rc;
  }

  /* directly execute SQL statements using SQLExecDirect */
  rc = StmtExecDirect(hdbc);

  /* perform transactions on one connection */
  rc = ConnExecTransact(hdbc);

  /* bind parameters to an SQL statement */
  rc = StmtBindParam(hdbc);

  /* prepare and execute an SQL statement */
  rc = StmtExecute(hdbc);

  /* execute a compound SQL statement */
  rc = StmtExecCompound(hdbc);

  /* using descriptors */
  /* get and set multiple fields of descriptor records */
  rc = DescSetGetRec(hdbc);
  /* get and set a single field of descriptor records */
  rc = DescSetGetField(hdbc);
  /* copy descriptors */
  rc = DescCopy(hdbc);

  /* terminate the CLI application by calling a helper
     utility function defined in utilcli.c */
  rc = CLIAppTerm(&henv, &hdbc, dbAlias);

  return rc;
} /* main */

/* directly execute SQL statements using SQLExecDirect */
int StmtExecDirect(SQLHANDLE hdbc)
{
  SQLRETURN cliRC = SQL_SUCCESS;
  int rc = 0;
  SQLHANDLE hstmt; /* statement handle */
  /* SQL statements to be executed */
  SQLCHAR *stmt1 = (SQLCHAR *)"CREATE TABLE table1(col1 INTEGER)";
  SQLCHAR *stmt2 = (SQLCHAR *)"DROP TABLE table1";

  printf("\n-----------------------------------------------------------");
  printf("\nUSE THE CLI FUNCTIONS\n");
  printf("  SQLSetConnectAttr\n");
  printf("  SQLAllocHandle\n");
  printf("  SQLExecDirect\n");
  printf("  SQLFreeHandle\n");
  printf("TO EXECUTE SQL STATEMENTS DIRECTLY:\n");

  /* set AUTOCOMMIT on */
  cliRC = SQLSetConnectAttr(hdbc,
                            SQL_ATTR_AUTOCOMMIT,
                            (SQLPOINTER)SQL_AUTOCOMMIT_ON,
                            SQL_NTS);
  DBC_HANDLE_CHECK(hdbc, cliRC);

  /* allocate a statement handle */
  cliRC = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
  DBC_HANDLE_CHECK(hdbc, cliRC);

  printf("\n  Directly execute %s.\n", stmt1);

  /* directly execute statement 1 */
  cliRC = SQLExecDirect(hstmt, stmt1, SQL_NTS);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  printf("\n  Directly execute %s.\n", stmt2);

  /* directly execute statement 2 */
  cliRC = SQLExecDirect(hstmt, stmt2, SQL_NTS);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

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

  return rc;
} /* StmtExecDirect */

/* perform transactions on one connection */
int ConnExecTransact(SQLHANDLE hdbc)
{
  SQLRETURN cliRC = SQL_SUCCESS;
  int rc = 0;
  SQLHANDLE hstmt; /* statement handle */
  /* SQL statements to be executed */
  SQLCHAR *stmt1 = (SQLCHAR *)"CREATE TABLE table1(col1 INTEGER)";
  SQLCHAR *stmt2 = (SQLCHAR *)"CREATE TABLE table2(col1 INTEGER)";
  SQLCHAR *stmt3 = (SQLCHAR *)"DROP TABLE table1";
  SQLCHAR *stmt4 = (SQLCHAR *)"DROP TABLE table2";

  printf("\n-----------------------------------------------------------");
  printf("\nUSE THE CLI FUNCTIONS\n");
  printf("  SQLSetConnectAttr\n");
  printf("  SQLAllocHandle\n");
  printf("  SQLExecDirect\n");
  printf("  SQLEndTran\n");
  printf("  SQLFreeHandle\n");
  printf("TO PERFORM A TRANSACTION ON ONE CONNECTION:\n");

  /* set AUTOCOMMIT OFF */
  cliRC = SQLSetConnectAttr(hdbc,
                            SQL_ATTR_AUTOCOMMIT,
                            (SQLPOINTER)SQL_AUTOCOMMIT_OFF,
                            SQL_NTS);
  DBC_HANDLE_CHECK(hdbc, cliRC);
  printf("\n  Transactions enabled\n");

  /* allocate a statement handle */
  cliRC = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
  DBC_HANDLE_CHECK(hdbc, cliRC);

  printf("\n  Perform a transaction on this connection\n");

  printf("    executing %s...\n", stmt1);

  /* directly execute statement 1 */
  cliRC = SQLExecDirect(hstmt, stmt1, SQL_NTS);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  printf("    executing %s...\n", stmt2);

  /* directly execute statement 2 */
  cliRC = SQLExecDirect(hstmt, stmt2, SQL_NTS);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  printf("\n  Committing the transaction...\n");

  /* end the transactions on the connection */
  cliRC = SQLEndTran(SQL_HANDLE_DBC, hdbc, SQL_COMMIT);
  DBC_HANDLE_CHECK(hdbc, cliRC);

  printf("  Transaction committed.\n");

  printf("\n  Perform another transaction on this connection\n");

  printf("    executing %s...\n", stmt3);

  /* directly execute statement 3 */
  cliRC = SQLExecDirect(hstmt, stmt3, SQL_NTS);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  /* directly execute statement 4 */
  printf("    executing %s...\n", stmt4);
  cliRC = SQLExecDirect(hstmt, stmt4, SQL_NTS);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  printf("\n  Committing the transaction...\n");

  /* end the transactions on the connection */
  cliRC = SQLEndTran(SQL_HANDLE_DBC, hdbc, SQL_COMMIT);
  DBC_HANDLE_CHECK(hdbc, cliRC);

  printf("  Transaction committed.\n");

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

  return rc;
} /* ConnExecTransact */

/* bind parameters to an SQL statement */
int StmtBindParam(SQLHANDLE hdbc)
{
  SQLRETURN cliRC = SQL_SUCCESS;
  int rc = 0;
  SQLHANDLE hstmt; /* statement handle */
  /* SQL statement to be executed, containing parameter markers */
  SQLCHAR *stmt = (SQLCHAR *)
    "DELETE FROM org WHERE deptnumb = ? AND division = ? ";
  SQLSMALLINT parameter1 = 0;

  char parameter2[20];

  printf("\n-----------------------------------------------------------");
  printf("\nUSE THE CLI FUNCTIONS\n");
  printf("  SQLSetConnectAttr\n");
  printf("  SQLAllocHandle\n");
  printf("  SQLBindParameter\n");
  printf("  SQLExecDirect\n");
  printf("  SQLEndTran\n");
  printf("  SQLFreeHandle\n");
  printf("TO BIND PARAMETERS TO AN SQL STATEMENT:\n");

  /* set AUTOCOMMIT OFF */
  cliRC = SQLSetConnectAttr(hdbc,
                            SQL_ATTR_AUTOCOMMIT,
                            (SQLPOINTER)SQL_AUTOCOMMIT_OFF,
                            SQL_NTS);
  DBC_HANDLE_CHECK(hdbc, cliRC);
  printf("\n  Transactions enabled\n");

  /* allocate a statement handle */
  cliRC = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
  DBC_HANDLE_CHECK(hdbc, cliRC);

  printf("\n  Bind parameter1 and parameter2 to the statement\n");
  printf("    %s\n", stmt);

  /* bind parameter1 to the statement */
  cliRC = SQLBindParameter(hstmt,
                           1,
                           SQL_PARAM_INPUT,
                           SQL_C_SHORT,
                           SQL_SMALLINT,
                           0,
                           0,
                           &parameter1,
                           0,
                           NULL);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  /* bind parameter2 to the statement */
  cliRC = SQLBindParameter(hstmt,
                           2,
                           SQL_PARAM_INPUT,
                           SQL_C_CHAR,
                           SQL_VARCHAR,
                           20,
                           0,
                           parameter2,
                           20,
                           NULL);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  /* execute the statement for parameter1 = 15 and parameter2 = 'Eastern' */
  printf("\n  Execute the statement for\n");
  printf("    parameter1 = 15 and parameter2 = 'Eastern'\n");
  parameter1 = 15;
  strcpy(parameter2, "Eastern");

  /* directly execute the statement */
  cliRC = SQLExecDirect(hstmt, stmt, SQL_NTS);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  /* execute the statement for parameter1 = 84 and parameter2 = 'Western' */
  printf("\n  Execute the statement for\n");
  printf("    parameter1 = 84 and parameter2 = 'Western'\n");
  parameter1 = 84;
  strcpy(parameter2, "Western");

  /* directly execute the statement */
  cliRC = SQLExecDirect(hstmt, stmt, SQL_NTS);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  printf("\n  Rolling back the transaction...\n");

  /* end the transactions on the connection */
  cliRC = SQLEndTran(SQL_HANDLE_DBC, hdbc, SQL_ROLLBACK);
  DBC_HANDLE_CHECK(hdbc, cliRC);

  printf("  Transaction rolled back.\n");

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

  return rc;
} /* StmtBindParam */

/* prepare and execute an SQL statement with bound parameters */
int StmtExecute(SQLHANDLE hdbc)
{
  SQLRETURN cliRC = SQL_SUCCESS;
  int rc = 0;
  SQLHANDLE hstmt; /* statement handle */
  /* SQL statement to be executed, containing a parameter marker */
  SQLCHAR *stmt = (SQLCHAR *)"DELETE FROM org WHERE deptnumb = ? ";
  SQLSMALLINT parameter1 = 0;

  printf("\n-----------------------------------------------------------");
  printf("\nUSE THE CLI FUNCTIONS\n");
  printf("  SQLSetConnectAttr\n");
  printf("  SQLAllocHandle\n");
  printf("  SQLPrepare\n");
  printf("  SQLBindParameter\n");
  printf("  SQLExecute\n");
  printf("  SQLEndTran\n");
  printf("  SQLFreeHandle\n");
  printf("TO EXECUTE A PREPARED SQL STATEMENT:\n");

  /* set AUTOCOMMIT OFF */
  cliRC = SQLSetConnectAttr(hdbc,
                            SQL_ATTR_AUTOCOMMIT,
                            (SQLPOINTER)SQL_AUTOCOMMIT_OFF,
                            SQL_NTS);
  DBC_HANDLE_CHECK(hdbc, cliRC);
  printf("\n  Transactions enabled\n");

  /* allocate a statement handle */
  cliRC = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
  DBC_HANDLE_CHECK(hdbc, cliRC);

  printf("\n  Prepare the statement\n");
  printf("    %s\n", stmt);

  /* prepare the statement */
  cliRC = SQLPrepare(hstmt, stmt, SQL_NTS);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  printf("\n  Bind parameter1 to the statement\n");
  printf("    %s\n", stmt);

  /* bind parameter1 to the statement */
  cliRC = SQLBindParameter(hstmt,
                           1,
                           SQL_PARAM_INPUT,
                           SQL_C_SHORT,
                           SQL_SMALLINT,
                           0,
                           0,
                           &parameter1,
                           0,
                           NULL);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  /* execute the statement for parameter1 = 15 */
  printf("\n  Execute the prepared statement for\n");
  printf("    parameter1 = 15\n");
  parameter1 = 15;

  /* execute the statement */
  cliRC = SQLExecute(hstmt);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  /* execute the statement for parameter1 = 84 */
  printf("\n  Execute the prepared statement for\n");
  printf("    parameter1 = 84\n");
  parameter1 = 84;

  /* execute the statement */
  cliRC = SQLExecute(hstmt);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  printf("\n  Rolling back the transaction...\n");

  /* end the transactions on the connection */
  cliRC = SQLEndTran(SQL_HANDLE_DBC, hdbc, SQL_ROLLBACK);
  DBC_HANDLE_CHECK(hdbc, cliRC);

  printf("    Transaction rolled back.\n");

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

  return rc;
} /* StmtExecute */

/* execute a compound SQL statement */
int StmtExecCompound(SQLHANDLE hdbc)
{
  SQLRETURN cliRC = SQL_SUCCESS;
  int rc = 0;
  SQLHANDLE hstmt, compnd_hstmt[4]; /* statement handles */
  /* compound SQL statement to be executed */
  SQLCHAR *compnd_stmt[] =
  {
    (SQLCHAR *)"INSERT INTO awards (id, award) "
      "SELECT id, 'Sales Merit' from staff "
      "WHERE job = 'Sales' AND (comm/100 > years)",

    (SQLCHAR *)"INSERT INTO awards (id, award) "
      "SELECT id, 'Clerk Merit' from staff "
      "WHERE job = 'Clerk' AND (comm/50 > years)",

    (SQLCHAR *)"INSERT INTO awards (id, award) "
      "SELECT id, 'Best ' concat job FROM STAFF "
      "WHERE comm = (SELECT max(comm) FROM staff WHERE job = 'Clerk')",

    (SQLCHAR *)"INSERT INTO awards (id, award) "
      "SELECT id, 'Best ' concat job FROM STAFF "
      "WHERE comm = (SELECT max(comm) FROM STAFF WHERE job = 'Sales')",
  };

  SQLINTEGER i;
  printf("\n-----------------------------------------------------------");
  printf("\nUSE THE CLI FUNCTIONS\n");
  printf("  SQLSetConnectAttr\n");
  printf("  SQLAllocHandle\n");
  printf("  SQLExecDirect\n");
  printf("  SQLPrepare\n");
  printf("  SQLExecute\n");
  printf("  SQLEndTran\n");
  printf("  SQLFreeHandle\n");
  printf("TO EXECUTE A COMPOUND SQL STATEMENT:\n");

  /* set AUTOCOMMIT OFF */
  cliRC = SQLSetConnectAttr(hdbc,
                            SQL_ATTR_AUTOCOMMIT,
                            (SQLPOINTER)SQL_AUTOCOMMIT_OFF,
                            SQL_NTS);
  DBC_HANDLE_CHECK(hdbc, cliRC);
  printf("\n  Transactions enabled\n");

  /* allocate a statement handle */
  cliRC = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
  DBC_HANDLE_CHECK(hdbc, cliRC);

  /* directly execute a statement - create the table AWARDS */
  cliRC = SQLExecDirect(hstmt,
                        (SQLCHAR *)
                        "CREATE TABLE AWARDS (ID INTEGER, AWARD CHAR(12))",
                        SQL_NTS);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  /* end the transactions on the connection */
  cliRC = SQLEndTran(SQL_HANDLE_DBC, hdbc, SQL_COMMIT);
  DBC_HANDLE_CHECK(hdbc, cliRC);

  /* prepare the 4 substatements of the compound SQL statement */
  for (i = 0; i < 4; i++)
  {
    /* allocate a statement handle */
    cliRC = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &compnd_hstmt[i]);
    DBC_HANDLE_CHECK(hdbc, cliRC);

    /* prepare a statement */
    cliRC = SQLPrepare(compnd_hstmt[i], compnd_stmt[i], SQL_NTS);
    STMT_HANDLE_CHECK(compnd_hstmt[i], hdbc, cliRC);
  }

  /* begin the COMPOUND statement */
  printf("\n  Directly execute:\n");
  printf("    BEGIN COMPOUND NOT ATOMIC STATIC\n");

  /* directly execute the statement */
  cliRC = SQLExecDirect(hstmt,
                        (SQLCHAR *)"BEGIN COMPOUND NOT ATOMIC STATIC",
                        SQL_NTS);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  /* execute the 4 sub-statements of the compound SQL statement */
  for (i = 0; i < 4; i++)
  {
    printf("\n  Execute the sub-statement %d\n", i + 1);
    printf("    of the COMPOUND statement\n");

    /* execute the statement */
    cliRC = SQLExecute(compnd_hstmt[i]);
    STMT_HANDLE_CHECK(compnd_hstmt[i], hdbc, cliRC);
  }

  printf("\n  Directly execute:"
         "\n    END COMPOUND COMMIT\n");

  /* directly execute a statement - end the COMPOUND statement */
  cliRC = SQLExecDirect(hstmt, (SQLCHAR *)"END COMPOUND COMMIT", SQL_NTS);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  for (i = 0; i < 4; i++)
  {
    /* free the statement handles */
    cliRC = SQLFreeHandle(SQL_HANDLE_STMT, compnd_hstmt[i]);
    STMT_HANDLE_CHECK(compnd_hstmt[i], hdbc, cliRC);
  }

  /* directly execute a statement - drop the table AWARDS */
  cliRC = SQLExecDirect(hstmt, (SQLCHAR *)"DROP TABLE AWARDS", SQL_NTS);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  /* end the transactions on the connection */
  cliRC = SQLEndTran(SQL_HANDLE_DBC, hdbc, SQL_COMMIT);
  DBC_HANDLE_CHECK(hdbc, cliRC);

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

  return rc;
} /* StmtExecCompound */

/* get and set multiple fields of descriptor records */
int DescSetGetRec(SQLHANDLE hdbc)
{
  SQLRETURN cliRC = SQL_SUCCESS;
  SQLRETURN rc = 0;
  SQLHANDLE hstmt, hstmt1; 
  SQLHANDLE hIRD, hARD; /* descriptor handles */
  SQLINTEGER indicator;
  SQLSMALLINT i;
  SQLCHAR colname[20];
  SQLSMALLINT namelen;
  SQLSMALLINT type;
  SQLSMALLINT subtype;
  SQLINTEGER width, length, datalen, nameleng;
  SQLSMALLINT precision, scale, nullable;
  SQLSMALLINT num_cols;
  SQLSMALLINT id_no;
  SQLCHAR thename[20];
  struct sqlca sqlca;
  char sp2[] = "  ", sp4[] = "    ";
  /* SQL SELECT statements to be executed */
  SQLCHAR *stmt = (SQLCHAR *)"SELECT id,name FROM staff where dept = 10 ";
  SQLCHAR *stmt1 = (SQLCHAR *)"SELECT id,name FROM staff where dept = 10 ";

  printf("\n-----------------------------------------------------------");
  printf("\nUSE THE CLI FUNCTIONS\n");
  printf("  SQLGetDescRec\n");
  printf("  SQLSetDescRec\n");
  printf("Other CLI FUNCTIONS\n");
  printf("  SQLSetConnectAttr\n");
  printf("  SQLAllocHandle\n");
  printf("  SQLGetStmtAttr\n");
  printf("  SQLPrepare\n");
  printf("  SQLBindParameter\n");
  printf("  SQLExecute\n");
  printf("  SQLBindCol\n");
  printf("  SQLFetch\n");
  printf("  SQLFreeHandle\n");
  printf("TO GET AND SET MULTIPLE FIELDS OF DESCRIPTOR RECORDS:\n");

  /* set AUTOCOMMIT on */
  rc = SQLSetConnectAttr(hdbc,
                         SQL_ATTR_AUTOCOMMIT,
                         (SQLPOINTER)SQL_AUTOCOMMIT_ON,
                         SQL_NTS);
  DBC_HANDLE_CHECK(hdbc, rc);

  /* allocate a statement handle */
  rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
  DBC_HANDLE_CHECK(hdbc, rc);

  /* allocate another statement handle */
  rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt1);
  DBC_HANDLE_CHECK(hdbc, rc);

  printf("\n%sPrepare the statement\n", sp2);
  printf("%s%s\n", sp4, stmt);

  /* prepare a statement */
  rc = SQLPrepare(hstmt, stmt, SQL_NTS);
  STMT_HANDLE_CHECK(hstmt, hdbc, rc);

  /* execute a statement */
  rc = SQLExecute(hstmt);
  STMT_HANDLE_CHECK(hstmt, hdbc, rc);

  /* get the handle for the implicitly allocated descriptor */
  rc = SQLGetStmtAttr(hstmt,
                      SQL_ATTR_IMP_ROW_DESC,
                      &hIRD,
                      SQL_IS_INTEGER,
                      &indicator);
  STMT_HANDLE_CHECK(hstmt, hdbc, rc);

  /* get information for each column in the result set */
  rc = SQLNumResultCols(hstmt, &num_cols);
  STMT_HANDLE_CHECK(hstmt, hdbc, rc);

  printf("\n%sRecord field/Column information within descriptor:\n", sp2);
  for (i = 1; i <= num_cols; i++)
  {
    /* get multiple field settings of the descriptor record */
    rc = SQLGetDescRec(hIRD,
                       i,
                       colname,
                       sizeof(colname),
                       &namelen,
                       &type,
                       &subtype,
                       &width,
                       &precision,
                       &scale,
                       &nullable);
    if (rc == SQL_SUCCESS)
    {
      printf("%sColumn = %d:\n", sp2, i);
      printf("%sName      = %s\n", sp4, colname);
      printf("%sData type = %d\n", sp4, type);
      printf("%sSub type  = %d\n", sp4, subtype);
      printf("%sWidth     = %d\n", sp4, width);
      printf("%sPrecision = %d\n", sp4, precision);
      printf("%sScale     = %d\n", sp4, scale);
      printf("%sNullable  = %d\n", sp4, nullable);
    }
    STMT_HANDLE_CHECK(hstmt, hdbc, rc);
  }

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

  strcpy((char *)colname, "Yes");
  type = 0;
  subtype = 0;
  width = 0;
  precision = 0;
  scale = 0;
  nullable = 0;

  /* prepare the statement */
  rc = SQLPrepare(hstmt1, stmt1, SQL_NTS);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);

  /* get the handle for the implicitly allocated descriptor */
  rc = SQLGetStmtAttr(hstmt1, SQL_ATTR_APP_ROW_DESC, &hARD, 0, NULL);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);

  /* set record/column values via a descriptor */
  type = SQL_SMALLINT;
  length = 2;

  /* set multiple descriptor fields for a column or parameter data */
  rc = SQLSetDescRec(hARD, 1, type, 0, length, 0, 0, &id_no, &datalen, NULL);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);

  type = SQL_CHAR;
  length = 20;

  /* set multiple descriptor fields for a column or parameter data */
  rc = SQLSetDescRec(hARD,
                     2,
                     type,
                     0,
                     length,
                     0,
                     0,
                     thename,
                     &nameleng,
                     NULL);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);

  printf("\n%sAfter setting record:\n", sp2);

  /* execute the  statement */
  rc = SQLExecute(hstmt1);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);

  for (i = 1; i <= num_cols; i++)
  {
    /* get the record/column value after setting */
    rc = SQLGetDescRec(hARD,
                       i,
                       colname,
                       sizeof(colname),
                       &namelen,
                       &type,
                       &subtype,
                       &width,
                       &precision,
                       &scale,
                       &nullable);
    STMT_HANDLE_CHECK(hstmt1, hdbc, rc);

    if (rc == SQL_SUCCESS)
    {
      printf("%sColumn = %d:\n", sp2, i);
      printf("%sName      = %s\n", sp4, colname);
      printf("%sData type = %d\n", sp4, type);
      printf("%sSub type  = %d\n", sp4, subtype);
      printf("%sWidth     = %d\n", sp4, width);
      printf("%sPrecision = %d\n", sp4, precision);
      printf("%sScale     = %d\n", sp4, scale);
      printf("%sNullable  = %d\n", sp4, nullable);
    }
  }

  /* get the result set and print it without using SQLBindCol */
  rc = SQLFetch(hstmt1);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);

  if (rc == SQL_SUCCESS)
  {
    printf("\n%sResult set after using SetDescRec\n", sp2);
    printf("%s-ID- ---NAME----\n", sp4);
  }
  while (rc == SQL_SUCCESS)
  {
    printf("%s%d  %s\n", sp4, id_no, thename);

    /* fetch next row */
    rc = SQLFetch(hstmt1);
  }
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);

  /* free the statement handle */
  rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt1);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);

  return rc;
} /* DescSetGetRec */

/* copy fields of a source descriptor to a target descriptor */
int DescCopy(SQLHANDLE hdbc)
{
  SQLRETURN rc = SQL_SUCCESS;
  SQLRETURN rc2 = SQL_SUCCESS;
  SQLHANDLE hstmt1, hstmt2;
  SQLHANDLE hARD, hAPD, hIRD, hIPD; /* descriptor handles */
  SQLCHAR *stmt1 = (SQLCHAR *) 
    "CREATE TABLE DESCTABLE (SOURCE_COL1 char(10), SOURCE_COL2 integer)";
  SQLCHAR *stmt2 = (SQLCHAR *)
    "CREATE TABLE DESCTABLECOPY (TARGET_COL1 char(10), TARGET_COL2 integer)";
  SQLCHAR *stmt3 = (SQLCHAR *) "INSERT INTO DESCTABLE VALUES ('column 1', 1)";
  SQLCHAR *stmt4 = (SQLCHAR *) "INSERT INTO DESCTABLE VALUES ('column 2', 2)";
  SQLCHAR *stmt5 = (SQLCHAR *) "SELECT * FROM DESCTABLE";
  SQLCHAR *stmt6 = (SQLCHAR *) "INSERT INTO DESCTABLECOPY VALUES (?,?)";
  SQLCHAR *stmt7 = (SQLCHAR *) "SELECT * FROM DESCTABLECOPY";
  SQLCHAR sourcecol1[11], targetcol1[11];
  SQLINTEGER sourcecol2, targetcol2;
  SQLINTEGER indicator;
  SQLINTEGER rowCount = 0;
  
  printf("\n-----------------------------------------------------------");
  printf("\nUSE THE CLI FUNCTIONS\n");
  printf("  SQLCopyDesc\n");
  printf("Other CLI FUNCTIONS\n");
  printf("  SQLSetConnectAttr\n");
  printf("  SQLAllocHandle\n");
  printf("  SQLExecDirect\n");
  printf("  SQLBindCol\n");
  printf("  SQLGetStmtAttr\n");
  printf("  SQLPrepare\n");
  printf("  SQLExecute\n");
  printf("  SQLFetch\n");
  printf("  SQLFreeHandle\n");
  printf("TO COPY DESCRIPTORS:\n");

  /* set AUTOCOMMIT on */
  rc = SQLSetConnectAttr(hdbc,
                         SQL_ATTR_AUTOCOMMIT,
                         (SQLPOINTER)SQL_AUTOCOMMIT_ON,
                         SQL_NTS);
  DBC_HANDLE_CHECK(hdbc, rc);

  /* allocate a statement handle */
  rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt1);
  DBC_HANDLE_CHECK(hdbc, rc);

  /* allocate a statement handle */
  rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt2);
  DBC_HANDLE_CHECK(hdbc, rc);
  
  /* create a temporary source table to copy from */
  rc = SQLExecDirect(hstmt1, stmt1, SQL_NTS);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);
  printf("\n  Create source table DESCTABLE to copy from:\n");
  printf("    CREATE TABLE DESCTABLE ");
  printf("(SOURCE_COL1 char(10), SOURCE_COL2 integer)\n");

  /* create a temporary target table to copy into from the source table */
  rc = SQLExecDirect(hstmt2, stmt2, SQL_NTS);
  STMT_HANDLE_CHECK(hstmt2, hdbc, rc);
  printf("\n  Create target table DESCTABLECOPY to copy into from ");
  printf("source DESCTABLE:\n");
  printf("    CREATE TABLE DESCTABLECOPY ");
  printf("(TARGET_COL1 char(10), TARGET_COL2 integer)\n");
  
  /* insert 2 rows of data into the source table */
  rc = SQLExecDirect(hstmt1, stmt3, SQL_NTS);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);
  printf("\n  Insert the following row into the source table DESCTABLE:\n");
  printf("    SOURCE_COL1: column 1     SOURCE_COL2: 1\n");
  
  rc = SQLExecDirect(hstmt1, stmt4, SQL_NTS);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);
  printf("\n  Insert the following row into the source table DESCTABLE:\n");
  printf("    SOURCE_COL1: column 2     SOURCE_COL2: 2\n");
  
  /* select the rows from the source table */
  rc = SQLExecDirect(hstmt1, stmt5, SQL_NTS);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);
  
  /* bind the columns of the source table */
  SQLBindCol(hstmt1, 1, SQL_C_CHAR, sourcecol1, 11, NULL);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);
  
  SQLBindCol(hstmt1, 2, SQL_C_LONG, &sourcecol2, 0, NULL);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);

  /* get the ARD of the source */
  rc = SQLGetStmtAttr(hstmt1,
		      SQL_ATTR_APP_ROW_DESC,
		      &hARD,
		      SQL_IS_INTEGER,
		      &indicator);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);
  /* get the IRD of the source */
  rc = SQLGetStmtAttr(hstmt1,
		      SQL_ATTR_IMP_ROW_DESC,
		      &hIRD,
		      SQL_IS_INTEGER,
		      &indicator);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);
  
  /* explicitly allocate an application descriptor */
  rc = SQLAllocHandle(SQL_HANDLE_DESC, hdbc, &hAPD);
  DBC_HANDLE_CHECK(hdbc, rc);
  
  /* get reference to implicit IPD on hstmt2 */
  rc = SQLGetStmtAttr(hstmt2,
		      SQL_ATTR_IMP_PARAM_DESC,
		      &hIPD,
		      SQL_IS_INTEGER,
		      &indicator);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);

  /* copy source ARD to target APD */
  rc = SQLCopyDesc(hARD, hAPD);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);
  printf("\n  Copy the source ARD to the target APD.\n");

  /* copy source IRD to target IPD */
  rc = SQLCopyDesc(hIRD, hIPD);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);
  printf("  Copy the source IRD to the target IPD.\n");

  rc = SQLPrepare(hstmt2, stmt6, SQL_NTS);
  STMT_HANDLE_CHECK(hstmt2, hdbc, rc);

  /* override hstmt2's implicit APD with
     the explicitly allocated application descriptor */
  rc = SQLSetStmtAttr(hstmt2,
		      SQL_ATTR_APP_PARAM_DESC,
		      (SQLPOINTER)hAPD,
		      SQL_IS_POINTER);
  STMT_HANDLE_CHECK(hstmt2, hdbc, rc);
  printf("\n  Override the implicit APD with the explicitly allocated \n");
  printf("    application descriptor.\n");
  
  /* fetch rows from the source table and insert into the target table */
  rc = SQLFetch(hstmt1);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);
  printf("\n  Fetch the rows from the source table:\n");
  printf("    SELECT * FROM DESCTABLE\n");
  printf("  And insert into the target table:\n");
  printf("    INSERT INTO DESCTABLECOPY VALUES (?,?)\n");
  while (rc == SQL_SUCCESS && rc2 == SQL_SUCCESS)
  {
    printf("\n    SOURCE_COL1: %s     SOURCE_COL2: %d\n",
           sourcecol1, sourcecol2);
    
    /* insert the row from the source table into the target table */
    rc2 = SQLExecute(hstmt2);
    STMT_HANDLE_CHECK(hstmt2, hdbc, rc2);
    rc = SQLFetch(hstmt1);
  }

  /* bind the columns for the target table */
  SQLBindCol(hstmt2, 1, SQL_C_CHAR, targetcol1, 11, NULL);
  STMT_HANDLE_CHECK(hstmt2, hdbc, rc);
  SQLBindCol(hstmt2, 2, SQL_C_LONG, &targetcol2, 0, NULL);
  STMT_HANDLE_CHECK(hstmt2, hdbc, rc);

  /* select the rows from the target table */
  rc = SQLExecDirect(hstmt2, stmt7, SQL_NTS);
  STMT_HANDLE_CHECK(hstmt2, hdbc, rc);
  printf("\n  Select the rows now in the target table:\n");
  printf("    SELECT * FROM DESCTABLECOPY\n");
  
  /* fetch the rows from the target table */
  rc = SQLFetch(hstmt2);
  STMT_HANDLE_CHECK(hstmt2, hdbc, rc);
  while (rc == 0)
  {
    printf("\n    TARGET_COL1: %s     TARGET_COL2: %d\n",
	   targetcol1, targetcol2);
    rc = SQLFetch(hstmt2);
  }
  
  rc = SQLEndTran(SQL_HANDLE_DBC, hdbc, SQL_ROLLBACK);
  DBC_HANDLE_CHECK(hdbc, rc);

  /* drop temporary tables */
  rc = DropTempTables(hdbc);
  
  SQLFreeHandle(SQL_HANDLE_STMT, hstmt1);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);
  SQLFreeHandle(SQL_HANDLE_STMT, hstmt2);
  STMT_HANDLE_CHECK(hstmt2, hdbc, rc);

  return rc;
} /* DescCopy */

/* helper function that drops the temporary tables
   used by the DescCopy function */
int DropTempTables (SQLHANDLE hdbc)
{
  SQLRETURN rc = 0;
  SQLHANDLE hstmt1, hstmt2;
  SQLCHAR *stmt1 = (SQLCHAR *) "DROP TABLE DESCTABLE";
  SQLCHAR *stmt2 = (SQLCHAR *) "DROP TABLE DESCTABLECOPY";

  rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt1);
  DBC_HANDLE_CHECK(hdbc, rc);
  rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt2);
  DBC_HANDLE_CHECK(hdbc, rc);

  /* drop desctable */
  rc = SQLExecDirect(hstmt1, stmt1, SQL_NTS);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);
  printf("\n  Drop the source table DESCTABLE.\n");

  /* drop desctablecopy */
  rc = SQLExecDirect(hstmt2, stmt2, SQL_NTS);
  STMT_HANDLE_CHECK(hstmt2, hdbc, rc);
  printf("\n  Drop the target table DESCTABLECOPY.\n");

  SQLFreeHandle(SQL_HANDLE_STMT, hstmt1);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);
  SQLFreeHandle(SQL_HANDLE_STMT, hstmt2);
  STMT_HANDLE_CHECK(hstmt2, hdbc, rc);
  
  return rc;
} /* DropTempTables */

/* get and set a single field of descriptor records */
int DescSetGetField(SQLHANDLE hdbc)
{
  SQLRETURN cliRC = SQL_SUCCESS;
  SQLRETURN rc = 0;
  SQLHANDLE hstmt, hstmt1;
  SQLHANDLE hIPD, hIRD, hIRD1, hARD; /* descriptor handles */
  SQLSMALLINT descFieldAllocType;
  SQLSMALLINT descFieldParameterType;
  /* SQL SELECT statements to be executed */
  SQLCHAR *stmt = (SQLCHAR *)
    "SELECT deptnumb, location FROM org WHERE division = ?";
  SQLCHAR *stmt1 = (SQLCHAR *)
    "SELECT deptnumb,location FROM org WHERE division = 'Western'";
  char divisionParam[15];

  struct
  {
    SQLINTEGER ind;
    SQLSMALLINT val;
  }
  deptnumb; /* variable to be bound to the DEPTNUMB column */

  struct
  {
    SQLINTEGER ind;
    SQLCHAR val[15];
  }
  location; /* variable to be bound to the LOCATION column */

  static char ALLOCTYPES[][21] =
  {
    "- No 0 Value-",
    "SQL_DESC_ALLOC_AUTO",
    "SQL_DESC_ALLOC_USER"
  };

  static char PARAMTYPE[][24] =
  {
    "- No 0 Value-",
    "SQL_PARAM_INPUT",
    "SQL_PARAM_INPUT_OUTPUT",
    "- No 3 Value -",
    "SQL_PARAM_OUTPUT"
  };

  int colCount;
  SQLCHAR descFieldTypeName[25];
  SQLCHAR descFieldLabel[25];
  SQLSMALLINT dept_no;
  char loc[15];
  char sp2[] = "  ", sp4[] = "    ";
  SQLINTEGER indicator;

  printf("\n-----------------------------------------------------------");
  printf("\nUSE THE CLI FUNCTIONS\n");
  printf("  SQLGetDescField\n");
  printf("  SQLSetDescField\n");
  printf("Other CLI FUNCTIONS\n");
  printf("  SQLSetConnectAttr\n");
  printf("  SQLAllocHandle\n");
  printf("  SQLGetStmtAttr\n");
  printf("  SQLPrepare\n");
  printf("  SQLBindParameter\n");
  printf("  SQLExecute\n");
  printf("  SQLBindCol\n");
  printf("  SQLFetch\n");
  printf("  SQLFreeHandle\n");
  printf("TO GET AND SET A SINGLE FIELD OF DESCRIPTOR RECORDS:\n");

  /* set AUTOCOMMIT on */
  cliRC = SQLSetConnectAttr(hdbc,
                            SQL_ATTR_AUTOCOMMIT,
                            (SQLPOINTER)SQL_AUTOCOMMIT_ON,
                            SQL_NTS);
  DBC_HANDLE_CHECK(hdbc, cliRC);

  /* allocate a statement handle */
  cliRC = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
  DBC_HANDLE_CHECK(hdbc, cliRC);

  /* allocate another statement handle */
  cliRC = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt1);
  DBC_HANDLE_CHECK(hdbc, cliRC);

  /* get the handle for the implicitly allocated descriptor */
  cliRC = SQLGetStmtAttr(hstmt,
                         SQL_ATTR_IMP_PARAM_DESC,
                         &hIPD,
                         SQL_IS_POINTER,
                         NULL);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  /* see how the header field SQL_DESC_ALLOC_TYPE is set */
  cliRC = SQLGetDescField(hIPD,
                          0, /* ignored for header fields */
                          SQL_DESC_ALLOC_TYPE,
                          &descFieldAllocType, /* result */
                          SQL_IS_SMALLINT,
                          NULL); /* ignored */
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  /* print the descriptor information */
  printf("\n  The IPD header descriptor field\n");
  printf("    SQL_DESC_ALLOC_TYPE is %s\n", ALLOCTYPES[descFieldAllocType]);

  printf("\n  Prepare the statement\n");
  printf("    %s\n", stmt);

  /* prepare a statement */
  cliRC = SQLPrepare(hstmt, stmt, SQL_NTS);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  printf("\n  Bind divisionParam to the statement\n");
  printf("    %s\n", stmt);

  /* bind divisionParam to the statement */
  cliRC = SQLBindParameter(hstmt,
                           1,
                           SQL_PARAM_INPUT,
                           SQL_C_CHAR,
                           SQL_CHAR,
                           15,
                           0,
                           divisionParam,
                           15,
                           NULL);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  /* see how the field SQL_DESC_PARAMETER_TYPE is set */
  cliRC = SQLGetDescField(hIPD,
                          1, /* look at the parameter */
                          SQL_DESC_PARAMETER_TYPE,
                          &descFieldParameterType, /* result */
                          SQL_IS_SMALLINT,
                          NULL); /* ignored */
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  /* print the descriptor information */
  printf("\n  The IPD record descriptor field\n");
  printf("    SQL_DESC_PARAMETER_TYPE is %s\n",
         PARAMTYPE[descFieldParameterType]);

  /* execute the statement for divisionParam = Eastern */
  printf("\n  Execute the prepared statement for\n");
  printf("    divisionParam = 'Eastern'\n");
  strcpy(divisionParam, "Eastern");

  /* execute the statement */
  cliRC = SQLExecute(hstmt);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  /* bind column DEPTNUMB to deptnumb variable */
  cliRC = SQLBindCol(hstmt, 1, SQL_C_SHORT, &deptnumb.val, 0, &deptnumb.ind);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  /* bind column LOCATION to location variable */
  cliRC = SQLBindCol(hstmt, 2, SQL_C_CHAR, location.val, 15, &location.ind);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  /* fetch each row, and display */
  printf("\n  Fetch each row and display.\n");
  printf("    DEPTNUMB LOCATION     \n");
  printf("    -------- -------------\n");

  /* fetch next row */
  cliRC = SQLFetch(hstmt);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  if (cliRC == SQL_NO_DATA_FOUND)
  {
    printf("\n  Data not found.\n");
  }
  while (cliRC != SQL_NO_DATA_FOUND)
  {
    printf("    %-8d %-14.14s\n", deptnumb.val, location.val);

    /* fetch next row */
    cliRC = SQLFetch(hstmt);
    STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);
  }

  /* get the handle for the implicitly allocated descriptor */
  cliRC = SQLGetStmtAttr(hstmt,
                         SQL_ATTR_IMP_ROW_DESC,
                         &hIRD,
                         SQL_IS_POINTER,
                         NULL);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  /* print out some implementation row descriptor fields
     from the last SQLFetch call above */
  for (colCount = 1; colCount <= 2; colCount++)
  {
    printf("\n  Information for column %i\n", colCount);

    /* see how the descriptor record field SQL_DESC_TYPE_NAME is set */
    rc = SQLGetDescField(hIRD,
                         (SQLSMALLINT)colCount,
                         SQL_DESC_TYPE_NAME, /* record field */
                         descFieldTypeName, /* result */
                         25,
                         NULL); /* ignored */
    STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

    printf("    IRD record descriptor field\n");
    printf("      SQL_DESC_TYPE_NAME is %s\n", descFieldTypeName);

    /* see how the descriptor record field SQL_DESC_LABEL is set */
    rc = SQLGetDescField(hIRD,
                         (SQLSMALLINT)colCount,
                         SQL_DESC_LABEL, /* record field */
                         descFieldLabel, /* result */
                         25,
                         NULL); /* ignored */
    STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

    printf("    IRD record descriptor field\n");
    printf("      SQL_DESC_LABEL is %s\n", descFieldLabel);

  }
  printf("\n%sPrepare the statement\n", sp2);
  printf("%s%s\n", sp4, stmt1);

  /* prepare a statement */
  cliRC = SQLPrepare(hstmt1, stmt1, SQL_NTS);
  STMT_HANDLE_CHECK(hstmt1, hdbc, cliRC);

  /* get the handle for the implicitly allocated descriptor */
  cliRC = SQLGetStmtAttr(hstmt1,
                         SQL_ATTR_APP_ROW_DESC,
                         &hARD,
                         SQL_IS_INTEGER,
                         &indicator);
  STMT_HANDLE_CHECK(hstmt1, hdbc, cliRC);

  /* execute the statement */
  cliRC = SQLExecute(hstmt1);
  STMT_HANDLE_CHECK(hstmt1, hdbc, cliRC);

  /* bind column to variables */
  cliRC = SQLBindCol(hstmt1, 2, SQL_C_CHAR, location.val, 15, &indicator);
  STMT_HANDLE_CHECK(hstmt1, hdbc, cliRC);

  /* set a single field of a descriptor record */
  rc = SQLSetDescField(hARD,
                       1,
                       SQL_DESC_TYPE,
                       (SQLPOINTER)SQL_SMALLINT,
                       SQL_IS_SMALLINT);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);

  /* set a single field of a descriptor record */
  rc = SQLSetDescField(hARD,
                       1,
                       SQL_DESC_DATA_PTR,
                       &dept_no, /* value set to the field */
                       SQL_IS_SMALLINT);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);

  /* set a single field of a descriptor record */
  rc = SQLSetDescField(hARD,
                       2,
                       SQL_DESC_TYPE,
                       (SQLPOINTER)SQL_CHAR,
                       SQL_IS_SMALLINT);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);

  /* set a single field of a descriptor record */
  rc = SQLSetDescField(hARD,
                       2,
                       SQL_DESC_LENGTH,
                       (SQLPOINTER)15,
                       SQL_IS_INTEGER);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);

  /* set a single field of a descriptor record */
  rc = SQLSetDescField(hARD, 2, SQL_DESC_DATA_PTR, (SQLPOINTER)loc, 15);
  STMT_HANDLE_CHECK(hstmt1, hdbc, rc);

  /* fetch each row, and display */
  printf("\n%sFetch rows and display after using SetDescField.\n", sp2);
  printf("%sDEPTNUMB LOCATION     \n", sp4);
  printf("%s-------- -------------\n", sp4);

  /* fetch next row */
  cliRC = SQLFetch(hstmt1);
  STMT_HANDLE_CHECK(hstmt1, hdbc, cliRC);

  if (cliRC == SQL_NO_DATA_FOUND)
  {
    printf("\n  Data not found.\n");
  }
  if (cliRC == SQL_SUCCESS_WITH_INFO)
  {
    printf("\n  SUCCESS_WITH_INFO\n");
  }
  while (cliRC != SQL_NO_DATA_FOUND)
  {
    printf("%s%-8d %s\n", sp4, dept_no, loc);

    /* fetch next row */
    cliRC = SQLFetch(hstmt1);
  }
  STMT_HANDLE_CHECK(hstmt1, hdbc, cliRC);

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

  /* free another statement1 handle */
  cliRC = SQLFreeHandle(SQL_HANDLE_STMT, hstmt1);
  STMT_HANDLE_CHECK(hstmt, hdbc, cliRC);

  return rc;
} /* DescSetGetField */