Skip to main content

 
IBM Power Systems software  >  IBM i  > Software  > 

IBM DB2 for i

  

DB2 Example: SQL Process Extended Dynamic API Interface

#define _MULTI_THREADED
#include ‹pthread.h›
#include ‹stdio.h›
#include ‹stdlib.h›
#include ‹string.h›
#include ‹recio.h›
#include ‹pointer.h›
#include ‹unistd.h›
#include ‹errno.h›
#include ‹qsqprced.h›
#include ‹ctype.h›

#define ERR_BEGIN 0

#pragma linkage (RESULTS, OS)            /* link RESULTS program     */

void var1(void);
void var2(void);
void var3(void);
void var4(void);
void var5(void);
void var6(void);
void var7(void);
void var8(void);
void var9(void);
void var10(void);
void var11(void);
void var12(void);
void var13(void);
void var14(void);
void var15(void);
void var16(void);
void var17(void);
void var18(void);
void var19(void);
void var20(void);
void var21(void);
void var22(void);
void var23(void);
void var24(void);
void var25(void);
void var26(void);
void var27(void);
void var28(void);
void var29(void);
void var30(void);

void *thrdins1(void *parm);
void runchild(void);

static void checkResults(char *string, int rc) {
  if (rc) {
    printf("Thread error on: %s rc=%d\n", string, rc);
  }
  return;
}

/*****************************************************************************/
/*  Setup RESULTS structure for automation                                   */
/*****************************************************************************/
int clr_errmsg(void);
int pass(int rcv, char * rcvstate);
int fail(int rcv, char * rcvstate);
void verify(int rcv, char * rcvstate);
void extern RESULTS (char *varname,     /* declare RESULTS program   */
                     char *passfail,    /*                           */
                     char *errmsg,      /*                           */
                     char *testname,    /*                           */
                     char *lib,         /*                           */
                     char *file,        /*                           */
                     short int,         /*                           */
                     short int);        /*                           */
char varname  [11] = " ";               /* Variation Name            */
char passfail  [2] = "F";               /* pass or fail variation    */
char errmsg   [81] = " ";               /* error message for fail    */
char testname [10] = "$SQEDA";          /* test case name            */
char lib      [11] = "SQEDAST   ";      /* collection for report     */
char file     [10] = "EDARESULTS";      /* table for reporting       */
int  expcode       = 0;                 /* expected sqlcode          */
char expstate  [6] = "*****";           /* expected sqlstate         */
short int cnt1;                         /* cnt1 & cnt 2 are used to  */
short int cnt2;                         /* substr lib & file fields  */
char cmd[1000];

/*****************************************************************************/
/*  The following are structure definitions for SQLCA and SQLDA              */
/*****************************************************************************/
Qsq_sqlca_t sqlca1;
/*void extern QSQROUTE(SQLCA *, ... ); */

char sqlda1data[1000];
Qsq_sqlda_t *sqlda1 = (Qsq_sqlda_t *)(&sqlda1data);

Qsq_SQLP0300_t qsq;
Qsq_Error_t err;

char format[8];
char actfile[] = "SQEDAST/TESTDATA";

char data[1000];
char copydata[1000];
char temp[200];
char *stmttxt;

pthread_t thread;
int       rc=0;
int       okStatus = 12;
void      *status;

void DumpStruct(void);
void CommitStmt(void);

/******************************************************************************/
/*                     Main()                                                 */
/******************************************************************************/
int main(int argc, char **argv)
{
    char name[30];

    printf("\n\n");
    printf("**********************************************************\n");
    printf("*--------------Ext Dyn by QSQPRCED API-------------------*\n");
    printf("**********************************************************\n");
    printf("Initial Thread %.8x %.8x\n", pthread_getthreadid_np());

    memcpy(qsq.SQL_Package_Name,"EDAPKG    ",10);
    memcpy(qsq.Library_Name,"SQEDAST   ",10);
    memcpy(qsq.Main_Pgm,"$SQEDA    ",10);
    memcpy(qsq.Main_Lib,"SQEDAST   ",10);
    memcpy(qsq.Date_Format,"USA",3);
    qsq.Date_Separator = '/';
    memcpy(qsq.Time_Format, "USA", 3);
    qsq.Time_Separator  = ':';
    qsq.Decimal_Point = '.';
    qsq.Commitment_Control   = 'N';
    memcpy(qsq.Naming_Option,"SYS",3);

    err.ErrorCod = 0;
    memcpy(format,"SQLP0300",8);
    memcpy(data,(char *)&qsq,sizeof(Qsq_SQLP0300_t));

/*  exec sql whenever sqlerror continue;        */


/******************************************************************************/
/* Set expected codes and call variations                                     */
/*                                                                            */
/******************************************************************************/

  expcode = 0;
  strcpy(expstate, "00000");
  err.ErrorCod = 0;

  clr_errmsg();
/*  Variation 1.  Build package SQLPKG                               */
  var1();

/*  Variation 2.  Prepare a statement for INSERT                     */
  var2();
  clr_errmsg();
/*  Variation 3.  Execute a the prepared INSERT statement            */
  var3();
  clr_errmsg();
/*  Variation 4.  Prepare and execute a DELETE statement             */
  var4();
  clr_errmsg();
/*  Variation 5.  Create a simple cursor                             */
  var5();
  clr_errmsg();
/*  Variation 6.  Open  a simple cursor                              */
  var6();
  clr_errmsg();
/*  Variation 7.  Fetch a simple cursor                              */
  var7();
  clr_errmsg();
/*  Variation 8.  Close a simple cursor                              */
  var8();
  clr_errmsg();
/*  Variation 9.  Prepare a dynamic statement for INSERT             */
  var9();
  clr_errmsg();
/*  Variation 10.  Execute the Static INSERT Statement               */
  var10();
  clr_errmsg();
/*  Variation 11.  Prepare a dynamic statement for BLOCK INSERT      */
  var11();
  clr_errmsg();
/*  Variation 12.  Create a block cursor                             */
  var12();
  clr_errmsg();
/*  Variation 13.  Block fetch from prepared cursor                  */
  var13();
  clr_errmsg();
/*  Variation 14.  Close Block Fetch Cursor                          */
  var14();
  clr_errmsg();
/*  Variation 15.  Create a scrollable cursor                        */
  var15();
  clr_errmsg();
/*  Variation 16.  Open  a scrollable cursor                         */
  var16();
  clr_errmsg();
/*  Variation 17.  Fetch FIRST from a scrollable cursor              */
  var17();
  clr_errmsg();
/*  Variation 18.  Fetch NEXT from a scrollable cursor               */
  var18();
  clr_errmsg();
/*  Runchild.  Create child thread and run variations 19 to 29       */
  runchild();

/*******************Explicit close and Cleanup************************/
  clr_errmsg();
  printf("----Program terminated normally----");
  return(0);
}

/*********************************************************************/
/*  Variation 1.  Build package SQLPKG                               */
/*********************************************************************/
void var1()
{
  sqlda1->sqld    = 0;
  sqlda1->sqln    = 99;
  sqlda1->sqldabc = sqlda1->sqln * 80 + 16;

  qsq.Function = '1';
  qsq.Commitment_Control   = 'N';
  qsq.Open_Options = 0x90;       /* write authority */
  memcpy(qsq.Statement_Name, "CREATEPACKAGE1           ", 18);
  memcpy(qsq.Cursor_Name, "UndefinedCursor            ", 18);
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);

  expcode = 0;
  strcpy(expstate, "00000");

  printf("\n**var1** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Package Created\n");
  } else  {
    printf("Package create --FAILED--\n");
    printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }

}

