#include "sql.h"
#include "stdio.h"

/*----------------------------------------------------------------*/
/*								  */
/*  Using Multiple Cursors Simultaneously 	  		  */
/*								  */
/*  This program scans an employee table and asks 		  */
/*  a supervisor which employee to award a bonus		  */
/*								  */
/*  Connect to two cursors (cur1 and cur2).   Compile and execute */
/*  the SQL SELECT command using the cur1 cursor.  Set the select */
/*  buffers using the cur1 cursor. Using the cur2 cursor, compile */
/*  the SQL UPDATE command.  Fetch a row with the cur1 cursor and */
/*  ask the supervisor to specify the desired bonus amount.  If a */
/*  bonus is specified then update the BONUS table utilizing the  */
/*  cur2 cursor.  Continue fetching until an end of fetch.	  */
/*								  */
/*  To test the program, get into SQLTALK and run the procedure   */
/*  BONUS.SQL that creates necessary tables and 	  	  */
/*  data to test the program.  Exit SQLTALK and run   	          */
/*  your program.  Use SQLTALK to verify the results.		  */
/*								  */
/*----------------------------------------------------------------*/

	  SQLTCUR   cur1 = 0;		/* scan cursor		  */
	  SQLTCUR   cur2 = 0;		/* update cursor	  */
	  SQLTRCD   rcd1 = 0;		/* return code (cur1)	  */
	  SQLTRCD   rcd2 = 0;		/* return code (cur2)	  */

	  main()
{
	  int	    dollars;		/* amount of the bonus	  */
	  int	    employe;		/* employe to grant bonus */
	  char	    empnam[21]; 	/* employe name fetched   */
	  char	    buf[80];		/* input buffer area	  */
	  int	    l;			/* length		  */
	  long	    lnum;		/* long number		  */
static	  char	    selcom[] =		/* SQL select string	  */
"SELECT EMP_NO,EMP_NAME FROM EMP";
static	  char	    updcom[] =		/* SQL update string	  */
"UPDATE BONUS SET BONUS_AMOUNT = :dollars WHERE BONUS_EMP_NO = :employe";

  /*
     CONNECT TO BOTH CURSORS (use the demo database and all defaults)
  */

  if (rcd1 = sqlcnc(&cur1, "SQLBASE", 0, NULL))
    failure("FIRST CONNECT");

  if (rcd2 = sqlcnc(&cur2, "SQLBASE", 0, NULL))
    failure("SECOND CONNECT");

  /*
    COMPILE AND EXECUTE SELECT COMMAND (selcom)
  */

  if (rcd1 = sqlcex(cur1,selcom,0))
    failure("COMPILE OF SELECT COMMAND");

  /*
    SET FETCH BUFFERS (select EMP_NO into employe & EMP_NAME into empnam)
  */

  if (rcd1 = sqlssb(cur1,1,SQLPUIN,(SQLTDAP)&employe,sizeof(employe),0,SQLNPTR,SQLNPTR))
    failure("SET FIRST SELECT BUFFER");

  if (rcd1 = sqlssb(cur1,2,SQLPSTR,empnam,sizeof(empnam),0,SQLNPTR,SQLNPTR))
    failure("SET SECOND SELECT BUFFER");

  /*
     COMPILE UPDATE COMMAND (updcom)
  */

  if (rcd2 = sqlcom(cur2,updcom,0))
    failure("COMPILE OF UPDATE");

  /*
     BIND UPDATE VARIABLES (bind variables with variables of same name)
  */

  if (rcd2 = sqlbnd(cur2,"dollars",7,(SQLTDAP)&dollars,sizeof(dollars),0,SQLPUIN))
    failure("DOLLARS BIND");

  if (rcd2 = sqlbnd(cur2,"employe",7,(SQLTDAP)&employe,sizeof(employe),0,SQLPUIN))
    failure("EMPLOYE BIND");

  /*
    FETCH ALL EMPLOYEES AND SPECIFY ANY BONUS AMOUNTS
  */

  while (!(rcd1 = sqlfet(cur1)))
    for (;;)
    {
      printf("\nEnter Bonus Amount for [%d] %s ",employe, empnam);
      fflush(stdout);
      fgets(buf,sizeof(buf),stdin);	/* read bonus amount	  */
      lnum = atol(buf); 		/* convert dollar amount  */
      if (strlen(buf) <= 0 ||		/* invalid number? or	  */
	  lnum < 0 ||			/* negative bonus amt? or */
	  lnum > 32000) 		/* too big a bonus?	  */
	continue;			/* ask user for amt again */
      if (!lnum)			/* no amount?		  */
	break;				/* no bonus for employe   */
      dollars = lnum;			/* set bonus dollar amt   */
      if (rcd2 = sqlexe(cur2))		/* perform update	  */
	failure("UPDATE");
      break;
    }

  if (rcd1 != 1)
    failure("FETCH");

  /*
    DISCONNECT BOTH CURSORS
  */

  if (rcd1 = sqldis(cur1))
    failure("DISCONNECT OF SELECT CURSOR");

  cur1 = 0;

  if (rcd2 = sqldis(cur2))
    failure("DISCONNECT OF UPDATE CURSOR");
}
	  failure(ep)
	  char*     ep; 		/* -> failure msg string  */
{
	  SQLTEPO   epo;		/* error position	  */
	  char	    errmsg[SQLMERR];	/* error msg text buffer  */

  printf("Failure on %s \n", ep);

  if (rcd1)				/* error on cursor 1?	  */
  {
    sqlerr(rcd1, errmsg);
    sqlepo(cur1, &epo);
  }

  if (rcd2)				/* error on cursor 2?	  */
  {
    sqlerr(rcd2, errmsg);
    sqlepo(cur2, &epo);
  }

  if (cur1)				/* cursor 1 exists?	  */
    sqldis(cur1);

  if (cur2)				/* cursor 2 exists?	  */
    sqldis(cur2);

  printf("%s(error: %u, position: %u) \n",errmsg,rcd1,epo);
  exit(1);
}
