/*******************************************************************************
**
** Source File Name = fillcli.sqC  1.6
**
** Licensed Materials - Property of IBM
**
** (C) COPYRIGHT International Business Machines Corp. 1995, 1997
** All Rights Reserved.
**
** US Government Users Restricted Rights - Use, duplication or
** disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
**
**
**    PURPOSE :
**       An stored procedure example which demonstrates the usage of SQLDA
**       by passing information to the server procedure on which table to
**       fill with random data. (server program : "fillsrv")
**
**    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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sql.h>
#include <sqlca.h>
#include <sqlda.h>
#include <sqlenv.h>
#include "util.h"

EXEC SQL INCLUDE SQLCA ;

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

class FillClient {

    EXEC SQL BEGIN DECLARE SECTION ;
      char database[9] ;
      char userid[9] ;
      char passwd[19] ;
      char procname[33] ;
      char sql_buffer[255] ;
    EXEC SQL END DECLARE SECTION ;

    struct sqlda * client_sqlda, * server_sqlda ;
    short org_rows ;

    int Disconnect() ;

  public:

    FillClient() ;
    ~FillClient() ;
    int Connect( char *, char *, char * ) ;
    int DescribeVars() ;
    int BrowseData() ;
    int CallStProc( char * ) ;
    short GetOrgRows() { return( org_rows ) ; } ;

} ;

FillClient::FillClient() {

  init_da( &client_sqlda, 1 ) ;
  init_da( &server_sqlda, 3 ) ;
  server_sqlda->sqld = 3 ;
  server_sqlda->sqlvar[0].sqltype = SQL_TYP_NCSTR ;
  server_sqlda->sqlvar[0].sqllen = 15 ;
  server_sqlda->sqlvar[1].sqltype = SQL_TYP_NSMALL ;
  server_sqlda->sqlvar[1].sqllen = sizeof( short ) ;
  server_sqlda->sqlvar[2].sqltype = SQL_TYP_NCSTR ;
  server_sqlda->sqlvar[2].sqllen = 13 ;

  alloc_host_vars( server_sqlda ) ;

  org_rows = 10 ;
  memcpy( ( void * ) server_sqlda->sqlvar[1].sqldata, &org_rows, sizeof( short ) ) ;
  strcpy( ( char * ) server_sqlda->sqlvar[2].sqldata, "Tasmania" ) ;

  memset( ( void * ) procname, 0, 33 ) ;
  strcpy( procname, "fillsrv" ) ;

}

FillClient::~FillClient() {

  Disconnect() ;

  free_da( client_sqlda ) ;
  free( server_sqlda ) ;

}

int FillClient::Connect( char * dbn_arg, char * uid_arg, char * pwd_arg ) {

  strcpy( database, dbn_arg ) ;
  strcpy( userid,   uid_arg ) ;
  strcpy( passwd,   pwd_arg ) ;

  printf( "\nConnecting to database %s\n", database ) ;
  EXEC SQL CONNECT TO :database USER :userid USING :passwd ;
  CHECKERR( "CONNECT TO DATABASE" ) ;

  return( 0 ) ;

}

int FillClient::Disconnect() {

  EXEC SQL CONNECT RESET ;
  CHECKERR( "DISCONNECT" ) ;

  return( 0 ) ;

}

int FillClient::DescribeVars() {

  memset( ( void * ) sql_buffer, 0, 255 ) ;
  strcpy( sql_buffer, "SELECT * FROM ORG" ) ;

  EXEC SQL PREPARE st FROM :sql_buffer ;
  CHECKERR( "PREPARE SELECT FROM ORG" ) ;

  EXEC SQL DESCRIBE st INTO :*client_sqlda ;
  int sqld_value = client_sqlda->sqld ;
  free( client_sqlda ) ;
  init_da( &client_sqlda, sqld_value ) ;
  EXEC SQL DESCRIBE st INTO :*client_sqlda ;
  CHECKERR( "DESCRIBE DESCRIPTOR" ) ;

  alloc_host_vars( client_sqlda ) ;

  EXEC SQL DECLARE c1 CURSOR FOR st ;

  return( 0 ) ;

}

int FillClient::BrowseData() {

  EXEC SQL OPEN c1 ;
  CHECKERR( "OPEN CURSOR" ) ;

  EXEC SQL FETCH c1 USING DESCRIPTOR :*client_sqlda ;
  CHECKERR( "OPEN CURSOR" ) ;

  printf( "\n" ) ;

  display_col_titles( client_sqlda ) ;
  int i = 0 ;
  while ( SQLCODE == 0 ) {
    display_da( client_sqlda ) ;
    EXEC SQL FETCH c1 USING DESCRIPTOR :*client_sqlda ;
    i++ ;
  }

  EXEC SQL CLOSE c1 ;
  CHECKERR( "CLOSE CURSOR" ) ;

  printf( "%d record(s) selected.\n", i ) ;

  return( 0 ) ;

}

int FillClient::CallStProc( char * transactType ) {

  memset( ( void * ) server_sqlda->sqlvar[0].sqldata, 0, 15 ) ;
  strcpy( ( char * ) server_sqlda->sqlvar[0].sqldata, transactType ) ;

  EXEC SQL CALL :procname USING DESCRIPTOR :*server_sqlda ;
  CHECKERR( transactType ) ;

  EXEC SQL COMMIT ;
  CHECKERR( "COMMIT" ) ;

  BrowseData() ;

  printf( "Server Procedure Completed.\n" ) ;

  return( 0 ) ;

}

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

  FillClient client ;

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

  client.Connect( argv[1], argv[2], argv[3] ) ;

  client.DescribeVars() ;

  client.BrowseData() ;

  client.CallStProc( "INSERT" ) ;
  printf( "%d record(s) added.\n", client.GetOrgRows() ) ;

  client.CallStProc( "DELETE" ) ;
  printf( "New record(s) deleted.\n" ) ;

  return( 0 ) ;

}