/*********************************************************************/
/*  Variation 2.  Prepare a statement for INSERT                     */
/*********************************************************************/
void var2()
{
  int x;
  qsq.Function = '2';
  qsq.Open_Options = 0x90;         /*  write authority  */

  sqlda1->sqln = 99;
  sqlda1->sqld = 0;
  sqlda1->sqldabc = sqlda1->sqln * 80 + 16;

  memcpy(qsq.Statement_Name, "INSERTROW1USINGFULLTEXTDESC", 18);
  strcpy(temp, "INSERT into ");
  strcat(temp, actfile);
  strcat(temp, " VALUES (9, 4.5, 2, 'inserted row')");
  qsq.Statement_Length = strlen(temp);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));
  memcpy(copydata,(char *)&qsq,sizeof(Qsq_SQLP0300_t));
  stmttxt = &data[0] + (offsetof(Qsq_SQLP0300_t, Statement_Length) +
    sizeof(qsq.Statement_Length));
  (void)memcpy(stmttxt, temp, strlen(temp));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);

  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var2** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Prepare Statment Completed\n");
  } else  {
    printf("Prepare Statment --FAILED--\n");
    DumpStruct();
    printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
  return;
}

/*********************************************************************/
/*  Variation 3.  Execute the Static INSERT Statement                */
/*********************************************************************/
void var3()
{
  qsq.Function = '3';
  qsq.Open_Options = 0x90;

  memcpy(qsq.Statement_Name, "INSERTROW1USINGFULLTEXTDESC", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));
  stmttxt = &data[0] + (offsetof(Qsq_SQLP0300_t, Statement_Length) +
    sizeof(qsq.Statement_Length));
  (void)memcpy(stmttxt, temp, strlen(temp));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);
  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var2** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Execute of insert statment Complete\n");
  } else  {
    printf("Execute of insert Statment --FAILED--\n");
    printf("   code: %d  state: %d err:%d msg: %s**\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
}

/*********************************************************************/
/*  Variation 4.  Prepare and execute delete statement               */
/*********************************************************************/
void var4()
{
  qsq.Function = '2';
  qsq.Open_Options = 0x90;         /*  WRITE authority  */

  sqlda1->sqln = 99;
  sqlda1->sqld = 0;
  sqlda1->sqldabc = sqlda1->sqln * 80 + 16;

  memcpy(qsq.Statement_Name, "DELETEALLINSERTEDIDS", 18);
  strcpy(temp, "DELETE FROM ");
  strcat(temp, actfile);
  strcat(temp, " WHERE ID > 5");
  qsq.Statement_Length = strlen(temp);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));
  stmttxt = &data[0] + (offsetof(Qsq_SQLP0300_t, Statement_Length) +
    sizeof(qsq.Statement_Length));
  (void)memcpy(stmttxt, temp, strlen(temp));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);

  qsq.Function = '3';
  qsq.Open_Options = 0x90;
  memcpy(qsq.Statement_Name, "DELETEALLINSERTEDIDS", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));
  stmttxt = &data[0] + (offsetof(Qsq_SQLP0300_t, Statement_Length) +
    sizeof(qsq.Statement_Length));
  (void)memcpy(stmttxt, temp, strlen(temp));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);
  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var4** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Prepare/Execute of delete statment Complete\n");
  } else  {
    printf("Prepare/Execute of delete Statment --FAILED--\n");
    printf("   code: %d  state: %d err:%d msg: %s**\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
}

/*********************************************************************/
/*  Variation 5.  Create a simple cursor                             */
/*********************************************************************/
void var5()
{
  qsq.Function = '2';
  qsq.Open_Options = 0x80;         /*  read authority  */
  qsq.Blocking_Factor = 1;

  sqlda1->sqln = 99;
  sqlda1->sqld = 4;
  sqlda1->sqldabc = sqlda1->sqln * 80 + 16;

  memcpy(qsq.Statement_Name, "SELECTSTMTGRP2CSRxxx", 18);
  memcpy(qsq.Cursor_Name, "SELECTWHEREGRP2CSRxxx", 18);
  strcpy(temp, "SELECT * FROM ");
  strcat(temp, actfile);
  strcat(temp, " WHERE grp = 1 ORDER BY ID");
  qsq.Statement_Length = strlen(temp);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));
  stmttxt = &data[0] + (offsetof(Qsq_SQLP0300_t, Statement_Length) +
    sizeof(qsq.Statement_Length));
  (void)memcpy(stmttxt, temp, strlen(temp));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);

  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var5** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Simple select cursor prepared\n");
  } else  {
    printf("Simple select cursor preparation --FAILED--\n");
    DumpStruct();
    printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
}

/*********************************************************************/
/*  Variation 6.  Open  a simple cursor                              */
/*********************************************************************/
void var6()
{
  char fetchvar[20][20];

  qsq.Function = '4';
  qsq.Open_Options = 0x80;         /*  read authority  */
  qsq.Blocking_Factor = 1;

  sqlda1->sqln = 99;
  sqlda1->sqld = 4;
  sqlda1->sqldabc = sqlda1->sqln * 80 + 16;

  sqlda1->sqlvar[0].sqltype = 496;
  sqlda1->sqlvar[0].sqllen = 4;
  sqlda1->sqlvar[0].sqldata = (char *)(&fetchvar[0]);
  sqlda1->sqlvar[1].sqltype = 480;
  sqlda1->sqlvar[1].sqllen = 8;
  sqlda1->sqlvar[1].sqldata = (char *)(&fetchvar[1]);
  sqlda1->sqlvar[2].sqltype = 496;
  sqlda1->sqlvar[2].sqllen = 4;
  sqlda1->sqlvar[2].sqldata = (char *)(&fetchvar[2]);
  sqlda1->sqlvar[3].sqltype = 452;
  sqlda1->sqlvar[3].sqllen = 20;
  sqlda1->sqlvar[3].sqldata = (char *)(&fetchvar[3]);

  memcpy(qsq.Statement_Name, "SELECTSTMTGRP2CSRxxx", 18);
  memcpy(qsq.Cursor_Name, "SELECTWHEREGRP2CSRxxx", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);

  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var6** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Simple select cursor opened\n");
  } else  {
    printf("Simple select cursor open --FAILED--\n");
    if (sqlca1.sqlcode == 502) {
       printf("   (Cursor is already open)\n");
    } else {
       printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
          sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
    }
  }
}

