/**************************************************************************** ** (c) Copyright IBM Corp. 2007 All rights reserved. ** ** The following sample of source code ("Sample") is owned by International ** Business Machines Corporation or one of its subsidiaries ("IBM") and is ** copyrighted and licensed, not sold. You may use, copy, modify, and ** distribute the Sample in any form without payment to IBM, for the purpose of ** assisting you in the development of your applications. ** ** The Sample code is provided to you on an "AS IS" basis, without warranty of ** any kind. IBM HEREBY EXPRESSLY DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR ** IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Some jurisdictions do ** not allow for the exclusion or limitation of implied warranties, so the above ** limitations or exclusions may not apply to you. IBM shall not be liable for ** any damages you suffer as a result of using, copying, modifying or ** distributing the Sample, even if IBM has been advised of the possibility of ** such damages. ***************************************************************************** ** ** SOURCE FILE NAME: nestif.sqc ** ** SAMPLE: To call the BUMP_SALARY_IF SQL procedure ** ** There are two parts to this program: ** 1. the nestif executable (placed on the client) ** 2. the BUMP_SALARY_IF SQL procedure (created on the ** server with the nestif.db2 CLP script) ** ** nestif calls the BUMP_SALARY_IF SQL procedure by preparing ** and executing a dynamic CALL statement: ** ** sprintf(stmt, "CALL %s (?)", procname); ** EXEC SQL prepare st from :stmt; ** EXEC SQL execute st USING :dept:deptind; ** ** When the CALL with Host Variable is used, ** the precompiler allocates and initializes an internal one ** variable SQLDA for both input and output. ** ** The BUMP_SALARY procedure uses nested IF statements to raise ** the salaries of employees in a department identified by ** the deptnum IN parameter from the "staff" table of the ** "sample" database. ** ** A cursor fetches rows from the "staff" table until the ** "not_found" (end of file) condition is met and the handler ** sets the value of the "at_end" variable to 1, ending the ** WHILE loop. ** ** The first IF statement provides three IF conditions: ** ** Condition 1: Employee salary is less than 2000 * years of service ** Result: Employee salary is updated to 2000 * years of service ** ** Condition 2: Employee salary is less than 5000 * years of service ** (Note that an employee that satisfies condition 1 cannot also ** satisfy condition 2, because the IF statement exits after the ** first condition was matched.) ** Result: Call nested IF statement 2. ** ** Condition 3: Employee salary does not match condition 1 or 2. ** Result: Update employee job to 'PREZ'. Note that any employee ** with a NULL salary would have their job updated to 'PREZ'. ** ** SQL STATEMENTS USED: ** CONNECT ** DECLARE CURSOR ** OPEN ** FETCH ** CLOSE ** CALL ** ** ***************************************************************************** ** ** For more information on the sample programs, see the README file. ** ** For information on creating SQL procedures and developing C applications, ** see the Developing SQL and External Routines book. ** ** For information on using SQL statements, see the SQL Reference. ** ** For the latest information on programming, building, and running DB2 ** applications, visit the DB2 Information Center: ** http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/index.jsp ****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <sql.h> #include <sqlda.h> #include <sqlca.h> #include <string.h> #include "utilemb.h" int main(int argc, char *argv[]) { 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[254] = "BUMP_SALARY_IF"; /* Declare a statement strings to call the procedure dynamically */ char stmt[1200]; /* Declare local variables for cursor statements */ char name[10]; sqlint16 dept_c = 0; sqlint16 years = 0; double salary = 0; char job[6]; /* Declare Local Variables for Holding Returned Data */ sqlint16 deptnum = 20; sqlint16 deptind = 0; EXEC SQL END DECLARE SECTION; /* Declare the output SQLDA */ struct sqlda *inout_sqlda = (struct sqlda *) malloc(SQLDASIZE(1)); /* :rk.2:erk. */ /* Declare the SQLCA */ struct sqlca sqlca; char eBuffer[1024]; /* error message buffer */ if (argc != 4) { printf ("\nUSAGE: nestif 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; EMB_SQL_CHECK("CONNECT TO RSAMPLE"); /********************************************************\ * Display the contents of STAFF table before CALL * \********************************************************/ EXEC SQL DECLARE c1 CURSOR FOR SELECT name, dept, years, salary, job FROM staff WHERE dept = :deptnum FOR READ ONLY; EXEC SQL OPEN c1; EMB_SQL_CHECK("OPEN CURSOR"); printf("\nDepartment %d before calling %s:\n", deptnum, procname); printf("\n%-9s %6s %5s %10s %-5s\n", "NAME", "DEPT", "YEARS", "SALARY", "JOB"); do { EXEC SQL FETCH c1 INTO :name, :dept_c, :years, :salary, :job; if (SQLCODE != 0) break; printf( "%-9s %6d %5d %10.2f %-5s\n", name, dept_c, years, salary, job ); } while ( 1 ); EXEC SQL CLOSE c1; EMB_SQL_CHECK("CLOSE CURSOR"); /********************************************************\ * Call the Remote Procedure via CALL with Host Variables * \********************************************************/ printf("\nUse CALL with Host Variable to invoke the Server Procedure " "named %s\n", procname); sprintf(stmt, "CALL %s (?)", procname); EXEC SQL prepare st from :stmt; EMB_SQL_CHECK("PREPATE CALL STATEMENT"); EXEC SQL execute st USING :deptnum:deptind; EMB_SQL_CHECK("EXECUTE CALL STATEMENT"); /* COMMIT or ROLLBACK the transaction */ if (SQLCODE == 0) { EXEC SQL OPEN c1; EMB_SQL_CHECK("OPEN CURSOR"); printf("\nDepartment %d after calling %s:\n", deptnum, procname); printf("%-9s %6s %5s %10s %-5s\n", "NAME", "DEPT", "YEARS", "SALARY", "JOB"); do { EXEC SQL FETCH c1 INTO :name, :dept_c, :years, :salary, :job; if (SQLCODE != 0) break; printf("%-9s %6d %5d %10.2f %-5s\n", name, dept_c, years, salary, job ); } while ( 1 ); EXEC SQL CLOSE c1; EMB_SQL_CHECK("CLOSE CURSOR"); EXEC SQL ROLLBACK; /* to preserve the sample database, changes are not committed; to commit the changes, you should use: EXEC SQL COMMIT */ printf("Server Procedure Complete.\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 ); /* Disconnect from Remote Database */ EXEC SQL CONNECT RESET; EMB_SQL_CHECK("CONNECT RESET"); return 0; } /* end of program : nestif.sqc */