//
// Source File Name = inpcli.sqC
//
// 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: This sample program demonstrates stored procedures in C++.
//
// 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.
//
//
// EXTERNAL DEPENDENCIES :
// - Existing database for precompile purposes.
// - Precompile with the SQL precompiler (PREP in DB2)
// - Binding to a database (BIND in DB2)
// - Compiling and linking 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 <iostream.h>
#include <stdlib.h>
#include <string.h>
#include <sqlenv.h>
#include <sqlda.h>
#include <sqlutil.h>
#include "util.h"
EXEC SQL INCLUDE SQLCA;
#define CHECKERR(CE_STR) if (check_error (CE_STR, &sqlca) != 0)
class Inpsrv {
public:
Inpsrv();
Inpsrv(char *, char *, char *);
InitHV();
CallSQLDA();
CallHV();
~Inpsrv();
private:
EXEC SQL BEGIN DECLARE SECTION;
char database[9];
char userid[9];
char passwd[19];
char procname[255];
char table_name[11];
char data_item0[21];
char data_item1[21];
char data_item2[21];
short tableind, dataind0, dataind1, dataind2;
EXEC SQL END DECLARE SECTION;
/* Declare Variables for CALL USING */
struct sqlda *inout_sqlda;
};
Inpsrv::Inpsrv () {
cout << "Connect to default database with default userid and password\n";
EXEC SQL CONNECT TO sample;
CHECKERR ("CONNECT TO") exit(1);
}
Inpsrv::Inpsrv (char *database, char *userid, char *passwd) {
cout << "Connecting to database " << database << "\n";
EXEC SQL CONNECT TO :database USER :userid USING :passwd;
CHECKERR ("CONNECT TO :database") exit(1);
}
Inpsrv::InitHV() {
strcpy(procname, "inpsrv");
strcpy(table_name, "PRESIDENTS");
strcpy(data_item0, "Washington");
strcpy(data_item1, "Jefferson");
strcpy(data_item2, "Lincoln");
return 0;
}
Inpsrv::CallSQLDA () {
// 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 = &dataind0;
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 = &dataind0;
// -----------------------------------------------//
// Call the Remote Procedure via CALL with SQLDA //
// -----------------------------------------------//
cout << "Use CALL with SQLDA to invoke the Server Procedure named inpsrv\n";
// Set the indicatore variables.
tableind = dataind0 = dataind1 = dataind2 = 0;
EXEC SQL CALL :procname USING DESCRIPTOR :*inout_sqlda; /* :rk.2b:erk. */
CHECKERR ("CALL WITH SQLDA") return 1;
cout << "Server Procedure Complete.\n\n";
// Free allocated memory.
free( inout_sqlda );
return 0;
}
Inpsrv::CallHV() {
// --------------------------------------------------------//
// Call the Remote Procedure via CALL with Host Variables //
// --------------------------------------------------------//
cout << "Use CALL with Host Variables to invoke the Server Procedure "
<< "named inpsrv.\n";
// Set the indicator variables.
tableind = dataind0 = dataind1 = dataind2 = 0;
EXEC SQL CALL :procname (:table_name:tableind, :data_item0:dataind0,
:data_item1:dataind1, :data_item2:dataind2); /* :rk.2a:erk. */
CHECKERR ("CALL WITH HOST VARIABLE") return 1;
cout << "Server Procedure Complete.\n\n";
return 0;
}
Inpsrv::~Inpsrv () {
// Disconnect from Remote Database
EXEC SQL CONNECT RESET;
CHECKERR ("CONNECT RESET") exit(1);
}
int main(int argc, char *argv[]) {
if (argc == 4) {
Inpsrv inpsrvSample (argv[1], argv[2], argv[3]);
inpsrvSample.InitHV();
inpsrvSample.CallHV();
inpsrvSample.CallSQLDA();
} else if (argc == 1) {
Inpsrv inpsrvSample;
inpsrvSample.InitHV();
inpsrvSample.CallHV();
inpsrvSample.CallSQLDA();
} else {
cout << "\nUSAGE: inpcli remote_database userid passwd\n\n";
} // end if
return 0;
}
// end of program : inpcli.sqC