/*********************************************************************/
/*  Variation 7.  Fetch a simple cursor                              */
/*********************************************************************/
void var7()
{
  int  rtid;
  double rtdbl;
  int rtgrp;
  char rtchar20[20];
  char fetchvar[20][20];
  char *dummy;

  qsq.Function = '5';
  qsq.Open_Options = 0x80;         /*  read authority  */
  qsq.Blocking_Factor = 1;

  sqlda1->sqln = 99;
  sqlda1->sqld = 4;
  sqlda1->sqldabc = sqlda1->sqln * 80 + 16;

  sqlda1->sqlvar[0].sqltype = 496;
  sqlda1->sqlvar[0].sqllen = 4;
  sqlda1->sqlvar[0].sqldata = (char *)(&rtid);
  sqlda1->sqlvar[1].sqltype = 480;
  sqlda1->sqlvar[1].sqllen = 8;
  sqlda1->sqlvar[1].sqldata = (char *)(&rtdbl);
  sqlda1->sqlvar[2].sqltype = 496;
  sqlda1->sqlvar[2].sqllen = 4;
  sqlda1->sqlvar[2].sqldata = (char *)(&rtgrp);
  sqlda1->sqlvar[3].sqltype = 452;
  sqlda1->sqlvar[3].sqllen = 20;
  sqlda1->sqlvar[3].sqldata = (char *)(&rtchar20);

  memcpy(qsq.Statement_Name, "SELECTSTMTGRP2CSRxxx", 18);
  memcpy(qsq.Cursor_Name, "SELECTWHEREGRP2CSRxxx", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);

  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var7** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Simple select cursor fetched\n");
    printf("   #1 ID=%i dbl=%f grp=%i char20=%s*\n", rtid, rtdbl, rtgrp,
       rtchar20);
  } else  {
    printf("Simple select cursor fetch --FAILED--\n");
    printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
}

/*********************************************************************/
/*  Variation 8.  Close a simple cursor                              */
/*********************************************************************/
void var8()
{
  qsq.Function = '6';

  memcpy(qsq.Statement_Name, "SELECTSTMTGRP2CSRxxx", 18);
  memcpy(qsq.Cursor_Name, "SELECTWHEREGRP2CSRxxx", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);

  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var8** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Close simple select cursor \n");
  } else  {
    printf("CLOSE simple select cursor --FAILED--\n");
    printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
}
/*********************************************************************/
/*  Variation 9.  Prepare a dynamic statement for INSERT             */
/*********************************************************************/
void var9()
{
  qsq.Function = '2';
  qsq.Open_Options = 0x90;         /*  write authority  */

  sqlda1->sqln = 99;
  sqlda1->sqld = 4;
  sqlda1->sqldabc = sqlda1->sqln * 80 + 16;

  memcpy(qsq.Statement_Name, "InsertRow1DynamicValuesStmt", 18);
  strcpy(temp, "INSERT into ");
  strcat(temp, actfile);
  strcat(temp, " VALUES (?, ?, ?, ?)");
  qsq.Statement_Length = strlen(temp);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));
  stmttxt = &data[0] + (offsetof(Qsq_SQLP0300_t, Statement_Length) +
    sizeof(qsq.Statement_Length));
  (void)memcpy(stmttxt, temp, strlen(temp));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);

  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var9** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Prepare Dynamic Statment Completed\n");
  } else  {
    printf("Prepare Statment --FAILED--\n");
    DumpStruct();
    printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
}

/*********************************************************************/
/*  Variation 10.  Execute the Dynamic INSERT Statement              */
/*********************************************************************/
void var10()
{
  int insid;
  double insdbl;
  int insgrp;
  char inschar20[20];

  qsq.Function = '3';
  qsq.Open_Options = 0x90;

  sqlda1->sqln = 99;
  sqlda1->sqld = 4;
  sqlda1->sqldabc = sqlda1->sqln * 80 + 16;

  sqlda1->sqlvar[0].sqltype = 496;
  sqlda1->sqlvar[0].sqllen = 4;
  sqlda1->sqlvar[0].sqldata = (char *)(&insid);
  sqlda1->sqlvar[1].sqltype = 480;
  sqlda1->sqlvar[1].sqllen = 8;
  sqlda1->sqlvar[1].sqldata = (char *)(&insdbl);
  sqlda1->sqlvar[2].sqltype = 496;
  sqlda1->sqlvar[2].sqllen = 4;
  sqlda1->sqlvar[2].sqldata = (char *)(&insgrp);
  sqlda1->sqlvar[3].sqltype = 460;
  sqlda1->sqlvar[3].sqllen = 20;
  sqlda1->sqlvar[3].sqldata = (char *)(&inschar20);

  insid = 10;
  insdbl = 5.3333;
  insgrp = 3;
  strcpy(inschar20, "12345678901234567890");

  strcpy(inschar20, "Dynamic Insert");
  memcpy(qsq.Statement_Name, "InsertRow1DynamicValuesStmt", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));
  stmttxt = &data[0] + (offsetof(Qsq_SQLP0300_t, Statement_Length) +
    sizeof(qsq.Statement_Length));
  (void)memcpy(stmttxt, temp, strlen(temp));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);
  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var10** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Execute dynamic insert statment Complete\n");
  } else  {
    printf("Execute dynamic insert Statment --FAILED--\n");
    printf("   code: %d  state: %d err:%d msg: %s**\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
}

/*********************************************************************/
/*  Variation 11.  Prepare a dynamic statement for BLOCK INSERT      */
/*********************************************************************/
void var11()
{
  _Packed struct {
    long sid;
    double  sdbl;
    long sgrp;
    char schar20[20];
  } fstruct[5];
  _Packed struct {
    int inid;
    int indbl;
    int ingrp;
    int inchar20;
   } instruct[5];

  int x;
  int insid[5];
  double insdbl[5];
  int insgrp[5];
  char inschar20[5][20];

  qsq.Function = '2';
  qsq.Open_Options = 0x90;         /*  write authority  */

  sqlda1->sqln = 99;
  sqlda1->sqld = 4;
  sqlda1->sqldabc = sqlda1->sqln * 80 + 16;

  memcpy(qsq.Statement_Name, "BlockInsertDynamicStatement", 18);
  strcpy(temp, "INSERT into ");
  strcat(temp, actfile);
  strcat(temp, " (ID, dbl, grp, char20) ? ROWS VALUES ");
  strcat(temp, "(?, ?, ?, ?)");

  qsq.Statement_Length = strlen(temp);
  qsq.Rows_To_Insert = 1;

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));
  stmttxt = &data[0] + (offsetof(Qsq_SQLP0300_t, Statement_Length) +
    sizeof(qsq.Statement_Length));
  (void)memcpy(stmttxt, temp, strlen(temp));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);

  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var11** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Prepare Block Insert Completed\n");
  } else  {
    printf("Prepare Block Insert --FAILED--\n");
    DumpStruct();
    printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }



  sqlda1->sqlvar[0].sqltype = 496;
  sqlda1->sqlvar[0].sqllen = 4;
  sqlda1->sqlvar[0].sqldata = (char *)(&fstruct[0].sid);
  sqlda1->sqlvar[1].sqltype = 480;
  sqlda1->sqlvar[1].sqllen = 8;
  sqlda1->sqlvar[1].sqldata = (char *)(&fstruct[0].sdbl);
  sqlda1->sqlvar[2].sqltype = 496;
  sqlda1->sqlvar[2].sqllen = 4;
  sqlda1->sqlvar[2].sqldata = (char *)(&fstruct[0].sgrp);
  sqlda1->sqlvar[3].sqltype = 452;
  sqlda1->sqlvar[3].sqllen = 20;
  sqlda1->sqlvar[3].sqldata = (char *)(&(fstruct[0].schar20[0]));
  sqlda1->sqlvar[0].sqlind = (short *)(&instruct[0].inid);
  sqlda1->sqlvar[1].sqlind = (short *)(&instruct[0].indbl);
  sqlda1->sqlvar[2].sqlind = (short *)(&instruct[0].ingrp);
  sqlda1->sqlvar[3].sqlind = (short *)(&instruct[0].inchar20);

  fstruct[0].sid = 15;
  fstruct[0].sdbl = 3.1415;
  fstruct[0].sgrp = 4;
  strcpy(fstruct[0].schar20, "12345678901234567890");
  strcpy(fstruct[0].schar20, "Block Ins Row 1");
  fstruct[1].sid = 16;
  fstruct[1].sdbl = 454.5;
  fstruct[1].sgrp = 4;
  strcpy(fstruct[1].schar20, "Block Ins Row 2");
  fstruct[2].sid = 17;
  fstruct[2].sdbl = 1.88e-3;
  fstruct[2].sgrp = 4;
  strcpy(fstruct[2].schar20, "Block Ins Row 3");
  fstruct[3].sid = 18;
  fstruct[3].sdbl = 0.6666;
  fstruct[3].sgrp = 4;
  strcpy(fstruct[3].schar20, "Block Ins Row 4");
  strcpy(inschar20[0], "Block Ins Row 1");
  strcpy(inschar20[1], "Block Ins Row 2");
  strcpy(inschar20[2], "Block Ins Row 3");
  strcpy(inschar20[3], "Block Ins Row 4");
  strcpy(inschar20[4], "Block Ins Row 5");

