/******************************************************************************
**
** Source File Name = inpcli.sqc  1.4
**
** Licensed Materials - Property of IBM
**
** (C) COPYRIGHT International Business Machines Corp. 1995, 1999 
** All Rights Reserved.
**
** US Government Users Restricted Rights - Use, duplication or
** disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
**
**
** PURPOSE: This sample program demonstrates stored procedures.
**
**          There are two parts to this program:
**              - the inpcli executable (placed on the client)
**              - the inpsrv library (placed on the server)
**
**          The inpcli routine will invoke the inpsrv routine
**          with the name of a table and the names of three
**          presidents of the United States.
**          The inpsrv routine will take the information received
**          and create a table called "presidents" in the sample
**          database.  It will then insert the values it received in
**          this table.
**
**          There are two different ways to invoke from inpcli:
**             1. EXEC SQL CALL :procname (:*table_name,
**                                         :*data_item0,
**                                         :*data_item1,
**                                         :*data_item2);
**             2. EXEC SQL CALL :procname USING DESCRIPTOR :inout_sqlda
**
**          When the CALL USING is used,
**          the inpcli routine will allocate and initialize a four
**          variables SQLDA to point to the data.
**          This SQLDA may be used for both input and output,
**          although in this program it is used for input only.
**
**          When the CALL with Host Variable is used,
**          the precompiler allocates and initialize an internal one
**          variable SQLDA, again for both input and output purpose.
**
**          Any of the above 2 ways will produce the same result.
**
** NOTE 1:  All variables on the EXEC SQL CALL statements are assummed to
**          be used for both input and output.  One technique to minimize
**          network flow is for the client program to provide indicator
**          variables with all its host variables.
**            -  The client program should set the "output-only" variable's
**               indicator value to -1 before issuing the CALL.
**            -  The server program should set the "input-only" variable's
**               indicator value to -128 before returning.
**
**          This will cause the transmission of just the indicator value
**          instead of the host variable itself.  This will be worthwhile
**          when dealing with fairly long character data.
**
** A external function "check_error" is contained in the file "util.c"
** which must be compiled along with this file.  
**
**
**    EXTERNAL DEPENDENCIES :
**       - Ensure existence of database for precompile purposes.
**       - Precompile with the SQL precompiler (PREP in DB2)
**       - Bind to a database (BIND in DB2)
**       - Compile and link with the IBM Cset++ compiler (AIX and OS/2)
**         or the Microsoft Visual C++ compiler (Windows) 
**         or the compiler supported on your platform.
**
** For more information about these samples see the README file.
**
** For more information on programming in C, see the:
**   -  "Programming in C and C++" section of the Application Development Guide
** For more information on Building C Applications, see the:
**   -  "Building C Applications" section of the Application Building Guide.
**
** For more information on the SQL language see the SQL Reference.
**
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlenv.h>
#include <sqlca.h>
#include <sqlda.h>
#include <sqlutil.h>
#include "util.h"

#ifdef DB268K
/* Need to include ASLM for 68K applications */
#include <LibraryManager.h>
#endif

#define  CHECKERR(CE_STR)   if (check_error (CE_STR, &sqlca) != 0) return 1;

