/* ================================================================ */
/* The CITY Benchmark Transactions.				    */
/* Transactions are grouped based on transaction type.	            */
/* Last Update: 29/7/93.                                            */
/* Executable form is cityc and results are in CITY.RES.	    */
/* To run after CITYCRT and CITYLOAD.				    */
/* Copyright 1993 Dr. Wagdy Youssef. All Rights Reserved.           */
/* ================================================================ */

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#define BEEP '\a'
#define MAXPATH 64
#define MAXLINE 80
#define DSECONDS 1
#define NLETTERS 10

/* ================================ */
/* Declare TPS record Structure TAG */
/* ================================ */

struct tps_rec_layout
      { /* Structure begining */
       char  dbtype[15];		/* database name.    */
       long  dbsize;			/* Database size.    */
       int   nloops;			/* Number of loops.  */
       int   looptime;			/* Loop time in seconds. */
       int   tottime;			/* Total time in seconds. */
       long  tot_trans;			/* Tot. number of transactions. */
       long  avr_trans;			/* Avr. transactions per loop. */
       double trn_per_sec;		/* Number of transactions/sec. */
       double it_resp_time;		/* Iteration response time. */
       time_t time_date;		/* Time and date of test. */
      }; /* Stucture end */

/* ============================ */
/* Declare TPS Record Structure */
/* ============================ */

struct tps_rec_layout tps_io_rec;

/* ======================= */
/* Declare print procedure */
/* ======================= */

    prn_rec1();


EXEC SQL BEGIN DECLARE SECTION;

/* ================================ */
/* The PassWord Declaration Section */
/* ================================ */

     VARCHAR uid[20];
     VARCHAR pwd[20];

/* ============================================== */
/* The Databases intermediate declaration section */
/* ============================================== */

     char    dbfc1 [8];
     int     dbfi;
     char    dbfc2 [30];
     long    dbfl;
     float   dbfr;
     double  dbfd;
     VARCHAR dbfv [40];

     unsigned int  key_value;

/* ========================================== */
/* The program variables declaration section. */
/* ========================================== */

     long   r_1   = 0; /* Unique No. of Rows Counter. */
     long   r_10  = 0; /* No. of Rows Counter repeated every 10 rows. */
     long   r_100 = 0; /* No. of Rows Counter repeated every 100 rows. */

     int    vi = 50;	 /* Integer value */
     long   vl = 50;	 /* Long value */
     float  vf = 50;	 /* Float value */
     float  vr = 50;	 /* Float value */
     double vd = 50;	 /* Double value */
     long  DB_Size; /* DATABASE SIZE */


      /* Character fields Car1field1, Char2field1 and Varfield1	*/

  static char Char1field1 [8]  = {"0000001"};
  static char Char2field1 [30] = {"ABABA ABABA ABABA ABABA ABABA"};
  static char Varfield1   [40] = {"ABABA ABABA ABABA ABABA ABABA ABA AAAAA"};

EXEC SQL END DECLARE SECTION;

/* ====================================== */
/* Include SQLCA command (SQL Comm Area). */
/* ====================================== */

EXEC SQL INCLUDE sqlca.h;


/* =========================================================== */
/* External variables for the random number generation program */
/* =========================================================== */
extern int srand1(), rand2(); /* extern is optional */


/* ======================= */
/* The main program start. */
/* ======================= */