/*      Execute block insert                                  */

  qsq.Rows_To_Insert = 4;
  sqlda1->sqln = 99;
  sqlda1->sqld = 4;
  sqlda1->sqldabc = sqlda1->sqln * 80 + 16;
  qsq.Function = '3';
  qsq.Open_Options = 0x90;
  memcpy(qsq.Statement_Name, "BlockInsertDynamicStatement", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));
  stmttxt = &data[0] + (offsetof(Qsq_SQLP0300_t, Statement_Length) +
    sizeof(qsq.Statement_Length));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);
  expcode = 0;
  strcpy(expstate, "00000");

  printf("********* ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Execute block insert statment Complete\n");
  } else  {
    printf("Execute block insert Statment --FAILED--\n");
    DumpStruct;
    printf("   code: %d  state: %d err:%d msg: %s**\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }

}


/*********************************************************************/
/*  Variation 12.  Prepare a block cursor                            */
/*********************************************************************/
void var12()
{
  qsq.Function = '2';
  qsq.Open_Options = 0x80;         /*  read authority  */
  qsq.Blocking_Factor = 1;
  qsq.Direct_Map = 'N';

  sqlda1->sqln = 99;
  sqlda1->sqld = 4;
  sqlda1->sqldabc = sqlda1->sqln * 80 + 16;

  memcpy(qsq.Statement_Name, "BlockSelectStatement", 18);
  memcpy(qsq.Cursor_Name, "BlockFetchCursorNxxxx", 18);
  strcpy(temp, "SELECT * FROM ");
  strcat(temp, actfile);
  strcat(temp, " WHERE grp = 1 ORDER BY ID");
  qsq.Statement_Length = strlen(temp);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));
  stmttxt = &data[0] + (offsetof(Qsq_SQLP0300_t, Statement_Length) +
    sizeof(qsq.Statement_Length));
  (void)memcpy(stmttxt, temp, strlen(temp));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);

  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var12** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Block fetch cursor prepared\n");
  } else  {
    printf("Block fetch cursor preparation --FAILED--\n");
    printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
}


/*********************************************************************/
/*  Variation 13.  Open a block fetch cursor                         */
/*********************************************************************/
void var13()
{
/*******************Open Block Fetch Cursor*******************/

  qsq.Function = '4';
  qsq.Open_Options = 0x80;         /*  read authority  */
  qsq.Blocking_Factor = 1;
  qsq.Scrollable_Option = 1;
  qsq.Direct_Map = 'N';


  memcpy(qsq.Statement_Name, "BlockSelectStatement", 18);
  memcpy(qsq.Cursor_Name, "BlockFetchCursorNxxxx", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);

  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var13** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Block fetch cursor opened\n");
  } else  {
    printf("Block fetch cursor open --FAILED--\n");
    if (sqlca1.sqlcode == 502) {
       printf("(FETCH Cursor is already open)\n");
    } else {
       printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
          sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
    }
  }
}

/*********************************************************************/
/*  Variation 14.  Block fetch from prepared cursor                  */
/*********************************************************************/
void var14()
{
  _Packed struct {
    long sid;
    double  sdbl;
    long sgrp;
    char schar20[21];
  } fstruct[5];

  short int  rtid[5];
  double rtdbl[5];
  short int rtgrp[5];
  char rtchar20[21][21];
  char fetchvar[20][20];
  char *dummy;
  char copystruct[100];

  qsq.Function = '5';
  qsq.Open_Options = 0x80;         /*  read authority  */
  qsq.Blocking_Factor = 3;
  qsq.Position_Option = 2;

  sqlda1->sqln = 99;
  sqlda1->sqld = 4;
  sqlda1->sqldabc = sqlda1->sqln * 80 + 16;

  sqlda1->sqlvar[0].sqltype = 496;
  sqlda1->sqlvar[0].sqllen = 4;
  sqlda1->sqlvar[0].sqldata = (char *)(&(fstruct[0].sid));
  sqlda1->sqlvar[1].sqltype = 480;
  sqlda1->sqlvar[1].sqllen = 8;
  sqlda1->sqlvar[1].sqldata = (char *)(&(fstruct[0].sdbl));
  sqlda1->sqlvar[2].sqltype = 496;
  sqlda1->sqlvar[2].sqllen = 4;
  sqlda1->sqlvar[2].sqldata = (char *)(&(fstruct[0].sgrp));
  sqlda1->sqlvar[3].sqltype = 460;
  sqlda1->sqlvar[3].sqllen = 21;
  sqlda1->sqlvar[3].sqldata = (char *)(&(fstruct[0].schar20[0]));

  memcpy(qsq.Cursor_Name, "BlockFetchCursorNxxxx", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);



  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var14** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("BLOCK Fetch cursor Completed\n");
    printf("  ID=%i dbl=%f grp=%i char20=%s*(%i)\n", fstruct[0].sid,
      fstruct[0].sdbl, fstruct[0].sgrp, fstruct[0].schar20,
      strlen(fstruct[0].schar20));
    printf("  ID=%i dbl=%f grp=%i char20=%s*(%i)\n", fstruct[1].sid,
      fstruct[1].sdbl, fstruct[1].sgrp, fstruct[1].schar20,
      strlen(fstruct[1].schar20));
    printf("  ID=%i dbl=%f grp=%i char20=%s*(%i)\n", fstruct[2].sid,
      fstruct[2].sdbl, fstruct[2].sgrp, fstruct[2].schar20,
      strlen(fstruct[2].schar20));
  } else  {
    printf("BLOCK FETCH cursor fetch --FAILED--\n");
    DumpStruct();
    printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
}



/*********************************************************************/
/*  Variation 15.  Create a scrollable cursor                        */
/*********************************************************************/
void var15()
{
  qsq.Function = '2';
  qsq.Open_Options = 0x80;         /*  read authority  */

  memcpy(qsq.Statement_Name, "ScrollableStatement", 18);
  memcpy(qsq.Cursor_Name, "SCROLLABLECURSORxxxxx", 18);
  strcpy(temp, "SELECT * FROM ");
  strcat(temp, actfile);
  strcat(temp, " ORDER BY ID");
  qsq.Statement_Length = strlen(temp);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));
  stmttxt = &data[0] + (offsetof(Qsq_SQLP0300_t, Statement_Length) +
    sizeof(qsq.Statement_Length));
  (void)memcpy(stmttxt, temp, strlen(temp));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);

  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var15** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Scrollable cursor prepared\n");
  } else  {
    printf("Scrollable cursor preparation --FAILED--\n");
    DumpStruct();
    printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
}

