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