// Source File Name: Stserver.java 1.5 // // Licensed Materials -- Property of IBM // // (c) Copyright International Business Machines Corporation, 1998, 1999. // All Rights Reserved. // // US Government Users Restricted Rights - // Use, duplication or disclosure restricted by // GSA ADP Schedule Contract with IBM Corp. // Sample Program Stserver - Stored Procedure // Steps to run the sample: // (1) create and populate the SAMPLE database (db2sampl) // (2) compile Stserver (javac Stserver.java) // (3) copy Stserver.class to the sqllib/function directory // (4) register the stored procedures using the Stcreate.db2 CLP script: // (i) db2 connect to sample // (ii) db2 -td@ -vf Stcreate.db2 // (3) compile Stclient (javac Stclient.java) // (4) run Stclient (java Stclient) // NOTES: (1) The jdk11_path database manager configuration parameter must // be set // (2) The CLASSPATH and shared library path environment variables // must be set, as for any JDBC application. // (3) Visit http://www.software.ibm.com/data/db2/java // for current DB2 Java information // For more information about this sample, refer to the README file. // For more information on Programming in Java, refer to the // "Programming in Java" section of the Application Development Guide. // For more information on creating stored procedures, refer to the // "Writing Stored Procedures" section of the Application Development Guide. // For more information on building and running Java programs for DB2, // refer to the "Building Java Applets and Applications" section of the // Application Building Guide. // For more information on the SQL language, refer to the SQL Reference. // Class Stserver contains nine methods: // (1) outLanguage: return language of the stored procedure library // (2) outParameter: return median salary of EMPLOYEE table // (3) inParams: accept 3 values and update salaries in EMPLOYEE table // accordingly // (4) inoutParam: accept an input value and return the median // salary of the EMPLOYEE table for employees who make more // than the input value // (5) resultSetToClient: return a result set to the client application // (6) twoResultSets: return two result sets to the client application // (7) clobExtract: return a section of a CLOB type as a string // (8) decimalType: pass a Java BigDecimal type as a DECIMAL data type // (9) allDataTypes: use all of the common data types in a stored procecure import java.sql.*; // JDBC classes import java.io.*; // Input/Output classes import java.math.BigDecimal; // Packed Decimal class import sqlj.runtime.*; import sqlj.runtime.ref.*; #sql iterator StserverSalary (double); #sql iterator StserverEmployees (String, String, double); class Stserver { public static void outLanguage (String[] outLang) throws Exception { try { String procName = "OUT_LANGUAGE"; String language; #sql { SELECT language INTO :language FROM syscat.procedures WHERE procname = :procName }; outLang[0] = language; } catch (Exception e) { throw e; } } public static void outParameter (double[] medianSalary, int[] errorCode, String[] errorLabel) throws SQLException /* :rk.1:erk. */ { try { StserverSalary c1; double salary; int counter, numRecords; // Initialize variables salary = 0; counter = 0; errorCode[0] = 0; // SQLCODE = 0 unless SQLException occurs #sql { SELECT COUNT(*) INTO :numRecords FROM staff }; errorLabel[0] = "COUNT NUMBER OF ROWS"; // declare salary iterator #sql c1 = { SELECT CAST(salary AS DOUBLE) FROM staff ORDER BY salary }; errorLabel[0] = "DECLARE SALARY ITERATOR"; while (counter < (numRecords / 2 + 1)) { #sql { FETCH :c1 INTO :salary }; errorLabel[0] = "MOVE TO ROW: " +counter; if (c1.endFetch()) break; counter++; } medianSalary[0] = salary; c1.close(); } catch (SQLException sqle) { errorCode[0] = sqle.getErrorCode(); } } public static void inParams (double inLowSal, double inMedSal, double inHighSal, String inDepartment, int[] errorCode, String[] errorLabel) throws SQLException { StserverIterator updateIterator; double salary, lowSal, medSal, highSal; String cursorName; // Initialize variables salary = 0; cursorName = ""; errorCode[0] = 0; // SQLCODE = 0 unless SQLException occurs try { errorLabel[0] = "DECLARE ITERATOR"; #sql updateIterator = { SELECT CAST(salary AS DOUBLE) FROM employee WHERE workdept = :inDepartment }; lowSal = inLowSal; medSal = inMedSal; highSal = inHighSal; errorLabel[0] = "FETCH FIRST ROW"; #sql { FETCH :updateIterator INTO :salary }; if (updateIterator.endFetch()) { /* Iterator contains no data, so return SQLCODE 100 to client */ errorCode[0] = 100; } else { while (!updateIterator.endFetch()) { if (lowSal > salary) { #sql { UPDATE employee SET salary = :lowSal WHERE CURRENT OF :updateIterator }; errorLabel[0] = "UPDATE -- LOW CASE"; } else if (medSal > salary) { #sql { UPDATE employee SET salary = :medSal WHERE CURRENT OF :updateIterator }; errorLabel[0] = "UPDATE -- MEDIUM CASE"; } else if (highSal > salary) { #sql { UPDATE employee SET salary = :highSal WHERE CURRENT OF :updateIterator }; errorLabel[0] = "UPDATE -- HIGH CASE"; } else { #sql { UPDATE employee SET salary = (salary * 1.10) WHERE CURRENT OF :updateIterator }; errorLabel[0] = "UPDATE -- FINAL CASE"; } #sql { FETCH :updateIterator INTO :salary }; } } updateIterator.close(); } catch (SQLException sqle) { errorCode[0] = sqle.getErrorCode(); } } public static void inoutParam (double[] inoutMedianSalary, int[] errorCode, String[] errorLabel) throws SQLException { int counter, numRecords; double salary, inSalary; StserverSalary c1; // Initialize variables counter = 0; salary = 0; errorCode[0] = 0; // SQLCODE = 0 unless SQLException occurs inSalary = inoutMedianSalary[0]; try { errorLabel[0] = "GET NUMBER OF RECORDS"; #sql { SELECT COUNT(*) INTO :numRecords FROM staff WHERE CAST(salary AS DOUBLE) > :inSalary }; if (numRecords == 0) { // Set errorCode to SQL0100 to indicate that no data was found errorCode[0] = 100; } else { errorLabel[0] = "GET SALARY RESULT SET"; #sql c1 = { SELECT CAST(salary AS DOUBLE) FROM staff WHERE CAST(salary AS DOUBLE) > :inSalary ORDER BY salary }; errorLabel[0] = "PREPARE SALARY STATEMENT"; while (counter < (numRecords / 2 + 1)) { errorLabel[0] = "MOVE TO ROW: " + counter; #sql { FETCH :c1 INTO :salary }; counter++; } inoutMedianSalary[0] = salary; c1.close(); } } catch (SQLException sqle) { errorCode[0] = sqle.getErrorCode(); } } public static void resultSetToClient (double inSalaryThreshold, // double input int[] errorCode, // SQLCODE output ResultSet[] rs) // ResultSet output throws SQLException { StserverEmployees c1; double inSalary; errorCode[0] = 0; // SQLCODE = 0 unless SQLException occurs inSalary = inSalaryThreshold; try { // Declare iterator for result set #sql c1 = { SELECT name, job, CAST(salary AS DOUBLE) FROM staff WHERE salary > :inSalary ORDER BY salary }; // get the result set that is returned to the client rs[0] = c1.getResultSet(); } catch (SQLException sqle) { errorCode[0] = sqle.getErrorCode(); } } public static void twoResultSets (double inSalaryThreshold, // double input int[] errorCode, // SQLCODE output ResultSet[] rs1, // first ResultSet output ResultSet[] rs2) // second ResultSet output throws SQLException { StserverEmployees c1, c2; double inSalary; errorCode[0] = 0; // SQLCODE = 0 unless SQLException occurs inSalary = inSalaryThreshold; try { // Declare iterator for first result set #sql c1 = { SELECT name, job, CAST(salary AS DOUBLE) FROM staff WHERE salary > :inSalary ORDER BY salary }; // get the first result set that is returned to the client rs1[0] = c1.getResultSet(); // Declare iterator for first result set #sql c2 = { SELECT name, job, CAST(salary AS DOUBLE) FROM staff WHERE salary < :inSalary ORDER BY salary DESC }; // get the second result set that is returned to the client rs2[0] = c2.getResultSet(); } catch (SQLException sqle) { errorCode[0] = sqle.getErrorCode(); } } public static void clobExtract (String empNo, // CHAR(6) input parameter String[] interests, // VARCHAR(1000) output parameter int errorCode[] // SQLINT32 output parameter ) throws IOException { int counter, index, maximumLength; byte[] clobBytes; char[] clobData; try { // Get caller's connection to the database Connection con = DriverManager.getConnection("jdbc:default:connection"); // choose the employee resume that matches the employee number Statement stmt = con.createStatement (); ResultSet rs = stmt.executeQuery("SELECT resume FROM emp_resume WHERE " + "empno = '" + empNo + "' AND resume_format = 'ascii'"); if (rs.next()) { // copy the CLOB into an array of characters by converting all // bytes into characters as they are read in InputStream inStream = rs.getAsciiStream (1); // InputStream.available() may not work on larger files maximumLength = inStream.available(); clobBytes = new byte[maximumLength]; clobData = new char[maximumLength]; inStream.read(clobBytes); for (counter = 0; counter < maximumLength; counter++) { clobData[counter] = (char)clobBytes[counter]; } String clob = String.valueOf (clobData); // Copy substring from "Department Info" to "Education" into OUT parameter index = clob.indexOf("Department Info"); if (index == -1) { interests[0] = ("Resume does not contain a Department Info section."); } else { interests[0] = clob.substring (clob.indexOf ("Department Info"), clob.indexOf("Education")); } } else { interests[0] = ("\nEmployee " + empNo + " does not have a resume."); } rs.close(); stmt.close(); } catch (SQLException sqle) { errorCode[0] = sqle.getErrorCode(); } } public static void decimalType (BigDecimal[] inoutDecimal, // DECIMAL(10,2) int[] errorCode, String[] errorLabel) throws Exception { errorCode[0] = 0; // SQLCODE = 0 unless SQLException occurs try { if (inoutDecimal[0].equals(BigDecimal.valueOf(0))) { inoutDecimal[0].add(BigDecimal.valueOf(1)); } else { inoutDecimal[0] = inoutDecimal[0].divide( BigDecimal.valueOf(2), BigDecimal.ROUND_HALF_UP); } } catch (Exception sqle) { errorCode[0] = 0; } } public static void allDataTypes (short[] inoutSmallint, // SMALLINT int[] inoutInteger, // INTEGER long[] inoutBigint, // BIGINT float[] inoutReal, // REAL double[] inoutDouble, // DOUBLE String[] outChar, // CHAR(1) String[] outChars, // CHAR(15) String[] outVarchar, // VARCHAR(12) Date[] outDate, // DATE Time[] outTime, // TIME int[] errorCode, String[] errorLabel) throws SQLException { String query, hvOutChar, hvOutChars, hvOutVarchar; ResultSet rs; Statement stmt; Date hvOutDate; Time hvOutTime; errorCode[0] = 0; // SQLCODE = 0 unless SQLException occurs errorLabel[0] = "START ALL_DATA_TYPES"; try { // Get caller's connection to the database Connection con = DriverManager.getConnection("jdbc:default:connection"); if (inoutSmallint[0] == 0) { inoutSmallint[0] = 1; } else { inoutSmallint[0] = (short) (inoutSmallint[0] / 2); } if (inoutInteger[0] == 0) { inoutInteger[0] = 1; } else { inoutInteger[0] = (inoutInteger[0] / 2); } if (inoutBigint[0] == 0) { inoutBigint[0] = 1; } else { inoutBigint[0] = (inoutBigint[0] / 2); } if (inoutReal[0] == 0) { inoutReal[0] = 1; } else { inoutReal[0] = (inoutReal[0] / 2); } if (inoutDouble[0] == 0) { inoutDouble[0] = 1; } else { inoutDouble[0] = (inoutDouble[0] / 2); } // get value of a CHAR(1) column (midinit) errorLabel[0] = "GET CHAR(1)"; #sql { SELECT midinit INTO :hvOutChar FROM employee WHERE empno = '000180' }; outChar[0] = hvOutChar; // get value of a CHAR(15) column (lastname) errorLabel[0] = "GET CHAR(15)"; #sql { SELECT lastname INTO :hvOutChars FROM employee WHERE empno = '000180' }; outChars[0] = hvOutChars; // get value of a VARCHAR(12) column (firstnme) errorLabel[0] = "GET VARCHAR(12)"; #sql { SELECT firstnme INTO :hvOutVarchar FROM employee WHERE empno = '000180' }; outVarchar[0] = hvOutVarchar; // get current date using JDBC query = "VALUES (CURRENT DATE)"; errorLabel[0] = "create VALUES (CURRENT DATE)"; // create the SQL statement stmt = con.createStatement(); // get the result set rs = stmt.executeQuery(query); // move to first row of result set rs.next(); // get the date value outDate[0] = rs.getDate(1); // clean up resources rs.close(); stmt.close(); // get current time using JDBC query = "VALUES (CURRENT TIME)"; errorLabel[0] = "create VALUES (CURRENT TIME)"; // create the SQL statement stmt = con.createStatement(); // get the result set rs = stmt.executeQuery(query); // move to first row of result set rs.next(); // get the time value outTime[0] = rs.getTime(1); // clean up resources rs.close(); stmt.close(); // close our connection con.close(); } catch (SQLException sqle) { errorCode[0] = sqle.getErrorCode(); } } }