/*********************************************************************/
/*  Variation 16.  Open  a scrollable cursor                         */
/*********************************************************************/
void var16()
{
  char fetchvar[20][20];

  qsq.Function = '4';
  qsq.Open_Options = 0x80;         /*  read authority  */
  qsq.Blocking_Factor = 1;
  qsq.Scrollable_Option = 1;

  memcpy(qsq.Statement_Name, "ScrollableStatement", 18);
  memcpy(qsq.Cursor_Name, "SCROLLABLECURSORxxxxx", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);

  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var16** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Scrollable cursor opened\n");
  } else  {
    printf("Scrollable cursor open --FAILED--\n");
    if (sqlca1.sqlcode == 502) {
       printf("   (Scrollable Cursor is already open)\n");
    } else {
       printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
          sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
    }
  }
}

/*********************************************************************/
/*  Variation 17.  Fetch FIRST from a scrollable cursor              */
/*********************************************************************/
void var17()
{
  int  rtid;
  double rtdbl;
  int rtgrp;
  char rtchar20[20];
  char fetchvar[20][20];
  char *dummy;

  qsq.Function = '5';
  qsq.Open_Options = 0x80;         /*  read authority  */
  qsq.Blocking_Factor = 1;
  qsq.Position_Option = 2;

  sqlda1->sqln = 99;
  sqlda1->sqld = 4;
  sqlda1->sqldabc = sqlda1->sqln * 80 + 16;

  sqlda1->sqlvar[0].sqltype = 496;
  sqlda1->sqlvar[0].sqllen = 4;
  sqlda1->sqlvar[0].sqldata = (char *)(&rtid);
  sqlda1->sqlvar[1].sqltype = 480;
  sqlda1->sqlvar[1].sqllen = 8;
  sqlda1->sqlvar[1].sqldata = (char *)(&rtdbl);
  sqlda1->sqlvar[2].sqltype = 496;
  sqlda1->sqlvar[2].sqllen = 4;
  sqlda1->sqlvar[2].sqldata = (char *)(&rtgrp);
  sqlda1->sqlvar[3].sqltype = 452;
  sqlda1->sqlvar[3].sqllen = 20;
  sqlda1->sqlvar[3].sqldata = (char *)(&rtchar20);

  memcpy(qsq.Cursor_Name, "SCROLLABLECURSORxxxxx", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);

  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var17** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Scrollable cursor fetched first\n");
    printf("  ID=%i dbl=%f grp=%i char20=%s*\n", rtid, rtdbl, rtgrp,
       rtchar20);
  } else  {
    printf("Simple select cursor fetch --FAILED--\n");
    DumpStruct();
    printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
}

/*********************************************************************/
/*  Variation 18.  Fetch NEXT from a scrollable cursor               */
/*********************************************************************/
void var18()
{
  int  rtid;
  double rtdbl;
  int rtgrp;
  char rtchar20[20];
  char fetchvar[20][20];
  char *dummy;

  qsq.Function = '5';
  qsq.Open_Options = 0x80;         /*  read authority  */
  qsq.Blocking_Factor = 1;
  qsq.Position_Option = 0;         /*  Fetch Next      */

  sqlda1->sqln = 99;
  sqlda1->sqld = 4;
  sqlda1->sqldabc = sqlda1->sqln * 80 + 16;

  sqlda1->sqlvar[0].sqltype = 496;
  sqlda1->sqlvar[0].sqllen = 4;
  sqlda1->sqlvar[0].sqldata = (char *)(&rtid);
  sqlda1->sqlvar[1].sqltype = 480;
  sqlda1->sqlvar[1].sqllen = 8;
  sqlda1->sqlvar[1].sqldata = (char *)(&rtdbl);
  sqlda1->sqlvar[2].sqltype = 496;
  sqlda1->sqlvar[2].sqllen = 4;
  sqlda1->sqlvar[2].sqldata = (char *)(&rtgrp);
  sqlda1->sqlvar[3].sqltype = 452;
  sqlda1->sqlvar[3].sqllen = 20;
  sqlda1->sqlvar[3].sqldata = (char *)(&rtchar20);

  memcpy(qsq.Cursor_Name, "SCROLLABLECURSORxxxxx", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);

  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var18** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Scrollable cursor fetched next\n");
    printf("  ID=%i dbl=%f grp=%i char20=%s*\n", rtid, rtdbl, rtgrp,
       rtchar20);
  } else  {
    printf("Simple select cursor fetch next --FAILED--");
    DumpStruct();
    printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
}

/*********************************************************************/
/*-------------------------------------------------------------------*/
/*--------  Child Thread is created between var18 & var19  ----------*/
/*------  BLOCK and SCROLLABLE cursors should still be open  --------*/
/*-------------------------------------------------------------------*/
/*********************************************************************/


/*********************************************************************/
/*  Variation 19.  Fetch FIRST from a scrollable cursor              */
/*********************************************************************/
void var19()
{
  int  rtid;
  double rtdbl;
  int rtgrp;
  char rtchar20[20];
  char fetchvar[20][20];
  char *dummy;

  qsq.Function = '5';
  qsq.Open_Options = 0x80;         /*  read authority  */
  qsq.Blocking_Factor = 1;
  qsq.Position_Option = 2;

  sqlda1->sqln = 99;
  sqlda1->sqld = 4;
  sqlda1->sqldabc = sqlda1->sqln * 80 + 16;

  sqlda1->sqlvar[0].sqltype = 496;
  sqlda1->sqlvar[0].sqllen = 4;
  sqlda1->sqlvar[0].sqldata = (char *)(&rtid);
  sqlda1->sqlvar[1].sqltype = 480;
  sqlda1->sqlvar[1].sqllen = 8;
  sqlda1->sqlvar[1].sqldata = (char *)(&rtdbl);
  sqlda1->sqlvar[2].sqltype = 496;
  sqlda1->sqlvar[2].sqllen = 4;
  sqlda1->sqlvar[2].sqldata = (char *)(&rtgrp);
  sqlda1->sqlvar[3].sqltype = 452;
  sqlda1->sqlvar[3].sqllen = 20;
  sqlda1->sqlvar[3].sqldata = (char *)(&rtchar20);

  memcpy(qsq.Cursor_Name, "SCROLLABLECURSORxxxxx", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);

  expcode = 0;
  strcpy(expstate, "00000");
                 */
  printf("**var19** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Scrollable cursor fetched first\n");
    printf("  ID=%i dbl=%f grp=%i char20=%s*\n", rtid, rtdbl, rtgrp,
       rtchar20);
  } else  {
    printf("Scrollable cursor fetch first --FAILED--\n");
    printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
}

/*********************************************************************/
/*  Variation 20.  Close Scrollable Cursor                           */
/*********************************************************************/
void var20()
{
  qsq.Function = '6';

  memcpy(qsq.Cursor_Name, "SCROLLABLECURSORxxxxx", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);

  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var20** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Close scrollable cursor \n");
  } else  {
    printf("CLOSE scrollable cursor --FAILED--\n");
    printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
}

