/******************************************************************************
**
** Source File Name = inpsrv.sqc  1.5
**
** 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 inpsrv function will take the information
**          received in the SQLDA to create a table and insert the
**          names of the presidents.
**
**          Refer to the inpcli.sqc program for more details on how
**          this program is invoked as the inpsrv function
**          in the inpsrv library by the EXEC SQL CALL statement.
**
** NOTE:    One technique to minimize network flow is to set the
**          variables that returns no output to null on the server program
**          before returning to the client program.
**          This can be achieved by setting the value -128 to the
**          indicator value associated with the data.
**
**          The inpsrv routine will take the information received
**          and create a table called "Presidents" in the "sample"
**          database.  It will then place the values it received in
**          the input/output SQLDA into the "Presidents" table.
**
**    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 <memory.h>
#include <string.h>
#include <sqlenv.h>
#include <sqlutil.h>

#ifdef __cplusplus
extern "C"
#endif
SQL_API_RC SQL_API_FN inpsrv(void *reserved1,      /* :rk.1:erk. */
           void *reserved2,
           struct sqlda   *inout_sqlda,
           struct sqlca   *ca)
{
   /* Declare a local SQLCA */
   EXEC SQL INCLUDE SQLCA;

   /* Declare Host Variables */
   EXEC SQL BEGIN DECLARE SECTION;
     char table_stmt[80]  = "CREATE TABLE ";
     char insert_stmt[80] = "INSERT INTO ";
     char insert_data[21];
   EXEC SQL END DECLARE SECTION;

   /* Declare Miscellanous Variables */
   int  cntr = 0;
   char *table_name;
   char *data_items[3];
   short  data_items_length[3];
   int  num_of_data = 0;

   /*-----------------------------------------------------------------*/
   /* Assign the data from the SQLDA to local variables so that we    */
   /* don't have to refer to the SQLDA structure further.  This will  */
   /* provide better portability to other platforms such as DB2 MVS   */
   /* where they receive the parameter list differently.              */
   /*-----------------------------------------------------------------*/


   table_name  = inout_sqlda->sqlvar[0].sqldata;
   num_of_data = inout_sqlda->sqld - 1;

   for (cntr = 0; cntr < num_of_data; cntr++)
   {
      data_items[cntr] = inout_sqlda->sqlvar[cntr+1].sqldata;
      data_items_length[cntr] = inout_sqlda->sqlvar[cntr+1].sqllen;
   }

   /*-----------------------------------------------------------------*/
   /* Create President Table                                          */
   /* - For simplicity, we'll ignore any errors from the              */
   /*   CREATE TABLE so that you can run this program even when the   */
   /*   table already exists due to a previous run.                   */
   /*-----------------------------------------------------------------*/

   EXEC SQL WHENEVER SQLERROR CONTINUE;
   strcat(table_stmt, table_name);
   strcat(table_stmt, " (name CHAR(20))");  /* :rk.2:erk. */

   EXEC SQL EXECUTE IMMEDIATE :table_stmt;

   EXEC SQL WHENEVER SQLERROR GOTO ext;

   /*-----------------------------------------------------------------*/
   /* Generate and execute a PREPARE for an INSERT statement, and     */
   /* then insert the three presidents.                               */
   /*-----------------------------------------------------------------*/

   strcat(insert_stmt, table_name );
   strcat(insert_stmt, "  VALUES (?)");  /* :rk.3:erk. */

   EXEC SQL PREPARE S1 FROM :insert_stmt;

   for (cntr = 0; cntr < num_of_data; cntr++)
   {
      strncpy(insert_data, data_items[cntr], data_items_length[cntr]);
      insert_data[data_items_length[cntr]] = '\0';
      EXEC SQL EXECUTE S1 USING :insert_data;  /* :rk.4:erk. */
   }

   /*-----------------------------------------------------------------*/
   /* Return to caller                                                */
   /*   -  Copy the SQLCA                                             */
   /*   -  Update the output SQLDA.  Since there's no output to       */
   /*      return, we are setting the indicator values to -128 to     */
   /*      return only a null value.                                  */
   /*-----------------------------------------------------------------*/

ext:  /* :rk.5:erk. */
   memcpy(ca, &sqlca, sizeof(struct sqlca));
   if (inout_sqlda != NULL)
   {
     for (cntr = 0; cntr < inout_sqlda->sqld; cntr++)
     {
       *(inout_sqlda->sqlvar[cntr].sqlind) = -128;
     }
   }

   return(SQLZ_DISCONNECT_PROC);
}