main()
{   /* Program START */

     FILE *tps_fp;
     long randp();

     long x, y, z;

     static char path_name_1[MAXPATH] ="CITY.RES";

      /* Random number generation variables */
     long seed, rt_value, n_rows, r_limit10;
     int r_limit = 30000; /* randp maximum value */
     unsigned long  ROWS; /* DATABASE SIZE */

     unsigned long  Rows_Start, /* Number of rows start value */
		    Rows_End,	/* Number of rows end value */
		    Rows_Step;	/* Number of rows step value */

     int SECONDS;

     int i1 = 0, /* loop1 index */
         i2 = 0, /* loop2 index */
	 i3 = 0; /* loop3 index */

     int     i,       /* Main loop index		*/
             j = 7,   /* End of 8 Char field pointer    */
             k = 29,  /* End of 30 Char field pointer   */
             l = 0,   /* Start of Var_fields pointer    */
             m = 38;  /* End of Var_fields pointer      */

     unsigned int     i_loops = 0;  /* Index of loops for time measues. */
     unsigned long    rows_loop = 0;  /* Database load loops Index */
     unsigned long    start   = 0, /* TPS Start time. */
		      end     = 0, /* TPS End time. */
		      g_time1 = 0, /* Used to get start value from time. */
		      g_time2 = 0; /* Used to get end value from time. */

     unsigned long   trans_count     = 0, /* Loop trans_counter.	*/
		     tot_trans_count = 0, /* Total of loop trans_counters. */
		     avr_trans_count = 0; /* Average of loop trans_counters. */

     double resp_time,	     /* Final transactions response time. */
            resp_time_t,     /* Total transactions response time. */
            resp_time_1,     /* One iteration response time. */
	    resp_per_step,   /* Response time per step. */
	    trans_per_sec;   /* Transactions/sec. */

     time_t resp_time_start, /* Response time Start. */
	    resp_time_stop;  /* Response time End. */

     unsigned long resp_count;

     static    char    db_type	[15] = {"ORACLE.       "};

     long    qs=0;
     long    qu1=0;
     long    qu2=0;
     long    qf=0;
     long    in_rec=0;

     double  tr_per_second= 0; /* Average number of transactions/sec. */

  static char error_message[71] =
{"                                                                      "};

  static char	 line[71] =
{"######################################################################"};

  static char conn_err[71] =
{"An error occurred during connection to the DBMS.                      "};

  static char ql_count_err[71] =
{"An error occurred during counting rows in DB100.                      "};

  static char ql_sel1_err[71] =
{"An error occurred during Qualified Retrieval Select 1.                "};

  static char ql_sel2_err[71] =
{"An error occurred during Qualified Retrieval Select 2.                "};

  static char ql_sel3_err[71] =
{"An error occurred during Qualified Retrieval Select 3.                "};

  static char ql_sel4_err[71] =
{"An error occurred during Qualified Retrieval Select 4.                "};

  static char ql_sel5_err[71] =
{"An error occurred during Qualified Retrieval Select 5.                "};

  static char ql_sel6_err[71] =
{"An error occurred during Qualified Retrieval Select 6.                "};

  static char ql_sel7_err[71] =
{"An error occurred during Qualified Retrieval Select 7.                "};

  static char ql_sel8_err[71] =
{"An error occurred during Qualified Retrieval Select 8.                "};

   static char row_insrt_err[71] =
{"An error occurred during inserting a row in DBINS.                    "};

   static char row_update_err1[71] =
{"An error occurred during updating a row in DBUPD, Update operation 1. "};

   static char row_update_err2[71] =
{"An error occurred during updating a row in DBUPD, Update operation 2. "};

   static char upd_cur_opn_err[71] =
{"An error has occurred during update cursor open.                      "};

   static char upd_cur_dcl_err[71] =
{"An error has occurred during update cursor declaration.               "};

   static char ft1_cur_opn_err[71] =
{"An error has occurred during FETCH1 cursor open.                      "};
   static char ft1_cur_dcl_err[71] =
{"An error has occurred during FETCH1 cursor declaration.               "};
   static char ft1_cur_ftch_err[71] =
{"An error has occurred during FETCH1 execution.                        "};

   static char ft2_cur_opn_err[71] =
{"An error has occurred during FETCH2 cursor open.                      "};
   static char ft2_cur_dcl_err[71] =
{"An error has occurred during FETCH2 cursor declaration.               "};
   static char ft2_cur_ftch_err[71] =
{"An error has occurred during FETCH2 execution.                        "};

   static char ft3_cur_opn_err[71] =
{"An error has occurred during FETCH3 cursor open.                      "};
   static char ft3_cur_dcl_err[71] =
{"An error has occurred during FETCH3 cursor declaration.               "};
   static char ft3_cur_ftch_err[71] =
{"An error has occurred during FETCH3 execution.                        "};

   static char ft4_cur_opn_err[71] =
{"An error has occurred during FETCH4 cursor open.                      "};
   static char ft4_cur_dcl_err[71] =
{"An error has occurred during FETCH4 cursor declaration.               "};
   static char ft4_cur_ftch_err[71] =
{"An error has occurred during FETCH4 execution.                        "};

   static char ft5_cur_opn_err[71] =
{"An error has occurred during FETCH5 cursor open.                      "};
   static char ft5_cur_dcl_err[71] =
{"An error has occurred during FETCH5 cursor declaration.               "};
   static char ft5_cur_ftch_err[71] =
{"An error has occurred during FETCH5 execution.                        "};

   static char ft6_cur_opn_err[71] =
{"An error has occurred during FETCH6 cursor open.                      "};
   static char ft6_cur_dcl_err[71] =
{"An error has occurred during FETCH6 cursor declaration.               "};
   static char ft6_cur_ftch_err[71] =
{"An error has occurred during FETCH6 execution.                        "};

   static char ft7_cur_opn_err[71] =
{"An error has occurred during FETCH7 cursor open.                      "};
   static char ft7_cur_dcl_err[71] =
{"An error has occurred during FETCH7 cursor declaration.               "};
   static char ft7_cur_ftch_err[71] =
{"An error has occurred during FETCH7 execution.                        "};

   static char ft8_cur_opn_err[71] =
{"An error has occurred during FETCH8 cursor open.                      "};
   static char ft8_cur_dcl_err[71] =
{"An error has occurred during FETCH8 cursor declaration.               "};
   static char ft8_cur_ftch_err[71] =
{"An error has occurred during FETCH8 execution.                        "};

   static char ft9_cur_opn_err[71] =
{"An error has occurred during FETCH9 cursor open.                      "};
   static char ft9_cur_dcl_err[71] =
{"An error has occurred during FETCH9 cursor declaration.               "};
   static char ft9_cur_ftch_err[71] =
{"An error has occurred during FETCH9 execution.                        "};

  static char tablins_drop_err[71] =
{"An error occurred during Table DBINS DROP.                            "};
  static char indxins_err[71] =
{"An error occurred during Index DBINS_IX creation.                     "};
  static char tablins_cr_err[71] =
{"An error occurred during Table DBINS creation.                        "};


     /* ===================================== */
     /* Open files for TPS and response time. */
     /* ===================================== */

     if( (tps_fp=fopen(path_name_1,"ab")) == NULL)
       { /* if start */
	putchar(BEEP);	/* Beep */
	putchar(BEEP);	/* Beep */
	printf("* ############################################## *\n");
	printf("* Cannot open the file, abnormal end of program. *\n");
	printf("* File Name is: %s\n",path_name_1);
	printf("* ############################################## *\n");
        getchar();
       } /* if end. */


/* ====================================== */
/* log into the DBMS userID and password. */
/* ====================================== */

    strcpy(uid.arr,"ops$za328");
    uid.len = strlen(uid.arr);
    strcpy(pwd.arr,"wagdy");
    pwd.len = strlen(pwd.arr);
		 

/* ========================================================== */
/* log into the DBMS every time the program start a new loop. */
/* ========================================================== */

    strcpy(error_message,conn_err);
    EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
    EXEC SQL CONNECT :uid IDENTIFIED BY :pwd;

    printf("* ======================================= *\n");
    printf("* Connected to The System user: %s *\n",uid.arr);
    printf("* ======================================= *\n\n");


     /* ================================= */
     /* Count Number of Rows in Tables	  */
     /* ================================= */

    strcpy(error_message,ql_count_err);
    EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
    EXEC SQL SELECT COUNT (DISTINCT (DB1FI1))
	     INTO   :DB_Size
	     FROM DB100;

    if (DB_Size < 1)
       { /* if DB_Size < 1 end */
	printf("\n\n* ============================================ *\n");
	printf("* The test database is empty.                  *\n");
	printf("* Please run CITYLOAD program before this run. *\n");
	printf("* The program has terminated abnormally.       *\n");
	printf("* ============================================ *\n");
	exit(1);
       } /* if DB_Size < 1 end */

    ROWS = DB_Size;

    printf("Current database size in rows is: %d.\n", ROWS);

/* ========================= */
/* Drop Table DBINS Section. */
/* ========================= */

   strcpy(error_message,tablins_drop_err);
   EXEC SQL WHENEVER SQLERROR GOTO Create_DBINS;
   EXEC SQL DROP TABLE DBINS;
   printf("* Table DBINS has been dropped. *\n");
   printf("* ============================= *\n");


Create_DBINS:

/* ============================== */
/* Create Table DBINS Section.    */
/* ============================== */

    strcpy(error_message,tablins_cr_err);
    EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
    EXEC SQL CREATE TABLE DBINS
	    (dbifc1   char(8),			  /* No-key field. */
	     dbifi1   number(8) not null,	  /* Secondary Key.*/
	     dbifc2   char(30), 		  /* No-key field. */
	     dbifl1   number(4),		  /* No-key field. */
	     dbifr1   number(4,2),		  /* No-key field. */
	     dbifd1   number(6,3),		  /* No-key field. */
	     dbifv1   char(40), 		  /* No-key field. */
	     dbifc3   char(8),			  /* No-key field. */
	     dbifi2   number(8) not null,	  /* No-key field. */
	     dbifc4   char(30), 		  /* No-key field. */
	     dbifl2   number(4),		  /* No-key field. */
	     dbifr2   number(4,2),		  /* No-key field. */
	     dbifd2   number(6,3),		  /* No-key field. */
	     dbifv2   char(40));		  /* No-key field. */

    printf("* ============================= *\n");
    printf("* Table DBINS has been created. *\n");
    printf("* ============================= *\n\n");

/* ================================= */
/* Create Indexes for DBINS Section. */
/* ================================= */

   strcpy(error_message,indxins_err);
   /* Secondary Key n times Depending on no. of transactions. */
   EXEC SQL CREATE INDEX DBIFI1_IX ON DBINS(DBIFI1);
   printf("* =========================================== *\n");
   printf("* SECONDARY INDEX DBIFI1_IX has been Created. *\n");
   printf("* An Index on DBINS table field dbifi1.       *\n");
   printf("* =========================================== *\n");


    EXEC SQL COMMIT WORK;
    printf("* ============================================================= *\n");
    printf("* DROP and CREATE DBUPD table have Been Committed Successfully. *\n");
    printf("* ============================================================= *\n");


     /* ================================= */
     /* Get Number of Rows To be Inserted */
     /* ================================= */

Get_time:
   printf("Loop time should be 300 seconds or more.\n");
   printf("Please enter test loop length in seconds: ");
    scanf("%d",&SECONDS);
    if (SECONDS < 300)
       { /* if SECONDS start */
	printf("* ============================================ *\n");
	printf("* Loop time should be 300 seconds or more.     *\n");
	printf("* Please enter new loop time then press enter. *\n");
	printf("* ============================================ *\n");
	goto Get_time;
       } /* if SECONDS end */


/* ==================================================================== */
/* The CITY benchmark transactions.					*/
/* ==================================================================== */


     /* =========================== */
     /* Dummy loops to adjust time. */
     /* =========================== */

	start	= time(&g_time1); /* Get system elapsed time in seconds. */
	end	= start + DSECONDS;  /* Calculate end time in seconds */
	do
          { /* start of do loop body. */
	   printf("Dummy loops to adjust time\n");
	  } /* end of do loop body. */
	  while (time(&g_time1) < end);

     /* ===================================================== */
     /* The program loops to calculate TPS and response time. */
     /* ===================================================== */

      trans_count = 0; /* set number of transactions/loop to 0 */
      resp_time_t = 0; /* set time of transactions/loop to 0 */
      

     /* ============================================= */
     /* Get time start and time end to calculate TPS. */
     /* ============================================= */

      start   = time(&g_time1); /* Get system elapsed time in seconds. */
      end     = start + SECONDS;	/* Calculate end time in seconds */
      r_limit10 = ROWS/10;

     do
      { /* start of do loop body. */

      /* ============================================== */
      /* Get start time to calculate response/iteration */
      /* ============================================== */

      time(&resp_time_start);


/* ================================================= */
/* 1. 1.1. Retrieve 1 Row from DB100.		     */
/* ================================================= */

 /* Get a random key */
    x = rand2(r_limit);
    y = rand2(r_limit);
    z = rand2(r_limit);
    key_value = randp(x,y,z,ROWS);

    strcpy(error_message,ql_sel1_err);
    EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
    EXEC SQL SELECT DB1FC1, DB1FI1, DB1FC2, DB1FL1, DB1FR1, DB1FD1, DB1FV1
	     INTO   :dbfc1, :dbfi,  :dbfc2, :dbfl,  :dbfr,  :dbfd,  :dbfv
	     FROM DB100
	     WHERE DB1FI1 = :key_value;


/* ============================================================== */
/* 2. 4.1. Retrieve 10 Rows from DB200.				  */
/* ============================================================== */

/* ====================================== */
/* Step 1 Declare the  cursor to be used. */
/* ====================================== */

 /* Get a random key */
    x = rand2(r_limit);
    y = rand2(r_limit);
    z = rand2(r_limit);
    key_value = randp(x,y,z,r_limit10);

       strcpy(error_message,ft1_cur_dcl_err);
       EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
       EXEC SQL DECLARE CF1 CURSOR FOR
		SELECT DB2FC1, DB2FI1, DB2FC2, DB2FL1, DB2FR1, DB2FD1, DB2FV1
		FROM DB200
		WHERE DB2FI2 = :key_value;

/* ================================== */
/* Step 2 Open the cursor to be used. */
/* ================================== */

       strcpy(error_message,ft1_cur_opn_err);
       EXEC SQL OPEN CF1;

/* ================================================== */
/* Step 3 Use FETCH to retrieve all required records. */
/* ================================================== */

       strcpy(error_message,ft1_cur_ftch_err);
       EXEC SQL WHENEVER NOT FOUND GOTO work_done_f1;

    for(;;)
     { /* for start */
      EXEC SQL FETCH CF1 INTO
		     :dbfc1, :dbfi, :dbfc2, :dbfl, :dbfr, :dbfd, :dbfv;
     } /* for end */

/* ======================== */
/* Step 4 Close the cursor. */
/* ======================== */

work_done_f1:
       EXEC SQL CLOSE CF1;

/* ================================================= */
/* 3. 1.2. Retrieve 1 Row from DB100.		     */
/* ================================================= */

 /* Get a random key */
    x = rand2(r_limit);
    y = rand2(r_limit);
    z = rand2(r_limit);
    key_value = randp(x,y,z,ROWS);

    strcpy(error_message,ql_sel2_err);
    EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
    EXEC SQL SELECT DB1FC1, DB1FI1, DB1FC2, DB1FL1, DB1FR1, DB1FD1, DB1FV1
	     INTO   :dbfc1, :dbfi,  :dbfc2, :dbfl,  :dbfr,  :dbfd,  :dbfv
	     FROM DB100
	     WHERE DB1FI1 = :key_value;


/* ============================================================== */
/* 4. 4.2. Retrieve 10 Rows from DB200.				  */
/* ============================================================== */

/* ====================================== */
/* Step 1 Declare the  cursor to be used. */
/* ====================================== */

 /* Get a random key */
    x = rand2(r_limit);
    y = rand2(r_limit);
    z = rand2(r_limit);
    key_value = randp(x,y,z,r_limit10);

       strcpy(error_message,ft2_cur_dcl_err);
       EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
       EXEC SQL DECLARE CF2 CURSOR FOR
		SELECT DB2FC1, DB2FI1, DB2FC2, DB2FL1, DB2FR1, DB2FD1, DB2FV1
		FROM DB200
		WHERE DB2FI2 = :key_value;

/* ================================== */
/* Step 2 Open the cursor to be used. */
/* ================================== */

       strcpy(error_message,ft2_cur_opn_err);
       EXEC SQL OPEN CF2;

/* ================================================== */
/* Step 3 Use FETCH to retrieve all required records. */
/* ================================================== */

       strcpy(error_message,ft2_cur_ftch_err);
       EXEC SQL WHENEVER NOT FOUND GOTO work_done_f2;

    for(;;)
     { /* for start */
      EXEC SQL FETCH CF2 INTO
		     :dbfc1, :dbfi, :dbfc2, :dbfl, :dbfr, :dbfd, :dbfv;
     } /* for end */

/* ======================== */
/* Step 4 Close the cursor. */
/* ======================== */

work_done_f2:
       EXEC SQL CLOSE CF2;

/* ======================================================= */
/* 5. 3.1. Update a single Row in DBUPD using integer key. */
/* ======================================================= */

/* ====================================== */
/* Print before update record image.	  */
/* ====================================== */

 /* Get a random key */
    x = rand2(r_limit);
    y = rand2(r_limit);
    z = rand2(r_limit);
    key_value = randp(x,y,z,ROWS);

    strcpy(error_message,row_update_err1);
    EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
    EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
    EXEC SQL  UPDATE DBUPD
		 SET DBUFL1 = :vl,
		     DBUFR1 = :vr,
		     DBUFD1 = :vd
	      WHERE DBUFI1 =:key_value;

/* ====================================== */
/* Print after	update record image.	  */
/* ====================================== */


/* ================================================= */
/* 6. 1.3. Retrieve 1 Row from DB200.		     */
/* ================================================= */

 /* Get a random key */
    x = rand2(r_limit);
    y = rand2(r_limit);
    z = rand2(r_limit);
    key_value = randp(x,y,z,ROWS);

    strcpy(error_message,ql_sel3_err);
    EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
    EXEC SQL SELECT DB2FC1, DB2FI1, DB2FC2, DB2FL1, DB2FR1, DB2FD1, DB2FV1
	     INTO   :dbfc1, :dbfi,  :dbfc2, :dbfl,  :dbfr,  :dbfd,  :dbfv
	     FROM DB200
	     WHERE DB2FI1 = :key_value;


/* ==================================================== */
/* 7. 1.7. Retrieve 1 Row from DB300.			*/
/* ==================================================== */

 /* Get a random key */
    x = rand2(r_limit);
    y = rand2(r_limit);
    z = rand2(r_limit);
    key_value = randp(x,y,z,ROWS);

    strcpy(error_message,ql_sel7_err);
    EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
    EXEC SQL SELECT DB3FC1, DB3FI1, DB3FC2, DB3FL1, DB3FR1, DB3FD1, DB3FV1
	     INTO   :dbfc1, :dbfi,  :dbfc2, :dbfl,  :dbfr,  :dbfd,  :dbfv
	     FROM DB300
	     WHERE DB3FI1 = :key_value;


/* ============================================================== */
/* 8. 4.3. Retrieve 10 Rows from DB200.				  */
/* ============================================================== */

/* ====================================== */
/* Step 1 Declare the  cursor to be used. */
/* ====================================== */

 /* Get a random key */
    x = rand2(r_limit);
    y = rand2(r_limit);
    z = rand2(r_limit);
    key_value = randp(x,y,z,r_limit10);

       strcpy(error_message,ft3_cur_dcl_err);
       EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
       EXEC SQL DECLARE CF3 CURSOR FOR
		SELECT DB2FC1, DB2FI1, DB2FC2, DB2FL1, DB2FR1, DB2FD1, DB2FV1
		FROM DB200
		WHERE DB2FI2 = :key_value;

/* ================================== */
/* Step 2 Open the cursor to be used. */
/* ================================== */

       strcpy(error_message,ft3_cur_opn_err);
       EXEC SQL OPEN CF3;

/* ================================================== */
/* Step 3 Use FETCH to retrieve all required records. */
/* ================================================== */

       strcpy(error_message,ft3_cur_ftch_err);
       EXEC SQL WHENEVER NOT FOUND GOTO work_done_f3;

    for(;;)
     { /* for start */
      EXEC SQL FETCH CF3 INTO
		     :dbfc1, :dbfi, :dbfc2, :dbfl, :dbfr, :dbfd, :dbfv;

     } /* for end */

/* ======================== */
/* Step 4 Close the cursor. */
/* ======================== */

work_done_f3:
       EXEC SQL CLOSE CF3;

/* ============================================================== */
/* 9. 4.6. Retrieve 10 Rows from DB300.				  */
/* ============================================================== */

/* ====================================== */
/* Step 1 Declare the  cursor to be used. */
/* ====================================== */

 /* Get a random key */
    x = rand2(r_limit);
    y = rand2(r_limit);
    z = rand2(r_limit);
    key_value = randp(x,y,z,r_limit10);

       strcpy(error_message,ft6_cur_dcl_err);
       EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
       EXEC SQL DECLARE CF6 CURSOR FOR
		SELECT DB3FC1, DB3FI1, DB3FC2, DB3FL1, DB3FR1, DB3FD1, DB3FV1
		FROM DB300
		WHERE DB3FI2 = :key_value;

/* ================================== */
/* Step 2 Open the cursor to be used. */
/* ================================== */

       strcpy(error_message,ft6_cur_opn_err);
       EXEC SQL OPEN CF6;

/* ================================================== */
/* Step 3 Use FETCH to retrieve all required records. */
/* ================================================== */

       strcpy(error_message,ft6_cur_ftch_err);
       EXEC SQL WHENEVER NOT FOUND GOTO work_done_f6;

    for(;;)
     { /* for start */
      EXEC SQL FETCH CF6 INTO
		     :dbfc1, :dbfi, :dbfc2, :dbfl, :dbfr, :dbfd, :dbfv;

     } /* for end */

/* ======================== */
/* Step 4 Close the cursor. */
/* ======================== */

work_done_f6:
       EXEC SQL CLOSE CF6;

/* ===================================================== */
/* 10. 1.4. Retrieve 1 Row from DB200.			 */
/* ===================================================== */

 /* Get a random key */
    x = rand2(r_limit);
    y = rand2(r_limit);
    z = rand2(r_limit);
    key_value = randp(x,y,z,ROWS);

    strcpy(error_message,ql_sel4_err);
    EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
    EXEC SQL SELECT DB2FC1, DB2FI1, DB2FC2, DB2FL1, DB2FR1, DB2FD1, DB2FV1
	     INTO   :dbfc1, :dbfi,  :dbfc2, :dbfl,  :dbfr,  :dbfd,  :dbfv
	     FROM DB200
	     WHERE DB2FI1 = :key_value;



/* ============================================================== */
/* 11. 4.7.	Retrieve 10 Rows from DB300.			  */
/* ============================================================== */

/* ====================================== */
/* Step 1 Declare the  cursor to be used. */
/* ====================================== */

 /* Get a random key */
    x = rand2(r_limit);
    y = rand2(r_limit);
    z = rand2(r_limit);
    key_value = randp(x,y,z,r_limit10);

       strcpy(error_message,ft7_cur_dcl_err);
       EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
       EXEC SQL DECLARE CF7 CURSOR FOR
		SELECT DB3FC1, DB3FI1, DB3FC2, DB3FL1, DB3FR1, DB3FD1, DB3FV1
		FROM DB300
		WHERE DB3FI2 = :key_value;

/* ================================== */
/* Step 2 Open the cursor to be used. */
/* ================================== */

       strcpy(error_message,ft7_cur_opn_err);
       EXEC SQL OPEN CF7;

/* ================================================== */
/* Step 3 Use FETCH to retrieve all required records. */
/* ================================================== */

       strcpy(error_message,ft7_cur_ftch_err);
       EXEC SQL WHENEVER NOT FOUND GOTO work_done_f7;

    for(;;)
     { /* for start */
      EXEC SQL FETCH CF7 INTO
		     :dbfc1, :dbfi, :dbfc2, :dbfl, :dbfr, :dbfd, :dbfv;

     } /* for end */

/* ======================== */
/* Step 4 Close the cursor. */
/* ======================== */

work_done_f7:
       EXEC SQL CLOSE CF7;

/* ============================================================== */
/* 12. 4.4. Retrieve 10 Rows from DB300.			  */
/* ============================================================== */

/* ====================================== */
/* Step 1 Declare the  cursor to be used. */
/* ====================================== */

 /* Get a random key */
    x = rand2(r_limit);
    y = rand2(r_limit);
    z = rand2(r_limit);
    key_value = randp(x,y,z,r_limit10);

       strcpy(error_message,ft4_cur_dcl_err);
       EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
       EXEC SQL DECLARE CF4 CURSOR FOR
		SELECT DB3FC1, DB3FI1, DB3FC2, DB3FL1, DB3FR1, DB3FD1, DB3FV1
		FROM DB300
		WHERE DB3FI2 = :key_value;

/* ================================== */
/* Step 2 Open the cursor to be used. */
/* ================================== */

       strcpy(error_message,ft4_cur_opn_err);
       EXEC SQL OPEN CF4;

/* ================================================== */
/* Step 3 Use FETCH to retrieve all required records. */
/* ================================================== */

       strcpy(error_message,ft4_cur_ftch_err);
       EXEC SQL WHENEVER NOT FOUND GOTO work_done_f4;

    for(;;)
     { /* for start */
      EXEC SQL FETCH CF4 INTO
		     :dbfc1, :dbfi, :dbfc2, :dbfl, :dbfr, :dbfd, :dbfv;

     } /* for end */

/* ======================== */
/* Step 4 Close the cursor. */
/* ======================== */

work_done_f4:
       EXEC SQL CLOSE CF4;

/* =================================================== */
/* 13. 1.8. Retrieve 1 Row from DB300.		       */
/* =================================================== */

 /* Get a random key */
    x = rand2(r_limit);
    y = rand2(r_limit);
    z = rand2(r_limit);
    key_value = randp(x,y,z,ROWS);

    strcpy(error_message,ql_sel8_err);
    EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
    EXEC SQL SELECT DB3FC1, DB3FI1, DB3FC2, DB3FL1, DB3FR1, DB3FD1, DB3FV1
	     INTO   :dbfc1, :dbfi,  :dbfc2, :dbfl,  :dbfr,  :dbfd,  :dbfv
	     FROM DB300
	     WHERE DB3FI1 = :key_value;



/* =================================================== */
/* 14. 1.5. Retrieve 1 Row from DB200.		       */
/* =================================================== */

 /* Get a random key */
    x = rand2(r_limit);
    y = rand2(r_limit);
    z = rand2(r_limit);
    key_value = randp(x,y,z,ROWS);

    strcpy(error_message,ql_sel5_err);
    EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
    EXEC SQL SELECT DB2FC1, DB2FI1, DB2FC2, DB2FL1, DB2FR1, DB2FD1, DB2FV1
	     INTO   :dbfc1, :dbfi,  :dbfc2, :dbfl,  :dbfr,  :dbfd,  :dbfv
	     FROM DB200
	     WHERE DB2FI1 = :key_value;


/* ============================================================== */
/* 15. 4.8.	Retrieve 10 Rows from DB300.			  */
/* ============================================================== */

/* ====================================== */
/* Step 1 Declare the  cursor to be used. */
/* ====================================== */

 /* Get a random key */
    x = rand2(r_limit);
    y = rand2(r_limit);
    z = rand2(r_limit);
    key_value = randp(x,y,z,r_limit10);

       strcpy(error_message,ft8_cur_dcl_err);
       EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
       EXEC SQL DECLARE CF8 CURSOR FOR
		SELECT DB3FC1, DB3FI1, DB3FC2, DB3FL1, DB3FR1, DB3FD1, DB3FV1
		FROM DB300
		WHERE DB3FI2 = :key_value;

/* ================================== */
/* Step 2 Open the cursor to be used. */
/* ================================== */

       strcpy(error_message,ft8_cur_opn_err);
       EXEC SQL OPEN CF8;

/* ================================================== */
/* Step 3 Use FETCH to retrieve all required records. */
/* ================================================== */

       strcpy(error_message,ft8_cur_ftch_err);
       EXEC SQL WHENEVER NOT FOUND GOTO work_done_f8;

    for(;;)
     { /* for start */
      EXEC SQL FETCH CF8 INTO
		     :dbfc1, :dbfi, :dbfc2, :dbfl, :dbfr, :dbfd, :dbfv;

     } /* for end */

/* ======================== */
/* Step 4 Close the cursor. */
/* ======================== */

work_done_f8:
       EXEC SQL CLOSE CF8;

/* ============================================================== */
/* 16. 4.5.	Retrieve 10 Rows from DB200.			  */
/* ============================================================== */

/* ====================================== */
/* Step 1 Declare the  cursor to be used. */
/* ====================================== */

 /* Get a random key */
    x = rand2(r_limit);
    y = rand2(r_limit);
    z = rand2(r_limit);
    key_value = randp(x,y,z,r_limit10);

       strcpy(error_message,ft5_cur_dcl_err);
       EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
       EXEC SQL DECLARE CF5 CURSOR FOR
		SELECT DB2FC1, DB2FI1, DB2FC2, DB2FL1, DB2FR1, DB2FD1, DB2FV1
		FROM DB200
		WHERE DB2FI2 = :key_value;

/* ================================== */
/* Step 2 Open the cursor to be used. */
/* ================================== */

       strcpy(error_message,ft5_cur_opn_err);
       EXEC SQL OPEN CF5;

/* ================================================== */
/* Step 3 Use FETCH to retrieve all required records. */
/* ================================================== */

       strcpy(error_message,ft5_cur_ftch_err);
       EXEC SQL WHENEVER NOT FOUND GOTO work_done_f5;

    for(;;)
     { /* for start */
      EXEC SQL FETCH CF5 INTO
		     :dbfc1, :dbfi, :dbfc2, :dbfl, :dbfr, :dbfd, :dbfv;

     } /* for end */

/* ======================== */
/* Step 4 Close the cursor. */
/* ======================== */

work_done_f5:
       EXEC SQL CLOSE CF5;

/* ======================================================================= */
/* 17. 3.2. Update 10 Rows in DBUPD.					   */
/* ======================================================================= */

       /* ======================== */
       /* 10 records update start. */
       /* ======================== */

 /* Get a random key */
    x = rand2(r_limit);
    y = rand2(r_limit);
    z = rand2(r_limit);
    key_value = randp(x,y,z,r_limit10);

       strcpy(error_message,upd_cur_dcl_err);
       EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
       EXEC SQL DECLARE UPD_CUR CURSOR
	    FOR   SELECT
		  DBUFC1, DBUFI1, DBUFC2, DBUFL1, DBUFR1, DBUFD1, DBUFV1
	    FROM  DBUPD
	    WHERE DBUFI2 = :key_value
	FOR UPDATE OF
                DBUFL1, DBUFR1, DBUFD1;

       strcpy(error_message,upd_cur_opn_err);
       EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
       EXEC SQL OPEN UPD_CUR;

       strcpy(error_message,row_update_err2);
       EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
       EXEC SQL WHENEVER NOT FOUND GOTO upd_work_done;

    for(;;)
     { /* for start */
       EXEC SQL FETCH UPD_CUR INTO
		      :dbfc1, :dbfi, :dbfc2, :dbfl, :dbfr, :dbfd, :dbfv;


       EXEC SQL UPDATE DBUPD
		 SET DBUFL1 = :vl,
		     DBUFR1 = :vr,
		     DBUFD1 = :vd
		WHERE CURRENT OF UPD_CUR;
     } /* for end */

upd_work_done:
       EXEC SQL CLOSE UPD_CUR;


/* ================================================= */
/* 18. 1.6. Retrieve 1 Row from DB200.		     */
/* ================================================= */

 /* Get a random key */
    x = rand2(r_limit);
    y = rand2(r_limit);
    z = rand2(r_limit);
    ROWS = ROWS;
    key_value = randp(x,y,z,ROWS);

    strcpy(error_message,ql_sel6_err);
    EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
    EXEC SQL SELECT DB2FC1, DB2FI1, DB2FC2, DB2FL1, DB2FR1, DB2FD1, DB2FV1
	     INTO   :dbfc1, :dbfi,  :dbfc2, :dbfl,  :dbfr,  :dbfd,  :dbfv
	     FROM DB200
	     WHERE DB2FI1 = :key_value;


/* =============================================================== */
/* 19. 4.9. Join DB200 (10 rows) and DB300 (100) Returns 100 rows. */
/* =============================================================== */

/* ====================================== */
/* Step 1 Declare the  cursor to be used. */
/* ====================================== */

 /* Get a random key */
    x = rand2(r_limit);
    y = rand2(r_limit);
    z = rand2(r_limit);
    key_value = randp(x,y,z,r_limit10);

       strcpy(error_message,ft9_cur_dcl_err);
       EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
       EXEC SQL DECLARE CF9 CURSOR
		FOR SELECT
		    DB2FC1, DB2FI1, DB2FC2, DB3FL1, DB3FR1, DB3FD1, DB3FV1
		FROM DB200, DB300
		WHERE	(DB2FI2 = DB3FI2)
		AND	(DB2FI2 = :key_value);

/* ================================== */
/* Step 2 Open the cursor to be used. */
/* ================================== */

       strcpy(error_message,ft9_cur_opn_err);
       EXEC SQL OPEN CF9;

/* ================================================== */
/* Step 3 Use FETCH to retrieve all required records. */
/* ================================================== */

       strcpy(error_message,ft9_cur_ftch_err);
       EXEC SQL WHENEVER NOT FOUND GOTO work_done_f9;

    for(;;)
     { /* for start */
      EXEC SQL FETCH CF9 INTO
		     :dbfc1, :dbfi, :dbfc2, :dbfl, :dbfr, :dbfd, :dbfv;

     } /* for end */

/* ======================== */
/* Step 4 Close the cursor. */
/* ======================== */

work_done_f9:
       EXEC SQL CLOSE CF9;

/* ==================================================================== */
/* 20. 2. Insert a Row In DBINS and check error then Commit Work.	*/
/* ==================================================================== */

    strcpy(error_message,row_insrt_err);
    EXEC SQL WHENEVER SQLERROR GOTO SQL_error_routine;
    EXEC SQL INSERT INTO
	 DBINS	(dbifc1,dbifi1,dbifc2,dbifl1,dbifr1,dbifd1,dbifv1,
		 dbifc3,dbifi2,dbifc4,dbifl2,dbifr2,dbifd2,dbifv2)
	 VALUES (:dbfc1,:dbfi,:dbfc2,:dbfl ,:dbfr,:dbfd, :dbfv,
		 :dbfc1,:dbfi,:dbfc2,:dbfl ,:dbfr,:dbfd, :dbfv);

     in_rec++;

    printf("* *********************************************** *\n");
    printf("* Row Number: %7d Has Been Inserted in DBINS. *\n",in_rec);
    printf("* *********************************************** *\n");


       /* ************************* */
       /* Commit work to databases. */
       /* ************************* */

       EXEC SQL WHENEVER SQLERROR CONTINUE;  /* don't trap errors. */
       EXEC SQL COMMIT WORK; /* commit work to datases & dont release. */
       trans_count++;  /* add one to number of transactions/iteration */

    /* **************************************** */
    /* Get end time to calculate response time. */
    /* **************************************** */

        time(&resp_time_stop);
        resp_time_1  = resp_time_stop - resp_time_start;
        resp_time_t  = resp_time_t +  resp_time_1;
	      
       } /* end of do loop body. */
    while (time(&g_time1) < end);


/* ===================================== */
/* File preparation and writing section. */
/* ===================================== */


      resp_time     =  (double) resp_time_t / (double) trans_count;
      trans_per_sec =  (float) trans_count  / (float) resp_time_t;

      strcpy(tps_io_rec.dbtype,db_type);
      tps_io_rec.dbsize = ROWS;
      tps_io_rec.nloops = 1; /* Number of loops.	*/
      tps_io_rec.looptime = SECONDS; /* Loop time in seconds. */
      tps_io_rec.tottime  = resp_time_t;/* Total time in seconds. */
      tps_io_rec.tot_trans = trans_count;/* Tot. transactions. */
      tps_io_rec.avr_trans = trans_count;/* Avr. transactions/loop. */
      tps_io_rec.trn_per_sec = trans_per_sec; /* Transactions/sec. */
      tps_io_rec.it_resp_time = (float) resp_time;
      time(&tps_io_rec.time_date);  /* test date & time */

      if(fwrite(&tps_io_rec, sizeof(struct tps_rec_layout),1,tps_fp) !=1)
        { /* if start */
	 putchar(BEEP);	/* Beep */
	 putchar(BEEP);	/* Beep */
	 putchar(BEEP);	/* Beep */
	 printf("# ######################################### #");
	 printf("# Error occurred while writing to %s #\n",path_name_1);
         printf("# ######################################### #");
         getchar();
        } /* if end   */


/* ==================================================================== */
/* Normal program termination section.					*/
/* Log out and terminate processing.					*/
/* ==================================================================== */

    EXEC SQL WHENEVER SQLERROR CONTINUE; /* don't trap errors. */
    EXEC SQL COMMIT WORK RELEASE;   /* log off database.  */
    fclose(tps_fp);
    printf("\n\n* ==================================== *\n");
    printf("* The program has terminated normally. *\n");
    printf("* ==================================== *\n");

exit(0);

/* *********************************************************************** */
/* The error handling traps and routines.				   */
/* *********************************************************************** */

SQL_error_routine:
	 putchar(BEEP);	/* Beep */
	 printf("* %70s *\n",line);
	 printf("* Database Size    : %lu\n",ROWS);
	 printf("* Last Key Value is: %d\n",key_value);
	 printf("* %70s *\n",line);
	 printf("* %70s *\n", error_message);
	 printf("* %70s *\n", sqlca.sqlerrm.sqlerrmc);
         printf("* %70s *\n",line);
	 putchar(BEEP);	/* Beep */
	 EXEC SQL WHENEVER SQLERROR CONTINUE;
         EXEC SQL ROLLBACK WORK RELEASE;
	 exit(1);

}   /* Program END */