/*********************************************************************/
/*  Variation 21.  Open  a scrollable cursor                         */
/*********************************************************************/
void var21()
{
  qsq.Function = '4';
  qsq.Open_Options = 0x80;         /*  read authority  */
  qsq.Blocking_Factor = 1;
  qsq.Scrollable_Option = 1;

  memcpy(qsq.Statement_Name, "ScrollableStatement", 18);
  memcpy(qsq.Cursor_Name, "SCROLLABLECURSORxxxxx", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);

  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var21** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Scrollable cursor opened\n");
  } else  {
    printf("Scrollable cursor open --FAILED--\n");
    if (sqlca1.sqlcode == 502) {
       printf("   (Scrollable Cursor is already open)\n");
    } else {
       printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
          sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
    }
  }
}

/*********************************************************************/
/*  Variation 22.  Fetch FIRST from a scrollable cursor              */
/*********************************************************************/
void var22()
{
  int  rtid;
  double rtdbl;
  int rtgrp;
  char rtchar20[20];
  char fetchvar[20][20];
  char *dummy;

  qsq.Function = '5';
  qsq.Open_Options = 0x80;         /*  read authority  */
  qsq.Blocking_Factor = 1;
  qsq.Position_Option = 2;

  sqlda1->sqln = 99;
  sqlda1->sqld = 4;
  sqlda1->sqldabc = sqlda1->sqln * 80 + 16;

  sqlda1->sqlvar[0].sqltype = 496;
  sqlda1->sqlvar[0].sqllen = 4;
  sqlda1->sqlvar[0].sqldata = (char *)(&rtid);
  sqlda1->sqlvar[1].sqltype = 480;
  sqlda1->sqlvar[1].sqllen = 8;
  sqlda1->sqlvar[1].sqldata = (char *)(&rtdbl);
  sqlda1->sqlvar[2].sqltype = 496;
  sqlda1->sqlvar[2].sqllen = 4;
  sqlda1->sqlvar[2].sqldata = (char *)(&rtgrp);
  sqlda1->sqlvar[3].sqltype = 452;
  sqlda1->sqlvar[3].sqllen = 20;
  sqlda1->sqlvar[3].sqldata = (char *)(&rtchar20);

  memcpy(qsq.Cursor_Name, "SCROLLABLECURSORxxxxx", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);

  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var22** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Scrollable cursor fetched first\n");
    printf("  ID=%i dbl=%f grp=%i char20=%s*\n", rtid, rtdbl, rtgrp,
       rtchar20);
  } else  {
    printf("Simple select cursor fetch --FAILED--\n");
    DumpStruct();
    printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
}

