/****************************************************************************** ** ** Source File Name = inpcli.sqc 1.4 ** ** 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: This sample program demonstrates stored procedures. ** ** 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. ** ** A external function "check_error" is contained in the file "util.c" ** which must be compiled along with this file. ** ** ** 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 <stdio.h> #include <stdlib.h> #include <string.h> #include <sqlenv.h> #include <sqlca.h> #include <sqlda.h> #include <sqlutil.h> #include "util.h" #ifdef DB268K /* Need to include ASLM for 68K applications */ #include <LibraryManager.h> #endif #define CHECKERR(CE_STR) if (check_error (CE_STR, &sqlca) != 0) return 1; int main(int argc, char *argv[]) { EXEC SQL BEGIN DECLARE SECTION; char database[9]; char userid[9]; char passwd[19]; char procname[255] = "inpsrv"; char table_name[11] = "PRESIDENTS"; char data_item0[21] = "Washington"; char data_item1[21] = "Jefferson"; char data_item2[21] = "Lincoln"; short tableind, dataind0, dataind1, dataind2; EXEC SQL END DECLARE SECTION; /* Declare Variables for CALL USING */ struct sqlca sqlca; struct sqlda *inout_sqlda = NULL; char eBuffer[1024]; /* error message buffer */ #ifdef DB268K /* Before making any API calls for 68K environment, need to initial the Library Manager */ InitLibraryManager(0,kCurrentZone,kNormalMemory); atexit(CleanupLibraryManager); #endif if (argc != 4) { printf ("\nUSAGE: inpcli remote_database userid passwd\n\n"); return 1; } strcpy (database, argv[1]); strcpy (userid, argv[2]); strcpy (passwd, argv[3]); /* Connect to Remote Database */ printf("CONNECT TO Remote Database.\n"); EXEC SQL CONNECT TO :database USER :userid USING :passwd; CHECKERR ("CONNECT TO SAMPLE"); /********************************************************\ * Call the Remote Procedure via CALL with Host Variables * \********************************************************/ printf("Use CALL with Host Variable to invoke the Server Procedure" " named inpsrv.\n"); tableind = dataind0 = dataind1 = dataind2 = 0; EXEC SQL CALL :procname (:table_name:tableind, :data_item0:dataind0, :data_item1:dataind1, :data_item2:dataind2); /* :rk.2a:erk. */ /* COMMIT or ROLLBACK the transaction */ if (SQLCODE == 0) { EXEC SQL COMMIT; printf("Server Procedure Complete.\n\n"); } else { /* print the error message, roll back the transaction and return */ sqlaintp (eBuffer, 1024, 80, &sqlca); printf("\n%s\n", eBuffer); EXEC SQL ROLLBACK; printf("Server Procedure Transaction Rolled Back.\n\n"); return 1; } /* 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 = &dataind1; 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 = &dataind2; /***********************************************\ * Call the Remote Procedure via CALL with SQLDA * \***********************************************/ printf("Use CALL with SQLDA to invoke the Server Procedure named " "inpsrv.\n"); tableind = dataind0 = dataind1 = dataind2 = 0; inout_sqlda->sqlvar[0].sqlind = &tableind; inout_sqlda->sqlvar[1].sqlind = &dataind0; inout_sqlda->sqlvar[2].sqlind = &dataind1; inout_sqlda->sqlvar[3].sqlind = &dataind2; EXEC SQL CALL :procname USING DESCRIPTOR :*inout_sqlda; /* :rk.2b:erk. */ /* COMMIT or ROLLBACK the transaction */ if (SQLCODE == 0) { EXEC SQL COMMIT; printf("Server Procedure Complete.\n\n"); } else { /* print the error message, roll back the transaction and return */ sqlaintp (eBuffer, 1024, 80, &sqlca); printf("\n%s\n", eBuffer); EXEC SQL ROLLBACK; printf("Server Procedure Transaction Rolled Back.\n\n"); return 1; } /* Free allocated memory */ free( inout_sqlda ); /* Drop the PRESIDENTS table created by the stored procedure */ EXEC SQL DROP TABLE PRESIDENTS; CHECKERR("DROP TABLE"); /* Disconnect from Remote Database */ EXEC SQL CONNECT RESET; CHECKERR ("CONNECT RESET"); return 0; } /* end of program : inpcli.sqc */