/*******************************************************************************
**                                                                        
** Source File Name = inpsrv2.c  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 :                                                           
**                                                                        
*******************************************************************************/
/********************************************************************
* SAMPLE PROGRAM: inpsrv2.c
********************************************************************/
/*--> SQLL1X43.SCRIPT */
/********************************************************************
*
* PURPOSE: This sample program demonstrates stored procedures,
*          using CLI.  It is rewrite of the inpsrv.sqc embedded SQL
*          stored procedure.
*
*          There are two parts to this program:
*              - the inpcli2 executable (placed on the client)
*              - the inpsrv2 library (placed on the server)
*          CLI stored procedures can be called by either CLI or embbeded
*          applications.
*
*          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 inpcli2.c program for more details on how
*          this program is invoked as the inpsrv2 function
*          in the inpsrv2 library by the EXEC SQL CALL statement.
*
*          The SQL CALL statement will pass in 2 identical SQLDA
*          structures for input and output because all parameters
*          on the CALL statement are assummed to have both the
*          input and output attributes.  However, only changes
*          make to the data and indicator fields in the output SQLDA
*          will be returned to the client program.
*
* 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 sqleproc API will call the inpsrv routine stored
*          in the inpsrv library.
*
*          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 SQLDA into the "Presidents" table.
*
** For more information about these samples see the README file.
**
** For more information on programming in CLI see the:
**     - "Building CLI Applications" section of the Application Building Guide, and the
**     - CLI Guide and Reference.
**
** For more information on the SQL language see the SQL Reference.
**
*********************************************************************/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sqlda.h>
#include <sqlcli1.h>
#include "samputil.h"          /* Header file for CLI sample code */

int SQL_API_FN inpsrv2( void         * reserved1,
                        void         * reserved2,
                        struct sqlda * inout_sqlda,
                        struct sqlca * ca
                      ) {

   /* Declare a local SQLCA */
   struct sqlca sqlca ;

   SQLCHAR table_stmt[80] = "CREATE TABLE " ;
   SQLCHAR insert_stmt[80] = "INSERT INTO " ;
   SQLCHAR insert_data[21] ;
   SQLINTEGER insert_data_ind ;

   /* Delare Miscellanous Variables */
   int cntr ;
   char * table_name ;
   short table_name_length ;
   char * data_item[3] ;
   short data_item_length[3] ;
   int num_of_data = 0 ;

   /* Delare CLI Variables */
   SQLHANDLE henv, hdbc, hstmt ;
   SQLRETURN rc ;

   /*-----------------------------------------------------------------*/
   /* 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.              */
   /* Note: Strings are not null-terminated in the SQLDA.             */
   /*-----------------------------------------------------------------*/

   table_name = inout_sqlda->sqlvar[0].sqldata ;
   table_name_length = inout_sqlda->sqlvar[0].sqllen ;
   num_of_data = inout_sqlda->sqld - 1 ;
   for ( cntr = 0; cntr < num_of_data; cntr++ ) {
       data_item[cntr] = inout_sqlda->sqlvar[cntr+1].sqldata ;
       data_item_length[cntr] = inout_sqlda->sqlvar[cntr+1].sqllen ;
   }

   /*-----------------------------------------------------------------*/
   /* Setup CLI required environment                                  */
   /*-----------------------------------------------------------------*/

   SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv ) ;
   SQLAllocHandle( SQL_HANDLE_DBC, henv, &hdbc ) ;

   /*-----------------------------------------------------------------*/
   /* Issue NULL Connect, since in CLI we need a statement handle     */
   /* and thus a connection handle and environment handle.            */
   /* A connection is not established, rather the current             */
   /* connection from the calling application is used                 */
   /*-----------------------------------------------------------------*/
   SQLConnect( hdbc, NULL, SQL_NTS, NULL, SQL_NTS, NULL, SQL_NTS ) ;
   SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt ) ;

   /*-----------------------------------------------------------------*/
   /* 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.                   */
   /*-----------------------------------------------------------------*/

   strncat( ( char * ) table_stmt,
            ( char * ) table_name,
            table_name_length
          ) ;
   strcat( ( char * ) table_stmt, " (name CHAR(20))" ) ;

   SQLExecDirect( hstmt, table_stmt, SQL_NTS ) ;

   SQLFreeStmt( hstmt, SQL_RESET_PARAMS ) ;

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

   strncat( ( char * ) insert_stmt,
            ( char * ) table_name,
            table_name_length
          ) ;
   strcat( ( char * ) insert_stmt, "  VALUES (?)" ) ;

   if ( SQLPrepare(hstmt, insert_stmt, SQL_NTS) != SQL_SUCCESS ) goto ext ;

   /* Bind insert_data to parameter marker */
   SQLBindParameter( hstmt,
                     1,
                     SQL_PARAM_INPUT,
                     SQL_C_CHAR,
                     SQL_CHAR,
                     20,
                     0,
                     insert_data,
                     21,
                     &insert_data_ind
                   ) ;

   for ( cntr = 0; cntr < num_of_data; cntr++ ) {
       strncpy( ( char * ) insert_data,
                ( char * ) data_item[cntr],
                data_item_length[cntr]) ;
       insert_data_ind = data_item_length[cntr] ;
       if ( SQLExecute( hstmt ) != SQL_SUCCESS ) goto ext ;
   }

   /*-----------------------------------------------------------------*/
   /* 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.                                  */
   /*   -  Commit or Rollback the inserts.                            */
   /*-----------------------------------------------------------------*/

ext:

    rc = SQLGetSQLCA( henv, hdbc, hstmt, &sqlca ) ;
    if ( rc != SQL_SUCCESS ) printf( "RC = %d\n", rc ) ;
    memcpy( ca, &sqlca, sizeof( sqlca ) ) ;
    if ( inout_sqlda != NULL ) {
       for ( cntr = 0; cntr < inout_sqlda->sqld; cntr++ ) {
           if ( inout_sqlda->sqlvar[cntr].sqlind != NULL )
              *( inout_sqlda->sqlvar[cntr].sqlind ) = -128 ;
       }
    }

    rc = SQLFreeHandle( SQL_HANDLE_STMT, hstmt ) ;
    CHECK_HANDLE( SQL_HANDLE_STMT, hstmt, rc ) ;

    rc = SQLEndTran( SQL_HANDLE_DBC, hdbc, SQL_COMMIT ) ;
    CHECK_HANDLE( SQL_HANDLE_DBC, hdbc, rc ) ;

    rc = SQLDisconnect( hdbc ) ;
    CHECK_HANDLE( SQL_HANDLE_DBC, hdbc, rc ) ;

    rc = SQLFreeHandle( SQL_HANDLE_DBC, hdbc ) ;
    CHECK_HANDLE( SQL_HANDLE_DBC, hdbc, rc ) ;

    rc = SQLFreeHandle( SQL_HANDLE_ENV,  henv ) ;
    if ( rc != SQL_SUCCESS )
        return( terminate( henv, rc ) ) ;

    return(1);  /* Return SQLZ_DISCONNECT_PROC */

}
/*<-- */