/*******************Create Block Fetch Cursor*******************/
/*********************************************************************/
/*  Variation 23.  Open block Fetch scrollable cursor                */
/*********************************************************************/
void var23()
{

  qsq.Function = '4';
  qsq.Open_Options = 0x80;         /*  read authority  */
  qsq.Blocking_Factor = 1;
  qsq.Scrollable_Option = 1;
  qsq.Direct_Map = 'N';


  memcpy(qsq.Statement_Name, "BlockSelectStatement", 18);
  memcpy(qsq.Cursor_Name, "BlockFetchCursorNxxxx", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);

  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var23** ");
  if (sqlca1.sqlcode == -502) {
    printf("Block fetch cursor alread open\n");
  } else  {
    printf("Block fetch cursor opened:  Variation  --FAILED--\n");
    printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
}

/*********************************************************************/
/*  Variation 24.  Block fetch from prepared cursor                  */
/*********************************************************************/
void var24()
{
  _Packed struct {
    long sid;
    double  sdbl;
    long sgrp;
    char schar20[21];
  } fstruct[5];

  short int  rtid[5];
  double rtdbl[5];
  short int rtgrp[5];
  char rtchar20[21][21];
  char fetchvar[20][20];
  char *dummy;
  char copystruct[100];

  qsq.Function = '5';
  qsq.Open_Options = 0x80;         /*  read authority  */
  qsq.Blocking_Factor = 3;
  qsq.Position_Option = 2;

  sqlda1->sqln = 99;
  sqlda1->sqld = 4;
  sqlda1->sqldabc = sqlda1->sqln * 80 + 16;

  sqlda1->sqlvar[0].sqltype = 496;
  sqlda1->sqlvar[0].sqllen = 4;
  sqlda1->sqlvar[0].sqldata = (char *)(&(fstruct[0].sid));
  sqlda1->sqlvar[1].sqltype = 480;
  sqlda1->sqlvar[1].sqllen = 8;
  sqlda1->sqlvar[1].sqldata = (char *)(&(fstruct[0].sdbl));
  sqlda1->sqlvar[2].sqltype = 496;
  sqlda1->sqlvar[2].sqllen = 4;
  sqlda1->sqlvar[2].sqldata = (char *)(&(fstruct[0].sgrp));
  sqlda1->sqlvar[3].sqltype = 460;
  sqlda1->sqlvar[3].sqllen = 21;
  sqlda1->sqlvar[3].sqldata = (char *)(&(fstruct[0].schar20[0]));

  memcpy(qsq.Cursor_Name, "BlockFetchCursorNxxxx", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);



  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var24** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("BLOCK Fetch cursor Completed\n");
    printf("  ID=%i dbl=%f grp=%i char20=%s*(%i)\n", fstruct[0].sid,
      fstruct[0].sdbl, fstruct[0].sgrp, fstruct[0].schar20,
      strlen(fstruct[0].schar20));
    printf("  ID=%i dbl=%f grp=%i char20=%s*(%i)\n", fstruct[1].sid,
      fstruct[1].sdbl, fstruct[1].sgrp, fstruct[1].schar20,
      strlen(fstruct[1].schar20));
    printf("  ID=%i dbl=%f grp=%i char20=%s*(%i)\n", fstruct[2].sid,
      fstruct[2].sdbl, fstruct[2].sgrp, fstruct[2].schar20,
      strlen(fstruct[2].schar20));
  } else  {
    printf("BLOCK FETCH cursor --FAILED--\n");
    DumpStruct();
    printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
}


/*********************************************************************/
/*  Variation 25.  Execute the Dynamic INSERT Statement from Child   */
/*********************************************************************/
void var25()
{
  int insid;
  double insdbl;
  int insgrp;
  char inschar20[20];

  qsq.Function = '3';
  qsq.Open_Options = 0x90;

  sqlda1->sqln = 99;
  sqlda1->sqld = 4;
  sqlda1->sqldabc = sqlda1->sqln * 80 + 16;

  sqlda1->sqlvar[0].sqltype = 496;
  sqlda1->sqlvar[0].sqllen = 4;
  sqlda1->sqlvar[0].sqldata = (char *)(&insid);
  sqlda1->sqlvar[1].sqltype = 480;
  sqlda1->sqlvar[1].sqllen = 8;
  sqlda1->sqlvar[1].sqldata = (char *)(&insdbl);
  sqlda1->sqlvar[2].sqltype = 496;
  sqlda1->sqlvar[2].sqllen = 4;
  sqlda1->sqlvar[2].sqldata = (char *)(&insgrp);
  sqlda1->sqlvar[3].sqltype = 460;
  sqlda1->sqlvar[3].sqllen = 20;
  sqlda1->sqlvar[3].sqldata = (char *)(&inschar20);

  insid = 90;
  insdbl = 33.333;
  insgrp = 9;

  strcpy(inschar20, "Child Dynamic Insert");
  memcpy(qsq.Statement_Name, "InsertRow1DynamicValuesStmt", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));
  stmttxt = &data[0] + (offsetof(Qsq_SQLP0300_t, Statement_Length) +
    sizeof(qsq.Statement_Length));
  (void)memcpy(stmttxt, temp, strlen(temp));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);
  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var25** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Execute dynamic insert statment Complete\n");
  } else  {
    printf("Execute dynamic insert Statment --FAILED--\n");
    printf("   code: %d  state: %d err:%d msg: %s**\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
}

/*********************************************************************/
/*  Variation 26.  Execute block insert from child thread            */
/*********************************************************************/
void var26()
{
  _Packed struct {
    long sid;
    double  sdbl;
    long sgrp;
    char schar20[20];
  } fstruct[5];
  _Packed struct {
    int inid;
    int indbl;
    int ingrp;
    int inchar20;
   } instruct[5];

  int x;
  int insid[5];
  double insdbl[5];
  int insgrp[5];
  char inschar20[5][20];

  sqlda1->sqlvar[0].sqltype = 496;
  sqlda1->sqlvar[0].sqllen = 4;
  sqlda1->sqlvar[0].sqldata = (char *)(&fstruct[0].sid);
  sqlda1->sqlvar[1].sqltype = 480;
  sqlda1->sqlvar[1].sqllen = 8;
  sqlda1->sqlvar[1].sqldata = (char *)(&fstruct[0].sdbl);
  sqlda1->sqlvar[2].sqltype = 496;
  sqlda1->sqlvar[2].sqllen = 4;
  sqlda1->sqlvar[2].sqldata = (char *)(&fstruct[0].sgrp);
  sqlda1->sqlvar[3].sqltype = 452;
  sqlda1->sqlvar[3].sqllen = 20;
  sqlda1->sqlvar[3].sqldata = (char *)(&(fstruct[0].schar20[0]));
  sqlda1->sqlvar[0].sqlind = (short *)(&instruct[0].inid);
  sqlda1->sqlvar[1].sqlind = (short *)(&instruct[0].indbl);
  sqlda1->sqlvar[2].sqlind = (short *)(&instruct[0].ingrp);
  sqlda1->sqlvar[3].sqlind = (short *)(&instruct[0].inchar20);

  fstruct[0].sid = 95;
  fstruct[0].sdbl = 6.022;
  fstruct[0].sgrp = 9;
  strcpy(fstruct[0].schar20, "Child Ins Row 1");
  fstruct[1].sid = 96;
  fstruct[1].sdbl = 1.1459;
  fstruct[1].sgrp = 9;
  strcpy(fstruct[1].schar20, "Child Ins Row 2");
  fstruct[2].sid = 97;
  fstruct[2].sdbl = 1.88e-3;
  fstruct[2].sgrp = 9;
  strcpy(fstruct[2].schar20, "Child Ins Row 3");
  fstruct[3].sid = 98;
  fstruct[3].sdbl = 87.5;
  fstruct[3].sgrp = 9;
  strcpy(fstruct[3].schar20, "Child Ins Row 4");
/*  strcpy(inschar20[0], "Child Ins Row 1");
  strcpy(inschar20[1], "Child Ins Row 2");
  strcpy(inschar20[2], "Child Ins Row 3");
  strcpy(inschar20[3], "Child Ins Row 4");                   */

/*      Execute block insert                                  */

  qsq.Rows_To_Insert = 4;
  sqlda1->sqln = 99;
  sqlda1->sqld = 4;
  sqlda1->sqldabc = sqlda1->sqln * 80 + 16;
  qsq.Function = '3';
  qsq.Open_Options = 0x90;
  memcpy(qsq.Statement_Name, "BlockInsertDynamicStatement", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));
  stmttxt = &data[0] + (offsetof(Qsq_SQLP0300_t, Statement_Length) +
    sizeof(qsq.Statement_Length));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);
  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var26** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Execute block insert statment Complete\n");
  } else  {
    printf("Execute block insert Statment --FAILED--\n");
    DumpStruct;
    printf("   code: %d  state: %d err:%d msg: %s**\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }

}


/*********************************************************************/
/*  Variation 27.  Fetch NEXT from a scrollable cursor               */
/*********************************************************************/
void var27()
{
  int  rtid;
  double rtdbl;
  int rtgrp;
  char rtchar20[20];
  char fetchvar[20][20];
  char *dummy;

  qsq.Function = '5';
  qsq.Open_Options = 0x80;         /*  read authority  */
  qsq.Blocking_Factor = 1;
  qsq.Position_Option = 0;         /*  Fetch Next      */

  sqlda1->sqln = 99;
  sqlda1->sqld = 4;
  sqlda1->sqldabc = sqlda1->sqln * 80 + 16;

  sqlda1->sqlvar[0].sqltype = 496;
  sqlda1->sqlvar[0].sqllen = 4;
  sqlda1->sqlvar[0].sqldata = (char *)(&rtid);
  sqlda1->sqlvar[1].sqltype = 480;
  sqlda1->sqlvar[1].sqllen = 8;
  sqlda1->sqlvar[1].sqldata = (char *)(&rtdbl);
  sqlda1->sqlvar[2].sqltype = 496;
  sqlda1->sqlvar[2].sqllen = 4;
  sqlda1->sqlvar[2].sqldata = (char *)(&rtgrp);
  sqlda1->sqlvar[3].sqltype = 452;
  sqlda1->sqlvar[3].sqllen = 20;
  sqlda1->sqlvar[3].sqldata = (char *)(&rtchar20);

  memcpy(qsq.Cursor_Name, "SCROLLABLECURSORxxxxx", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);

  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var27** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Scrollable cursor fetched next\n");
    printf("  ID=%i dbl=%f grp=%i char20=%s*\n", rtid, rtdbl, rtgrp,
       rtchar20);
  } else  {
    printf("Simple select cursor fetch next --FAILED--\n");
    DumpStruct();
    printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
}

/*********************************************************************/
/*  Variation 28.  Close Scrollable Cursor                           */
/*********************************************************************/
void var28()
{
  qsq.Function = '6';

  memcpy(qsq.Cursor_Name, "SCROLLABLECURSORxxxxx", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);

  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var28** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Close Scrollable cursor \n");
  } else  {
    printf("CLOSE Scrollable cursor --FAILED--\n");
    DumpStruct();
    printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
}


/*********************************************************************/
/*  Variation 29.  Close Block Fetch Cursor                          */
/*********************************************************************/
void var29()
{
  qsq.Function = '6';

  memcpy(qsq.Statement_Name, "BlockSelectStatement", 18);
  memcpy(qsq.Cursor_Name, "BlockFetchCursorNxxxx", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);

  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var29** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Close block fetch cursor \n");
  } else  {
    printf("CLOSE block fetch cursor --FAILED--\n");
    DumpStruct();
    printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
}

/*********************************************************************/
/*  Variation 30.  Execute delete statement for cleanup              */
/*********************************************************************/
void var30()
{
  int sysresult;

  qsq.Function = '3';
  qsq.Open_Options = 0x90;
  memcpy(qsq.Statement_Name, "DELETEALLINSERTEDIDS", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));
  stmttxt = &data[0] + (offsetof(Qsq_SQLP0300_t, Statement_Length) +
    sizeof(qsq.Statement_Length));
  (void)memcpy(stmttxt, temp, strlen(temp));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);
  expcode = 0;
  strcpy(expstate, "00000");

  printf("**var30** ");
  if (sqlca1.sqlcode == 0 ) {
    printf("Execute of delete statment Complete\n");
  } else  {
    printf("Execute of delete Statment --FAILED--\n");
    printf("   code: %d  state: %d err:%d msg: %s**\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
  sysresult = system("dltsqlpkg sqedast/edapkg");
  if (sysresult) {
    printf("\nWARNING:  SQL PACKAGE SQEDAST/EDAPKG WAS NOT DELETED\n");
  }

}


/*********************************************************************/
/*  Runchild.  Initializes a new thread and runs variations 19 to 30 */
/*********************************************************************/
void runchild()
{
  printf(">>initializing first thread<<\n");
  rc = pthread_create(&thread, NULL, thrdins1,
    NULL);
  checkResults("pthread_create()\n", rc);
  rc = pthread_join(thread, &status);
  checkResults("pthread_join()\n", rc);
  if (__INT(status) != okStatus) {
    printf("thread create FAILED: status=%i\n");
  } else {
    printf("<>\n");
  }

}

/*********************************************************************/
/*  thrdins1. Run variations 18-30                                   */
/*********************************************************************/
void *thrdins1(void *parm)
{
  int insid;
  double insdbl;
  int insgrp;
  char inschar20[20];

  qsq.Function = '3';
  qsq.Open_Options = 0x90;
  qsq.Rows_To_Insert = 0;

  sqlda1->sqln = 99;
  sqlda1->sqld = 4;
  sqlda1->sqldabc = sqlda1->sqln * 80 + 16;

  sqlda1->sqlvar[0].sqltype = 496;
  sqlda1->sqlvar[0].sqllen = 4;
  sqlda1->sqlvar[0].sqldata = (char *)(&insid);
  sqlda1->sqlvar[1].sqltype = 480;
  sqlda1->sqlvar[1].sqllen = 8;
  sqlda1->sqlvar[1].sqldata = (char *)(&insdbl);
  sqlda1->sqlvar[2].sqltype = 496;
  sqlda1->sqlvar[2].sqllen = 4;
  sqlda1->sqlvar[2].sqldata = (char *)(&insgrp);
  sqlda1->sqlvar[3].sqltype = 460;
  sqlda1->sqlvar[3].sqllen = 20;
  sqlda1->sqlvar[3].sqldata = (char *)(&inschar20);

  insid = 910;
  insdbl = 9.9999;
  insgrp = 9;

  strcpy(inschar20, "Thread Dynamic Insert");
  memcpy(qsq.Statement_Name, "InsertRow1DynamicValuesStmt", 18);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));
  stmttxt = &data[0] + (offsetof(Qsq_SQLP0300_t, Statement_Length) +
    sizeof(qsq.Statement_Length));
  (void)memcpy(stmttxt, temp, strlen(temp));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);
  expcode = 0;
  strcpy(expstate, "00000");

  if (sqlca1.sqlcode == 0 ) {
    printf("Execute simple insert statment Complete\n");
  } else  {
    printf("Execute simple insert Statment FAILED\n");
    printf("   code: %d  state: %d err:%d msg: %s**\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
/*  Variation 19.  Reopen block Fetch scrollable cursor              */
  printf("Thread %.8x %.8x: ", pthread_getthreadid_np());
  var19();
/*  Variation 20.  Execute the Dynamic INSERT Statement from Child   */
  printf("Thread %.8x %.8x: ", pthread_getthreadid_np());
  var20();
/*  Variation 21.  Execute block insert from child thread            */
  printf("Thread %.8x %.8x: ", pthread_getthreadid_np());
  var21();
/*  Variation 22.  Fetch FIRST from a scrollable cursor              */
  printf("Thread %.8x %.8x: ", pthread_getthreadid_np());
  var22();
/*  Variation 23.  Open block Fetch scrollable cursor                */
  printf("Thread %.8x %.8x: ", pthread_getthreadid_np());
  var23();
/*  Variation 24.  Block fetch from prepared cursor                  */
  printf("Thread %.8x %.8x: ", pthread_getthreadid_np());
  var24();
  printf("Thread %.8x %.8x: ", pthread_getthreadid_np());
/*  Variation 25.  Execute the Dynamic INSERT Statement from Child   */
  var25();
  printf("Thread %.8x %.8x: ", pthread_getthreadid_np());
/*  Variation 26.  Execute block insert from child thread            */
  var26();
/*  Variation 27.  Fetch NEXT from a scrollable cursor               */
  printf("Thread %.8x %.8x: ", pthread_getthreadid_np());
  var27();
/*  Variation 28.  Close Scrollable Cursor                           */
  printf("Thread %.8x %.8x: ", pthread_getthreadid_np());
  var28();
/*  Variation 29.  Close Block Fetch Cursor                          */
  printf("Thread %.8x %.8x: ", pthread_getthreadid_np());
  var29();
/*  Variation 30.  Execute delete inserted rows and drop package     */
  printf("Thread %.8x %.8x: ", pthread_getthreadid_np());
  var30();
  printf("/n/n       --Program terminated normally--");
}

/*********************************************************************/
/*  COMMIT STATEMENT (explicit)                                      */
/*********************************************************************/
void CommitStmt()
{
  strcpy(temp, "Commit");
  qsq.Function = '2';
  qsq.Open_Options = 0x90;         /*  write authority  */

  sqlda1->sqln = 99;
  sqlda1->sqld = 0;
  sqlda1->sqldabc = sqlda1->sqln * 80 + 16;

  memcpy(qsq.Statement_Name, "COMMITTRANSACTIONSNOW", 18);
  qsq.Statement_Length = strlen(temp);

  printf("L=%d Statement: %s\n", strlen(temp), temp);

  memset(data, 0, sizeof(data));
  memcpy(data, (char *)&qsq, sizeof(Qsq_SQLP0300_t));
  stmttxt = &data[0] + (offsetof(Qsq_SQLP0300_t, Statement_Length) +
    sizeof(qsq.Statement_Length));
  (void)memcpy(stmttxt, temp, strlen(temp));

  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);

  expcode = 0;
  strcpy(expstate, "00000");

  if (sqlca1.sqlcode == 0 ) {
    printf("Prepare COMMIT Completed\n");
  } else  {
    printf("Prepare Statment FAILED\n");
    printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);
  }
  qsq.Function = '3';
  QSQPRCED(&sqlca1, sqlda1, format, &data, &err);
  printf("   code: %d  state: %d err:%d msg: %s\n", sqlca1.sqlcode,
       sqlca1.sqlstate, err.ErrorCod, err.ErrorTxt);

  expcode = 0;
  strcpy(expstate, "00000");

  if (sqlca1.sqlcode == 0 ) {
    printf("COMMIT Completed\n");
  } else  {
    printf("CCOMMIT FAILED\n");
  }
}


void DumpStruct()
{
  printf("  >> Lib: %10c\n  >> Package: %10s\n", qsq.Library_Name,
     qsq.SQL_Package_Name);
  printf("  >> Dt -%c- %3s  Time -%c- %3s\n", qsq.Date_Separator,
    qsq.Date_Format, qsq.Time_Separator, qsq.Time_Format);
  printf("  >> Commit: %c  sqld=%d  sqln= %d\n", qsq.Commitment_Control,
    sqlda1->sqld, sqlda1->sqln);
  printf("  >> StmtLen: %d Statment: %s\n", qsq.Statement_Length, stmttxt);
  printf("  qsq:%d  Qsq_SQLP:%d data:%d\n", sizeof(qsq), sizeof(Qsq_SQLP0300_t),
    strlen(data));
  printf("\n");
}