/* ========================= */
/* Line printing subroutine. */
/* ========================= */

prn_rec1(qp) long qp;
       { /* prn_rec1() start */
	 printf ("Transaction Number: %8d\n", qp);
	 printf ("Integer   Field : %8d \n", dbfi );
	 printf ("Character Field1: %8s \n", dbfc1);
	 printf ("Character Field2: %30s \n", dbfc2);
	 printf ("Long      Field : %8d \n", dbfl);
	 printf ("Real      Field : %f \n", dbfr);
	 printf ("Double    Field : %f \n", dbfd);
	 printf ("VarChar   Field : %40s \n", dbfv.arr);
      } /* prn_rec1() end */

/* ************************************************************** */
/* This procedure generates random numbers within a given range.  */
/* ************************************************************** */

/* =============================== */
/* Generate pseudo random numbers. */
/* =============================== */

long randp ( x, y, z,limit )
     long x, y, z,limit;
      { /* random function start */
      /* This random number generator is based upon NPL Report DITC 6/82 by
         B.A.Wichmann and I.D.Hill. x,y,z are global variables to be given
         initial random integer values which should be less than 30000 */

       float w;
       long lw;
       long random;

       x = 171*(x % 177) - 2*(x / 177);
       if (x < 0) x = x+30269;

       y = 172*(y % 176) - 35*(y / 176);
       if (y < 0) y = y+30307;

       z =170*(z % 178) - 63*(z / 178);
       if (z < 0) z = z+30323;

       w = (float) x/30269 + (float) y/30307+ (float) z/30323;
       lw = w;
       random = (w - lw) * limit /* max value */ ;

       return (random);
      } /* randp function end */

/* ************************************************************** */
/* This procedure generates random numbers within a given range.  */
/* ************************************************************** */

#define SCALE 32768.0
extern int rand1(); /* extern keyword is optional */
int rand2(limit) int limit;
   {
    float k_value;
    k_value = ( (float) rand1() / SCALE + 1.0) * limit / 2.0 + 1.0;
    return ( (int) k_value);
   }

static int randx = 1; /* external static function */
int rand1()
     {
      randx = (randx * 25173 + 13849) % 65536; /* magic fromula */
      return ( (int) randx);
     }

int srand1(x) unsigned x;
    {
     randx = x;
    }
