// Source File Name: Spserver.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 Spserver - Stored Procedure // Steps to run the sample: // (1) create and populate the SAMPLE database (db2sampl) // (2) compile Spserver (javac Spserver.java) // (3) copy Spserver.class to the sqllib/function directory // (4) register the stored procedures using the Spcreate.db2 CLP script: // (i) db2 connect to sample // (ii) db2 -td@ -vf Spcreate.db2 // (3) compile Spclient (javac Spclient.java) // (4) run Spclient (java Spclient) // 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 Spserver 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: manipulates an INOUT DECIMAL parameter // (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 // ///// // Java stored procedure is in this class // ///// public class Spserver { public static void outLanguage (String[] outLang) throws Exception { try { String procName; // Initialize variables procName = "OUT_LANGUAGE"; // Get caller's connection to the database Connection con = DriverManager.getConnection("jdbc:default:connection"); String query = "SELECT language FROM syscat.procedures " + "WHERE procname = ? "; PreparedStatement stmt = con.prepareStatement(query); stmt.setString(1, procName); ResultSet rs = stmt.executeQuery(); // move to first row of result set rs.next(); // set value for the output parameter outLang[0] = rs.getString(1); // clean up resources rs.close(); stmt.close(); con.close(); } catch (Exception e) { throw e; } } public static void outParameter (double[] medianSalary, int[] errorCode, String[] errorLabel) throws SQLException /* :rk.1:erk. */ { try { int counter, numRecords; // Initialize variables counter = 0; errorCode[0] = 0; // SQLCODE = 0 unless SQLException occurs // Get caller's connection to the database Connection con = DriverManager.getConnection("jdbc:default:connection"); errorLabel[0] = "GET CONNECTION"; String query = "SELECT COUNT(*) FROM staff"; errorLabel[0] = "PREPARE COUNT STATEMENT"; PreparedStatement stmt = con.prepareStatement(query); errorLabel[0] = "GET COUNT RESULT SET"; ResultSet rs = stmt.executeQuery(); // move to first row of result set rs.next(); // set value for the output parameter errorLabel[0] = "GET NUMBER OF RECORDS"; numRecords = rs.getInt(1); /* :rk.3:erk. */ // clean up first result set rs.close(); stmt.close(); // get salary result set query = "SELECT CAST(salary AS DOUBLE) FROM staff " + "ORDER BY salary"; errorLabel[0] = "PREPARE SALARY STATEMENT"; PreparedStatement stmt2 = con.prepareStatement(query); errorLabel[0] = "GET SALARY RESULT SET"; ResultSet rs2 = stmt2.executeQuery(); /* :rk.2:erk. */ while (counter < (numRecords / 2 + 1)) { errorLabel[0] = "MOVE TO NEXT ROW"; rs2.next(); /* :rk.4:erk. */ counter++; } errorLabel[0] = "GET MEDIAN SALARY"; medianSalary[0] = rs2.getDouble(1); /* :rk.5:erk. */ // clean up resources rs2.close(); stmt2.close(); con.close(); /* :rk.6:erk. */ } 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 { double salary; String cursorName; errorCode[0] = 0; // SQLCODE = 0 unless SQLException occurs // Initialize variables salary = 0; cursorName = ""; try { // Get caller's connection to the database Connection con = DriverManager.getConnection("jdbc:default:connection"); errorLabel[0] = "GET CONNECTION"; String query = "SELECT CAST(salary AS DOUBLE) " + "FROM employee " + "WHERE workdept = '" + inDepartment + "' " + "FOR UPDATE"; errorLabel[0] = "PREPARE STATEMENT 1"; PreparedStatement stmt = con.prepareStatement(query); errorLabel[0] = "GET RESULT SET"; ResultSet rs = stmt.executeQuery(); cursorName = rs.getCursorName(); errorLabel[0] = "GET FIRST ROW"; if (!rs.next()) { /* Cursor contains no data, so return SQLCODE 100 to client */ errorCode[0] = 100; } else { boolean foundData = true; String updateLow = "UPDATE employee SET salary = " + inLowSal + " WHERE CURRENT OF " + cursorName; String updateMed = "UPDATE employee SET salary = " + inMedSal + " WHERE CURRENT OF " + cursorName; String updateHigh = "UPDATE employee SET salary = " + inHighSal + " WHERE CURRENT OF " + cursorName; String updateFinal = "UPDATE employee SET salary = (salary * 1.10)" + " WHERE CURRENT OF " + cursorName; errorLabel[0] = "PREPARE STATEMENT 2"; PreparedStatement stmtLow = con.prepareStatement(updateLow); PreparedStatement stmtMed = con.prepareStatement(updateMed); PreparedStatement stmtHigh = con.prepareStatement(updateHigh); PreparedStatement stmtFinal = con.prepareStatement(updateFinal); while (foundData) { errorLabel[0] = "GET SALARY"; salary = rs.getDouble(1); if (inLowSal > salary) { errorLabel[0] = "UPDATE -- LOW CASE"; stmtLow.executeUpdate(); } else if (inMedSal > salary) { errorLabel[0] = "UPDATE -- MEDIUM CASE"; stmtMed.executeUpdate(); } else if (inHighSal > salary) { errorLabel[0] = "UPDATE -- HIGH CASE"; stmtHigh.executeUpdate(); } else { errorLabel[0] = "UPDATE -- FINAL CASE"; stmtFinal.executeUpdate(); } if (!rs.next()) // if next row is not found { foundData = false; } } stmtLow.close(); stmtMed.close(); stmtHigh.close(); stmtFinal.close(); } rs.close(); stmt.close(); con.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; String cursorName; // Initialize variables counter = 0; salary = 0; cursorName = ""; errorCode[0] = 0; // SQLCODE = 0 unless SQLException occurs try { // Get caller's connection to the database errorLabel[0] = "GET CONNECTION"; Connection con = DriverManager.getConnection("jdbc:default:connection"); String query = "SELECT COUNT(*) FROM staff " + "WHERE CAST(salary AS DOUBLE) > ? "; errorLabel[0] = "PREPARE COUNT STATEMENT"; PreparedStatement stmt = con.prepareStatement(query); stmt.setDouble(1, inoutMedianSalary[0]); errorLabel[0] = "GET COUNT RESULT SET"; ResultSet rs = stmt.executeQuery(); // move to first row of result set rs.next(); // set value for the output parameter errorLabel[0] = "GET NUMBER OF RECORDS"; numRecords = rs.getInt(1); // clean up first result set rs.close(); stmt.close(); if (numRecords == 0) { // Set errorCode to SQL0100 to indicate data not found errorCode[0] = 100; } else { // get salary result set query = "SELECT CAST(salary AS DOUBLE) FROM staff " + "WHERE CAST(salary AS DOUBLE) > ? " + " ORDER BY salary"; errorLabel[0] = "PREPARE SALARY STATEMENT"; PreparedStatement stmt2 = con.prepareStatement(query); stmt2.setDouble(1, inoutMedianSalary[0]); errorLabel[0] = "GET SALARY RESULT SET"; ResultSet rs2 = stmt2.executeQuery(); while (counter < (numRecords / 2 + 1)) { errorLabel[0] = "MOVE TO NEXT ROW"; rs2.next(); counter++; } errorLabel[0] = "GET MEDIAN SALARY"; inoutMedianSalary[0] = rs2.getDouble(1); // clean up resources rs2.close(); stmt2.close(); } // close connection con.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 { errorCode[0] = 0; // SQLCODE = 0 unless SQLException occurs try { // Get caller's connection to the database Connection con = DriverManager.getConnection("jdbc:default:connection"); // get salary result set using a parameter marker String query = "SELECT name, job, CAST(salary AS DOUBLE) FROM staff " + "WHERE salary > ? " + "ORDER BY salary"; // prepare the SQL statement PreparedStatement stmt = con.prepareStatement(query); // set the value of the parameter marker (?) stmt.setDouble(1, inSalaryThreshold); // get the result set that will be returned to the client rs[0] = stmt.executeQuery(); // to return a result set to the client, do not close ResultSet con.close(); } 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 { errorCode[0] = 0; // SQLCODE = 0 unless SQLException occurs try { // Get caller's connection to the database Connection con = DriverManager.getConnection("jdbc:default:connection"); // get salary result set using a parameter marker String query = "SELECT name, job, CAST(salary AS DOUBLE) FROM staff " + "WHERE salary > ? " + "ORDER BY salary"; // prepare the SQL statement PreparedStatement stmt = con.prepareStatement(query); // set the value of the parameter marker (?) stmt.setDouble(1, inSalaryThreshold); // get the result set that will be returned to the client rs1[0] = stmt.executeQuery(); // get salary result set using a parameter marker String query2 = "SELECT name, job, CAST(salary AS DOUBLE) FROM staff " + "WHERE salary < ? " + "ORDER BY salary DESC"; // prepare the SQL statement PreparedStatement stmt2 = con.prepareStatement(query2); // set the value of the parameter marker (?) stmt2.setDouble(1, inSalaryThreshold); // get the result set that will be returned to the client rs2[0] = stmt2.executeQuery(); // to return the result sets to the client, do not close the ResultSet con.close(); } 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 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 { errorCode[0] = 0; // SQLCODE = 0 unless SQLException occurs 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) String query = "SELECT midinit FROM employee " + "WHERE empno = '000180' "; errorLabel[0] = "create CHAR(1) select"; // create the SQL statement Statement stmt = con.createStatement(); errorLabel[0] = "get result set for CHAR(1) select"; // get the result set ResultSet rs = stmt.executeQuery(query); errorLabel[0] = "move to first row for CHAR(1) select"; // move to first row of result set rs.next(); errorLabel[0] = "get value for CHAR(1) select"; // get the value of the midinit column outChar[0] = rs.getString(1); // clean up resources rs.close(); stmt.close(); // get value of a CHAR(15) column (lastname) query = "SELECT lastname FROM employee " + "WHERE empno = '000180' "; errorLabel[0] = "create CHAR(15) select"; // 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 value of the lastname column outChars[0] = rs.getString(1); // clean up resources rs.close(); stmt.close(); // get value of a VARCHAR(12) column (firstnme) query = "SELECT firstnme FROM employee " + "WHERE empno = '000180' "; errorLabel[0] = "create VARCHAR(12) select"; // 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 value of the firstnme column outVarchar[0] = rs.getString(1); // clean up resources rs.close(); stmt.close(); // get current date from DB2 server 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 from DB2 server 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(); } } public static void decimalType (BigDecimal[] inoutDecimal, // DECIMAL(10,2) int[] errorCode, String[] errorLabel) throws SQLException { errorCode[0] = 0; // SQLCODE = 0 unless SQLException occurs try { // Get caller's connection to the database Connection con = DriverManager.getConnection("jdbc:default:connection"); 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); } // close our connection con.close(); } catch (SQLException sqle) { errorCode[0] = sqle.getErrorCode(); } } }