// // Source File Name = outcli.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: // 1. the outcli executable (placed on the client) // 2. the outsrv library (placed on the server) // // There are two different ways to invoke from outcli: // 1. EXEC SQL CALL :procname (:sal:salind) // 2. EXEC SQL CALL :procname USING DESCRIPTOR :*inout_sqlda // // When the CALL USING and sqleproc API are used, // the outcli routine will allocate and initialize a one // variable SQLDA to point to the data. // This SQLDA may be used for both input and output, // although in this program it is used for output 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 call the outsrv routine stored // in the outsrv library. // // The outsrv routine will obtain the median salary of // employees in the "staff" table of the "sample" database. // This value will be placed in the output SQLDA and // returned to the outcli routine. The outcli routine will // then print out the median salary. // // NOTE: 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. // // An external function "check_error" is contained in the file "util.C" // which must be compiled along with this file. // // 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 <sql.h> /* :rk.1:erk. */ #include <sqlda.h> #include <sqlca.h> #include <string.h> #include "util.h" EXEC SQL INCLUDE SQLCA; #define CHECKERR(CE_STR) if (check_error (CE_STR, &sqlca) != 0) class Outsrv { public: Outsrv(); Outsrv(char *, char *, char *); InitHV(); CallSQLDA(); CallHV(); ~Outsrv(); private: EXEC SQL BEGIN DECLARE SECTION; char database[9]; char userid[9]; char passwd[19]; /* Declare a Local Variable for Holding the Procedure's Name */ char procname[255]; /* Declare Local Variables for Holding Returned Data */ double sal; short salind; EXEC SQL END DECLARE SECTION; struct sqlda *inout_sqlda; }; Outsrv::Outsrv () { cout << "Connect to default database with default userid and password\n"; EXEC SQL CONNECT TO sample; CHECKERR ("CONNECT TO") exit(1); } Outsrv::Outsrv (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); } Outsrv::InitHV () { strcpy (procname, "outsrv"); sal = 0.0; salind = 0; return 0; } Outsrv::CallSQLDA () { // -----------------------------------------------// // Call the Remote Procedure via CALL with SQLDA // // -----------------------------------------------// inout_sqlda = (struct sqlda *) malloc (SQLDASIZE(1)); // Initialize the output SQLDA inout_sqlda->sqln = 1; inout_sqlda->sqld = 1; inout_sqlda->sqlvar[0].sqltype = SQL_TYP_NFLOAT; inout_sqlda->sqlvar[0].sqllen = sizeof( double ); inout_sqlda->sqlvar[0].sqldata = (char *)&sal; inout_sqlda->sqlvar[0].sqlind = (short *)&salind; cout << "Use CALL with SQLDA to invoke the Server Procedure name outsrv\n"; salind = -1; // Sal has no input, so set to null EXEC SQL CALL :procname USING DESCRIPTOR :*inout_sqlda; CHECKERR ("CALL WITH SQLDA") return 1; cout << "Server Procedure Complete.\n"; // Print Salary Returned in The Host Variables cout << "Median Salary = " << sal << "\n\n"; // Free allocated memory free( inout_sqlda ); return 0; } Outsrv::CallHV () { // --------------------------------------------------------// // Call the Remote Procedure via CALL with Host Variables // // --------------------------------------------------------// cout << "Use CALL with Host Variable to invoke the Server Procedure " "named outsrv\n"; salind = -1; // Sal has no input, so set to null EXEC SQL CALL :procname (:sal :salind); /* :rk.6a:erk. */ CHECKERR ("CALL WITH HOST VARIABLES") return 1; cout << "Server Procedure Complete.\n"; // Print Salary Returned in The Host Variables cout << "Median Salary = " << sal << "\n\n"; return 0; } Outsrv::~Outsrv () { // Disconnect from Remote Database EXEC SQL CONNECT RESET; CHECKERR ("CONNECT RESET") exit(1); } int main(int argc, char *argv[]) { if (argc == 4) { Outsrv outsrvSample (argv[1], argv[2], argv[3]); outsrvSample.InitHV(); outsrvSample.CallHV(); outsrvSample.CallSQLDA(); } else if (argc == 1) { Outsrv outsrvSample; outsrvSample.InitHV(); outsrvSample.CallHV(); outsrvSample.CallSQLDA(); } else { cout << "\nUSAGE: outcli remote_database userid passwd\n\n"; } // end if return 0; } // end of program : outcli.sqC