int main(int argc, char *argv[]) {

   EXEC SQL BEGIN DECLARE SECTION;
     char database[9];
     char userid[9];
     char passwd[19];
     char procname[255]  = "inpsrv";
     char table_name[11]    = "PRESIDENTS";
     char data_item0[21]    = "Washington";
     char data_item1[21]    = "Jefferson";
     char data_item2[21]    = "Lincoln";
     short tableind, dataind0, dataind1, dataind2;
   EXEC SQL END DECLARE SECTION;

   /* Declare Variables for CALL USING */
   struct sqlca    sqlca;
   struct sqlda   *inout_sqlda = NULL;
   char eBuffer[1024]; /* error message buffer */


#ifdef DB268K
   /* Before making any API calls for 68K environment,
      need to initial the Library Manager */
	InitLibraryManager(0,kCurrentZone,kNormalMemory);
	atexit(CleanupLibraryManager);
#endif

   if (argc != 4) {
      printf ("\nUSAGE: inpcli remote_database userid passwd\n\n");
      return 1;
   }

   strcpy (database, argv[1]);
   strcpy (userid, argv[2]);
   strcpy (passwd, argv[3]);
   /* Connect to Remote Database */
   printf("CONNECT TO Remote Database.\n");
   EXEC SQL CONNECT TO :database USER :userid USING :passwd;
   CHECKERR ("CONNECT TO SAMPLE");

   /********************************************************\
   * Call the Remote Procedure via CALL with Host Variables *
   \********************************************************/
   printf("Use CALL with Host Variable to invoke the Server Procedure"
      " named inpsrv.\n");
   tableind = dataind0 = dataind1 = dataind2 = 0;

   EXEC SQL CALL :procname (:table_name:tableind, :data_item0:dataind0,
      :data_item1:dataind1, :data_item2:dataind2); /* :rk.2a:erk. */
   /* COMMIT or ROLLBACK the transaction */
   if (SQLCODE == 0)
   { EXEC SQL COMMIT;
     printf("Server Procedure Complete.\n\n");
   }
   else
   { /* print the error message, roll back the transaction and return */
     sqlaintp (eBuffer, 1024, 80, &sqlca);
     printf("\n%s\n", eBuffer);
  
     EXEC SQL ROLLBACK;
     printf("Server Procedure Transaction Rolled Back.\n\n");
     return 1;
   }


   /* Allocate and Initialize Input SQLDA */   /* :rk.1:erk. */
   inout_sqlda = (struct sqlda *)malloc( SQLDASIZE(4) );
   inout_sqlda->sqln = 4;
   inout_sqlda->sqld = 4;

   inout_sqlda->sqlvar[0].sqltype = SQL_TYP_NCSTR;
   inout_sqlda->sqlvar[0].sqldata = table_name;
   inout_sqlda->sqlvar[0].sqllen  = strlen( table_name ) + 1;
   inout_sqlda->sqlvar[0].sqlind  = &tableind;

   inout_sqlda->sqlvar[1].sqltype = SQL_TYP_NCSTR;
   inout_sqlda->sqlvar[1].sqldata = data_item0;
   inout_sqlda->sqlvar[1].sqllen  = strlen( data_item0 ) + 1;
   inout_sqlda->sqlvar[1].sqlind  = &dataind0;

   inout_sqlda->sqlvar[2].sqltype = SQL_TYP_NCSTR;
   inout_sqlda->sqlvar[2].sqldata = data_item1;
   inout_sqlda->sqlvar[2].sqllen  = strlen( data_item1 ) + 1;
   inout_sqlda->sqlvar[2].sqlind  = &dataind1;

   inout_sqlda->sqlvar[3].sqltype = SQL_TYP_NCSTR;
   inout_sqlda->sqlvar[3].sqldata = data_item2;
   inout_sqlda->sqlvar[3].sqllen  = strlen( data_item2 ) + 1;
   inout_sqlda->sqlvar[3].sqlind  = &dataind2;

   /***********************************************\
   * Call the Remote Procedure via CALL with SQLDA *
   \***********************************************/
   printf("Use CALL with SQLDA to invoke the Server Procedure named "
      "inpsrv.\n");

   tableind = dataind0 = dataind1 = dataind2 = 0;
   inout_sqlda->sqlvar[0].sqlind  = &tableind;
   inout_sqlda->sqlvar[1].sqlind  = &dataind0;
   inout_sqlda->sqlvar[2].sqlind  = &dataind1;
   inout_sqlda->sqlvar[3].sqlind  = &dataind2;

   EXEC SQL CALL :procname USING DESCRIPTOR :*inout_sqlda;  /* :rk.2b:erk. */
   /* COMMIT or ROLLBACK the transaction */
   if (SQLCODE == 0)
   { EXEC SQL COMMIT;
     printf("Server Procedure Complete.\n\n");
   }
   else
   { /* print the error message, roll back the transaction and return */
     sqlaintp (eBuffer, 1024, 80, &sqlca);
     printf("\n%s\n", eBuffer);
  
     EXEC SQL ROLLBACK;
     printf("Server Procedure Transaction Rolled Back.\n\n");
     return 1;
   }

   /* Free allocated memory */
   free( inout_sqlda );

   /* Drop the PRESIDENTS table created by the stored procedure */
   EXEC SQL DROP TABLE PRESIDENTS;
   CHECKERR("DROP TABLE");
   
   /* Disconnect from Remote Database */
   EXEC SQL CONNECT RESET;
   CHECKERR ("CONNECT RESET");
   return 0;
}
/* end of program : inpcli.sqc */