You are on page 1of 418

DB2 Java Stored Procedures

Learning by Example

Implementation guide for DB2 Java


stored procedures

DB2 Java stored procedures


across platforms

Reference guide for


network computing
enhancements in DB2 UDB
for OS/390 V6

Maria Sueli Almeida


Kirk Condon
Michael Fischer
Julian Stuhler

ibm.com/redbooks
SG24-5945-00

International Technical Support Organization

DB2 Java Stored Procedures


Learning by Example

September 2000
Take Note!
Before using this information and the product it supports, be sure to read the general information in
Appendix F, “Special notices” on page 355.

First Edition (September 2000)

This edition applies to Version 6 of IBM DATABASE 2 Universal Database Server for OS/390 (DB2 UDB
Server for OS/390 Version 6), Program Number 5645-DB2, Version 7 of DB2 UDB for UNIX, Windows,
OS/2, and other current versions and releases of IBM products. Make sure you are using the correct
edition for your level of product.

This document was created or updated on September 5, 2000.

Comments may be addressed to:


IBM Corporation, International Technical Support Organization
Dept. QXXE Building 80-E2
650 Harry Road
San Jose, California 95120-6099

When you send information to IBM, you grant IBM a non-exclusive right to use or distribute the
information in any way it believes appropriate without incurring any obligation to you.

© Copyright International Business Machines Corporation 2000. All rights reserved.


Note to U.S Government Users – Documentation related to restricted rights – Use, duplication or disclosure is
subject to restrictions set forth in GSA ADP Schedule Contract with IBM Corp.
Contents

Figures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .xi

Tables. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii

Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xv
How this book is structured . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xv
The team that wrote this redbook . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvi
Comments welcome . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xviii

Part 1. Background. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

Chapter 1. Java platform support . . . . . . .. . . . . .. . . . .. . . . . .. . . . . .3


1.1 Java overview . . . . . . . . . . . . . . . . . . . .. . . . . .. . . . .. . . . . .. . . . . .3
1.2 Java and the OS/390 Platform . . . . . . . .. . . . . .. . . . .. . . . . .. . . . . .4
1.2.1 OS/390 UNIX System Services. . . .. . . . . .. . . . .. . . . . .. . . . . .4
1.2.2 Enterprise Toolkit for OS/390 . . . . .. . . . . .. . . . .. . . . . .. . . . . .4
1.3 Java and the UNIX Platform . . . . . . . . . .. . . . . .. . . . .. . . . . .. . . . . .6
1.4 Java and the Windows NT Platform . . . .. . . . . .. . . . .. . . . . .. . . . . .6

Chapter 2. Java and DB2 . . . . . . . . . . . . . . . . . . . . ..... . . . . . . . . . . . .7


2.1 Java database connectivity . . . . . . . . . . . . . . . . ..... . . . . . . . . . . . .7
2.1.1 DB2 JDBC programs . . . . . . . . . . . . . . . . . ..... . . . . . . . . . . . .7
2.1.2 DB2 SQLJ programs. . . . . . . . . . . . . . . . . . ..... . . . . . . . . . . . .8
2.1.3 Choosing the access method: JDBC versus SQLJ . . . . . . . . . . . .9
2.1.4 JDBC driver types. . . . . . . . . . . . . . . . . . . . ..... . . . . . . . . . . . 11
2.2 Java and DB2 stored procedures . . . . . . . . . . . . ..... . . . . . . . . . . . 12
2.2.1 What is a stored procedure? . . . . . . . . . . . . ..... . . . . . . . . . . . 12
2.2.2 Supported stored procedure languages . . . ..... . . . . . . . . . . . 13
2.2.3 DB2 Java stored procedures . . . . . . . . . . . ..... . . . . . . . . . . . 14

Part 2. Developing Java stored procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

Chapter 3. Java sample application: the ACME software company . . 19


3.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.2 System design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.3 Sample application components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.3.1 DB2 naming conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.4 Portability issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
3.4.1 Java stored procedure portability . . . . . . . . . . . . . . . . . . . . . . . . 24
3.4.2 DB2 portability issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
3.5 Sample stored procedures — standard . . . . . . . . . . . . . . . . . . . . . . . 24

© Copyright IBM Corp. 2000 iii


3.5.1 JDBC stored procedure sample . . . . . . . . . . . . . .. . . . . .. . . . . 25
3.5.2 SQLJ stored procedure sample . . . . . . . . . . . . . .. . . . . .. . . . . 27
3.5.3 COBOL stored procedure sample . . . . . . . . . . . . .. . . . . .. . . . . 29
3.5.4 Combined SQLJ and JDBC example . . . . . . . . . .. . . . . .. . . . . 32
3.6 Sample stored procedures — enhanced . . . . . . . . . . . .. . . . . .. . . . . 34
3.6.1 JDBC enhanced stored procedure sample . . . . . .. . . . . .. . . . . 34
3.6.2 SQLJ enhanced sample . . . . . . . . . . . . . . . . . . . .. . . . . .. . . . . 39
3.7 Sample Client Code . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . .. . . . . 45
3.7.1 Calling the Java stored procedure from Java . . . .. . . . . .. . . . . 45
3.7.2 COBOL client application sample . . . . . . . . . . . . .. . . . . .. . . . . 48
3.7.3 SQLJ client application sample . . . . . . . . . . . . . . .. . . . . .. . . . . 50
3.7.4 JDBC client application sample . . . . . . . . . . . . . .. . . . . .. . . . . 52

Chapter 4. System setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . 57


4.1 OS/390 system setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . 57
4.1.1 Prerequisites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . 57
4.1.2 Installation tasks. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . 59
4.1.3 Step 1: Design library structure . . . . . . . . . . . . . . . . . . . .. . . . . 60
4.1.4 Step 2: Provide .profile for users . . . . . . . . . . . . . . . . . . .. . . . . 63
4.1.5 Step 3: Setting up RRS. . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . 66
4.1.6 Step 4: Define WLM stored procedure address space . . .. . . . . 66
4.1.7 Step 5: Install JDBC/SQLJ driver for OS/390 . . . . . . . . . .. . . . . 68
4.1.8 Step 6: Set up the JAVAENV data set . . . . . . . . . . . . . . .. . . . . 69
4.1.9 Step 7: Verify JDBC cursor and SQLJ properties files . . .. . . . . 71
4.1.10 Data sharing considerations . . . . . . . . . . . . . . . . . . . . . .. . . . . 73
4.1.11 Maintenance considerations . . . . . . . . . . . . . . . . . . . . . .. . . . . 75
4.1.12 Some common setup issues . . . . . . . . . . . . . . . . . . . . . .. . . . . 76
4.2 Windows NT system setup . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . 78
4.2.1 Prerequisites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . 78
4.2.2 Installation tasks. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . 79
4.2.3 Some common setup issues . . . . . . . . . . . . . . . . . . . . . . .. . . . . 79
4.3 UNIX system setup. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . 80
4.3.1 Prerequisites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . 80
4.3.2 Installation tasks. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . 80

Chapter 5. Designing Java stored procedures . . . . . . . . . . . . . .. . . . . 83


5.1 General design issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . 83
5.1.1 Naming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . 83
5.1.2 Parameter style: Java or DB2GENERAL . . . . . . . . . . . . .. . . . . 89
5.1.3 Public static method with void return type . . . . . . . . . . . . .. . . . . 90
5.1.4 Parameters must be mappable to base SQL data types . .. . . . . 90
5.1.5 LOBS not supported for Java stored procedures . . . . . . .. . . . . 90
5.1.6 Why do we use [ ] on the output parameters? . . . . . . . . . .. . . . . 90

iv DB2 Java Stored Procedures: Learning by Example


5.1.7 Using JDBC, SQLJ, or both . . . . . . . . . . . . . . . . . . . . . . .. . . . . 91
5.1.8 Java packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . 91
5.1.9 Case sensitivity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . 92
5.1.10 Nested Java stored procedures . . . . . . . . . . . . . . . . . . .. . . . . 92
5.2 Design issues for OS/390 Java stored procedures . . . . . . . . . .. . . . . 93
5.2.1 Must use HPJ compiler . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . 93
5.2.2 Must have Java Package as first statement . . . . . . . . . . .. . . . . 93
5.2.3 Packaging considerations . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . 93
5.2.4 Environmental considerations . . . . . . . . . . . . . . . . . . . . . .. . . . . 94
5.3 Design issues for the UNIX, Windows, OS/2 platforms . . . . . . .. . . . . 96

Chapter 6. Coding Java stored procedures . . . . . . . . . . . . . . . . . . . . . 97


6.1 Null handling with JDBC stored procedures . . . . . . . . . . . . . . . . . . . . 97
6.1.1 Calling a stored procedure with a null value . . . . . . . . . . . . . . . . 97
6.1.2 Using a Java base type as a parameter . . . . . . . . . . . . . . . . . . . 97
6.1.3 Determining if a selected item was an SQL null via wasNull() . . . 99
6.1.4 Inserting a NULL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
6.2 Null handling with SQLJ stored procedures . . . . . . . . . . . . . . . . . . . 100
6.3 SQLJ Iterators and ResultSets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
6.3.1 Return ResultSets from SQLJ stored procedures . . . . . . . . . . . 101
6.3.2 Avoid returning a used ResultSet . . . . . . . . . . . . . . . . . . . . . . . 101
6.3.3 Close interim ResultSets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
6.3.4 Returning Multiple ResultSets. . . . . . . . . . . . . . . . . . . . . . . . . . 102
6.4 Error Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
6.4.1 Getting the results of printStackTrace . . . . . . . . . . . . . . . . . . . . 102
6.5 Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
6.5.1 Initially writing as a standalone program . . . . . . . . . . . . . . . . . . 103
6.5.2 Writing debugging statements to a table . . . . . . . . . . . . . . . . . . 103
6.5.3 OS/390 debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
6.5.4 UNIX and Windows NT debugging . . . . . . . . . . . . . . . . . . . . . . 104
6.6 Using the DB2 Stored Procedure Builder . . . . . . . . . . . . . . . . . . . . . 105
6.6.1 Advantages of the SPB. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
6.7 Common errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
6.7.1 OS/390 errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
6.7.2 UNIX and Windows NT errors . . . . . . . . . . . . . . . . . . . . . . . . . . 112

Chapter 7. Preparing Java stored procedures . . . . . . . .. . . . . .. . . . 119


7.1 Program preparation concepts . . . . . . . . . . . . . . . . . . .. . . . . .. . . . 119
7.2 OS/390 Java stored procedure preparation . . . . . . . . .. . . . . .. . . . 119
7.2.1 Java stored procedure and DB2 package . . . . . . .. . . . . .. . . . 119
7.2.2 DB2 authorization issues . . . . . . . . . . . . . . . . . . .. . . . . .. . . . 120
7.2.3 OS/390 JDBC program preparation process . . . . .. . . . . .. . . . 122
7.2.4 OS/390 SQLJ program preparation process . . . . .. . . . . .. . . . 129

v
7.2.5 Using UNIX System Services (USS) . . . . . . . . . . .. . . . . .. . . . 143
7.3 NT / AIX Java stored procedure preparation . . . . . . . . .. . . . . .. . . . 144
7.3.1 NT / AIX JDBC program preparation process . . . .. . . . . .. . . . 144
7.3.2 NT / AIX SQLJ program preparation process . . . .. . . . . .. . . . 149
7.3.3 The sqlj.install_jar and sqlj.replace_jar routines . .. . . . . .. . . . 155

Chapter 8. Deployment and execution . . . . . . . . . . . . . . . . . . . . . . . . 157


8.1 Deployment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
8.1.1 Migrating between environments on S/390 . . . . . . . . . . . . . . . . 157
8.1.2 Migrating between environments on UNIX/NT . . . . . . . . . . . . . 160
8.1.3 Porting between UNIX/NT and S/390 . . . . . . . . . . . . . . . . . . . . 161
8.2 Execution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
8.2.1 OS/390 execution considerations . . . . . . . . . . . . . . . . . . . . . . . 163
8.2.2 UNIX and Windows NT execution considerations . . . . . . . . . . . 163
8.3 Stored procedure management and version control on OS/390 . . . . 164
8.3.1 Source code control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
8.3.2 Version control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
8.3.3 Sample of a test and production version . . . . . . . . . . . . . . . . . . 165
8.3.4 Running two versions in the same DB2 subsystem . . . . . . . . . . 165

Chapter 9. Client applications invoking Java stored procedures . . . 167


9.1 DB2 plans and packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
9.1.1 JDBC client requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
9.1.2 SQLJ client requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
9.1.3 Stored procedure requirements . . . . . . . . . . . . . . . . . . . . . . . . 168
9.1.4 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
9.1.5 Usage recommendations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
9.2 Client coding considerations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
9.2.1 General client coding considerations . . . . . . . . . . . . . . . . . . . . 170
9.2.2 JDBC client coding considerations . . . . . . . . . . . . . . . . . . . . . . 172
9.2.3 SQLJ client coding considerations . . . . . . . . . . . . . . . . . . . . . . 174
9.3 Client authorization issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
9.3.1 JDBC client authorization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
9.3.2 DB2 for OS/390 stored procedure execute authority . . . . . . . . . 174
9.4 Sample Java client preparation scripts . . . . . . . . . . . . . . . . . . . . . . . 175
9.4.1 Sample javacl script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
9.4.2 Sample bindcl.rexx script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176

Chapter 10. Migration of DB2 for OS/390 Version 5 to Version 6 . . . . 181


10.1 Stored procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
10.1.1 SYSIBM.SYSPROCEDURES no longer used . . . . . . . . . . . . . 182
10.1.2 Java stored procedures under Version 5. . . . . . . . . . . . . . . . . 182
10.1.3 DB2 catalog maintenance . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
10.1.4 Fallback considerations from Version 6 to Version 5 . . . . . . . . 184

vi DB2 Java Stored Procedures: Learning by Example


Part 3. DB2 UDB for OS/390 V6 — various enhancements . . . . . . . . . . . . . . . . . . . . . 185

Chapter 11. DB2 UDB for OS/390 network computing enhancements187


11.1 DRDA support for three-part names . . . . . . . . . . . . . . . . . . . . . . . . 187
11.1.1 Three-part names prior to Version 6 . . . . . . . . . . . . . . . . . . . . 187
11.1.2 Three-part names in Version 6 . . . . . . . . . . . . . . . . . . . . . . . . 189
11.1.3 Package requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
11.1.4 How it works . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
11.1.5 DBPROTOCOL bind option . . . . . . . . . . . . . . . . . . . . . . . . . . 193
11.1.6 Stored procedures — considerations . . . . . . . . . . . . . . . . . . . 193
11.1.7 Hopping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
11.1.8 Advantages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196
11.1.9 Impacts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
11.2 DRDA query block size. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
11.2.1 OPTIMIZE FOR n ROWS clause enhancements. . . . . . . . . . . 198
11.2.2 How it works . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
11.2.3 Usage recommendations . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
11.3 DDF connection pooling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
11.4 STOP DDF MODE(SUSPEND) command . . . . . . . . . . . . . . . . . . . 203
11.4.1 Command syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204
11.5 Declared Global Temporary Tables . . . . . . . . . . . . . . . . . . . . . . . . 205
11.5.1 Usability considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
11.6 Savepoints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
11.6.1 Connecting to other DB2 systems. . . . . . . . . . . . . . . . . . . . . . 209
11.6.2 Restrictions on using savepoints . . . . . . . . . . . . . . . . . . . . . . 210
11.6.3 Savepoint performance. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
11.7 Identity columns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
11.7.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
11.7.2 Data definition issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
11.7.3 Data manipulation issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
11.7.4 Utility issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
11.7.5 Other properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220
11.7.6 DB2 catalog table considerations . . . . . . . . . . . . . . . . . . . . . . 221
11.7.7 Usage recommendations . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
11.7.8 Use of identity columns versus ROWID columns . . . . . . . . . . 228
11.7.9 Data propagation considerations . . . . . . . . . . . . . . . . . . . . . . 229
11.7.10 Influencing insert order in a data sharing environment . . . . . 230
11.7.11 Differences in implementation across the DB2 Family. . . . . . 230

Chapter 12. DB2 UDB for OS/390 schema support . . . . .. . . . . .. . . . 233


12.1 Schema characteristics . . . . . . . . . . . . . . . . . . . . . . .. . . . . .. . . . 234
12.2 How schemas are used . . . . . . . . . . . . . . . . . . . . . . .. . . . . .. . . . 234
12.2.1 Explicit specification . . . . . . . . . . . . . . . . . . . . . .. . . . . .. . . . 234

vii
12.2.2 Implicit specification . . . . . . . . ...... ....... .. . . . . .. . . . 235
12.3 Schemas and the CURRENT PATH special register . .. . . . . .. . . . 236
12.3.1 SET CURRENT PATH . . . . . . ...... ....... .. . . . . .. . . . 237
12.3.2 PATH bind option . . . . . . . . . . ...... ....... .. . . . . .. . . . 240

Chapter 13. DB2 UDB for OS/390 stored procedures enhancements 243
13.1 Stored procedures: an overview . . . . . . . . . . . . . . . . . . . . . . . . . . . 243
13.1.1 Why use stored procedures? . . . . . . . . . . . . . . . . . . . . . . . . . 244
13.1.2 SQL CALL — processing flow. . . . . . . . . . . . . . . . . . . . . . . . . 246
13.1.3 Stored procedures — time line characteristics . . . . . . . . . . . . 247
13.2 The CREATE PROCEDURE DDL statement . . . . . . . . . . . . . . . . . 259
13.2.1 Parameter definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262
13.2.2 New options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263
13.2.3 Enhanced options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
13.2.4 Advantages of DDL. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
13.2.5 Schema name: CREATE PROCEDURE . . . . . . . . . . . . . . . . . 269
13.2.6 Schema name: CALL statement . . . . . . . . . . . . . . . . . . . . . . . 270
13.3 Lifted DML restrictions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272
13.4 Nested stored procedures: characteristics . . . . . . . . . . . . . . . . . . . 274
13.5 Authorization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275
13.5.1 Who has EXECUTE privilege on a stored procedure? . . . . . . 277
13.6 DISPLAY PROCEDURE command. . . . . . . . . . . . . . . . . . . . . . . . . 280
13.7 Migration considerations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281

Part 4. Appendices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283

Appendix A. New messages and error codes . . . . . . . . . . . . . . . . . . . . 285


A.1 STOP DDF MODE SUSPEND . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285

Appendix B. Sample code, DDL, and preparation scripts . . . . . . . . . . 287


B.1 Sample DDL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287
B.1.1 DB2 UDB for OS/390 DDL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287
B.1.2 DB2 UDB for AIX and Windows DDL . . . . . . . . . . . . . . . . . . . . . . . 297
B.2 Sample stored procedure definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . 307
B.2.1 DB2 UDB for OS/390 stored procedure definitions . . . . . . . . . . . . 307
B.2.2 DB2 UDB for AIX and Windows stored procedure definitions . . . . 317
B.3 Sample stored procedure code. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318
B.4 Sample client code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318
B.5 Sample program preparation scripts. . . . . . . . . . . . . . . . . . . . . . . . . . . . 318
B.5.1 OS/390 program preparation scripts. . . . . . . . . . . . . . . . . . . . . . . . 318
B.5.2 AIX program preparation scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . 318
B.5.3 NT program preparation scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . 321

viii DB2 Java Stored Procedures: Learning by Example


Appendix C. OS/390 Recoverable Resource Services (RRS) . . . . . . . 329
C.1 RRS attachment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329

Appendix D. Define WLM stored procedure address space . . . . . . . . 331


D.1 Enable stored procedure support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331
D.1.1 Step 1. Run the installation CLIST in INSTALL or MIGRATE mode.. .
331
D.1.2 Step 2. Edit DSNTIJUZ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332
D.2 How to use the WLM ISPF application . . . . . . . . . . . . . . . . . . . . . . . . . . 332
D.3 Starting the WLM application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333
D.4 Control of stored procedures in a WLM environment . . . . . . . . . . . . . . . 334
D.5 Defining the application environment . . . . . . . . . . . . . . . . . . . . . . . . . . . 335
D.6 Refreshing the environment for stored procedures . . . . . . . . . . . . . . . . 337
D.7 Using WLM application environments in compatibility mode . . . . . . . . . 338
D.8 Using WLM application environments in goal mode . . . . . . . . . . . . . . . . 339
D.9 Restricting access. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341
D.10 Summary of service definition / service policy concepts. . . . . . . . . . . . 342
D.11 Recommendations for full implementation of OS/390 WLM . . . . . . . . . 344
D.12 Considerations for compatibility mode . . . . . . . . . . . . . . . . . . . . . . . . . 345
D.13 Considerations for goal mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345

Appendix E. Using the additional material . . . . . . . . . . . . . . . . . . . . . . 347


E.1 Using the CD-ROM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
E.1.1 Sample client code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348
E.1.2 Sample stored procedure code. . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
E.1.3 Sample S390 utilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
E.1.4 Sample SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353
E.2 Locating the additional material on the Internet . . . . . . . . . . . . . . . . . . . 354
E.3 Using the Web material. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354
E.3.1 How to use the Web material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354

Appendix F. Special notices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355

Appendix G. Related publications. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359


G.1 IBM Redbooks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359
G.2 IBM Redbooks collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359
G.3 Other resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
G.4 Referenced Web sites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361

How to get IBM Redbooks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363


IBM Redbooks fax order form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364

ix
Glossary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365

Abbreviations and acronyms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383

Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387

IBM Redbooks review . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393

x DB2 Java Stored Procedures: Learning by Example


Figures

1. Java and DB2 for OS/390 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15


2. Java and DB2 for UWO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3. ACME Software Company System Design . . . . . . . . . . . . . . . . . . . . . . . . 20
4. SQLJ load library — data set definition . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
5. Application load library — data set definition . . . . . . . . . . . . . . . . . . . . . . . 63
6. JAVAENV file — data set definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
7. RACF command to assign home directory . . . . . . . . . . . . . . . . . . . . . . . . 66
8. JAVAENV data set — contents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
9. DB2SQLJDBC.PROPERTIES — contents . . . . . . . . . . . . . . . . . . . . . . . . 72
10. DB2 data sharing group with Java stored procedures . . . . . . . . . . . . . . . . 75
11. Java stored procedure object interrelationships . . . . . . . . . . . . . . . . . . . . 84
12. Our Java stored procedure object structure. . . . . . . . . . . . . . . . . . . . . . . . 85
13. Runtime environment overview — SQLJ stored procedure. . . . . . . . . . . . 95
14. OS/390 JDBC program preparation process . . . . . . . . . . . . . . . . . . . . . . 122
15. OS/390 SQLJ program preparation process . . . . . . . . . . . . . . . . . . . . . . 129
16. AIX and Windows NT JDBC program preparation process . . . . . . . . . . . 145
17. AIX and Windows NT SQLJ program preparation process . . . . . . . . . . . 149
18. Source-centric migration for a JDBC application . . . . . . . . . . . . . . . . . . . 158
19. Executable-centric migration for a JDBC application. . . . . . . . . . . . . . . . 160
20. Three-part names — prior to DB2 for OS/390 Version 6 . . . . . . . . . . . . . 187
21. Three-part name — Version 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
22. Package requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
23. How it works. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
24. Hopping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
25. Loop back . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196
26. OPTIMIZE FOR large number . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
27. OPTIMIZE FOR — how it works . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
28. Potential issue when using OPTIMIZE FOR n ROWS. . . . . . . . . . . . . . . 202
29. DDF connection pooling. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
30. Typical parent / dependent relationship . . . . . . . . . . . . . . . . . . . . . . . . . . 223
31. Example DDL for a global temporary table . . . . . . . . . . . . . . . . . . . . . . . 225
32. Example DDL for an after-insert trigger . . . . . . . . . . . . . . . . . . . . . . . . . . 225
33. After-insert trigger to retrieve the generated value of an id-column. . . . . 227
34. Identity column data propagation issues . . . . . . . . . . . . . . . . . . . . . . . . . 229
35. What is a schema? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233
36. How a schema is used — explicit specification . . . . . . . . . . . . . . . . . . . . 235
37. How a schema is used — implicit specification . . . . . . . . . . . . . . . . . . . . 236
38. CURRENT PATH special register . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
39. SET CURRENT PATH — syntax. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238
40. Stored procedures — overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245

© Copyright IBM Corp. 2000 xi


41. DB2 stored procedures access DL/I databases. . . . . . . . . . . . . . . . . . . . 256
42. Stored procedures: parameters definition . . . . . . . . . . . . . . . . . . . . . . . . 263
43. Schema name: CALL statement 1/2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271
44. Schema name: CALL statement 2/2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272
45. SQL CALL statement (nesting) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273
46. Authorization — CALL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276
47. Authorization — who is checked? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278
48. Authorization — example. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
49. DISPLAY PROCEDURE command . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280
50. Sample files — directory structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348

xii DB2 Java Stored Procedures: Learning by Example


Tables

1. JDBC driver types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12


2. Stored procedure languages supported by DB2 platform . . . . . . . . . . . . . 14
3. ACME sample application components . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
4. Sample Code — Java package names . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
5. DB2 for OS/390 Java APAR enhancements . . . . . . . . . . . . . . . . . . . . . . . 58
6. VisualAge for Java Enterprise Edition for OS/390 . . . . . . . . . . . . . . . . . . 58
7. Sample USS library structure. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
8. Sample OS/390 library structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
9. Null handling within SQL stored procedures . . . . . . . . . . . . . . . . . . . . . . 100
10. Contents of SQLJPLAN by client and SP type using COLLID. . . . . . . . . 168
11. Contents of SQLJPLAN by client and SP type not using COLLID. . . . . . 169
12. Private protocol v DRDA access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
13. START / STOP command versus DDF status . . . . . . . . . . . . . . . . . . . . . 204
14. Comparison of Identity and ROWID columns . . . . . . . . . . . . . . . . . . . . . 228

© Copyright IBM Corp. 2000 xiii


xiv DB2 Java Stored Procedures: Learning by Example
Preface

Stored procedures can provide major benefits in the areas of application


performance, code re-use, security, and integrity. The DB2 Family of products
has offered support for stored procedures for some time, with each release
offering significant enhancements over the last.

In the meantime, Java has been making steady inroads as the standard
application development language for many companies large and small. Its
inherent portability and openness, combined with the good availability of
skilled programming resource, has made it an increasingly attractive choice,
and the central plank in many organization’s e-business strategy.

Until recently, DB2 did not support stored procedures written in Java, so the
advantages of the two technologies could not be combined. The latest
releases of DB2 have changed all that, opening up new possibilities for
efficient, secure, highly portable application development.

This IBM Redbook aims to give the reader an in-depth understanding of the
techniques and issues associated with the development of DB2 stored
procedures written in Java and using SQLJ and/or JDBC for their SQL
operations. The extensive collection of sample code presented in this book
and included on the accompanying CD-ROM was designed to run against
DB2 UDB Server across the OS/390, Windows, and UNIX platforms.

We have assumed that the reader has at least a basic understanding of Java
terminology (such as classes, methods and packages) in addition to exposure
to general DB2 application development concepts.

How this book is structured


This book is organized in four major sections:
• Part 1, “Background” provides background information on Java support
on the various platforms covered in this book, together with an overview of
the ways in which DB2 can be accessed from within Java programs.
• Part 2, “Developing Java stored procedures” forms the main body of
the book. In it, we provide detailed guidance on how to configure your
environment to use Java stored procedures, and how to design, code,
prepare, and test them.
• Part 3, “DB2 UDB for OS/390 V6 — various enhancements” covers
some of the various network computing enhancements delivered in DB2
UDB for OS/390 Version 6.

© Copyright IBM Corp. 2000 xv


• Part 4, “Appendices” contains complete listings of all of the sample code
referred to throughout the book, together with additional reference
material.

The team that wrote this redbook


This redbook was produced by a team of specialists from around the world
working at the International Technical Support Organization San Jose Center.

Maria Sueli Almeida is a Certified I/T Specialist - Systems Enterprise Data,


and is currently a DB2 for OS/390 and Distributed Relational Database
System (DRDS) specialist at the International Technical Support
Organization, San Jose Center. Before joining the ITSO in 1998, Maria Sueli
worked at IBM Brazil assisting customers and IBM technical professionals on
DB2, data sharing, database design, performance, and DRDA connectivity.

Kirk Condon is a Senior Systems Manager for SBC Communications,


working in St. Louis, Missouri. He has 17 years of experience in the software
field. He holds two degrees from the University of Kansas: one in Computer
Science, the other in English. He currently specializes in DBMS issues,
helping to guide internal projects to the DBMS technologies that will meet the
scaling, performance, and reliability objectives of the project. He currently
specializes in Java issues that impact DBMS technologies, such as JDBC
and SQLJ. He also reviews emerging technologies to assess their impact to
the technologies supported by the SBC DBMS Organization.

He has worked extensively with TUXEDO, ORACLE, C, and UNIX. He has


developed programs for MVS and WINDOWS in disparate languages such as
COBOL, PL/1, and PowerBuilder, using database technologies such as DB2,
IMS, and SYBASE. He also has supported the ORACLE Transparent
Gateway and the ORACLE Application Server.

Michael Fischer is a DB2 Technical Specialist at the Santa Theresa


Laboratory in San Jose, CA, working out of Minneapolis, MN. He has 29
years of experience in information services and 8 years experience working
with DB2 OS/390. He has a degree in Business from the Metropolitan State
University of Minnesota. In this time he has gained a significant amount of
practical experience in application programming, database administration,
technical architecture, performance tuning, and systems programming. He
has worked at IBM for the 3 last years. His areas of expertise at IBM include
DB2 OS/390, data sharing, SAP DB2 data sharing, and performance and
tuning.

xvi DB2 Java Stored Procedures: Learning by Example


Michael is the co-author of the IBM Redbook, Getting Started with DB2
Stored Procedures: Give Them a Call through the Network. He has also given
presentations for the local DB2 User Groups of the Midwest, in the area of
DB2 OS/390.

Julian Stuhler is a Principal Consultant with Triton Consulting in the


United Kingdom. He has over 14 years experience working with the DB2
Family of products for a number of large UK customers, including insurance,
telecommunications, banking, financial services and manufacturing
companies. In that time he has obtained a large amount of practical
experience in areas as diverse as systems programming, application
programming, database administration, technical architecture and
performance tuning. More recently, Julian has specialized in distributed
database performance and the relational database connectivity issues
surrounding Internet and intranet applications.

Julian has lectured widely on DB2 subjects, both in the UK and Europe. This
includes presentations for the International DB2 Users Group (IDUG), Candle
Performance Seminars, the UK GUIDE DB2 Working Group, and European
GUIDE meetings. Julian is an IBM DB2 Gold Consultant, a regular teacher for
IBM's European Education Centre in Belgium, and is currently a member of
both the IDUG European Conference Planning Committee and the UK DB2
Guide Committee.

Thanks to the following people for their invaluable contributions to this


project:

Peggy Abelite
John Campbell
Curt Cotner
Ramani Croisettier
Thomas Eng
Christopher Farrar
Claire McFeely
Todd Munk
Judy Tobias
Tom Toomire
IBM Silicon Valley Laboratory

Brent Gross
Robert Indrigo

xvii
Mike Winer
IBM Toronto Laboratory

Paolo Bruni
Yvonne Lyon
IBM International Technical Support Organization, San Jose Center

Vasilis Karras
Rich Conway
Bob Haimowitz
IBM International Technical Support Organization, Poughkeepsie Center

Comments welcome
Your comments are important to us!

We want our Redbooks to be as helpful as possible. Please send us your


comments about this or other Redbooks in one of the following ways:
• Fax the evaluation form found in “IBM Redbooks review” on page 393 to
the fax number shown on the form.
• Use the online evaluation form found at ibm.com/redbooks
• Send your comments in an Internet note to redbook@us.ibm.com

xviii DB2 Java Stored Procedures: Learning by Example


Part 1. Background

© Copyright IBM Corp. 2000 1


2 DB2 Java Stored Procedures: Learning by Example
Chapter 1. Java platform support

This chapter presents an overview of Java and how it is supported by the


various platforms covered within this book.

1.1 Java overview


Java is a cross-platform language developed by Sun. Most companies have
embraced Java, and are well on their way towards integrating Java with their
existing technology. IBM is no exception, having become a leader in the use
of Java technology.

Java is designed to be portable, and Java programs developed on one


platform can often run unchanged on many computer systems. The most
important characteristics that make Java portable are:
• Java compiles to machine-independent bytecode.
Java is typically compiled and executed in a two-step process. First, the
Java code is compiled to bytecode, which means an assembly language
for an idealized Java virtual machine (JVM). Second, this bytecode is
executed by a run-time system, which can be either an interpreter, that is,
an emulator for the JVM, or a “Just-In-Time” (JIT) compiler that first
compiles the bytecode to native code, then executes the result.
Summarizing, the two steps of this process can be done on totally
separate platforms.
• Java has a portable graphic library.
In many software systems, the biggest hindrance to portability is the user
interface. Interfaces have typically been developed using a native
windowing system rather than a cross platform graphics toolkit, because
until now, this was the most convenient and widely available option.
However, this often meant that distribution on a different operating system
required a complete rewrite of the GUI. The Java developers realized that
a truly portable language would need a standard graphics library, and
included one from the beginning of the language’s development.
• Java avoids hard-to-port constructs.
The Java specification defines the size of primitive data structures such as
booleans, doubles, unlike some languages that allow this to vary among
implementations. For objects, Java programs cannot inadvertently depend
on implementation-specific details such as the amount of memory an
object consumes, or the internals of how fields or functions are laid out
within an object. Java even avoids reference to the local file system when

© Copyright IBM Corp. 2000 3


specifying which classes your program needs, using operating system
neutral class and package name instead.

Objects are central to Java. Understanding how they are created and used is
the first task for a Java programmer. Therefore, if you are not familiar with
object-oriented programming, you will need to spend some time to acquire an
understanding of this concept.

This book covers the use of the Java programming language for coding stored
procedures within DB2 UDB. We make the assumption that the reader
understands basic concepts of Java, such as:
• Classes
• Methods
• Packages
• JAR files
• Java Development Kit (JDK)
• Java environment variables, such as CLASSPATH

A number of excellent publications exist that can assist you in understanding


these concepts (see Appendix G, “Related publications” on page 359).

1.2 Java and the OS/390 Platform


In this section, we describe the Java support available on the OS/390
platform, together with some of the additional utilities required to implement
Java stored procedures.

1.2.1 OS/390 UNIX System Services


OS/390 UNIX System Services is an optional, no-charge feature of OS/390
that supplies UNIX functionality on the OS/390 platform. It runs concurrently
with the MVS system as a separate task. Applications can run under USS; in
fact, some products require USS (and Java is one of these).

1.2.2 Enterprise Toolkit for OS/390


The Enterprise Toolkit for OS/390 (ET/390) is part of VisualAge for Java
Enterprise Edition for OS/390. ET/390 provides a number of facilities to allow
you to code and test enterprise Java applications on the S/390 platform.

4 DB2 Java Stored Procedures: Learning by Example


1.2.2.1 The OS/390 High Performance Java Compiler
The OS/390 High Performance Java Compiler is part of ET/390. Its purpose
is to bind standard Java bytecode into native S/390 object code, which can
then run as an executable.

Note
The high performance Java compiler is also known by several other names,
including;
• VisualAge for Java Enterprise Toolkit for OS/390 Byte Code Binder
• ET/390 Byte Code Binder
• OS/390 Byte Code Binder

For convenience, we will simply refer to the compiler as the “HPJ” within
this book.

The HPJ was created for two major reasons:


• To allow performance-critical Java code to execute more quickly than it
would in the interpretive OS/390 Java Virtual Machine (JVM) environment.
• To allow Java code to be executed in environments that do not have their
own JVM (such as DB2 stored procedure address spaces).

The HPJ is therefore necessary if you wish to implement Java stored


procedures on DB2 for OS/390.

Although use of the HPJ creates an OS/390 specific module that will not
execute in other environments, code portability is retained, as the Java
source and bytecode files are still completely standard.

In the future, DB2 stored procedure address spaces will support a JVM
environment, allowing the use of stored procedures executing as native Java
bytecode, and the HPJ will not be necessary. However, depending upon the
level of performance achieved with the JVM implementation, it is possible that
you will still want to use the HPJ for performance-critical stored procedures.

1.2.2.2 Other ET/390 tools


ET/390 provides a number of additional tools to assist with S/390 Java
development and testing. These include:
• A workstation-based interactive debugger, to allow you to debug your code
as it runs.

Chapter 1. Java platform support 5


• A workstation-based performance analyzer, to allow you to graphically
identify parts of your programs that may be worth tuning.

These and other facilities are described in the Java Programming Guide for
OS/390, SG24-5619.

1.3 Java and the UNIX Platform


Thousands of Java programs run on the UNIX platform. Many developers
work directly with the Java Standard Development kits available from Sun and
IBM to compile and test their Java programs. There are a number of add-on
utilities, such as native-code compilers, debuggers, visual builders,
performance analyzers, and other tools commonly found for programming
languages.

DB2 UDB for UNIX, Windows, OS/2 ships with a JDK. If another version is
desired, the database can be configured to use a JDK installed anywhere on
the system.

It is not necessary to use a native-code compiler to transform Java to


something that can be used by the database.

1.4 Java and the Windows NT Platform


Like the UNIX platform, many Java programs run on the UNIX platform. Many
developers work directly with the Java Standard Development kits available
from Sun and IBM to compile and test their Java programs. There are a
number of add-on utilities, such as native-code compilers, debuggers, visual
builders, performance analyzers, and other tools commonly found for
programming languages. VisualAge for Java is a widely popular GUI builder
that many developers run on Windows NT.

DB2 UDB for UNIX, Windows NT, and OS/2 all ship with a JDK. If another
version is desired, the database can be configured to use a JDK installed
anywhere on the system.

It is not necessary to use a native-code compiler to transform Java to


something that can be used by the database.

6 DB2 Java Stored Procedures: Learning by Example


Chapter 2. Java and DB2

This chapter provides some background information on Java database


connectivity and DB2 stored procedures, and introduces many of the
concepts used throughout the rest of the book.

2.1 Java database connectivity


Java database connectivity has matured to the extent that the developer now
has two alternative APIs for accessing a database from within a Java
application: SQLJ and JDBC.

JDBC is a component of the core Java API standard as defined by Sun, as it


is an integral part of the Java JDK. JDBC does not directly embed SQL in the
Java code, but implements a set of methods (much like ODBC) that allow
SQL statements to be passed to the database, and results to be accessed
and manipulated.

SQLJ is an ANSI (and soon to be ISO) standard set of extensions to the core
Java classes that allow SQL to be directly embedded within Java applications,
in much the same way as it can be embedded in other languages such as
COBOL and PL/1.

This book will cover Java stored procedure support within DB2, but it is
important to know that you can also make extensive use of JDBC and SQLJ
from stand-alone Java programs.

2.1.1 DB2 JDBC programs


The JDBC API is a standard Java interface for connecting to relational
databases from Java. JDBC consists of two parts: the high level API and
multiple low-level drivers for connecting to different databases. It specifies
Java interface, classes, and exceptions to support connections, SQL data
manipulation language (DML), SQL data definition language (DDL),
processing of data result sets, and so on.

JDBC supports use of dynamic SQL so it can deal with situations where you
do not know the table and column names at the time the application is written.
Unlike static embedded SQL programs, dynamic SQL programs involve the
execution of at least some SQL statements that are not completely known
until runtime. Dynamic SQL allows you to create general and flexible
applications, because the full text of the SQL statement does not have to be
known at compilation time.

© Copyright IBM Corp. 2000 7


2.1.1.1 JDBC and DB2 UDB for OS/390
JDBC is supported by VisualAge for Java based tools. It requires DB2 Version
5 or higher and OS/390 Version 2 release 5 or higher.

As shown in Figure 1, JDBC-based Java programs are compiled into Java


bytecode using the javac compiler, which is part of the Java Development
Toolkit (JDK). Once compiled, they can be executed in the OS/390 JVM.

To use JDBC, your program needs to include the java.sql package and to
invoke methods according to the JDBC specification. The JDBC driver for
DB2 UDB for OS/390 is a Type-2 driver, which gives substantial performance
improvements to JDBC applications.

2.1.2 DB2 SQLJ programs


IBM's DB2 SQLJ driver complies with the ANSI X.3.135 standard, and allows
you to create, build, and run Java applications containing embedded static
SQL statements that are bound to a DB2 database.

SQLJ can provide better performance and security than JDBC, based on the
program author’s SQL privileges. SQLJ is pre-processed by the DB2 SQLJ
Translator. Coding SQLJ is much simpler, is more efficient, and performs
better at runtime. This means more programmer productivity and better
system utilization.

SQLJ consists of a set of clauses that extend Java programs. The language
specification is a joint one, supported by leading database vendors such as
IBM, Oracle and Tandem. It is supported by IBM’s VisualAge for Java tools,
and requires DB2 Version 5 or higher and OS/390 Version 2 release 5 or
higher.

When using SQLJ, you directly embed SQL statements within your Java
program following certain standard syntax rules.

The DB2 SQLJ program preparation requires three steps:


1. Run the SQLJ translator, which is done using the SQLJ command against
the source code.
The SQLJ translator is comparable to the preprocessors used to support
embedded static SQL in other languages, such as COBOL, and is
responsible for extracting the embedded SQL commands from the source
file and replacing them with calls to the SQLJ runtime library.
The result is a Java source code program (.java file) that can be compiled
using a Java compiler, and zero or more SQL profiles that contain

8 DB2 Java Stored Procedures: Learning by Example


information about the SQL operations in the program. SQLJ profiles are
vendor-independent, and need to be customized for the target database in
a later step. By default, SQLJ profile filenames have .ser as extension.
The SQLJ translator generates a profile for each connection context class
in the application (a connection context class corresponds to a particular
type of database schema to which your program connects). SQLJ profiles
are not produced if there are no SQLJ executable statements in the SQLJ
source code.
2. Compile the Java source code output by the translator, using the javac
command. This results in one or more .class files containing Java
bytecode. By default, the SQLJ command invokes the Java compiler
automatically.
3. Customize the SQLJ profiles for DB2, which is done using the db2profc
command.
Profiles are vendor-independent; therefore, they must be customized. The
customization process essentially transforms the generic SQLJ profiles
into DB2-specific DBRMs, which can then be bound to DB2 in the normal
way.

See Part 2, “Developing Java stored procedures” on page 17 for detailed


information.

2.1.3 Choosing the access method: JDBC versus SQLJ


The JDBC and SQLJ APIs are both widely accepted open industry standards.
However, each has its own set of advantages and disadvantages, which are
covered below.

2.1.3.1 Application coding considerations


If you come from a database background and have SQL skills, SQLJ is
usually quicker and more intuitive than JDBC, as it allows you to directly
embed SQL within your application code, as shown in the code fragment
below:
...
System.out.println("Add_customer: about to get hi cust no");

#sql
{
SELECT HI_CUST_NO+1
INTO :new_cust_no
FROM HI_CUST_NO
}; // #sql

Chapter 2. Java and DB2 9


...

In contrast, JDBC uses a series of generic methods to perform the data


access, which is almost always more verbose than the SQLJ equivalent. For
example, the JDBC equivalent of the SQLJ code above would look like this:

...
System.out.println("Add_customer: about to get hi cust no");

sql = "SELECT HI_CUST_NO+1 "


+ "FROM HI_CUST_NO";
res = stmt.executeQuery(sql);
res.next();
new_cust_no = res.getInt(1);
...

You can see that the JDBC version requires more code, and a knowledge of
JDBC methods such as executeQuery, next and getInt. Note also that JDBC
does not support the SELECT ... INTO statement.

2.1.3.2 Performance: static versus dynamic SQL


Another major differentiator between JDBC and SQLJ can be the way in
which your programs perform.

JDBC presents a string containing an SQL statement to the database at


runtime (which may have just been constructed within the Java application).
The first time DB2 gets to see the SQL is when it is actually executed, so all
JDBC calls, by their very nature, consist of dynamic SQL . When DB2 is
passed the SQL statement, it must perform a number of steps to prepare the
statement before it is able to execute it (including syntax checking,
authorization checking, and access path selection), and this can often require
longer to perform than the actual SQL itself.

SQLJ is able to use static SQL by actually embedding the SQL statements
within the application code. The SQLJ program preparation process extracts
this SQL and binds it against the database, allowing DB2 to perform all of the
checks and access path selection as a one-off process. At run time, DB2
uses the pre-prepared access plan and is able to immediately execute the
SQL.

In general, an SQLJ statement should therefore run more quickly than an


equivalent JDBC statement1 .

10 DB2 Java Stored Procedures: Learning by Example


2.1.3.3 Authorization
The way in which authorization is handled can also differ, due to the way in
which dynamic and static SQL authority checking is managed by DB2.

As JDBC uses dynamic SQL, all authorization checking is performed at


execution time. By default, DB2 will use the authorization ID of the application
process for authorization of dynamic SQL statements. This requires granting
sufficient authority directly to that authorization ID to be able to execute any
of the SQL statements the JDBC program is likely to submit.

SQLJ uses static SQL, so all authority checking is performed at BIND time.
The BIND authorization ID is used in the authorization checks, and all that is
required at run time is authority to execute the DB2 package associated with
the stored procedure (and, for DB2 for OS/390 V6, the authority to run the
stored procedure itself).

This is a complex area that is covered in more detail in 9.3, “Client


authorization issues” on page 174.

2.1.3.4 So which access method should I use?


As usual, the answer to this question is “It depends!”

As a general rule, we recommend that you use SQLJ wherever possible, as it


offers significant benefits in developer productivity, performance, and security
when compared to JDBC.

However, you may encounter situations that require the ability to build the
SQL statement within your Java application at run time, and only JDBC’s
dynamic SQL support can offer this sort of additional flexibility. In these
cases, you may be able to benefit from the fortunate situation that both SQLJ
and JDBC can be mixed in the same source logic.

The majority of the sample code included in this book and the accompanying
CD-ROM is provided in both SQLJ and JDBC versions.

2.1.4 JDBC driver types


To allow the generic functions and methods implemented by JDBC to be
translated into database-specific calls, each database vendor must deliver a
JDBC driver to act as an interface.

1
Note that DB2 for OS/390 has introduced several features (such as the dynamic statement cache) that help to reduce
the overheads associated with dynamic SQL and bring JDBC and SQLJ performance closer together. The degree to
which these features will assist the performance of your JDBC calls will depend on a large number of factors - “your
mileage may vary”.

Chapter 2. Java and DB2 11


The JDBC standard defines four different types of driver, as defined in Table 1
below.
Table 1. JDBC driver types

Type Description Contains Portable? a Uses


native ODBC?
methods?

1 JDBC/ODBC Bridge Yes No Yes

2 Native - API part Java Yes No No

3 Net - protocol all Java No Yes No

4 Native - protocol all Java No Yes No


a. Note that this column refers to the portability of the driver itself across various
platforms and operating systems, and not the portability of the application using it.

IBM currently supplies Type 2 and some Type 3 drivers for the various
members of the DB2 family, as detailed in the following sections.

2.1.4.1 DB2 UDB for OS/390


DB2 UDB for OS/390 Version 5 and Version 6 have Type 2 drivers available
as part of the SQLJ support APAR (this SQL service APAR is a prerequisite
for Java stored procedures - see 4.1.1, “Prerequisites” on page 57 for further
information).

2.1.4.2 DB2 UDB for UNIX, NT and OS/2


Both Version 6 and Version 7 of DB2 UDB for UNIX, Windows, and OS/2
provide Type 2 and Type 3 drivers. These are installed along with the rest of
the Java support components if so requested during the DB2 UDB install
process.

2.2 Java and DB2 stored procedures


In this section, we provide a general description of DB2 stored procedures,
together with an overview of the prerequisites necessary if you are to write
them in the Java language.

2.2.1 What is a stored procedure?


Simply put, a stored procedure is a program or routine that is invoked via an
SQL CALL statement issued from a client program, and executes under the
control of the database manager. Parameters can be passed to, and received
from, the stored procedure.

12 DB2 Java Stored Procedures: Learning by Example


Stored procedures offer a number of powerful advantages for distributed
application development. These include the following;
• Common business functions can be encapsulated in stored procedures
and made universally accessible, promoting code re-use and consistency,
and providing support for object-oriented application design.
• Performance can be significantly improved for distributed applications that
require several SQL calls to be made by the client against a remote
database. Instead of one trip across the network for each of these calls,
they can be combined and executed locally within a stored procedure so
only a single trip across the network is needed. This performance
improvement can also create subsequent benefits in reducing lock
contention.
• Security can be enhanced, as developers are only able to work with the
stored procedure input and output parameters, and are prevented from
viewing or altering the underlying code that implements the business
function.

DB2 stored procedures are integrated with and exploit some of the key
OS/390 scalability and availability features. Stored procedures benefit from
OS/390 Workload Manager (WLM) address spaces, allowing individual stored
procedures to be scheduled according to their business priority and optimized
for the system workload. In addition, multiple WLM-controlled address spaces
for DB2 stored procedures provide improved program isolation.

2.2.2 Supported stored procedure languages


DB2 stored procedures can be written in a number of languages, with the
intention of supporting a common set of languages across the entire DB2
Family in the future. Table 2 summarizes the language support at the time this
book was written.

Chapter 2. Java and DB2 13


Table 2. Stored procedure languages supported by DB2 platform

DB2 Version

DB2 for OS/390 DB2 for UNIX, Windows NT,


and OS/2

Java Version 5 with APAR PQ31845 Version 5


Version 6 with APAR PQ31846

SQL Version 6 with APARS PQ29782, Version 7


Procedures PQ30467 & PQ433026
Languagea

COBOL Version 4 Version 2

C/C++ Version 4 Version 2

PL/1 Version 4 N/A

REXX Version 5 with APAR PQ29706 Version 2b


Version 6 with APAR PQ30219
a. SQL Procedures Language is based on PSM, or Persistent Stored Modules,
which is an ISO standard procedural SQL language.
b. Use of REXX for stored procedures on the UNIX, Windows and OS/2 platforms
is not encouraged for security reasons.

This book concentrates on the development of stored procedures written in


the Java language.

2.2.3 DB2 Java stored procedures


DB2 for OS/390 Version 5 and Version 6 provide support for compiled Java
stored procedures only. This means that you have to compile them into native
OS/390 executable modules before execution, using the OS/390 High
Performance Java Compiler described in 1.2.2.1, “The OS/390 High
Performance Java Compiler” on page 5. An additional consideration is that,
unlike stored procedures written in other languages, Java stored procedures
have to run in a WLM address space.

Figure 1 shows how DB2 provides Java support on the OS/390 platform
through JDBC programs, SQLJ programs, and compiled stored procedures
written in Java

14 DB2 Java Stored Procedures: Learning by Example


Java and DB2 UDB for OS/390

ET/390 hpj Compiler


Java Source Code SQLJ Translator OS/390
Java Byte

Java Compiler
Native
Code
Instructions
DB2 Bind

SQLJ

JDBC

DB2 Stored
Java Virtual Machine
Procedure
UNIX System Services DB2 UDB for OS/390

OS/390

Figure 1. Java and DB2 for OS/390

Figure 2 shows a similar diagram for DB2 on the UNIX, OS/2, and Windows
platforms. You can see that the picture here is somewhat simpler, because
there is no requirement to compile Java stored procedures into native
operating system instructions before execution (as there is on the OS/390
platform).

Java and DB2 UDB for Unix, Windows, OS/2

Java Source Code SQLJ Translator


Java Byte
Java Compiler

Code
DB2 Bind

SQLJ

JDBC
DB2 Stored
Procedure
Java Virtual Machine
DB2 UDB for Unix, Windows, OS/2

Unix, Windows, OS/2

Figure 2. Java and DB2 for UWO

Chapter 2. Java and DB2 15


16 DB2 Java Stored Procedures: Learning by Example
Part 2. Developing Java stored procedures

© Copyright IBM Corp. 2000 17


18 DB2 Java Stored Procedures: Learning by Example
Chapter 3. Java sample application: the ACME software company

This chapter describes the sample application that we created to demonstrate


the implementation of Java stored procedures in DB2 UDB on the OS/390,
NT, and UNIX platforms.

All of the files necessary to reconstruct the sample application can be found
on the CD-ROM. Alternatively, you can download them directly from the IBM
Redbooks Web site: ibm.com/redbooks. Refer to Appendix E, “Using the
additional material” on page 347 for more details.

3.1 Overview
The Java examples in this book explore the initial programs of a mythical
start-up software company named ACME. This company chose to develop
their customer management systems using DB2 UDB.

3.2 System design


The ACME system design, shown in Figure 3 on page 20, wraps the business
logic and database access within DB2 using stored procedures written in
Java. This allows the company’s software ordering system to be accessed
worldwide via a simple HTML browser as well as by batch programs.

If the application architecture changes over time, these same stored


procedures could also be called in a large number of alternative ways (such
as from within Java applets, Enterprise Java beans, ODBC applications, and
many more). Similarly, if ACME’s hardware platform changes in the future, the
Java stored procedures can be easily ported to the new environment with
very few changes being required.

Our sample application consists of only those components necessary to


implement a single business function (to add a software order for a new
customer). Of course, in a real situation, many additional business functions
would need to be handled, but these could all use the same basic approach
as shown in our examples.

© Copyright IBM Corp. 2000 19


S/390
Websphere

HTTP Server
Java Servlet
...
Internet Call...
...

DB2 UDB For OS/390 V6

DB2 DB2
Data

Browser
Batch COBOL Program
...
Call...
...

Figure 3. ACME Software Company System Design

20 DB2 Java Stored Procedures: Learning by Example


3.3 Sample application components
Table 3 lists the individual components of the sample application.
Table 3. ACME sample application components

Type Name Description

Table CUSTOMER Stores customer details

PRODUCT Stores product details

ORDER Stores order details

ORDER_ITEM Stores order item details

Stored Procedure Add_customer Adds new customer details into ACME’s system.

Query_oi_summ Summarizes order information by order number or


customer number in groups of 5 items

COBOL Program ADDCUST Reads new customer / order information from a batch
file and invokes the Add_cust_order stored procedure.

To provide practical examples that covered as many different situations as


possible, we produced versions of the stored procedures and clients that ran
on different platforms — OS/390, AIX and Windows NT — and used different
APIs to access DB2 data such as JDBC only, SQLJ only, and a combination
of both JDBC and SQLJ. We also produced a COBOL version of the OS/390
programs, to allow those readers familiar with that language to more easily
interpret what the Java programs are doing.

Finally, to allow us to make use of some of the new network computing


features being introduced to DB2 while retaining compatibility with older
releases, we produced two versions of the code. The standard version uses
features available today across the entire DB2 family. The enhanced version
uses some of the new features available in the DB2 family. The enhanced
version also includes the Query_oi_summ stored procedure, which explores
advanced topics in Java stored procedures.

Chapter 3. Java sample application: the ACME software company 21


The stored procedures were packaged according to the following naming
conventions:

ACMEapf where a refers to the API J for JDBC


S for SQLJ
B for Both JDBC and SQLJ
C for COBOL

p refers to the platform O for OS/390


U for UNIX (AIX)
N for Windows NT

f refers to the features S for standard


E for enhanced

These Java package names are shown in full in Table 4 below. The Java
package names in bold italics are included in the sample code that
accompanies this book (see Appendix B, “Sample code, DDL, and
preparation scripts” on page 287).
Table 4. Sample Code — Java package names

API Platform Features

Standard Enhanced

JDBC OS/390 ACMEJOS ACMEJOE

AIX ACMEJUS ACMEJUE

Windows NT ACMEJNS ACMEJNE

SQLJ OS/390 ACMESOS ACMESOE

AIX ACMESUS ACMESUE

Windows NT ACMESNS ACMESNE

BOTH OS/390 ACMEBOS ACMEBOE


(SQLJ and JDBC)
AIX ACMEBUS ACMEBUE

Windows NT ACMEBNS ACMEBNE

COBOL OS/390 ACMECOS ACMECOE

AIX N/A N/A

Windows NT N/A N/A

22 DB2 Java Stored Procedures: Learning by Example


In addition, client applications invoking these stored procedures were written
in Java and COBOL. For the Java client applications, there is a JDBC version
and a separate SQLJ version.

3.3.1 DB2 naming conventions


The sample DDL and source code refer to various database names, table
names and stored procedure names, which we describe below. See 5.1.1,
“Naming” on page 83 for a more detailed discussion of object naming in a
Java stored procedures environment.

3.3.1.1 Database names


To allow us to concurrently develop the samples against both the standard
and enhanced versions of the tables, we placed the tables in different
databases as follows:

ACMES is the database in which we put the Standard objects.

ACMEE is the database in which we put the Enhanced objects.

3.3.1.2 Table qualifiers


To allow us to concurrently develop the samples against both the standard
and enhanced versions of the tables, we used different table creators as
follows:

ACMES is the qualifier referring to Standard tables.

ACMEE is the qualifier referring to to Enhanced tables.

3.3.1.3 Stored procedure names


DB2 for OS/390 Version 5 does not support the use of schemas in stored
procedure names. Therefore, we prefixed the stored procedure name with the
type and level it was aimed at, as follows:

af_spname where a refers to the API J for JDBC


S for SQLJ
B for Both JDBC and
SQLJ
C for COBOL

f refers to the S for standard


features

spname refers to the stored


procedure name

Chapter 3. Java sample application: the ACME software company 23


For DB2 UDB for OS/390 V6 and DB2 UDB for UNIX, Windows, OS/2 (the
enhanced feature level in our examples), we were able to use schemas to
qualify the stored procedure name, with the schema name being set to the
Java package name that the example belonged to.

3.4 Portability issues


Java is highly-touted in the trade press as being portable. This section
discusses the portability of the Java stored procedures built for this book.

3.4.1 Java stored procedure portability


The “standard” version of Add_customer was initially written to NT, which
then ported immediately and easily to UNIX and OS/390. The only difference
within the Java code came in the Java clients that invoked the Add_customer
stored procedure....and these changes were limited to the URL and the driver
name. (Exception: DB2 V5 for OS/390 does not support schemas.)

3.4.2 DB2 portability issues


Although there is a high degree of consistency between the implementations
of DB2 on various platforms at an application level, some minor differences
exist in areas such as DDL.

This required a few changes to be made to the DB2 for OS/390 version of the
DDL in order for it to work in the NT and AIX environments. Examples of
these changes include;
• Changing the CREATE DATABASE SQL statement to a CREATE
DATABASE COMMAND (with associated parameter changes).
• Removing references to storage groups.
• Altering parameters in CREATE TABLESPACE statements.
• Altering table space references in CREATE TABLE statements.

No changes were required to any of the DML embedded within the application
code.

3.5 Sample stored procedures — standard


We demonstrate Java stored procedures with four examples.

24 DB2 Java Stored Procedures: Learning by Example


3.5.1 JDBC stored procedure sample
Below is the source code of the stored procedure Add_customer written in
Java using JDBC.
////////////////////////////////////////////////////
// JDBC Stored Procedure Add_customer
//
////////////////////////////////////////////////////
package ACMEJNS ;

import java.sql.*;
import java.math.*;

public class Add_customer


{
public static void add_customer (
String in_cust_firstname,
String in_cust_lastname,
String in_cust_address,
int[] out_cust_no,
String[] mark,
String[] mark_error_text
) throws SQLException, Exception
{
try
{
java.sql.PreparedStatement pstmt;
ResultSet res;
int new_cust_no;
int updateCount;
int selectCount;
String sql;
////////////////////////////////////////////////////////
// mark_error_text and mark are used to report
// errors trapped in the catch block
////////////////////////////////////////////////////////
mark_error_text[0] = "OK";
new_cust_no = 0;

////////////////////////////////////////////////////////
// get the connection
////////////////////////////////////////////////////////
mark[0] = "Add_customer: getConnection";
Connection con =
DriverManager.getConnection("jdbc:default:connection");

////////////////////////////////////////////////////////

Chapter 3. Java sample application: the ACME software company 25


// find the next customer number to use
////////////////////////////////////////////////////////
mark[0] = "Add_customer: createStatement";
Statement stmt = con.createStatement();
stmt.execute("set schema = ACMES");
mark[0] = "Add_customer: Get high cust no";
sql = "SELECT HI_CUST_NO+1 "
+ "FROM HI_CUST_NO";
res = stmt.executeQuery(sql);

////////////////////////////////////////////////////////
// there will be only one number so use next() to
// get the first row
////////////////////////////////////////////////////////
res.next();
new_cust_no = res.getInt(1);

////////////////////////////////////////////////////////
// update the table -- note that this should be
// modified in a multi-user application
////////////////////////////////////////////////////////
mark[0] = "Add_customer: Update high cust no";
sql = "UPDATE HI_CUST_NO "
+ "SET HI_CUST_NO = ?";
pstmt = con.prepareStatement(sql);
pstmt.setInt(1, new_cust_no);
updateCount = pstmt.executeUpdate();

////////////////////////////////////////////////////////
// insert a new customer using the calculated cust no
////////////////////////////////////////////////////////
mark[0] = "Add_customer: Insert new cust row";
sql = "INSERT INTO CUSTOMER "
+ "( "
+ "CUST_NO, "
+ "CUST_FIRSTNAME, "
+ "CUST_LASTNAME, "
+ "CUST_ADDRESS "
+ ") "
+ "VALUES"
+ "( "
+ "? , "
+ "'"+ in_cust_firstname + "' , "
+ "'"+ in_cust_lastname + "' , "
+ "'"+ in_cust_address + "'"
+ " )";
pstmt = con.prepareStatement(sql);

26 DB2 Java Stored Procedures: Learning by Example


pstmt.setInt(1, new_cust_no);
updateCount = pstmt.executeUpdate();
out_cust_no[0] = new_cust_no;
mark[0] = "Add_customer: Complete";
if (stmt != null) stmt.close();
if (con != null) con.close();
} // try
catch (SQLException e)
{
mark_error_text[0] = "SQLException raised, SQLState = "
+ e.getSQLState() + " SQLCODE = " + e.getErrorCode()
+ " :" + e.getMessage();
}
catch (Exception e)
{ mark_error_text[0] = "Add_customer: major exception caught: "
+ e.getMessage();
}
} // add_customer
}

3.5.2 SQLJ stored procedure sample


Below is the source code of the stored procedure Add_customer written in
Java using SQLJ.

package ACMESNE ;

////////////////////////////////////////////////////
// SQLJ Stored Procedure add_customer
////////////////////////////////////////////////////

import java.sql.*;
import sqlj.runtime.*;
import sqlj.runtime.ref.*;
import java.math.*;

public class Add_customer


{
public static void add_customer (
String in_cust_firstname,
String in_cust_lastname,
String in_cust_address,
int[] out_cust_no,
String[] mark,
String[] mark_error_text

Chapter 3. Java sample application: the ACME software company 27


) throws SQLException, Exception
{
System.out.println("Add_customer: start - SQLJ version");
try
{
////////////////////////////////////////////////////////
// mark_error_text and mark are used to report
// errors trapped in the catch block
////////////////////////////////////////////////////////

int new_cust_no;
mark_error_text[0] = "OK";

mark[0] = "Add_customer: Get context";


System.out.println("Add_customer: about to getDefaultContext" );
DefaultContext ctx = DefaultContext.getDefaultContext();

mark[0] = "Add_customer: insert into customer";


#sql {
INSERT INTO CUSTOMER
(
CUST_FIRSTNAME,
CUST_LASTNAME,
CUST_ADDRESS
)
VALUES
(
:in_cust_firstname,
:in_cust_lastname,
:in_cust_address
)
}; // #sql

/////////////////////////////////////////////////////////////
// get the value of the identity column which is passed back
/////////////////////////////////////////////////////////////
mark[0] = "Add_customer: retrieve cust no";

#sql {
SELECT CUST_NO INTO :new_cust_no
FROM GTT_CUST_NO
}; //#sql
out_cust_no[0] = new_cust_no;
mark[0] = "Add_customer: complete";

} // try
catch (SQLException e)

28 DB2 Java Stored Procedures: Learning by Example


{
mark_error_text[0] = "Add_Customer: SQLException raised: "
+ "SQLState = "
+ e.getSQLState() + " SQLCODE = " + e.getErrorCode()
+ " :" + e.getMessage();
System.out.println("Add_customer: caught sqlexception");
System.out.println("Add_customer: "+ mark_error_text[0]);
e.printStackTrace();
}
catch (Exception e)
{
mark_error_text[0] = "Add_customer: major exception caught: "
+ e.getMessage();
System.out.println("Add_customer: caught java exception");
System.out.println("Add_customer: "+ mark_error_text[0]);
e.printStackTrace();
}
} // add_customer
}

3.5.3 COBOL stored procedure sample


Below is the source code of the stored procedure Add_customer written in
COBOL. This example was tested on OS/390.
IDENTIFICATION DIVISION.
PROGRAM-ID. "ADDCUST".
*****************************************************
* *
* ACME Software Company - Add New Customer *
* *
* This stored procedure inserts a row into the *
* ACME.CUSTOMER table. *
* *
* The file PREPCUST contains the preparation JCL *
* for this program. *
* *
*****************************************************
DATA DIVISION.
WORKING-STORAGE SECTION.
EXEC SQL
INCLUDE SQLCA
END-EXEC.
01 NEW-CUST-NO PIC S9(9) COMP.
* DSNTIAR PARMS
01 ERROR-MESSAGE.
02 ERROR-LEN PIC S9(4) COMP VALUE +240.

Chapter 3. Java sample application: the ACME software company 29


02 ERROR-TEXT PIC X(80) OCCURS 3 TIMES
INDEXED BY ERROR-INDEX.
77 ERROR-TEXT-LEN PIC S9(9) COMP VALUE +80.

77 ERR-CODE PIC 9(8) VALUE 0.


77 ERR-MINUS PIC X VALUE SPACE.
77 LINE-EXEC PIC X(20) VALUE SPACE.

LINKAGE SECTION.
01 CUST-FNAME PIC X(20).
01 CUST-LNAME PIC X(20).
01 CUST-ADDR PIC X(30).
01 CUST-NO PIC S9(9) COMP.
01 MARK PIC X(40).
01 MARK-ERROR-TEXT PIC X(240).
*
*****************************************************
* Procedure Division *
*****************************************************
*
PROCEDURE DIVISION USING CUST-FNAME, CUST-LNAME, CUST-ADDR,
CUST-NO, MARK, MARK-ERROR-TEXT.

EXEC SQL WHENEVER SQLERROR GOTO SQL-ERROR END-EXEC.

DISPLAY "ADD_CUSTOMER: START".


MOVE "OK" TO MARK-ERROR-TEXT.
*
* Get new customer number
*
*
MOVE "ADD_CUSTOMER: GET HIGH CUSTOMER NO" TO MARK.
DISPLAY "ADD_CUSTOMER: GET HIGH CUSTOMER NO".
EXEC SQL
SELECT HI_CUST_NO+1
INTO :NEW-CUST-NO
FROM HI_CUST_NO
END-EXEC.

*
* Update high customer number
*
*
MOVE "ADD_CUSTOMER: UPDATE HIGH CUSTOMER NO" TO MARK.
DISPLAY "ADD_CUSTOMER: UPDATE HIGH CUSTOMER NO".
EXEC SQL
UPDATE HI_CUST_NO

30 DB2 Java Stored Procedures: Learning by Example


SET HI_CUST_NO = :NEW-CUST-NO
END-EXEC.

*
* Insert into Customer table
*
MOVE "ADD_CUSTOMER: INSERT INTO CUSTOMER" TO MARK.
DISPLAY "ADD_CUSTOMER: INSERT INTO CUSTOMER".
EXEC SQL
INSERT INTO CUSTOMER
(CUST_NO, CUST_FIRSTNAME, CUST_LASTNAME, CUST_ADDRESS)
VALUES (:NEW-CUST-NO, :CUST-FNAME, :CUST-LNAME, :CUST-ADDR)
END-EXEC.

MOVE NEW-CUST-NO TO CUST-NO.

MOVE "ADD_CUSTOMER: COMPLETE" TO MARK.


DISPLAY "ADD_CUSTOMER: COMPLETE".

EXIT-PROG.
GOBACK.

SQL-ERROR.
MOVE SQLCODE TO ERR-CODE .
IF SQLCODE < 0 THEN MOVE '-' TO ERR-MINUS.
DISPLAY "ADD_CUSTOMER: NEGATIVE SQLCODE ENCOUNTERED".
DISPLAY "ADD_CUSTOMER: SQLCODE = " ERR-MINUS ERR-CODE.
CALL 'DSNTIAR' USING SQLCA ERROR-MESSAGE ERROR-TEXT-LEN.
IF RETURN-CODE < 8
PERFORM ERROR-PRINT VARYING ERROR-INDEX
FROM 1 BY 1 UNTIL ERROR-INDEX GREATER THAN 3
STRING ERROR-TEXT(1)
ERROR-TEXT(2)
ERROR-TEXT(3)
DELIMITED BY SIZE
INTO MARK-ERROR-TEXT
ELSE
DISPLAY "ADD_CUSTOMER: BAD RETURN CODE FROM DSNTIAR"
DISPLAY "ADD_CUSTOMER: " RETURN-CODE.
GO TO EXIT-PROG.

ERROR-PRINT.
DISPLAY "ADD_CUSTOMER: " ERROR-TEXT (ERROR-INDEX).

Chapter 3. Java sample application: the ACME software company 31


3.5.4 Combined SQLJ and JDBC example
The following example shows a combination of SQLJ and JDBC.

package ACMEBNS ;

////////////////////////////////////////////////////
// SQLJ/JDBC Stored Procedure add_customer
////////////////////////////////////////////////////

import java.sql.*;
import sqlj.runtime.*;
import sqlj.runtime.ref.*;
import java.math.*;

public class Add_customer


{
public static void add_customer (
String in_cust_firstname,
String in_cust_lastname,
String in_cust_address,
int[] out_cust_no,
String[] mark,
String[] mark_error_text
) throws SQLException, Exception
{
try
{
////////////////////////////////////////////////////////
// mark_error_text and mark are used to report
// errors trapped in the catch block
////////////////////////////////////////////////////////
ResultSet res;
String sql;
int new_cust_no;
mark_error_text[0] = "OK";
new_cust_no = 0;

////////////////////////////////////////////////////////
// get default contect and connection
////////////////////////////////////////////////////////
mark[0] = "Add_customer: Set context";
DefaultContext ctx = DefaultContext.getDefaultContext();
mark[0] = "Add_customer: getConnection";
Connection con = DriverManager.getConnection(
"jdbc:default:connection");

32 DB2 Java Stored Procedures: Learning by Example


mark[0] = "Add_customer: createStatement";
Statement stmt = con.createStatement();
mark[0] = "Add_customer: Get high cust no";

////////////////////////////////////////////////////////
// determine high customer number using JDBC
////////////////////////////////////////////////////////
sql = "SELECT HI_CUST_NO+1 "
+ "FROM ACMES.HI_CUST_NO";
res = stmt.executeQuery(sql);
while (res.next())
{
new_cust_no = res.getInt(1);
}
mark[0] = "Add_customer: Update high cust no";

////////////////////////////////////////////////////////
// update the table using SQLJ
////////////////////////////////////////////////////////
#sql
{
UPDATE HI_CUST_NO
SET HI_CUST_NO = :new_cust_no
}; // #sql
mark[0] = "Add_customer: Insert new cust row";

////////////////////////////////////////////////////////
// now can update the Customer table, using SQLJ
////////////////////////////////////////////////////////
#sql
{
INSERT INTO
CUSTOMER
(
CUST_NO,
CUST_FIRSTNAME,
CUST_LASTNAME,
CUST_ADDRESS
)
VALUES
(
:new_cust_no ,
:in_cust_firstname ,
:in_cust_lastname ,
:in_cust_address
)
}; // #sql

Chapter 3. Java sample application: the ACME software company 33


out_cust_no[0] = new_cust_no; //set output cust no
mark[0] = "Add_customer: Complete";
} // try
catch (SQLException e)
{
mark_error_text[0] = "Add_Customer: SQLException raised: "
+ "SQLState = "
+ e.getSQLState() + " SQLCODE = " + e.getErrorCode()
+ " :" + e.getMessage();
}
catch (Exception e)
{
mark_error_text[0] = "Add_customer: major exception caught: "
+ e.getMessage();
}
} // add_customer
}

3.6 Sample stored procedures — enhanced


The previous examples, which showed the stored procedure Add_customer in
various flavors, introduced using Java for building a stored procedure. In the
following sections we show examples of more complex Java stored
procedures.

We developed the stored procedure, Query_oi_summ, which explores


issues that will be encountered by programmers building a complex
application. The problems addressed by this stored procedure include:
• Null handling
• Using ResultSets
• Error handling

3.6.1 JDBC enhanced stored procedure sample


Below is the JDBC version of the Query_oi_summ stored procedure.
////////////////////////////////////////////////////
// JDBC Stored Procedure Query_oi_summ
//
// This stored procedure demonstrates:
// 1) handling null input fields
// 2) generating interim values
// into a temporary table which is returned
// as a ResultSet to the client
// 3) debugging by writing to a local file

34 DB2 Java Stored Procedures: Learning by Example


// 4) handling nulls returned from a query
//
// NOTE: if this stored procedure fails hard (dumps)
// it may be because you have not created
// a TMP directory on NT
////////////////////////////////////////////////////
package ACMEJNE ;

import java.sql.*;
import java.math.*;
import java.io.*;
import java.io.StringWriter;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.util.Date;
import java.text.SimpleDateFormat;

public class Query_oi_summ


{
public static void query_oi_summ (
String in_cust_no,
String in_order_no,
String[] mark,
String[] mark_error_text,
ResultSet[] out_rs
) throws SQLException, Exception
{
PrintWriter pwx = null; // declare outside try for catch to close
final boolean dbg = true; // this could be set by an input parm
try
{
////////////////////////////////////////////////////////
// establish debugging file: name is timestamped
////////////////////////////////////////////////////////
Date debugDate = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance();
((SimpleDateFormat)dateFormat).applyPattern("MM_dd_HH_mm_ss");
String debugdf = dateFormat.format(debugDate);
if (dbg)
{
pwx = new
PrintWriter( new FileWriter("/tmp/" + debugdf + ".txt"),
true);
}

////////////////////////////////////////////////////////
// mark_error_text and mark are used to report

Chapter 3. Java sample application: the ACME software company 35


// errors trapped in the catch block
////////////////////////////////////////////////////////
mark_error_text[0] = "OK";
mark[0] = "Query_oi_summ: getConnection";
Connection con =
DriverManager.getConnection("jdbc:default:connection");

////////////////////////////////////////////////////////
// establish where clause: either an order number is
// sent in or a customer number is sent in
////////////////////////////////////////////////////////
String where_clause = "";
if (null != in_cust_no)
where_clause = " where OI.ord_item_prod_no = P.prod_no " +
" and OI.ord_item_ord_no = O.ord_no " +
" and O.ord_cust_no = C.cust_no " +
" and C.cust_no = " +
in_cust_no;
else
where_clause = " where OI.ord_item_ord_no = " + in_order_no +
" and OI.ord_item_prod_no = P.prod_no" ;

////////////////////////////////////////////////////////
// construct SQL statement and execute the Query
////////////////////////////////////////////////////////
String sql = "select sum(OI.ORD_ITEM_QTY) Total_Qty ," +
" P.prod_no Product#," +
" P.prod_desc DESCRIPTION " +
" from acmee.order_item OI, acmee.product P," +
" acmee.order O, acmee.customer C" +
where_clause +
" group by P.prod_no, P.prod_desc " +
" order by P.prod_desc ";
if (dbg) pwx.println("sql =>" + sql + "<=");
if (dbg) pwx.println("in_cust_no=" + in_cust_no);
if (dbg) pwx.println("in_order_no=" + in_order_no);
mark[0] = "Query_oi_summ: createStatement";
if (dbg) pwx.println(mark[0]);
Statement stmt = con.createStatement();
mark[0] = "Query_oi_summ: executeQuery";
if (dbg) pwx.println(mark[0]);
ResultSet rs = stmt.executeQuery(sql);
if (dbg) pwx.println("post stmt.executeQuery");
String insert_vals = "";
Statement stmt2 = con.createStatement();

////////////////////////////////////////////////////////

36 DB2 Java Stored Procedures: Learning by Example


// walk thru the result set, using the returned values
// to insert to the correct category in the
// summary table
////////////////////////////////////////////////////////
if (rs == null)
{
mark_error_text[0] = "Query_oi_summ: query failed for " + sql;
}
else
{
while (rs.next())
{
if (dbg) pwx.println("rs=" + rs.getString(1) + "," +
rs.getString(2) + "," + rs.getString(3));
if (rs.getInt(1) < 6)
insert_vals = " 'X' , ' ', ' ' ";
else
if (rs.getInt(1) < 11)
insert_vals = " ' ' , 'X', ' ' ";
else
insert_vals = " ' ' , ' ', 'X' ";

//////////////////////////////////////////////////////////////
// determine if production description is SQL null, in
// which case we specifically tell JDBC that we are
// inserting a null
//////////////////////////////////////////////////////////////
String ins_prod_desc = "";
String ret_prod_desc = rs.getString(3);
if (rs.wasNull())
ins_prod_desc = "NULL";
else
ins_prod_desc = "'" + rs.getString(3) + "'" ;

//////////////////////////////////////////////////////////////
// finally have all the calculated pieces to build the
// full insert statement and execute it
//////////////////////////////////////////////////////////////
String sql2 = "insert into acmee.order_item_summ " +
"(prod_desc, qty_1_to_5,QTY_6_TO_10,QTY_11_PLUS) " +
"values(" +
ins_prod_desc + "," +
insert_vals +
")";
if (dbg) pwx.println("sql2=" + sql2);
stmt2.executeUpdate(sql2);
} // while

Chapter 3. Java sample application: the ACME software company 37


} // else
stmt.close();
stmt2.close();
if (dbg) pwx.println("stmt and stmt2 close");

////////////////////////////////////////////////////////
// get the summarized information into a ResultSet
// to return to the client
////////////////////////////////////////////////////////
Statement stmt3 = con.createStatement();
if (dbg) pwx.println("stmt3 executeQuery");
out_rs[0] =
stmt3.executeQuery("select * from acmee.order_item_summ");
if (con != null) con.close();
if (dbg) pwx.println("graceful end");
if (dbg) pwx.close();
} // try
catch (IOException e)
{
mark_error_text[0] = "Query_oi_summ: IOException: "
+ e.getMessage();
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
mark_error_text[0] += ":printStackTrace=" + sw.toString() ;
if (dbg) pwx.close();
}
catch (SQLException e)
{
mark_error_text[0] = "Query_oi_summ: "
+ "SQLException raised, SQLState = "
+ e.getSQLState() + " SQLCODE = " + e.getErrorCode()
+ " :" + e.getMessage();
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
mark_error_text[0] += ":printStackTrace=" + sw.toString() ;
if (dbg) pwx.close();
}
catch (Exception e)
{
mark_error_text[0] = "Query_oi_summ: Exception: "
+ e.getMessage();
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
mark_error_text[0] += ":printStackTrace=" + sw.toString() ;

38 DB2 Java Stored Procedures: Learning by Example


if (dbg) pwx.close();
}

} // query_oi_summ
}

3.6.2 SQLJ enhanced sample


Below is the SQLJ version of the Query_oi_summ stored procedure.
////////////////////////////////////////////////////////////
// SQLJ Stored Procedure Query_oi_summ
//
// This stored procedure demonstrates:
// 1) Handling null input fields.
// 2) Generating interim values
// into an interim results table which is returned
// as a ResultSet to the client.
// 3) Debugging by writing to a local file.
// 4) Handling nulls returned from a query.
// 5) Using both named and positional iterators.
/////////////////////////////////////////////////////////////
package ACMESNE ;

import java.sql.*;
import sqlj.runtime.*;
import sqlj.runtime.ref.*;
import java.math.*;
import java.io.*;
import java.text.*;
import java.util.Date;

//////////////////////////////////////////
// iter1 is a named iterator
// iter2 is a positional iterator
//////////////////////////////////////////
#sql iterator Defined_iter1 (int Total_Qty , int Product_no ,
String Description);
#sql iterator Defined_iter2 (String, int, int, int);

public class Query_oi_summ


{
public static void query_oi_summ (
String in_cust_no,
String in_order_no,

Chapter 3. Java sample application: the ACME software company 39


String[] mark,
String[] mark_error_text,
ResultSet[] out_rs
) throws SQLException, Exception
{
PrintWriter pwx = null;
final boolean dbg = false;
String all_errs;
try
{
Defined_iter1 iter1 = null;
////////////////////////////////////////////////////////
// establish debugging file: name is timestamped
////////////////////////////////////////////////////////
Date debugDate = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance();
((SimpleDateFormat)dateFormat).applyPattern("MM_dd_HH_mm_ss");
String debugdf = dateFormat.format(debugDate);
if (dbg)
{
pwx = new
PrintWriter( new FileWriter("/tmp/" + debugdf + ".txt"),true );
}
if (dbg) pwx.println("Query_oi_summ: SQLJ version");

////////////////////////////////////////////////////////
// mark_error_text and mark are used to report
// errors trapped in the catch block
////////////////////////////////////////////////////////
mark_error_text[0] = "OK";

////////////////////////////////////////////////////////
// query based either upon the input customer number
// or the input order number
////////////////////////////////////////////////////////
if (null != in_cust_no)
{
int int_in_cust_no = Integer.parseInt(in_cust_no.trim());
if (dbg) pwx.println("Query_oi_summ: in_cust_no not null, ="
+ in_cust_no);
#sql iter1 =
{
select sum(OI.ORD_ITEM_QTY) Total_Qty ,
OI.ord_item_prod_no Product_no,
P.prod_desc Description
from acmee.order_item OI,
acmee.product P,

40 DB2 Java Stored Procedures: Learning by Example


acmee.order O,
acmee.customer C
where OI.ord_item_prod_no = P.prod_no
and OI.ord_item_ord_no = O.ord_no
and O.ord_cust_no = C.cust_no
and C.cust_no = :int_in_cust_no
group by OI.ord_item_prod_no,
P.prod_desc
order by OI.ord_item_prod_no
}; // #sql
}
else
{
int int_in_order_no = Integer.parseInt(in_order_no.trim());
if (dbg) pwx.println("Query_oi_summ: in_order_no not null, ="
+in_order_no);
#sql iter1 =
{
select sum(OI.ORD_ITEM_QTY) Total_Qty ,
OI.ord_item_prod_no Product_no,
P.prod_desc Description
from acmee.order_item OI,
acmee.product P
where OI.ord_item_prod_no = P.prod_no
and OI.ord_item_ord_no = :int_in_order_no
group by OI.ord_item_prod_no,
P.prod_desc
order by OI.ord_item_prod_no
}; // #sql
} // else

////////////////////////////////////////////////////////
// walk thru the iterator, using the returned values
// to insert to the correct category in the
// summary table
////////////////////////////////////////////////////////
if (dbg) pwx.println("Query_oi_summ: post selects");
if (null == iter1)
{
mark_error_text[0] = "Query_oi_summ: query failed";
if (dbg) pwx.println("Query_oi_summ:" + mark_error_text[0]);
}
else
{
while (iter1.next())
{
if (dbg) pwx.println("iter1=" + iter1.Total_Qty() + "," +

Chapter 3. Java sample application: the ACME software company 41


iter1.Product_no() + "," + iter1.Description());
String five_or_below = " ";
String six_to_ten = " ";
String eleven_and_above = " ";
if (dbg) pwx.println("about to get total variable");
int total = iter1.Total_Qty();
if (total < 6)
five_or_below = "X";
else
if (total < 11)
six_to_ten = "X";
else
eleven_and_above = "X";
if (dbg) pwx.println("just set X marks");

String ins_prod_desc = "";


String ret_prod_desc = iter1.Description();
ins_prod_desc = ret_prod_desc ;

//////////////////////////////////////////////////////////////
// finally have all the calculated pieces to build the
// full insert statement and execute it
//////////////////////////////////////////////////////////////
if (dbg) pwx.println("about to insert to ois with " + "/" +
ins_prod_desc + "/" + five_or_below + "/" +
six_to_ten + "/" + eleven_and_above + "/" );
#sql {
insert into acmee.order_item_summ
(prod_desc, qty_1_to_5, QTY_6_TO_10, QTY_11_PLUS)
values
(:ins_prod_desc, :five_or_below ,
:six_to_ten , :eleven_and_above)
}; // #sql
} // while
} // else
iter1.close();
////////////////////////////////////////////////////////
// get the summarized information into an Iterator
// to return to the client
////////////////////////////////////////////////////////
if (dbg) pwx.println("Query_oi_summ: about to do iter2");
Defined_iter2 iter2;
#sql iter2 =
{
select
prod_desc, qty_1_to_5, QTY_6_TO_10, QTY_11_PLUS

42 DB2 Java Stored Procedures: Learning by Example


from acmee.order_item_summ
}; // #sql
out_rs[0] = iter2.getResultSet();
////////////////////////////////////////////////////////
// walk thru iterator here -- data will not be available
// in client (according to design) after viewing here
////////////////////////////////////////////////////////
if (dbg)
{
ResultSet tmp_rs = iter2.getResultSet();
if (dbg) pwx.println("Query_oi_summ: tmp_rs has data");
ResultSetMetaData stmtInfo = tmp_rs.getMetaData();
int numOfColumns = stmtInfo.getColumnCount();

////////////////////////////////////////
// print column labels
////////////////////////////////////////
for( int i=1; i <= numOfColumns; i++ )
{
if (dbg) pwx.print(stmtInfo.getColumnLabel(i));
if( i != numOfColumns )
{
if (dbg) pwx.print(" , ");
}
}
if (dbg) pwx.println("");
////////////////////////////////////////
// print data in table
////////////////////////////////////////
while( tmp_rs.next() )
{
for( int i=1; i <= numOfColumns; i++ )
{
String tmp_get_desc = tmp_rs.getString(i);
if (tmp_rs.wasNull())
{
if (dbg) pwx.print("Null Description ");
}
else
{
if (dbg) pwx.print(tmp_get_desc);
}
if( i != numOfColumns )
{
if (dbg) pwx.print(" , ");
}
} //for

Chapter 3. Java sample application: the ACME software company 43


if (dbg) pwx.println("");
} // while
} // else if (dbg)
//iter2.close();
if (dbg) pwx.println("Query_oi_summ: graceful end");
if (dbg) pwx.close();
} // try
catch (IOException e)
{
all_errs = "Query_oi_summ: IOException: "
+ e.getMessage();
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
all_errs += ":printStackTrace=" + sw.toString() ;
if (dbg) pwx.println(all_errs);
if (dbg) pwx.close();
mark_error_text[0] = all_errs.substring(0,199);
}
catch (SQLException e)
{
all_errs = "Query_oi_summ: "
+ "SQLException raised, SQLState = "
+ e.getSQLState() + " SQLCODE = " + e.getErrorCode()
+ " :" + e.getMessage();
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
all_errs += ":printStackTrace=" + sw.toString() ;
if (dbg) pwx.println(all_errs);
if (dbg) pwx.close();
mark_error_text[0] = all_errs.substring(0,199);
}
catch (Exception e)
{
all_errs = "Query_oi_summ: Exception: "
+ e.getMessage();
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
all_errs += ":printStackTrace=" + sw.toString() ;
if (dbg) pwx.println(all_errs);
if (dbg) pwx.close();
mark_error_text[0] = all_errs.substring(0,199);
}
} // query_oi_summ
}

44 DB2 Java Stored Procedures: Learning by Example


3.7 Sample Client Code
The sections that follow provide some sample code for invoking the stored
procedures we have listed above. The URL and the driver name may need to
change depending upon the platform upon which the client runs (see 8.1.3,
“Porting between UNIX/NT and S/390” on page 161).

3.7.1 Calling the Java stored procedure from Java


Below is a Java client application calling the Java stored procedure
Add_Customer using JDBC.

Platform differences
This sample ran on NT. A UNIX version would require no change. An
OS/390 version requires changes to the driver name and to the URL. If the
stored procedure is to be run under Version 5 of DB2 for OS/390, the
source code would need to be modified where the schema name is used,
because schemas were not a valid construct in Version 5.

import java.sql.*;

//////////////////////////////////////////////////////////////////////////
/
// jscall_Add_customer
//
// Simple Java application that calls the Add_customer stored procedure.
// UNIX and NT version.
//
// example: java jscall_Add_customer ACMEJNS lastname firstname address
//////////////////////////////////////////////////////////////////////////
/

class jscall_Add_customer
{
static
{
try
{
Class.forName("COM.ibm.db2.jdbc.app.DB2Driver");
}
catch (Exception e)

Chapter 3. Java sample application: the ACME software company 45


{
System.out.println("\nError loading DB2 Driver...\n");
e.printStackTrace();
}
} // static

public static void main(String argv[])


{
Connection con = null;
String url;
String procName = "";
CallableStatement callStmt;
try
{
if (argv.length < 4)
{
String usage_stmt =
"Usage: java jscall_Add_customer schema lastname firstname address";
System.out.println(usage_stmt);
System.exit(0);
} // argv.length

///////////////////////////////////////
// connect
///////////////////////////////////////
System.out.println("Trying to connect...");
url = "jdbc:db2:ACMES";
con = DriverManager.getConnection(url);
con.setAutoCommit(false);

/////////////////////////////////////////////////
// prepare the call to the stored procedure
/////////////////////////////////////////////////
System.out.println("Preparing call...");
procName = argv[0] + ".Add_customer";
String sql = "CALL " + procName + "(?,?,?,?,?,?)";
callStmt = con.prepareCall(sql);

///////////////////////////////////////
// register the output parameters
///////////////////////////////////////
System.out.println("Preparing parms...");
callStmt.registerOutParameter (4, Types.INTEGER); // cust nbr
callStmt.registerOutParameter (5, Types.CHAR); // mark
callStmt.registerOutParameter (6, Types.CHAR); // mark_error_text

///////////////////////////////////////

46 DB2 Java Stored Procedures: Learning by Example


// set input parameters
///////////////////////////////////////
callStmt.setString (1, argv[1]); // lastname
callStmt.setString (2, argv[2]); // firstname
callStmt.setString (3, argv[3]); // address

///////////////////////////////////////
// call the stored procedure
///////////////////////////////////////
System.out.println ("\nCall stored procedure named " + procName);
callStmt.execute();

///////////////////////////////////////
// retrieve output parameters
///////////////////////////////////////
int returned_cust_no = callStmt.getInt(4);
String returned_mark = callStmt.getString(5);
String returned_mark_error_text = callStmt.getString(6);

////////////////////////////////////////
// report results and commit or rollback
////////////////////////////////////////
if (returned_mark_error_text.trim().equals("OK"))
{
System.out.println ("returned_cust_no: " + returned_cust_no );
con.commit();
}
else
{
System.out.println ("returned_mark: " + returned_mark );
System.out.println ("returned_mark_error_text:"
+ returned_mark_error_text.trim() );
con.rollback();
}

///////////////////////////////////////
// tidy up
///////////////////////////////////////
callStmt.close ();
con.close ();

} // try
catch (Exception e)
{
System.out.println
("catch Exception being executed" );
try { con.close(); } catch (Exception x) { }

Chapter 3. Java sample application: the ACME software company 47


e.printStackTrace ();
} // catch
} // main
}

3.7.2 COBOL client application sample


Below is the OS/390 COBOL client application calling the Java stored
procedure Add_customer :

Platform differences
Note that the call is to CS_Add_Customer. This version was written for
OS/390 DB2 Version 5 which does not support schemas. This client source
code could be modified to take advantage of schemas in a Version 6
system. See 3.3.1, “DB2 naming conventions” on page 23 for more details.

IDENTIFICATION DIVISION.
PROGRAM-ID. "CSCALLAC".
*****************************************************
* *
* ACME Software Company - Driver for proc ADDCUST *
* *
* This program calls the Add_customer stored *
* procedure (COBOL version). *
* *
* The file PREPCALL contains the preparation JCL *
* for this program. *
* *
*****************************************************

ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
EXEC SQL
INCLUDE SQLCA
END-EXEC.
* PARM TO RECEIVE THE SQLCODE ERROR MESSAGES
01 ERROR-MESSAGE.
02 ERROR-LEN PIC S9(4) COMP VALUE +960.
02 ERROR-TEXT PIC X(120) OCCURS 8 TIMES
INDEXED BY ERROR-INDEX.
77 ERROR-TEXT-LEN PIC S9(8) COMP VALUE +120.

48 DB2 Java Stored Procedures: Learning by Example


77 ERR-CODE PIC 9(8) VALUE 0.
77 ERR-MINUS PIC X VALUE SPACE.
77 LINE-EXEC PIC X(20) VALUE SPACE.

01 CUST-FNAME PIC X(20).


01 CUST-LNAME PIC X(20).
01 CUST-ADDRESS PIC X(30).
01 CUST-NO PIC S9(9) COMP.
01 MARK PIC X(80).
01 MARK-ERROR-TEXT PIC X(240).
01 INDARRAY.
05 INDVAR1 PIC S9(4) COMP.
05 INDVAR2 PIC S9(4) COMP.
05 INDVAR3 PIC S9(4) COMP.
05 INDVAR4 PIC S9(4) COMP.
05 INDVAR5 PIC S9(4) COMP.
05 INDVAR6 PIC S9(4) COMP.
*
*****************************************************
* Procedure Division *
*****************************************************
*
PROCEDURE DIVISION.
DISPLAY "PROGRAM CSCALLAC STARTED"

MOVE 0 TO INDVAR1.
MOVE 0 TO INDVAR2.
MOVE 0 TO INDVAR3.
MOVE 0 TO INDVAR4.
MOVE 0 TO INDVAR5.
MOVE 0 TO INDVAR6.
MOVE "JOHN" TO CUST-FNAME.
MOVE "SMITH" TO CUST-LNAME.
MOVE "FROM VERSION ACMECOS" TO CUST-ADDRESS.
MOVE 0 TO CUST-NO.
MOVE SPACES TO MARK.
MOVE SPACES TO MARK-ERROR-TEXT.

EXEC SQL
CALL CS_ADD_CUSTOMER (:CUST-FNAME:INDVAR1,
:CUST-LNAME:INDVAR2,
:CUST-ADDRESS:INDVAR3,
:CUST-NO:INDVAR4,
:MARK:INDVAR5,
:MARK-ERROR-TEXT:INDVAR6)
END-EXEC.

Chapter 3. Java sample application: the ACME software company 49


MOVE SQLCODE TO ERR-CODE .
IF SQLCODE < 0 THEN
MOVE '-' TO ERR-MINUS
PERFORM SQL-ERROR THRU END-SQL-ERROR.
DISPLAY "SQLCODE FROM CALL = " ERR-MINUS ERR-CODE.
DISPLAY "RETURN VALUES: "
DISPLAY "Customer no: " Cust-no.
DISPLAY "CALL RESULT 1: " MARK.
DISPLAY "CALL RESULT 2: " MARK-ERROR-TEXT.

EXIT-PROG.

GOBACK.

SQL-ERROR.

CALL 'DSNTIAR' USING SQLCA ERROR-MESSAGE ERROR-TEXT-LEN.

IF RETURN-CODE = ZERO
PERFORM ERROR-PRINT VARYING ERROR-INDEX
FROM 1 BY 1 UNTIL ERROR-INDEX GREATER THAN 8
ELSE
DISPLAY "BAD RETURN CODE FROM DSNTIAR:" RETURN-CODE.
END-SQL-ERROR.

ERROR-PRINT.
DISPLAY ERROR-TEXT (ERROR-INDEX).

3.7.3 SQLJ client application sample


Below is the SQLJ client application invoking the Add_customer stored
procedure.
import java.sql.*;
import sqlj.runtime.ref.*;

///////////////////////////////////
// call Add_customer as sqlj
//////////////////////////////////
#sql context SACCTX;

class sscall_Add_customer
{
static
{
try

50 DB2 Java Stored Procedures: Learning by Example


{
System.out.println(" sscall_Add_customer");
Class.forName("COM.ibm.db2.jdbc.app.DB2Driver");
}
catch (Exception e)
{
System.out.println("\nError loading DB2 Driver...\n");
e.printStackTrace();
}
} // static

public static void main(String argv[])


{
String url;
String procName = "";
try
{
if (argv.length != 3)
{
System.out.println("Usage: " +
"java call_Add_customer lastname firstname address");
System.exit(0);
} // argv.length

///////////////////////////////////////
// connect
///////////////////////////////////////
url = "jdbc:db2:ACMES";
Connection con = DriverManager.getConnection(url);

con.setAutoCommit(false);
SACCTX myconn = new SACCTX (con);
SACCTX.setDefaultContext(myconn);

String lastname = argv[0];


String firstname = argv[1];
String address = argv[2];
if (address.equalsIgnoreCase("null"))
{
System.out.println("setting address to null");
address = null;
}
int cust_no = 0;
String returned_mark = "OK";
String returned_mark_error_text = "OK";

#sql[myconn]{ CALL ACMEJNS.Add_customer

Chapter 3. Java sample application: the ACME software company 51


(:IN lastname,:IN firstname,:IN address,:OUT cust_no,
:OUT returned_mark,:OUT returned_mark_error_text)};

////////////////////////////////////////
// report results and commit or rollback
////////////////////////////////////////
if (returned_mark_error_text.trim().equals("OK"))
{
System.out.println ("returned cust_no =" + cust_no);
con.commit();
}
else
{
System.out.println ("returned_mark: " + returned_mark );
System.out.println ("returned_mark_error_text:"
+ returned_mark_error_text.trim() );
con.rollback();
}

///////////////////////////////////////
// tidy up
///////////////////////////////////////
con.close ();

} // try
catch (Exception e)
{
System.out.println ("catch Exception being executed" );
e.printStackTrace ();
} // catch
} // main
}

3.7.4 JDBC client application sample


Below is a JDBC client application invoking the Query_oi_summ stored
procedure.
import java.sql.*;
///////////////////////////////////////////////////////////////////////
// call the Query_oi_summ stored procedure
// which summarizes qty of purchases into buckets
// and displays the ResultSet
///////////////////////////////////////////////////////////////////////

class jecall_Query_oi_summ
{

52 DB2 Java Stored Procedures: Learning by Example


static
{
try
{
System.out.println("test Query_oi_summ");
Class.forName("COM.ibm.db2.jdbc.app.DB2Driver");
}
catch (Exception e)
{
System.out.println("\nError loading DB2 Driver...\n");
e.printStackTrace();
}
} // static

public static void main(String argv[])


{
Connection con = null;
String url;
String procName = "";
CallableStatement callStmt;

if (argv.length != 3)
{
System.out.println("\nUsage: ");
System.out.println(" java call_Query_oi_summ schema cust# order#");
System.out.println(" where one of them equals the string null");
System.out.println(" and the other a number. Example:");
System.out.println(" java call_Query_oi_summ ACMESUE 1 null");
System.exit(0);
} // argv.length

///////////////////////////////////////
// connect
///////////////////////////////////////
try
{
System.out.println("Trying to connect...");
url = "jdbc:db2:ACMEE";
con = DriverManager.getConnection(url);
con.setAutoCommit(false);

/////////////////////////////////////////////////
// prepare the call to the stored procedure
/////////////////////////////////////////////////
System.out.println("Preparing call...");
procName = argv[0] + ".Query_oi_summ";
String sql = "CALL " + procName + "(?,?,?,?)";

Chapter 3. Java sample application: the ACME software company 53


callStmt = con.prepareCall(sql);

///////////////////////////////////////
// register the output parameters
///////////////////////////////////////
System.out.println("Preparing parms...");
callStmt.registerOutParameter (3, Types.CHAR); // mark
callStmt.registerOutParameter (4, Types.CHAR); // mark_error_text

///////////////////////////////////////
// set input parameters
///////////////////////////////////////
if (argv[1].equalsIgnoreCase("null"))
callStmt.setNull (1, Types.CHAR); // null cust no
else
callStmt.setString (1, argv[1].trim()); // cust no
if (argv[2].equalsIgnoreCase("null"))
callStmt.setNull (2, Types.CHAR); // null order no
else
callStmt.setString (2, argv[2].trim()); // order no

///////////////////////////////////////
// call the stored procedure
///////////////////////////////////////
System.out.println ("\nCall stored procedure named " + procName);
callStmt.execute();

///////////////////////////////////////
// retrieve output parameters
///////////////////////////////////////

String returned_mark = callStmt.getString(3);


String returned_mark_error_text = callStmt.getString(4);

////////////////////////////////////////
// report results and commit or rollback
////////////////////////////////////////
if (returned_mark_error_text.trim().equals("OK"))
{
System.out.println ("returned OK" );
ResultSet rs = callStmt.getResultSet();
if (null == rs)
{
System.out.println("Oh oh, rs was null");
System.exit(1);
}

54 DB2 Java Stored Procedures: Learning by Example


ResultSetMetaData stmtInfo = rs.getMetaData();
if (null == stmtInfo)
System.out.println("Oh oh, stmtInfo was null");

int numOfColumns = stmtInfo.getColumnCount();

////////////////////////////////////////
// print column labels
////////////////////////////////////////
for( int i=1; i <= numOfColumns; i++ )
{
System.out.print(stmtInfo.getColumnLabel(i));
if( i != numOfColumns ) System.out.print(" , ");
}
System.out.println("");
////////////////////////////////////////
// print data in table
////////////////////////////////////////
while( rs.next() )
{
for( int i=1; i <= numOfColumns; i++ )
{
String get_desc = rs.getString(i);
if (rs.wasNull())
System.out.print("Null Description ");
else
System.out.print(get_desc);
if( i != numOfColumns ) System.out.print(" , ");
}
System.out.println("");
}
con.commit();
}
else
{
System.out.println ("returned_mark: " + returned_mark );
System.out.println ("returned_mark_error_text:"
+ returned_mark_error_text.trim() );
con.rollback();
}

///////////////////////////////////////
// tidy up
///////////////////////////////////////
callStmt.close ();
con.close ();

Chapter 3. Java sample application: the ACME software company 55


} // try
catch (Exception e)
{
System.out.println ("catch Exception being executed" );
e.printStackTrace ();
} // catch

} // main
} // class

56 DB2 Java Stored Procedures: Learning by Example


Chapter 4. System setup

This chapter details the prerequisites for the deployment of Java stored
procedures on the major application platforms, together with an overview of
the steps necessary to enable this support, and some of the common
problems you may encounter.

4.1 OS/390 system setup


In this section we summarize the requirements to run a compiled Java stored
procedure in an OS/390 environment. As mentioned before, at the first
delivery of Java stored procedures on OS/390, DB2 provides support only for
compiled Java stored procedures.

In the following sections we cover the prerequisite code levels, install tasks,
design library structure, setting up the Recoverable Resource Manager
Services (RRS) attachment facility and the OS/390 Workload Manager
(WLM) environment.

The compilation of Java stored procedures into native OS/390 instructions is


done using the VisualAge for Java Enterprise Toolkit for OS/390 (ET/390)
through the use of the High Performance Java Compiler (HPJ) component of
the ET/390. We document how to install HPJ JDBC/SQLJ drivers, setting up
the JAVAENV data set, and verifying the contents of the JDBC cursors and
SQLJ properties files. In addition, we discuss some common setup issues.

4.1.1 Prerequisites
To be able to use Java stored procedures on the S/390 platform, the following
prerequisites exist:
• OS/390 V2 R6 or above, with UNIX Systems Services (USS) enabled.
• Java for OS/3901 , implementing JDK 1.1.8 (a non-priced OS/390 feature
that can be downloaded from the Web or ordered directly from IBM).

1
It is possible to remove this prerequisite, provided you perform application development and some of your program
preparation steps on another platform. However, we assume in this book that if you are developing stored procedures for
the OS/390 platform, you will want to develop and prepare them there as well.

© Copyright IBM Corp. 2000 57


DB2 UDB for OS/390 Version 5 and above. For Version 5 and 6 with JDBC,
SQLJ and Java stored procedure support are enabled, as shown in Table 5.
Table 5. DB2 for OS/390 Java APAR enhancements

Version Feature APAR / PTF

Version 5 JDBC and SQLJ driver PQ36643/UQ43898


including support for
Visual Age Java'
Java Stored Procedures PQ31845/ UQ46170
PQ31845/UQ46171

Version 6 JDBC and SQLJ driver PQ36644/UQ43899


including support for
Visual Age Java'
Java Stored Procedures PQ31846/ UQ46114
PQ31846/UQ46115

• The prerequisites for VisuaAge for Java Enterprise Edition for OS/390 are
in Table 6.
Table 6. VisualAge for Java Enterprise Edition for OS/390

Version Feature APAR / PTF

Version VisualAge for Java, APAR PQ38178/ UQ43439 Rel. 2.01


2.0 Enterprise Edition for APAR PQ38179/UQ43443 Rel. 2.02
OS/390

Use Of Type 2 Drivers


Implementation of SQLJ support for both Version 5 and Version 6 will
result in JDBC Type 2 drivers being installed.
For the OS/390 platform and Java stored procedure support, the Type 2
drivers must be made available. This is done when you apply the APAR
PQ36644. You can only support one JDBC driver at a time in OS/390,
so the JDBC Type 1 driver will not exist in your system anymore!

• The Enterprise Toolkit for OS/390, part of VisualAge for Java, Enterprise
Edition. This product provides the HPJ compiler needed for Java stored
procedures on the OS/390 platform.
• OS/390 Recoverable Resource Services (RRS) and Workload Manager
(WLM) Java stored procedures can only be run in a WLM-established
stored procedure address space, so implementation of OS/390
Recoverable Resource Services (RRS) is necessary.

58 DB2 Java Stored Procedures: Learning by Example


We recommend that you apply the USS APAR OW41492, which significantly
improves performance of the “multi-context” support in the Type 2 driver.

4.1.2 Installation tasks


To prepare your OS/390 environment to execute Java stored procedures, you
should perform the following tasks.

It is assumed that all of the products and services listed in the previous
section on prerequisites have been installed and properly configured.

JDBC Support
Part of the install process for JDBC support involves running the db2genJDBC
utility, which creates 4 generic DBRMs for use by JDBC programs (and
JDBC stored procedures).

We recommend that you bind these 4 DBRMs into DB2 packages


belonging to a suitably named collection (we used DSNJDBC). This makes
it simpler to ensure that these DB2 packages are picked up at execution
time, as described in 9.1, “DB2 plans and packages” on page 167).

1. Design your library structure and naming standards. Java stored


procedure support requires libraries to be set up both within the USS and
the native OS/390 environment, and your job will be made much easier if
you decide upon these in advance.
2. Tailor the .profile script for the stored procedure developers, to ensure
that the necessary USS environment variables are being defined.
3. Set up the RRS environment for support of WLM-established stored
procedures (if you have not already done so).
4. Set up a new WLM application environment for Java stored procedures,
and the associated address space JCL.

WLM environments
While it is not strictly necessary for you to do so, we strongly advise you to
set up at least one separate WLM application environment and JCL
procedure to handle your Java stored procedures.

5. Create high performance Java versions of the JDBC/SQLJ drivers.

Chapter 4. System setup 59


6. Set up the JAVAENV data set, and add an associated DD card to the WLM
stored procedure address space JCL. JAVAENV contains the USS
environmental variables (such as CLASSPATH and LIBPATH) that will be
allocated within the WLM stored procedure address space.
7. Tailor the contents of the SQLJ properties file and cursors file, to ensure
that correct values are being set.

These tasks are described in more detail in the sections that follow.

4.1.3 Step 1: Design library structure


Java stored procedure support requires a fairly complex network of libraries
to be set up both within the USS and the native OS/390 environment, and
your job will be made much easier if you decide upon these libraries in
advance. It is recommended that you set up one hierarchical file system
(HFS) per DB2 subsystem or data sharing group. Table 7 provides a summary
of the USS libraries required, together with the settings we used in our
environment.
Table 7. Sample USS library structure

Type Description Sample Name

USS HPJ base libraries. /USR/LPP/HPJ/LIB


Contains all HPJ libraries (installed as part of
ET/390 — see 4.1.1, “Prerequisites” on page 57).

Must be in included in CLASSPATH environment


variable of the Java SP environment data set (see
Figure 8 on page 70).

SQLJ/JDBC base libraries. /USR/LPP/DB2/DB2nnn/CLASSES


Contains all SQLJ and JDBC classes, libraries and /USR/LPP/DB2/DB2nnn/BIN
binaries. Delivered as part of base SQLJ/JDBC /USR/LPP/DB2/DB2nnn/LIB
support (installed as part of SQLJ support — see where nnn is release level (510, 610,
4.1.1, “Prerequisites” on page 57). and so on).
See “set environmental variables
The LIB directory must be in included in LIBPATH for SQLJ/JDBC” on
environment variables of the Java SP environment Page 65, and “include the HPJ and SQLJ
data set (see Figure 8 on page 70). libraries in the environmental
variables ” on Page 65.

60 DB2 Java Stored Procedures: Learning by Example


Type Description Sample Name

Links directory. /u/ssss/links/


Contains all USS links to PDSE load libraries that where ssss is the DB2 subsystem ID
contain compiled Java routines. or data sharing group attached name.

Must be in included in LIBPATH environment variable


of the Java SP environment data set (see Figure 8
on page 70).

Must be the HOME path for the Java SP procedure


owner (see Figure 7 on page 66).

The SQLJ properties file:


db2sqljjdbc.properties and the cursor
definitions file db2jdbc.cursors must also be
installed in this directory.

The SQLJ properties file must be referenced by the


DB2SQLJPROPERTIES environment variable (see
“define where the SQLJ run-time properties
file is located” on Page 64).

Serialized profiles directory. /u/ssss/ser/


Contains all of the serialized profiles generated by where ssss is the DB2 subsystem ID.
the sqlj precompiler (used as input to db2profc,
the profile customizes).

The JDBC serialized profile:


DSNJDBC_JDBCProfile.ser, should be moved in
this directory.

Must be included in the CLASSPATH environment


variable of the Java SP environment data set (see
Figure 8 on page 70).

Chapter 4. System setup 61


Table 8 provides a summary of the OS/390 libraries required, together with
the settings we used in our environment.
Table 8. Sample OS/390 library structure

Type Description Sample Name

OS/390 SQLJ load library. Site specific. One library per


Contains HPJ compiled versions of JDBC/SQLJ subsystem recommended.
classes. See Figure 4.

Application load library. Site specific. One library per


Contains HPJ compiled versions of Java stored subsystem/testing level
procedure code. See Figure 5. recommended.

JAVAENV data set. Site specific. One library per WLM


Contains settings for Java environment variables environment recommended.
used within the stored procedures address space.
See Figure 6.

DBRM library. Site specific. One library per


Contains DBRMs generated by db2profc step for subsystem/testing level
SQLJ procedures. See DB2SQLJDBRMLIB recommended.
parameter in Figure 9 on page 72.

The SQLJ load library must be defined as a PDSE library. Figure 4 shows an
example of this data set definition:

Data Set Name . . . : HPJ.SDSNJDBC.DBZ2


General Data
Management class . . : **None**
Storage class . . . : **None**
Volume serial . . . : TOTDB1
Device type . . . . : 3380
Data class . . . . . : **None**
Organization . . . : PO
Record format . . . : U
Record length . . . : 0
Block size . . . . : 24760
1st extent tracks . : 5
Secondary tracks . : 5
Data set name type : LIBRARY

Figure 4. SQLJ load library — data set definition

The application load library must be defined as a PDSE library. Figure 5


shows an example of this data set definition.

62 DB2 Java Stored Procedures: Learning by Example


Data Set Name . . . : USER.HPJSP.PDSE.DBZ2
General Data
Management class . . : **None**
Storage class . . . : **None**
Volume serial . . . : TOTDB1
Device type . . . . : 3380
Data class . . . . . : **None**
Organization . . . : PO
Record format . . . : U
Record length . . . : 0
Block size . . . . : 24760
1st extent tracks . : 5
Secondary tracks . : 5
Data set name type : LIBRARY

Figure 5. Application load library — data set definition

The JAVAENV data set must be defined as a variable blocked sequential data
set, as in Figure 6 below:

Data Set Name . . . : HPJ.JAVAENV


General Data
Volume serial . . . : TOTTSY
Device type . . . . : 3390
Organization . . . : PS
Record format . . . : VB
Record length . . . : 255
Block size . . . . : 4096
1st extent tracks . : 2
Secondary tracks . : 2

Figure 6. JAVAENV file — data set definition

4.1.4 Step 2: Provide .profile for users


Use of HPJ, SQLJ and JDBC requires some environmental variables to be
set. By creating a standard .profile script that is automatically executed by
developers as they login to USS, you can ensure that these variables are
being set to their correct values.

Chapter 4. System setup 63


Use of .profile scripts
In the UNIX world it is standard practice to establish a .profile script for
every USS user. It is equivalent to the ISPF logon proc, in that it
establishes the initial environment for the user. Some shops may wish to
create a centralized script that establishes the basic DB2 environment.
Each user’s .profile would then execute that centralized script within their
.profile. If a centralized script is used, be sure to ‘dot’ the command within
the .profile.

For example, if the centralized script is called /usr/apps/db2/db25/profile,


then each .profile script would execute it using the following
command.....notice the period followed by a space followed by the
script.....this executes the script within the current process instead of
forking a separate process:
. /usr/apps/db2/db25/profile

Here is a example of the .profile used for our sample users. (We did not use
a centralized script).
#----------------------------------------------------------------------
# Profile for the common EC environment to compile SQLJ and JDBC code
#----------------------------------------------------------------------
echo off
cls
I=0
while test $I = 0
do
echo "5 For DB21 V5 properties file"
echo "6 For DBZ2 V6 properties file"
echo "enter number for DB2 properties file"
read DBPROP
case $DBPROP in
5) I=1
export SSID=DB21
export SSIDHFS=db2510
SSIDLIB=DB2V510;;
6) I=1
export SSID=DBZ2
export SSIDHFS=db2610
SSIDLIB=DSN610;;
*) echo "Huh? Did not enter 5 or 6 entered > $DBPROP";;
esac
done

echo "SSID = $SSID SSIDHFS = $SSIDLIB SSIDLIB = $SSIDHFS"


#------------------------------------------------------
# define where the SQLJ run-time properties file is located
#------------------------------------------------------
export DB2SQLJPROPERTIES=/u/$SSID/links/db2sqljjdbc.properties

##### Added for tso -t from telnet

64 DB2 Java Stored Procedures: Learning by Example


# Assign the DD names to allocate
#
export TSOALLOC=sysexec
#
# Allocate the OpenMVS EXEC data set to SYSEXEC
#
export sysexec=SYS1.OS390.EXEC
#end# Added for tso -t from telnet

#------------------------------------------------------
# set environmental variables for HPJ
#------------------------------------------------------
export IBMHPJ_HOME="/usr/lpp/hpj"
export IBMHPJ_RTL="CEE.SCEELKED:CEE.SCEELKEX:CEE.SCEEOBJ:CEE.SCEECPP"

#------------------------------------------------------
# set environmental variables for DSNAOINI data set
#------------------------------------------------------
export DSNAOINI=DB2V610.$SSID.DSNAOINI

#------------------------------------------------------
# set environmental variables for SQLJ/JDBC
#------------------------------------------------------
export SQLJ_HOME=/usr/lpp/db2/$SSIDHFS
export JDBC_HOME=/usr/lpp/db2/$SSIDHFS
#

# Java_HOME is where the current JDK is installed


#export Java_HOME=/usr/lpp/Java/J1.1

# Java_COMPILER is used to turn the JIT OFF


export Java_COMPILER=

# Tell make and others we are NOT using Optimized versions


unset SQLJ_OPTIMIZED

#------------------------------------------------------
# include the HPJ and SQLJ libraries in the environmental variables
#------------------------------------------------------
export CLASSPATH=.:$JDBC_HOME/classes/db2sqljclasses.zip:\
$Java_HOME/lib/classes.zip:\
$SQLJ_HOME/classes/db2sqljruntime.zip:\
$SQLJ_HOME/classes/db2jdbcclasses.zip:\
/u/$SSID/links:\
/u/$SSID/ser:\
$Java_HOME/lib:$IBMHPJ_HOME/lib

export PATH=$PATH:$SQLJ_HOME/bin:$IBMHPJ_HOME/bin:$PATH

export LIBPATH=$SQLJ_HOME/lib:$JDBC_HOME/lib:\
$Java_HOME/lib/mvs/native_threads:$IBMHPJ_HOME/lib:$LIBPATH

#
export STEPLIB=$SSIDLIB.sdsnload.test:$STEPLIB ix
export STEPLIB=$SSIDLIB.sdsnload:$STEPLIB
export STEPLIB=$SSIDLIB.sdsnlink:$STEPLIB

export LD_LIBRARY_PATH=.:$SQLJ_HOME/bin:$JDBC_HOME/lib:\

Chapter 4. System setup 65


$Java_HOME/lib/mvs/native_threads

#------------------------------------------------------
# print out Java and hpj versions
#------------------------------------------------------
Java -version
hpJava -version
export EDITOR=vi
set -o vi

echo '*---------------------------------------------------------------'
echo ' profile executed for HPJ, Java and SQLJ '
echo '*---------------------------------------------------------------'

4.1.5 Step 3: Setting up RRS


OS/390 Recoverable Resource Services (RRS) is a feature of MVS that
coordinates two-phase commit processing of recoverable resources in an
MVS system. The RRS attachment is required for stored procedures that run
in a WLM-established address space. If you do not have RRS active in your
OS/390 system, see Appendix C, “OS/390 Recoverable Resource Services
(RRS)” on page 329.

4.1.6 Step 4: Define WLM stored procedure address space


If you do not have WLM-established stored procedures active, see Appendix
D, “Define WLM stored procedure address space” on page 331.

To add Java support to the WLM-established address space you will have to
add these two steps. First, assign a RACF STC userid to the procedure; and
second, modify the JCL procedure for the Java required files.

4.1.6.1 RACF STC userid


Assigning a RACF STC userid to the Java WLM stored procedure address
space is required. For Java stored procedures, you will also need to assign a
home directory to the environment variable HOME of user ID assign to it. This
will be the links directory that contains all USS links to PDSE load libraries
that contain compiled Java routines. Figure 7 shows the RACF command that
you should use to do this:

alu db2stcZ2 omvs(home(/u/DBZ2/links))

Figure 7. RACF command to assign home directory

Then you create a profile in the STARTED class names DBZ2Java.* for the
WLM Java address space, as follows:

66 DB2 Java Stored Procedures: Learning by Example


rdefine started
DBZ2Java.* stdata(user(db2stcz2)group(sys1)privileged(no)trace(no)trusted(no))

Finally, since STARTED is a RACLISTed class, you must do a RACF refresh


using the following command:
setropts raclist(started) refresh

4.1.6.2 JCL procedure of a Java WLM-established address space


Here is an example of a JCL procedure for starting the WLM-established
address space with Java support:
//DBZ2Java PROC RGN=0K,APPLENV=WLMJavaDBZ2,DB2SSN=DBZ2,
// NUMTCB=1,TME=NOLIMIT
//DBZ2Java EXEC PGM=DSNX9WLM,REGION=&RGN,TIME=&TME,
// PARM=’&DB2SSN,&NUMTCB,&APPLENV’
//STEPLIB DD DISP=SHR,DSN=DB2V610V.RUNLIB.LOAD
// DD DISP=SHR,DSN=SYS1.SCEERUN
// DD DISP=SHR,DSN=DSN510.SDSNLOAD
// DD DISP=SHR,DSN=USER.HPJSP.PDSE.DBZ2 #1
// DD DISP=SHR,DSN=HPJ.SDSNJDBC.DBZ2 #2
// DD DISP=SHR,DSN=HPJ.SHPJMOD #3
// DD DISP=SHR,DSN=HPJ.SHPOMOD #4
//JAVAENV DD DISP=SHR,DSN=HPJ.JAVAENV.DBZ2 #5
//JSPDEBUG DD SYSOUT=A #6
//DSSPRINT DD SYSOUT=A
//UTPRINT DD SYSOUT=A
//SYSPRINT DD UNIT=SYSDA,SPACE=(4000,(20,20),,,ROUND)
//SYSUDUMP DD SYSOUT=A

This procedure contains the following statements:


1. DD statement for the high performance Java compiled stored procedure
PDSE load library.
2. DD statement for the high performance Java JDBC/SQLJ library.
3. DD statement for the high performance Java SHPJMOD library.
4. DD statement for the high performance Java SHPOMOD library.
5. JAVAENV DD statement for the work load managed Java stored procedure
runtime environment options. This data set applies to the entire WLM
environment, not just individual stored procedures. See 4.1.8, “Step 6: Set
up the JAVAENV data set” on page 69 for more details.
JSPDEBUG DD statement for Java stored procedure debug information. This
is a critical source of information when debugging Java stored procedures in
an S/390 environment (see 6.5, “Debugging” on page 103)

Chapter 4. System setup 67


4.1.7 Step 5: Install JDBC/SQLJ driver for OS/390
You need to use the Java high performance compiler (HPJ) to compile the
JDBC/SQLJ Driver for OS/390 DB2 into an OS/390 executable that can be
used within the WLM address space. This is done with the shell script
“installVAJDLLs”, that can be found in /usr/lpp/db2/db2610.

Create a subdirectory “install” in the rood directory /usr/lpp/db2/db2610 and


copy the script installVAJDLLs to this directory. Modify this script for your
environment. Here are the modifications we made to it.

We customized the installation root directory of the JDBC/SQLJ driver


installation as follows:
export IBMJDBC_HOME=/usr/lpp/db2/db2610

We modified the PDSE to hold the JDBC/SQLJ driver as follows:


-o "//'HPJ.SDSNJDBC.DBZ2(DSNAQDLL)'" \

We modified the external HFS link to PDSE member DLL to our /u/DBZ2/links
directory as follows:
rm -f /u/DBZ2/links/libdb2os390vaj.so
ln -e DSNAQDLL /u/DBZ2/links/libdb2os390vaj.so

We modified the build PDSE Java DLL for the output as follows:
-o "//'HPJ.SDSNJDBC.DBZ2(DSNAQJLL)'" \

and the links as follows:


-t /u/DBZ2/links

HPJ Storage Requirements


This step requires a large amount of storage, so when you log onto TSO,
make sure you have set the logon region size to 1100000.

Failure to do so will result in messages such as:


HPJ3115(S) Unable to fetch module "HPJ3TBY".

After running “installVAJDLLs”, the directory /u/DBZ2/links will contain the


following:
/u/DBZ2/links/

68 DB2 Java Stored Procedures: Learning by Example


COM
ibm
libdb2os390vaj.so -> DSNAQDLL
sqlj
sqlj.jll -> DSNAQJLL
/u/DBZ2/links/sqlj
mesg.jll runtime runtime.jll util
/u/DBZ2/links/sqlj/runtime
error.jll profile profile.jll ref.jll
/u/DBZ2/links/sqlj/runtime/profile
ref.jll util.jll
/u/DBZ2/links/sqlj/util
io.jll

Also, the PDS library HPJ.SDSNJDBC.DBZ2 will contain:


sqlj.jll alias of DSNAQJLL
DSNAQDLL
DSNAQJLL

Applying maintenance
This step must be repeated when any related maintenance has been
applied to the system that effects the JDBC/SQLJ drivers.

In addition, there are other considerations that you have to keep in mind;
see 4.1.11, “Maintenance considerations” on page 75.

4.1.8 Step 6: Set up the JAVAENV data set


You need to define a data set to hold the Java environment statements to be
used by Java stored procedures running within your WLM established stored
procedures address space. Depending upon how you intend to segregate
your stored procedure workloads, we recommend that you have a different
JAVAENV data set for each WLM application environment.

See 4.1.3, “Step 1: Design library structure” on page 60 for details of the data
set attributes for the JAVAENV data set.

4.1.8.1 Data set composition


The contents of this data set are described below.

LIBPATH
The environment variables point to load libraries.

Chapter 4. System setup 69


SQLJ contains sqlj .so dynamic load libraries.

JDBC contains jdbc .so dynamic load libraries.

HPJ contains hpj .so dynamic load library.

The USS directories containing these libraries must be referenced in the


LIBPATH environment variables. See Figure 8 on page 70 on how LIBPATH is
used.

CLASSPATH
CLASSPATH contains all the directories that contain the required SQLJ and
JDBC class files .zip:

CLASSPATH must also point to the directory used to store your SQLJ serialized
profiles and JDBC cursors and SQLJ properties files (see 4.1.9, “Step 7:
Verify JDBC cursor and SQLJ properties files” on page 71).

Finally, the location where you will store the external links for your stored
procedure modules must also be referenced.

TZ
TZ is used to set the local time zone. It is an optional parameter.

4.1.8.2 Sample contents


Figure 8 shows an example of the contents of a JAVAENV data set.

ENVAR("CLASSPATH=.:/usr/lpp/hpj/lib:/u/DBZ2/ser",
"LIBPATH=/usr/lpp/hpj/lib:/usr/lpp/db2/db2610/lib:/u/DBZ2/links")

Figure 8. JAVAENV data set — contents

Note: This data set is supplied on the CD-ROM in directory SAMPLES\S390


UTILITIES\INSTALLATION\JAVAENV. See Appendix E, “Using the additional
material” on page 347 for more details.

70 DB2 Java Stored Procedures: Learning by Example


Note:
The current restriction for the total length of the ENVAR variable is 255
characters. You must be careful when structuring your libraries to ensure
that this limit is not exceed.

No error messages are issued if the limit is exceeded: any characters


beyond position 255 will be ignored, which may lead to errors such as
failure to load classes.

4.1.9 Step 7: Verify JDBC cursor and SQLJ properties files


The JDBC cursors file and the SQLJ properties file contain critical
configuration parameters that will affect your environment. Sample versions
of each of these files will be created as part of the base JDBC/SQLJ driver
installation process, but they are likely to require some tailoring for your
environment.

4.1.9.1 JDBC cursors file


The JDBC cursors file contains a definition of the cursors to be used by JDBC
programs running within the USS environment.

A sample cursor definition file called db2jdbc.cursors is created as part of the


base JDBC/SQLJ installation. This contains 250 cursor definitions (125
cursors WITH HOLD and 125 without). This file can be amended (or an
alternative version defined) if you wish to have more cursors available, or to
rename the cursors that JDBC will use.

Because the cursors file is used as input to the db2genJDBC utility that creates
the generic JDBC DBRMs used by all JDBC programs, you need to re-run
db2genJDBC after amending the cursors file. Refer to 4.1.11, “Maintenance
considerations” on page 75 for some further actions you should take after
doing this.

4.1.9.2 SQLJ properties file


The SQLJ run-time properties file contains parameters that specify any
program preparation or run-time information that is not in environmental
variables. Use the environmental variable DB2SQLJPROPERTIES in your . PROFILE
to point to this file. For Example:
export DB2SQLJPROPERTIES=/u/DBZ2/links/db2sqljjdbc.properties

Chapter 4. System setup 71


Using multiple SQLJ properties files
As the SQLJ properties file contains information such as the plan used for
all SQLJ/JDBC client programs that execute under USS, you may want to
consider defining multiple properties files (for different groups of users, or
different applications, for instance) and tailoring your .profile scripts to
point to each as necessary.

See 9.1.5, “Usage recommendations” on page 170 for more details.

Here is a sample of the contents of an SQLJ properties file. This sample can
also be found in file DB2SQLJDBC.PROPERTIES on the CD-ROM in directory
SAMPLES\S390 UTILITIES\INSTALLATION\. See Appendix E, “Using the additional
material” on page 347 for more details.

DB2SQLJSSID=DBZ2
#DB2SQLJ_TRACE_FILENAME=/tmp/mytrc
#DB2SQLJ_TRACE_BUFFERSIZE=4096
DB2SQLJPLANNAME=SQLJPLAN
DB2SQLJATTACHTYPE=RRSAF
DB2SQLJJDBCPROGRAM=DSNJDBC
DB2SQLJDBRMLIB=SG245945.DBRMLIB.DBZ2

Figure 9. DB2SQLJDBC.PROPERTIES — contents

These parameters are discussed in the sections that follow. For a full
explanation of these and other parameters, please refer to the Application
Programming Guide and Reference for Java, SC26-9018.

DB2SQLJSSID
Specifies the name of the DB2 subsystem to which a JDBC or an SQLJ
application connects.

DB2SQLJPLANNAME
Specifies the name of the plan that is associated with JDBC and SQLJ
serialized profile. This is used by Java clients that run in the USS
environment and JDBC dynamic SQL Java stored procedures programs.

DB2SQLJATTACHTYPE
Specifies the attachment facility that a JDBC or an SQLJ application
program uses to connect to DB2.

DB2SQLJJDBCPROGRAM
Specifies the name of a JDBC connected profile that is used by SQLJ
run-time environment.

72 DB2 Java Stored Procedures: Learning by Example


DB2SQLJDBRMLIB
Specifies the fully-qualified name of the OS/390 partition data set into
which DBRMs are placed. DBRMs are generated by the creation of a
JDBC profile and the customization step of the SQLJ program preparation
process.

4.1.10 Data sharing considerations


In a DB2 OS/390 data sharing environment you will have to consider how you
define your WLM application environment and set up your USS HFS.

4.1.10.1 WLM application environment


When defining you application environment to WLM to run in a data sharing
group, use the symbolic parm &IWMSSNM for the DB2SSN parm of your JCL
procedure. This will allow you to use one JCL procedure for the application
environment for all members of the data sharing group. Example:
Start parameters .. DB2SSN=&IWMSSNM,NUMTCB=2,APPLENV='WLMJavaDBZ2'

4.1.10.2 Data sharing and HFS


In a data sharing environment, you are sharing the catalog, directory, and all
databases among all members of the group. You will only have one copy of
these data sets in the sysplex environment. However, the USS HFS is unique
for each member of the sysplex under OS/390 V2 R8.
*** Note ***
With OS/390 V2 R9 and above, there will be shared HFS in a sysplex.

OS/390 V2 R8 will require you to do some special planning on how to set up


and use the HFS for each member. You will have to duplicate the HFS
directory structure in each member of the sysplex. This will allow you to bring
any DB2 member of the group up in any OS/390 sysplex member and to run
the Java store procedure in the other members of the group. Using the group
name for the higher directory level for the links and user directories will make
it easier to duplicate and to migrate to OS/390 V2 R9 and above. This will
allow you to use the same HOME path name for the WLM stored procedure
address space and the same owner name across the sysplex.

The following are steps that you will have to do to duplicate the work done on
one sysplex member in each other sysplex member or members that run DB2
members of the data sharing group:
• Follow “Step 1: Design library structure” on page 60.
• Follow “Step 2: Provide .profile for users” on page 63.

Chapter 4. System setup 73


• Follow “Step 5: Install JDBC/SQLJ driver for OS/390” on page 68.
• Follow “Step 7: Verify JDBC cursor and SQLJ properties files” on page 71.
• Transmit all of the related Java program class files over to the other
sysplex member or members HFS. This is input to the HPJ compiler to
create the LINKs.
• You will need to run the HPJ compiler over on the other sysplex member or
members to create the LINKs into the /u/DB2Groupname/links path.
• This will restrict you to do all of your Java development on only one
sysplex member within the sysplex.

Figure 10 shows a diagram of a DB2 data sharing group called DBZ1 with two
members, DBZ1 and DBZ2. The WLM application environment for the Java
stored procedures that run in this group are set up to use a started task
procedure named DBZ1JAVA. The RACF owner for this STC is the procedure
name DBZ1JAVA with an OMVS Home path set to /u/DBZ1/links. You can see
that each OS/390 member in the sysplex has its own OS/390 USS HFS and
shares the same OS/390 DASD.

74 DB2 Java Stored Procedures: Learning by Example


MVSPLEX V2 R8 DB2 DS Group DBZ1
os/390 Members
Shared Dasd DBZ1
DBZ1 Cat & Directory DBZ2
DBZ1 Tables
DBZ1 Logs
DBZ1 BSDS
HPJ.JAVAENV.DBZ!
HPJ.SQLJ.PDSE
USER.JAVA.PDSE.DBZ1

MVS1 MVS2
DBZ1MSTR STC
DBZ2MSTR STC
DBZ1DBM1 STC
DBZ2DBM1 STC
DBZ1IRLM STC
DBZ2IRLM STC
DBZ1JAVA DBZ1JAVA
DBZ1JAVA DBZ1JAVA
Home=/u/DBZ1/links
Home=/u/DBZ1/links

OS/390 USS OS/390 USS


HFS HFS
/u/DBZ1/links /u/DBZ1/links
/u/DBZ1/ser /u/DBZ1/ser
/u/JAVA/Package /u/JAVA/Package
/usr/lpp/db2/db2610/classes /usr/lpp/db2/db2610/classes

Figure 10. DB2 data sharing group with Java stored procedures

4.1.11 Maintenance considerations


From time to time, IBM may issue maintenance for the JDBC drivers requiring
the drivers to be prepared again, using the db2genJDBC2 utility supplied for the
purpose. If this occurs, you must perform some important follow-up actions
once db2genJDBC has been successfully executed:
• Re-create the high performance Java compiled versions of the
JDBC/SQLJ drivers, as described in 4.1.7, “Step 5: Install JDBC/SQLJ
driver for OS/390” on page 68.

2
The db2genJDBC utility resides in the bin subdirectory of the USS directory where your SQLJ/JDBC support has been
located (for example, /usr/lpp/db2/db2610/bin). It is used at the time JDBC is installed, to generate the generic
JDBC DBRMs that will be needed by all JDBC stored procedures and clients. See the Application Programming Guide
and Reference for Java , SC26-9018 for more details.

Chapter 4. System setup 75


• Re-bind all DB2 packages that use the generic JDBC DBRMs (DSNJDBC1,
DSNJDBC2, DSNJDBC3 and DSNJDBC4).

4.1.12 Some common setup issues


The paragraphs below cover some of the more common errors that we
encountered during the setup process.

4.1.12.1 Out of storage — HPJ compile JDBC and SQLJ classes

Symptom:

An out-of-storage error message is issued during HPJ compile:

Class missing for error: Java/lang/OutOfMemoryError

Possible resolution:
• Increase TSO region size if logged on via TSO. We recommend a value of
1100000.

4.1.12.2 Unable to load HPJ module during HPJ compile

Symptom:

A message is issued during HPJ compile indicating that an HPJ module


cannot be fetched:
HPJ3115(S) Unable to fetch module "HPJ3TBY".

Possible resolution:
• Increase TSO region size if logged on via TSO. We recommend a value of
1100000.

4.1.12.3 00E79107 Unable to find user class

Symptom:

The reason code 00E79107 is encountered when attempting to invoke a Java


stored procedure.

Additional SQLCA information provided with the message has the name of
the class that could not be found.

Possible resolution:

76 DB2 Java Stored Procedures: Learning by Example


• Make sure that all classes have been bound into the PDSE data set.
• Make sure external links are to packages.

4.1.12.4 Unable to find user method

Symptom:

00E79107 or 00E79108 reason code on -471 when calling a complied Java


stored procedure. Additional SQLCA information provided with the message
has signature provided by SQL types.

Possible resolution:
• Make sure the PARAMETERS column maps to JDBC types.
• Check the Java signature using Javap -s -private <classname>

Remember, result sets are in the signature, but not in the PARAMETERS
column.

4.1.12.5 CEE5207E The signal SIGABRT was received

Symptom:

This message is printed out in the Java SP address space and the client
receives a -965. SQLCODE back.

invoking class: ACMEJOS/Add_customer, method: add_customer

Add_customer: start - JDBC version

Add_customer: getConnection

CEE5207E The signal SIGABRT was received.

Possible resolution:

Either the db2jdbc.cursors or db2sqljjdbc.properties file was not found in the


HOME path of the Java stored procedure environment (/u/DBZ2/links).
• Make sure these two files are included in the HOME PATH.

4.1.12.6 ICH408I USER(uuuu) GROUP(ggggg) NAME(nnnn) 928

Symptom:

Chapter 4. System setup 77


This message is shown on the OS/390 console log. The client application
receives a SQLCODE of -965 and the Java stored procedure shows an error
loading the JDBC driver.
PROC= DBZ2Java ASID= 0085 WLM_ENV= WLM_Java_DBZ2
DSNX906I =DBZ2 DSNX9CAC PROCEDURE JS_ADD_CUSTOMER 927
TERMINATED ABNORMALLY. THE PROCEDURE HAS BEEN STOPPED. ASID= 0085
WLM_ENV= WLM_Java_DBZ2
ICH408I USER(DB2STC ) GROUP(SYS1 ) NAME(Java DB2 STCS ) 928
/u/DBZ2/links CL(DIRSRCH ) FID(01E3E2D4E2F4F100690C000000000003)
INSUFFICIENT AUTHORITY TO LOOKUP
ACCESS INTENT(--X) ACCESS ALLOWED(GROUP ---)
- --TIMINGS (MINS.)--

Possible resolution:

The HFS /u/DBZ2 was not built with the proper permission setting to allow
search of directories down from /u/DBZ2. Make sure that the directory is set
with 755.

To make sure your directories are set at 755, use the UNIX command ls -l
to verify that it is set, as follows:
drwxr-xr-x 2 DB2RES3 DBZ2 8192 Mar 16 13:44 aa
• Use the chmod command to set the permissions to 755 on directory DBZ2,
executing the following UNIX commands:
- cd /u
- chmod 755 DBZ2
- ls -l

4.2 Windows NT system setup


Establishing Windows NT for Java stored procedures is considerably easier,
as compared to the method used for the OS/390 environment.

4.2.1 Prerequisites
• Windows NT Version 4 or above
• A JDK — any one of the following will suffice:
- The Java Development Kit (JDK) and Java Runtime Environment (JRE)
for Win32 (version 1.1.7 or above) from IBM. These are shipped with
DB2 for Windows NT.
- The Java Development Kit (JDK) Version 1.1 or later for Win32 from
Sun Microsystems
- Microsoft Software Developer's Kit for Java, Version 3.1.

78 DB2 Java Stored Procedures: Learning by Example


4.2.2 Installation tasks
To prepare your Windows NT environment to execute Java stored procedures,
you should perform the following tasks:
1. Install the DB2 UDB SDK for Windows NT. This includes the Java JDK
1.1.8, as well as the necessary DB2 data access drivers and utilities to
prepare DB2 Java programs for execution.
2. Ensure that the PATH system variable includes the directory that contains
the JDK binaries (usually c:\sqllib\Java\jdk\bin). The PATH system
variable can be set from the Environment tab of the Windows NT Control
Panel System Properties applet.
3. Update the jdk11_path DBM configuration parameter to point to the
location of the JDK you are using (probably c:\SQLLIB\Java\jdk if you are
using the IBM JDK supplied with DB2). For example:
db2 update dbm cfg using JDK11_PATH c:\SQLLIB\Java\jdk

A comprehensive set of sample applications is supplied with DB2, and you


may want to try running some of these before writing your own code to verify
that the environment is properly configured. The samples can be found in the
sqllib\samples\Java directory.

4.2.3 Some common setup issues


The paragraphs below cover some of the more common errors encountered
during the setup process.

4.2.3.1 Path or file name "Java" not found

Symptom:

The following error message is produced when you try to use any of the DB2
preparation utilities (SQLJ, DB2PROFC, etc.):

Error in sqlj: path or file name "Java" not found.

Possible resolution:
• Ensure that Windows NT PATH variable includes the directory that
contains the JDK binaries (usually c:\sqllib\Java\jdk\bin). See 4.2.2,
“Installation tasks” on page 79 for more details.
• Try building a simple Java application at the DOS command level to make
sure that Java works. Simple Java examples can be found on Web sites
that introduce the language to novice Java programmers.

Chapter 4. System setup 79


4.3 UNIX system setup
As for Windows NT, establishing UNIX for Java stored procedures is
considerably easier than for OS/390. We used AIX for our testing. Other UNIX
platforms should be similar, but be sure to read the platform-specific
documentation.

4.3.1 Prerequisites
For AIX, use JDK 1.1.8 Fixpak 4 or later. For other UNIX variations, obtain the
most recent JDK that has been tested by IBM as being compatible. The list of
JDKs can be found at:
http://www-4.ibm.com/software/data/db2/Java/index.html

4.3.2 Installation tasks


Install the JDK. On AIX, this must be installed by the system administrator
using smit or installp or an equivalent system tool. The JDK may be installed
in a location different than the default location. This may be necessary due to
multiple applications sharing the same machine requiring different releases of
the JDK.

Confirm that DB2 uses the JDK you installed. To change the location, use the
following command (in this case, setting it to /usr/jdk_base):
db2 update dbm cfg using JDK11_PATH /usr/jdk_base

The userid owning DB2 must establish some environment variables to tell
DB2 where the JDBC and SQLJ runtime support can be found. This can be
done in the .profile file. This includes the following tasks:
• Establishing the general DB2 environment variables, typically done by
executing the sqllib/db2profile, which is in the directory of the install
userid.
• Setting Java_HOME.
• Setting CLASSPATH to include the classes and ZIP files containing JDBC
and SQLJ functionality.
• Setting the PATH variable to use the bin directory for DB2.
• Setting LIBPATH and LD_LIBRARY_PATH to use the libraries shipped with
DB2.

80 DB2 Java Stored Procedures: Learning by Example


The following is a sample from our test environment:
if [ -f sqllib/db2profile ]; then
. sqllib/db2profile
fi

export Java_HOME=/usr/jdk_base
export DB26=/usr/lpp/db2_06_01
export DB26J=$DB26/Java

export CLASSPATH=.:$DB26J/db2Java.zip:\
$Java_HOME/lib/classes.zip:\
$Java_HOME/lib:\
$DB26J/runtime.zip:\
$DB26J/sqlj.zip

export PATH=$Java_HOME/bin:$DB26/bin:$PATH
export LIBPATH=$DB26/lib:$LIBPATH
export LD_LIBRARY_PATH=$DB26/lib:$LD_LIBRARY_PATH

Each developer wishing to create Java stored procedures would use the
same .profile information with a minor change for the location of the
db2profile script.

Chapter 4. System setup 81


82 DB2 Java Stored Procedures: Learning by Example
Chapter 5. Designing Java stored procedures

In this chapter we discuss the various issues that an application designer


must be aware of when developing Java stored procedures.

5.1 General design issues


The following sections present some general issues that you need to consider
when designing your Java stored procedures.

5.1.1 Naming
There are a number of interrelationships between the various components
used in a Java stored procedure environment. Therefore, it is a good idea to
come up with some naming standards as soon as possible in the design
process.

The following sections provide some general naming recommendations for a


Java stored procedure environment (see Figure 13 on page 95 for a
discussion of how the various programming objects interact).

Remember that there are some issues surrounding case sensitivity with many
of these names. Be consistent in your use of case, and implement some site
conventions for everybody to follow.

5.1.1.1 Relationships between stored procedure components


Figure 11 shows the interrelationship between the various components in a
Java stored procedure environment:
• Each stored procedure is implemented as a Java method, and there is a
one-to-one relationship between a method and a stored procedure.
• One or more methods belong to a Java class. There is a one-to-one
relationship between a Java class and a Java source file.
• One or more classes reside in a Java package. There is a one-to-one
relationship between a Java package and an operating system directory
(which stores all of the Java source files for that package).
• One or more Java packages reside within an OS/390 executable module
(on the OS/390 platform) or within a JAR file (on the UNIX and NT
platforms).

© Copyright IBM Corp. 2000 83


Load Module (OS/390) or JAR (Unix/Windows)
Java Package = OS Directory Java Package = OS Directory

Class = Java Source File Class = Java Source File


Method = Stored Procedure Method = Stored Procedure

Method = Stored Procedure Method = Stored Procedure

Class = Java Source File Class = Java Source File


Method = Stored Procedure Method = Stored Procedure

Method = Stored Procedure Method = Stored Procedure

Figure 11. Java stored procedure object interrelationships

Most code management products and procedures operate at source code file
level. Therefore, we felt that storing any more than one stored procedure
within a single source code file can cause version management issues.

For this reason, we chose to implement a single method per class, which
resulted in a single stored procedure per source file. We also implemented a
single Java package per OS/390 executable or JAR file, to keep the size of
these objects manageable. This approach is summarized in Figure 12.

Note
As with any other naming conventions, there are no definitive “right” and
“wrong” ways to name components.

Within this section we present the conventions that we used during the
production of this book. This approach seemed to provide a good
compromise between flexibility and manageability.

However, your mileage may vary: you must define your own conventions
based upon any existing standards and the particular environment that you
are working within.

84 DB2 Java Stored Procedures: Learning by Example


Load Module (OS/390) or JAR (Unix/Windows)
Java Package = OS Directory

Class = Java Source File


Method = Stored Procedure

Class = Java Source File


Method = Stored Procedure

Figure 12. Our Java stored procedure object structure

5.1.1.2 Stored procedure name


If you already use non-Java stored procedures, you will probably have
standards in place for stored procedure names (the name you specify in the
SQL CALL statement to invoke the stored procedure).

Remember that you have a full 18 characters to use, so make the name as
meaningful as possible in relation to the stored procedure’s function. For
example, Add_customer, Promote_employee, and Bill_client are all good
descriptive names.

DB2 UDB for OS/390 Version 6 and DB2 UDB for UNIX, Windows NT, and
OS/2 support 2-part stored procedure names, which give you still more
flexibility in your naming convention.

5.1.1.3 Java method name


There is a one-to-one relationship between a method name and a stored
procedure name. Although the names can be dissimilar, for ease of
understanding, we suggest that the stored procedure and the method be
named the same.

Chapter 5. Designing Java stored procedures 85


5.1.1.4 Java class name
A Java class contains one or more methods. We found it easiest to place one
method in a class and to name the method the same as the class, changing
the initial character of the class name to upper case.

In our example, the Java method called add_customer is the only method in a
Java class called Add_customer.

5.1.1.5 JDBC source file / SQLJ Source File


There is a one-to-one relationship between a Java class and the file the
source is stored in. Therefore, we recommend that you name the source file
after the Java class it contains.

So, if you are following our previous recommendation of one method (stored
procedure) per Java class, you can name the source file after the stored
procedure name.

In our example, the stored procedure Add_customer would be implemented as


a method called add_customer, within a class called Add_customer, and stored in
a file called Add_customer.java (for a JDBC procedure) or Add_customer.sqlj
(for a SQLJ procedure).

How many stored procedures per source file?


We feel that the approach we have described above provides the greatest
flexibility in a typical development environment, where version
management and concurrent development requirements would make the
placement of multiple stored procedures within each source file much more
difficult to manage.

However, there is nothing to stop you from setting up your environment in


such a way as to place multiple stored procedures in each .java source file
if you wish. In this case, each stored procedure becomes a separate
method within the class represented by the source file. You will need to
create a meaningful name for the source file that encompasses the stored
procedures within it.

5.1.1.6 Java package


The Java package name is the basic grouping unit within the Java stored
procedures environment, allowing you to associate related stored procedures
with each other.

86 DB2 Java Stored Procedures: Learning by Example


Some of the items you may wish to include in your standard for Java package
are listed below:
• An application identifier, if you are grouping your procedures into
packages by application (PAYROLL, for example).
• An environment identifier, if you will be mixing several development
environments within the same system (for example, development, unit
test, or system test).

How many Java packages per load module or JAR?


In our tests, we created a discrete OS/390 load module (on the S/390
platform) or JAR file (on UNIX and Windows NT) for each Java package.
However, you may incorporate several Java packages into a single HJP
load module or JAR file if you wish.

The remainder of this discussion assumes a one-to-one relationship


between the Java package and the OS/390 load module or JAR.

The source files for all stored procedures that belong to a given Java package
should be grouped together in a single USS directory named after the Java
package.

For example, the Add_customer and Add_order SQLJ procedures both belong in
the ACME package. Therefore, the ACME directory contains the source files
Add_customer.sqlj and Add_order.sqlj.

Chapter 5. Designing Java stored procedures 87


Case sensitivity in Java package names on S/390
As we are suggesting that you implement a one-to-one relationship
between Java packages and OS/390 load modules, you may be tempted
(as we were initially) to simply name the OS/390 load module after the Java
package.

This should be avoided, as it has a number of disadvantages:


• It imposes a limit of 8 characters on your Java package names (the
maximum length of a PDSE member name), making them less
descriptive.
• It can lead to case sensitivity problems with Java package names, due
to the fact that the OS/390 load module name is always in upper-case.
For instance, two Java packages named package1 and PACKAGE1 will be
completely discrete within the USS environment, but will both result in a
load module name of PACKAGE1 with the PDSE dataset. This may lead to
existing modules being overwitten during the program preparation
process.

For these reasons, we recommend that your program preparation scripts


use different names for the Java package and the PDSE member name.
The sample scripts described in 7.2, “OS/390 Java stored procedure
preparation” on page 119 reflect this.

5.1.1.7 OS/390 load module


The HPJ load module contains an optimized, OS/390 specific, compiled
version of all of the stored procedures within one or more Java packages.

We recommend the use of a single Java package per OS/390 load module.
However, as the OS/390 load module can only be a maximum of 8 characters
in length, you will probably need to create a suitable means of shortening or
transforming the Java package name to fit.

5.1.1.8 JAR file


In a DB2 UDB for UNIX, Windows, OS/2 environment, the JAR file is used to
contain all of the .class files associated with a particular Java package.
Therefore, it is functionally equivalent to a HPJ executable module on the
S/390 platform.

We recommend that you name your JAR file the same as your Java package
name to ease problem solving. There is no technical limitation requiring the
JAR name to be named the same as the Java package name.

88 DB2 Java Stored Procedures: Learning by Example


5.1.1.9 DB2 package
The program preparation process for each SQLJ procedure will result in 4
DB2 packages being produced (one for each isolation level). Therefore, if you
have 2 SQLJ procedures in a Java package, that Java package will have 8
DB2 packages associated with it (the terminology is a little confusing here —
make sure you are clear about the differences between Java packages and
DB2 packages).

DB2 package names must be limited to 7 characters, as the db2profc process


appends a number (between 1 and 4) after the supplied name to generate the
4 packages.

You must therefore create a reasonable 7-character abbreviation for your


18-character stored procedure name.

For example, for the Add_Customer stored procedure, you could decide to use a
package name of ADDCUST, which would cause db2profc to generate DBRMs to
bind into packages ADDCUST1, ADDCUST2, ADDCUST3, and ADDCUST4.

For JDBC stored procedures, a generic set of DB2 packages (DSNJDBC1,


DSNJDBC2, DSNJDBC3, and DSNJDBC4) are used.

5.1.1.10 DB2 package collection


Once again, you will probably already have some standards set up for
collection naming within your organization.

Unless your existing site standards dictate otherwise, we suggest that you
use one DB2 package collection for each Java package, and name that
collection after it.

So, for Java package ACME containing SQLJ stored procedures Add_customer
(DB2 package name ADDCUST) and Add_order (DB2 package name ADDORD),
you may have a package collection called ACME, containing 8 DB2 packages
(ADDCUST1 to ADDCUST4 and ADDORD1 to ADDORD4).

See 9.1, “DB2 plans and packages” on page 167 for details on the
relationship between client plans and Java stored procedure package
colelctions.

5.1.2 Parameter style: Java or DB2GENERAL


This document describes the Java stored procedures that correspond to the
SQLJ Routines specification. These are known as parameter style Java
stored procedures.

Chapter 5. Designing Java stored procedures 89


For DB2 UDB for UNIX, Windows, OS/2, an earlier, more proprietary, solution
for making Java stored procedures is known by the name Parameter Style
DB2GENERAL. It was developed before industry standards had been
established.

5.1.3 Public static method with void return type


A DB2 Java stored procedure returns no return code. Any value determined
by the stored procedure must return in one of the parameters passed into the
stored procedure.

The declaration of the method looks something like this:


public class Add_customer
{
public static void add_customer (
String in_cust_firstname,
String in_cust_lastname,
String in_cust_address,
int[] out_cust_no,
String[] mark,
String[] mark_error_text
) throws SQLException, Exception

The stored procedure in this example has the name of Add_customer. The
method to be invoked is add_customer.

5.1.4 Parameters must be mappable to base SQL data types


The parameters used by a Java stored procedure must be able to be mapped
to base SQL data types. The mapping between Java and SQL data types is
explained in the section “Supported SQL Data Types” in the chapter
“Programming in Java” in the DB2 UDB Application Development Guide,
SC09-2845.

5.1.5 LOBS not supported for Java stored procedures


At this point in time, LOBS are not supported for any SQLJ or JDBC
programs. Therefore, they are not supported as parameters for Java stored
procedures.

5.1.6 Why do we use [ ] on the output parameters?


The output parameters must be declared within the SQLJ source as Java
arrays. However, only the [0] element is used. The SQLJ standard requires
this form of parameter style.

90 DB2 Java Stored Procedures: Learning by Example


Note
If you use an output parameter in a SELECT statement, be sure to enclose
the entire name, including the ‘[0]’, with parantheses. Failure to do will
result in a syntax error.

Example: SET HI_CUST_NO = :(out_cust_no[0])

5.1.7 Using JDBC, SQLJ, or both


A stored procedure may be built using JDBC, SQLJ, or both.

JDBC can be considered the Java equivalent of ODBC. The JDBC statements
are executed dynamically.

SQLJ can be considered the Java equivalent of embedded SQL for the Java
language. SQLJ source code runs through a precompiler to produce Java
(JDBC) source code as well as other files that go through additional
processing to allow DB2 to prepare the SQL into compiled static statements.

A stored procedure may mix both SQLJ and JDBC. For recommendations on
which API to use, refer to 2.1.3, “Choosing the access method: JDBC versus
SQLJ” on page 9.

5.1.8 Java packages


A stored procedure may be built using the Java package statement (not to be
confused with a DB2 package!). The OS/390 platform requires the use of the
Java package statement. For other platforms, use of Java packages is
optional.

Portability
If it is important to you to be able to easily port your stored procedure code
between OS/390 and other platforms, we recommend that you code all of
your stored procedures using Java packages.

For this reason, all of the Windows NT and UNIX examples in this book use
the Java package statement.

From a design perspective, use of Java packages helps organize stored


procedures into application groups. Most shops host more than one

Chapter 5. Designing Java stored procedures 91


application on a machine, consequently, we recommend using Java packages
for your stored procedures.

A Java program becomes part of a Java package if it has the token package
followed by the Java package name at the top of the source file.

Example:
package ACMESOS;

For recommendations regarding Java package, module, and JAR naming


standards, see 5.1.1, “Naming” on page 83.

5.1.9 Case sensitivity


Some recommendations on naming various objects within a Java stored
procedures environment can be found in 5.1.1, “Naming” on page 83. You
should be aware that with the exception of purely DB2 objects such as plans
and packages, most object names are case sensitive, so it is vital that you be
consistent in your naming. We suggest that you formulate some conventions
for use at your site.

In particular, you should be aware of the following issues:


• On the OS/390 platform, all OS/390 load module names are folded to
upper case. Therefore, it is possible to accidentally overwrite load modules
if you specify a PDSE member name of module1 during the HPJ step, and
subsequently specify another called MODULE1.
• A Java client (SQLJ or JDBC) calling an S/390 stored procedure must
code the stored procedure name in upper case. See 9.2.1.2, “The SQL
CALL statement” on page 171 for further information.
• An SQLJ stored procedure on the OS/390 platform must refer to DB2
object names in upper-case within embedded SQL statements, or a
SQLCODE -204 results.

5.1.10 Nested Java stored procedures


DB2 UDB for OS/390 Version 6 allows one Java stored procedure to call
another (nesting).

For DB2 UDB for UNIX, Windows, OS/2, as of Version 7, a Java stored
procedure may not call another Java stored procedure. This restriction may
change in a future version. Stored procedures written in other languages may
nest, and they may be written in different languages, if they meet the following
requirements:

92 DB2 Java Stored Procedures: Learning by Example


- Java is not a language used to build one of the stored procedures
- All the procedures must be fenced and catalogued.

5.2 Design issues for OS/390 Java stored procedures


The following sections present some issues that you need to consider when
designing your Java stored procedures for OS/390.

5.2.1 Must use HPJ compiler


The OS/390 platform requires Java stored procedures to be compiled with the
High Performance Java compiler (HPJ). The HPJ compiler produces a load
module similar to COBOL or PL/1, or any other LE 3GL load module. The HPJ
step must be completed because a Java Virtual Machine does not execute
within the address space that DB2 executes. This restriction may change in a
future version.

5.2.2 Must have Java Package as first statement


The OS/390 platform requires a Java package statement to be the first
statement in the source. The Java package name subsequently is mapped to
the load module produced by the HPJ. For example, these two techniques are
functionally equivalent: a Java package groups a number of class files, and
an HPJ-produced load module groups a number of class files into an
executable unit.

5.2.3 Packaging considerations


The number of routines you choose to group together, and their degree of
complexity, may impact the performance of the system.

For instance, placing many very large procedures into a single Java package
will result in all of the code being compiled into a single HPJ executable
module. At run time, the entire module has to be loaded into the stored
procedure address space, which can be wasteful if only a single, small
routine is required.

On the other hand, grouping commonly-used routines into a single Java


package may provide some benefits, as the chances of the required module
already being resident in the stored procedure address space are increased.

There are no hard-and-fast rules for this packaging. We suggest the following
rules of thumb:
• Cluster together (package) the small, often-used stored procedures.

Chapter 5. Designing Java stored procedures 93


• Larger, less-used procedures should stand by themselves in order to allow
them to be paged out of memory when not being used.
• Whenever possible, package the most frequently used of the remaining
procedures together.

5.2.4 Environmental considerations


The environment required to execute Java stored procedures on the S/390
platform is a fairly complex one, utilizing both base OS/390 and USS.

The program preparation process (which is described in detail in 7.2, “OS/390


Java stored procedure preparation” on page 119) results in the following
objects being produced:
• An OS/390 load module for the stored procedure, stored in a PDSE data
set
• A link to the load module, within a nominated HFS directory under OS/390
UNIX Systems Services (USS)
• A set of DB2 packages, if the stored procedure accesses DB2 using SQLJ
(JDBC procedures use a set of generic JDBC packages).
• A serialized profile, if the stored procedure accesses DB2 using SQLJ
(again, JDBC procedures use a generic JDBC profile).

Figure 13 shows how these objects are used when a client issues a call to a
Java SQLJ stored procedure.

94 DB2 Java Stored Procedures: Learning by Example


DB2 Packages
SQLJ Source
Program
Preparation
ACMESOS/ ACMESOS1
Process
Add_customer.sqlj ACMESOS2
ACMESOS3
ACMESOS4

Via ound plan


USS Directory

b t's
c oll in
clie

ect
n
via PDSE link 4

ion
via 6
ACMESOS ST E
PLIB
ACMESOS
PDSE Link
via
CLA
HPJ load module
SSP
PDSE dataset 5 ADD_CUSTOMER
3 ATH

JAVAENV via JAVAENV DD


WLMJAVA
Dataset SP WLM Address Space

2
SYSROUTINES (V6)
NAME EXTERNAL_NAME WLM_ENV ...

ADD_CUSTOMER ACMESOS/Add_customer.add_customer WLMJAVA

Client
...
SYSPROCEDURES (V5)
CALL
1
ADD_CUSTOMER PROCEDURE RUNOPTS WLM_ENV ...
(FIRSTNAME, ....) ADD_CUSTOMER ACMESOS/Add_customer.add_customer WLMJAVA
...

Figure 13. Runtime environment overview — SQLJ stored procedure

1. The client issues a call to the stored procedure ADD_CUSTOMER.


2. Depending upon the version of DB2 for OS/390 being used, either the
RUNOPTS column of SYSIBM.SYSPROCEDURES or the EXTERNAL_NAME column of
SYSIBM.SYSROUTINES is used to determine the Java package, class, and
method associated with the call.
This is defined within the catalog according to standard Java syntax:
package/classname.methodname
3. The JAVAENV data set specified in the procedure JCL for the selected WLM
environment (also obtained from SYSPROCEDURES or SYSROUTINES) is used to
obtain the value of the CLASSPATH parameter. The USS libraries specified in
CLASSPATH are searched to find a link named after the Java package name

Chapter 5. Designing Java stored procedures 95


specified in the SYSROUTINES or SYSPROCEDURES definition (ACMESOS in our
example).
4. The link is used to obtain the PDSE member name containing the HPJ
compiled stored procedure load module for the Java package being used.
5. This load module is loaded into the relevant WLM stored procedure
address space.
6. DB2 searches for the stored procedure’s DB2 packages in the collection
that the client’s plan/package belongs to (or looks in the collection
specified in the COLLID keyword on the CREATE PROCEDURE command).

5.3 Design issues for the UNIX, Windows, OS/2 platforms


There are no major design issues for Java stored procedures on the UNIX,
Windows, or OS/2 platforms.

Programmers coming from OS/390 to a UNIX, Windows, or OS/2 platform


should understand that Java stored procedures within DB2 UDB are able to
execute stored procedures as native Java bytecode running within a Java
Virtual Machine (JVM). They do not require the HPJ compiler, nor are they
able to execute a Java stored procedure that has been put through the HPJ
compile process, as the resultant module is an S/390 executable.

96 DB2 Java Stored Procedures: Learning by Example


Chapter 6. Coding Java stored procedures

This chapter provides some practical guidance on the techniques you can
use when coding your DB2 Java stored procedures.

The following sections are not intended to be a programming reference. We


assume that you have at least a basic knowledge of Java, DB2, JDBC and
SQLJ. If you need more background information on these subjects, please
refer to the resources listed in Appendix G., “Related publications” on page
359.

6.1 Null handling with JDBC stored procedures


A Java stored procedure requires special programming when handling null
values.

6.1.1 Calling a stored procedure with a null value


JDBC programs handle SQL nulls with a special technique when passing a
null.

When calling the stored procedure from a JDBC client, use the special
function setNull for marking the parameter as null. You cannot simply pass a
null Java object.

6.1.1.1 Invalid coding


Here is an example of invalid coding:
String nullguy = null;
callStmt.setString (3, nullguy); // null address, fails for JDBC

6.1.1.2 Valid coding


Here is an example of valid coding:
callStmt.setNull(3,Types.CHAR);// null address, works for JDBC

6.1.2 Using a Java base type as a parameter


You may need to establish the parameters of the stored procedure in a
different format than the way that they are defined to the database, if you are
passing in nulls.

© Copyright IBM Corp. 2000 97


For example, the following code fragment defines several parameters:
public class Query_test1
{
public static void query_test1 (
int in_prod_no,
String prod_desc,
int in_qty_on_hand )

These parameters were defined to match the DDL for the table:
create table test1
(
PROD_NO integer not null,
PROD_DESC char(30),
QTY_ON_HAND integer
)

Notice that QTY_ON_HAND is nullable (under the business assumption that


at a point in time it may not be known how many items of that product are
available). Because the SQL field is defined as an integer, it appears to make
sense to define the stored procedure parameter as an integer. Unfortunately,
this will fail when trying to invoke the stored procedure with a null value. A
Java int field is a base type and thus cannot be set to an actual null value.

To work around this issue, define the parameter as a String. This gives you
the ability to assess if the String is a null object.

Trim a Numeric String


If you use a String to pass a numeric value, be sure to trim the spaces from
the string.

Example:

callStmt.setString (2, argv[2].trim());

98 DB2 Java Stored Procedures: Learning by Example


For example:
public class Query_test1
{
public static void query_test1 (
int in_prod_no,
String prod_desc,
String in_qty_on_hand )
.
.
.
int local_in_qty_on_hand;
if (null == in_qty_on_hand)
{
//do special handling for when it is null
}
else
local_in_qty_on_hand = Integer.parseInt(in_qty_on_hand.trim());

6.1.3 Determining if a selected item was an SQL null via wasNull()


Use the wasNull method of ResultSet to determine if the field just examined
equals an SQL null. A ResultSet holds the contents of an executed SQL
select.

Example:
String ins_prod_desc = "";
String ret_prod_desc = rs.getString(3);
if (rs.wasNull())
ins_prod_desc = "NULL";
else
ins_prod_desc = "'" + rs.getString(3) + "'" ;

6.1.4 Inserting a NULL


Inserting a NULL in JDBC follows the same rules as any other language —
use the NULL value when building the insert statement.

For example:

String sql2 = "insert into acmee.order_item_summ " +


"(prod_desc, qty_1_to_5,QTY_5_TO_10,QTY_11_PLUS) " +
"values(" +
ins_prod_desc + "," +
insert_vals +

Chapter 6. Coding Java stored procedures 99


")";
stmt2.executeUpdate(sql2);

This example builds upon the previous example, which calculated the
ins_prod_desc field either to the value in the third column of the ResultSet
surrounded by single quotes, or to the value NULL.

6.2 Null handling with SQLJ stored procedures


Null handling in SQLJ stored procedures is considerably easier than for
JDBC. SQLJ is intuitive about null-handling. For example, a null Java object
translates to a nullable column without needing to use a special method as in
JDBC.
Table 9. Null handling within SQL stored procedures

Requirement Restrictions

Calling a stored procedure When calling a stored procedure from an


from an SQLJ client SQLJ client, you can send a null Java
object.

Using a base Java type as a It is not possible to set a base Java type to
parameter null and have it actually understood by
downstream processing as a null. Instead,
you can cast parameters to a String type
(or other Java type subclassed from
Object) which can then be set to null.

Receiving a null in an SQLJ A SQLJ stored procedure can receive a


stored procedure null Java object as a parameter.

Inserting a null from an SQLJ SQLJ understands that when a Java


stored procedure object is null and it is being inserted to the
database that a null value is to be placed
in the associated nullable column in the
table.

Receiving a null within an The host variable is set to Java null when
SQLJ stored procedure a select statement reads an SQL null
value into that host variable.

6.3 SQLJ Iterators and ResultSets


SQLJ introduces the concept of the Iterator, which is SQLJ’s version of a
ResultSet where the fields have been cast to Java types. This allows for some
up front cross-checking.

100 DB2 Java Stored Procedures: Learning by Example


There are two types of Iterators:
• Positional — refers to the fields by position
• Named — refers to the fields by name

6.3.1 Return ResultSets from SQLJ stored procedures


Consider returning a ResultSet instead of an Iterator from an SQLJ stored
procedure. The technique to do this is shown in the following code fragment
(where ‘out_rs[0]’ is a ResultSet in the parameter list):
Defined_iter2 iter2;
#sql iter2 =
{
select
prod_desc, qty_1_to_5, QTY_6_TO_10, QTY_11_PLUS
from acmee.order_item_summ
}; // #sql
out_rs[0] = iter2.getResultSet();

There are two reasons why you might choose to return ResultSets instead of
Iterators. First, on the UNIX and Windows NT platforms, the system has been
designed to recognize only ResultSets, not Iterators. (This may change some
time in the future). Secondly, on the OS/390 platform, although it has been
tested as being able to return Iterators, it is less efficient than using
ResultSets.

6.3.2 Avoid returning a used ResultSet


An Iterator points to an underlying cursor. Once you walk through that
Iterator, the cursor is considered exhausted. (Future versions of DB2 UDB for
OS/390 will allow backwards walking through a cursor). If you cast to a
ResultSet and walk through it, that activity also exhausts the cursor.
Therefore, the only ResultSets that can be returned to the client are those
that have been freshly created from a select statement without a subsequent
review.

6.3.3 Close interim ResultSets


If you code a stored procedure that uses an interim ResultSet then be sure to
close that interim ResultSet. Failure to do so may cause data not to be
returned. It is good coding practice to close ResultSets that no longer need to
be used.

Chapter 6. Coding Java stored procedures 101


6.3.4 Returning Multiple ResultSets
A SQLJ stored procedure can return multiple ResultSets. Adherence to SQL
standards requires that ResultSets be returned to the client in the order in
which they are opened. Consequently, if you need two ResultSets, open the
first declared ResultSet before opening the second declared ResultSet.
Reversal of the order of the opening will produce odd results in your client.

6.4 Error Handling


A Java stored procedure does not return a value.

We suggest sending in two parameters for determining successful


(or unsuccessful) execution. One is used to mark where the stored procedure
last successfully executed. The second holds the text produced by the catch
block of an exception. The following code fragment illustrates this:
.
.
mark[0] = "Add_customer: getConnection";
Connection con = DriverManager.getConnection("jdbc:default:connection");
.
.

catch (SQLException e)
{
mark_error_text[0] = "SQLException raised, SQLState = "
+ e.getSQLState() + " SQLCODE = " + e.getErrorCode()
+ " :" + e.getMessage();
e.printStackTrace();
}
catch (Exception e)
{ mark_error_text[0] = "Add_customer: major exception caught: "
+ e.getMessage();
e.printStackTrace();
}

6.4.1 Getting the results of printStackTrace


The code fragment above executes the statement e.printStackTrace() .
However, that output goes to the standard output (or perhaps standard error).
What this means is that the invoking client will not see the stack trace. It will
be printed, on OS/390, to the output of the WLM address space location
specified by JSPDEBUG. On UNIX and Windows NT, the output drops off the
edge.

102 DB2 Java Stored Procedures: Learning by Example


To return the printStackTrace to the client, use StringWriter and PrintWriter
methods to get the output into a string.

For example:
mark_error_text[0] = "Query_oi_summ: "
+ "SQLException raised, SQLState = "
+ e.getSQLState() + " SQLCODE = " + e.getErrorCode()
+ " :" + e.getMessage();
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
mark_error_text[0] += ":printStackTrace=" + sw.toString() ;

6.5 Debugging
Sadly, our computers often remind us that, unlike them, we are not perfect!
Our programs rarely work correctly the first time. Stored procedures can be
difficult to debug, due to the limitation that they run underneath the control of
a separate process, perhaps on a different machine than that of the invoking
client.

6.5.1 Initially writing as a standalone program


One common technique when writing stored procedures in any language has
the developer start by writing the code as a standalone program. Write the
stored procedure as one class and the driver as a separate class. When you
complete the draft version you customize the stored procedure class to fit
within the database. One item that must change will be the Connection, which
would have been established by the driver in the standalone program.

6.5.2 Writing debugging statements to a table


One approach to debugging is to write debugging statements to a table. We
question the feasibility of this approach, due to rollbacks. Quite frankly, the
stored procedures that most need debugging are the ones that will end so
badly the system rolls back the work, erasing all the debug data!

6.5.3 OS/390 debugging


You can use three techniques for OS/390 debugging:

6.5.3.1 ET/390 Debugger


The ET/390 Debugger can be useful for debugging Java stored procedures.
Refer to the ET/390 Concepts & Overview manual for further details1.

Chapter 6. Coding Java stored procedures 103


6.5.3.2 System.out.println
The developer may choose to put statements in the source code of the Java
stored procedure to say, “Here is where I am right now, and this is the value of
a questionable variable”. This technique is quite similar to the use of COBOL
Display statements or the C printf statements.

These statements show in the WLM output (as pointed to by the JSPDEBUG
DD) of the job executing the Java stored procedures. Your systems
programmer can tell you the name of the data set on your system. These
statements must be used with care, and only on the development platform —
if they get pushed out to production, the performance of the production
system may be negatively impacted.

6.5.3.3 Writing to an output file


A technique for writing stored procedure output to a file is described in 6.5.4,
“UNIX and Windows NT debugging” on page 104. This technique also works
on OS/390. The file is created on the UNIX Systems Services file system,
because a USS environment is created within the WLM address space.

6.5.4 UNIX and Windows NT debugging


The UNIX and Windows NT platforms offer two techniques for debugging.

6.5.4.1 Debugging option of the SPB


The debugging feature of the Stored Procedure Builder may be useful. Refer
to 6.6, “Using the DB2 Stored Procedure Builder” on page 105 for more
information.

6.5.4.2 Writing to a text file


Using the system.out.println statement within a Java stored procedure on the
UNIX or Windows NT platforms produces no output, by design. However,
these types of statements can be directed to a file.

In the following example, a file is created with a date and time stamp for the
file name. (Note that Java is smart enough to convert the ‘/tmp’ to ‘\tmp’ on
the Windows NT platform.)

1 At the time of writing, the ET/390 manuals did not have formal IBM publication numbers. However, they can be

downloaded from the Web in PDF format at http://www-4.ibm.com/software/ad/vajava/library.htm.

104 DB2 Java Stored Procedures: Learning by Example


////////////////////////////////////////////////////////
// establish debugging file: name is timestamped
////////////////////////////////////////////////////////
Date debugDate = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance();
(SimpleDateFormat)dateFormat).applyPattern("MM_dd_HH_mm_ss");
String debugdf = dateFormat.format(debugDate);
PrintWriter pwx =
new PrintWriter( new FileWriter("/tmp/" + debugdf + ".txt"),true );
pwx.println("sql =>" + sql + "<=");

An example file name on Windows NT created from this process is


\tmp\03_16_09_25_59.txt , which indicates that the stored procedure ran on
March 16 at 9:25AM at 59 seconds past the minute. The ‘pwx.println’
statement at the end of the code fragment writes what the stored procedure
considers to be the value of the ‘sql’ variable to this debugging file.

Observe these two cautions:


1. If the stored procedure fails, the pwx.close() statement (not shown) will not
have executed; a DB2 process will still own this file in an open mode, thus
the file cannot be deleted until the database is brought down. A better
approach is to put the pwx.close() not only in the main body of the stored
procedure, but also in the catch blocks, as seen in some of the examples,
to close the file.
2. Never allow this debugging technique to go onto the production system. It
will hurt performance and possibly bring down the system.

6.6 Using the DB2 Stored Procedure Builder


The DB2 Stored Procedure Builder (SPB) is a GUI tool to assist developing
DB2 stored procedures.

You will need to assess the SPB for your own use. Our investigation
uncovered both advantages and limitations. Most GUI tools are improved on a
rapid basis, such that the difficulties we see now may be corrected by the time
you read this book.

6.6.1 Advantages of the SPB


The SPB offers the following useful features.

Chapter 6. Coding Java stored procedures 105


6.6.1.1 Testing existing stored procedures
One of the most attractive benefits to the SPB is that it gives you the ability to
test an already-built stored procedure.

You need not make the source available on the platform upon which the SPB
runs; the SPB reads the catalog definitions to build the window that asks for
the input parameters.

This facility frees you from the requirement to write a specific client “driver”
program for each stored procedure when testing.

DB2 Connect is required for being able to invoke stored procedures located
within DB2 databases on other platforms, such as OS/390 or UNIX.

6.7 Common errors


In the following sections we document some of the errors we have seen when
working with Java stored procedures.

6.7.1 OS/390 errors


Errors produced by OS/390 Java stored procedures sometimes return data
back to the client. Other errors show in the WLM logs.

6.7.1.1 HPJ3115(S) message received during HPJ compile

Symptom

HPJ compile issues this error message:

HPJ3115(S) Unable to fetch module "HPJ3TBY".

Possible Solution

Increase region size.

6.7.1.2 Class Not Found at runtime

Symptom

This error message is issued at runtime:

class not found in classpath: ACME/ADD_CUSTOMER

to String string from error is: java.lang.NoSuchMethodError

106 DB2 Java Stored Procedures: Learning by Example


Possible Solution

The PDSE member created by the HPJ compiler will have its name folded into
upper case (OS/390 does not support lower case PDSE member names).

Check that the USS link to the PDSE member in your links directory points to
an upper case version of the PDSE member name. If this has been
incorrectly specified as a lower case name, the link will not work, and this
error message will be returned. See 5.1.9, “Case sensitivity” on page 92 for
more details.

6.7.1.3 Method Not Found at runtime

Symptom

This error message is issued at runtime:


error GetStaticMethodID
class name: ACMESOE/Add_customer func name: Add_customer
toString string from error is: java.lang.NoSuchMethodError: Add_customer

Possible Solutions
• Ensure case of method name in SYSPROCEDURES or SYSROUTINES
matches that defined in SP
• Ensure that SP code has method defined as public static, with void return
type
• Ensure that parameter definition in SYSPROCEDURES or
SYSROUTINES matches CALL definition.

6.7.1.4 SQLCODE -104 At DB2 Package Bind

Symptom

SQLCODE -104 is issued at package bind;


DSNX200I =DBZ2 BIND SQL ERROR
USING DB2RES2 AUTHORITY
PLAN=(NOT APPLICABLE)
DBRM=ADDCUST1
STATEMENT=1
SQLCODE=-104
SQLSTATE=42601
TOKENS=;-<END-OF-STATEMENT
CSECT NAME=DSNHPARS
RDS CODE=0

Chapter 6. Coding Java stored procedures 107


DSNT233I =DBZ2 UNSUCCESSFUL BIND FOR
PACKAGE = DBZ1.ACMESOE.ADDCUST1.()

Possible Solutions
• Ensure that you haven’t put semicolons within the #SQLJ curly brackets at
end of SQL statements (normal Java statement terminator — semicolons
— are still required outside the #SQLJ curly brackets).

6.7.1.5 SQLCODE -113 when executing from a Java client

Symptom

SQLCODE -113 is issued when executing from a Java client.

The error looks something like this:


java.sql.SQLException: DB2JDBCSection Received Error in Method
execute_call:SQLCODE==> -113 SQLSTATE ==> 42602 Error Tokens ==>
<<DB2/OS390 V5.1 ANSI SQLJ-0/JDBC 1.0>> Add_customer 000 €

at
COM.ibm.db2os390.sqlj.jdbc.DB2SQLJJDBCSection.setError(DB2SQLJJDBCSection.
java:1049)
at
COM.ibm.db2os390.sqlj.jdbc.DB2SQLJJDBCSection.execute_call(DB2SQLJJDBCSect
ion.java:874)
at
COM.ibm.db2os390.sqlj.runtime.DB2SQLJRTStatement.execute(DB2SQLJRTStatemen
t.java:987)
at
sqlj.runtime.ExecutionContext$StatementFrame.execute(ExecutionContext.java
:741)
at sqlj.runtime.ExecutionContext.execute(ExecutionContext.java:419)
at acmecl.sscall_Add_customer.main(sscall_Add_customer.java:169)

Solution

Define the stored procedure in SYSPROCEDURES to be known by an


uppercase name. This uppercase name now becomes the name used by the
Java client to invoke the stored procedure. Please note that the stored
procedure itself can still be written with lowercase letters: it is the indirection
in SYSPROCEDURES that makes it visible as uppercase.

6.7.1.6 SQLCODE -440 when trying to invoke a stored procedure

Symptom

108 DB2 Java Stored Procedures: Learning by Example


DB2 is not able to find the stored procedure or the caller does not have
execute authority on stored procedure.

Solution

One thing DB2 checks is whether the stored procedure was created after the
original bind of the CALL statement. This can only happen during autobind.
The calling DB2 package has to be explicitly rebound in this case.

Solution

Another check is whether the caller has execute authority to the stored
procedure. The owner of the stored procedure needs to issue a GRANT EXECUTE
ON PROCEDURE to this user. Callers of stored procedures that were migrated
from V5 and have not been dropped and recreated do not need this authority,
as they have no OWNER.

Solution

The most common error is that a procedure by this name with this number of
parameters was not found in the catalog table.

To resolve this, you should obtain the result of a SELECT of all columns of
SYSIBM.SYSROUTINES for the SP that you want to invoke.

First, verify that the number of parameters sent on the CALL statement, or
described in the SQLDA if it is a USING DESCRIPTOR call, matches the number of
parameters column in SYSIBM.SYSROUTINES. If this is correct, then it's a
problem with the stored procedure name.

Now you need to determine exactly what name was specified on the SQL CALL
statement. The name can be either explicitly specified, or contained in a host
variable. If you are running on a distributed client using a workstation
development tool that uses ODBC or JDBC, then you are definitely running
the SQL CALL statement with the name specified in a host variable. Either
way, the name can be a 1-part, 2-part, or 3-part name. A 3-part name is
LOCATION.SCHEMA.PROCNAME. In this case, make sure that LOCATION
is the current location. and SCHEMA and PROCNAME match what is in
SYSIBM.SYSROUTINES, which was filled in by CREATE PROCEDURE. Similarly, a
2-part name is SCHEMA.PROCNAME, so make sure that they match what is
in SYSROUTINES.

For a 1-part name, only PROCNAME is specified, and in this case, DB2 must
determine the schema name. DB2 uses a combination of CURRENT SQLID and
CURRENT PATH to look for a match, so you need to make sure that the schema

Chapter 6. Coding Java stored procedures 109


name in SYSIBM.SYSROUTINES is in the concatenation of schemes used to
resolve the SP name. It is different for call with a literal than call with a host
variable:
CALL <literal> SQL statements are resolved at bind time. The PATH bind
option is used to determine schema name.
CALL <host variable> SQL statements are resolved at run time. The
CURRENT_PATH special register is used to determine the list of potential
schema names.

Note
With APAR PQ39037 is applied, this situation changes. Refer to the
APAR text for further details.

Solution if CLIENT/SERVER with DB2 for OS/390 as the CLIENT:

If you are invoking a remote DB2 stored procedure from a DB2 for OS/390 V6
client, it's possible that since we now process the CALL statement at bind
time in V6, DB2 packages that were bound in V5 will fail to bind on V6. Stored
procedures are now real DB2 objects, so a reference to a remote stored
procedure when binding a DBRM into a plan or DB2 package locally behaves
just like a reference to a remote table. This is what the calling application may
look like in this case:
CONNECT TO B;
CALL P1;

P1 doesn't exist at the local site. This doesn't fail on the BIND in V5, but does
in V6.

The way to fix this is to handle it exactly the same way as you would handle a
reference to a remote table, which will get a -204 if you try to bind the DBRM
locally with VALIDATE(BIND). Here are some suggestions:
1. Don't bind the calling DB2 package locally, i.e., don't use MEMBER(x) on
the BIND PLAN, use pklist(location.collection.x). This only works if DBRM
x doesn't contain SQL to access the local location.
2. Use VALIDATE(RUN) on the BIND. This is the recommended approach,
and what is usually done for other remote objects, like tables. Don't worry,
VALIDATE(RUN) has no overall performance degradation on the local SQL
statements. It only affects those specific SQL statements that cannot be
bound during the static BIN. because the objects or auth aren't found at
that time -- like SQL referencing remote objects (non 3-part names),
including this specific type of CALL statements.

110 DB2 Java Stored Procedures: Learning by Example


3. Use SQLERROR(CONTINUE) on the BIND. SQLERROR(CONTINUE) is
usually used only if the DB2 package uses an SQL statements that DB2
390 doesn't support but the application will only execute the statements
after a CONNECT to a non -390 DB2 server.
4. Modify the calling application to use a 3-part name on the CALL
statement. A 3-part name in V6, when the DB2 package is bound with
DBPROTOCOL(DRDA), uses DRDA to implicitly connect to the remote
location.
5. Issue a CREATE PROCEDURE P1 at the local site to act as a dummy
entry and get past BIND errors.

Solution if just migrated stored procedures from V5 to V6 :

When you run CATMAINT, the resulting V6 stored procedure has no OWNER.
This means that the authorization rules don't change from V5. If you
subsequently DROP and CREATE the stored procedure, now it has an
OWNER, so the caller must have EXECUTE ON PROCEDURE authority to
invoke it.

Migrated stored procedures have SCHEMA set to 'SYSPROC'. This means


that to invoke them, SYSPROC has to be in the concatenation of schemes
that DB2 uses in resolution.

6.7.1.7 Location name not listed SQLSTATE=42705, SQLCODE=-950

Symptom

When running a client the following error is seen:


java.sql.SQLException: DB2SQLJConnection error in native method:
constructor: LOCATION NAME NOT LISTED IN CDB SQLSTATE=42705 and
SQLCODE=-950

Solution

The wrong location name was argued in the connect statement, therefore
DB2 attempts to find the remote DB2, however, one is not listed. Details
described at 9.2.1, “General client coding considerations” on page 170.

6.7.1.8 SQLCODE==> -113 SQLSTATE ==> 42602 Error Tokens ==> <

Symptom

Chapter 6. Coding Java stored procedures 111


When running a client, the following error message appears:
java.sql.SQLException: DB2JDBCSection Received Error in Method
execute_call:SQLCODE==> -113 SQLSTATE ==> 42602 Error Tokens ==>
<<DB2/OS390 V5.1 ANSI SQLJ-0/JDBC 1.0>> SS_ADD_CUSTOMER
000
at
COM.ibm.db2os390.sqlj.jdbc.DB2SQLJJDBCSection.setError(DB2SQLJJDBCSec
tion.java:1106)
at
COM.ibm.db2os390.sqlj.jdbc.DB2SQLJJDBCSection.execute_call(DB2SQLJJDB
CSection.java:897)
at
COM.ibm.db2os390.sqlj.runtime.DB2SQLJRTStatement.execute(DB2SQLJRTSta
tement.java:1054)
at
sqlj.runtime.ExecutionContext$StatementFrame.execute(ExecutionContext
.java:741)
at sqlj.runtime.ExecutionContext.execute(ExecutionContext.java:419)

Solution

Remove hidden whitespace characters that somehow were introduced into


the sample. (Speculation: perhaps FTP’ing between platforms introduces this
kind of error). Carefully remove or retype what looks like blanks, especially at
the ends of lines.

6.7.2 UNIX and Windows NT errors


In the following sections we list of some errors you may see on UNIX or
Windows NT.

6.7.2.1 SQL4301N Java interpreter start-up or communication failed

Symptom

When trying to execute a Java stored procedure, an error message says there
was a Java Interpreter start-up or communication failure.

For example:
db2inst3@azov:[/u/db2inst3/apps/test1/samples]>java DB2SpCli

Java Stored Procedure Sample


debug: drop procedure
debug: completed drop procedure

112 DB2 Java Stored Procedures: Learning by Example


Registering Java stored procedure SAMPLESTOREDPROC
as DB2Stp!salaryModification
in not fenced mode
debug: starting prepareCall
debug: completed prepareCall

Calling stored procedure: SAMPLESTOREDPROC


COM.ibm.db2.jdbc.app.DB2Exception: [IBM][CLI Driver][DB2/6000] SQL4301N
Java interpreter startup or communication failed, reason code "0".
SQLSTATE=58004

at java.sql.SQLException.<init>(Compiled Code)
at COM.ibm.db2.jdbc.app.DB2Exception.<init>(Compiled Code)
at
COM.ibm.db2.jdbc.app.SQLExceptionGenerator.throw_SQLException(Compiled
Code)
at
COM.ibm.db2.jdbc.app.SQLExceptionGenerator.check_return_code(Compiled
Code)
at COM.ibm.db2.jdbc.app.DB2CallableStatement.execute2(Compiled
Code)
at COM.ibm.db2.jdbc.app.DB2PreparedStatement.execute(Compiled Code)
at DB2SpCli.callStoredProc(Compiled Code)
at DB2SpCli.main(Compiled Code)

Solution

Reconfigure the DB2 instance to point to the correct JDK on the machine. For
example, it may be in /usr/jdk_base, although it could be installed anywhere,
as in /usr/lpp/J1.8.1. Your DBA reconfigures this value. It can be seen doing
a get dbm cfg, DB2 command, or by looking at the Instance configuration
values from Control Center.

6.7.2.2 SQL10013N The specified library could not be loaded

Symptom

When trying to execute a Java stored procedure, an error message says the
<DB2HOME>/sqllib/function/<Java class name> could not be loaded.
Example:
COM.ibm.db2.jdbc.app.DB2Exception: [IBM][CLI Driver][DB2/6000] SQL10013N
The specified library "/u/db2inst3/sqllib/function/Add_customer" could not
be loaded.

Chapter 6. Coding Java stored procedures 113


at java.sql.SQLException.<init>(Compiled Code)
at COM.ibm.db2.jdbc.app.DB2Exception.<init>(Compiled Code)
at
COM.ibm.db2.jdbc.app.SQLExceptionGenerator.throw_SQLException(Compiled
Code)
at
COM.ibm.db2.jdbc.app.SQLExceptionGenerator.check_return_code(Compiled
Code)
at COM.ibm.db2.jdbc.app.DB2CallableStatement.execute2(Compiled
Code)
at COM.ibm.db2.jdbc.app.DB2PreparedStatement.execute(Compiled Code)
at call_Add_customer_with_userid.main(Compiled Code)

Solution

The JAR or class has not been made available to the database. If you are
using JAR files, you must use the ‘sqlj.install_jar’ routine.

If you are not using JAR files, you copy the .class to location specified in the
statement.

6.7.2.3 SQL20201N JAR name is invalid during sqlj.install_jar

Symptom

An error message is produced when trying to insert a valid JAR name.

Example
The command:
call
sqlj.install_jar('file:/u/db2inst3/apps/ACMESUS/ACMESUS.jar','ACMESUS');

Produced the error message:


SQL20201N The install, replace or remove of "ACMES .ACMESUS" failed as
the jar name is invalid. SQLSTATE=46002

Solution

The JAR is already defined to the database. You need to remove it or replace
it.

114 DB2 Java Stored Procedures: Learning by Example


6.7.2.4 SQL1000N CALL" is not a valid database alias name

Symptom

When issuing any sqlj.xxxxxx command from Windows NT, such as:

call sqlj.refresh_classes(void)

You receive the following error message:

SQL1000N "CALL" is not a valid database alias name.

Solution

This is a maintenance issue, which has been resolved in Version 7 Fixpak 1.


Note that despite this message, the command actually works.

6.7.2.5 The sqlj command hangs

Symptom

The sqlj command “hangs” after producing .java and .ser files.

Possible Solution

Try using the -compile=false option to split the precompile step from the Java
compile. Often, sqlj will complete successfully and a subsequent javac will
reveal Java errors that need to be corrected in your program source.

6.7.2.6 SQLCODE -818 when executing SQLJ stored procedure

Symptom

Client receives SQLCODE -818 (timestamp mismatch error) when trying to


invoke an SQLJ stored procedure on the Windows NT or AIX platform, even
after the program preparation process has been completely re-run.

Possible Solution

Check the subdirectories within the SQLLIB/function directory to ensure that


an old version of the .jar file containing your stored procedure code has not
found its way into another directory. If this happens, DB2 may pick up the old
version, generating the -818 error. Try to remove the old version using the
sqlj.remove_jar command; if that fails, simply delete the culprit.

Chapter 6. Coding Java stored procedures 115


6.7.2.7 SQL4304N .. could not load Java class reason code "1"

Symptom

When trying to execute a Java stored procedure that appears to have


installed correctly, the following error message returns to the client:
COM.ibm.db2.jdbc.app.DB2Exception: [IBM][CLI Driver][DB2/6000] SQL4304N
Java stored procedure or user-defined function "ACMEBUS .ADD_CUSTOMER",
specific name "SQL000322080850190" could not load Java class
"ACMEBUS/Add_customer", reason code "1". SQLSTATE=42724

Solution

This is typically caused by forgetting to change the Java package name in the
Java source code after having copied source code from one directory to
another. Everything compiles and installs fine. However, during execution the
stored procedure actually has a different Java package name. It is peculiar
that the mismatch is not found during the javac step.

6.7.2.8 SQLCODE==> -965 SQLSTATE ==> 51021

Symptom

The system cannot find a matching method (stored procedure), even if you
were able to install it in the database with no errors.
java.sql.SQLException: DB2JDBCSection Received Error in Method
execute_call:SQLCODE==> -965 SQLSTATE ==> 51021 Error Tokens ==> <<DB
2/OS390 V5.1 ANSI SQLJ-0/JDBC 1.0>> QUERY_OI_SUMM
java.lang.NoSuchMethodError: query_oi_summ ^20^L ^20^L ^20^L ^20^L ^20^L
at
COM.ibm.db2os390.sqlj.jdbc.DB2SQLJJDBCSection.setError(DB2SQLJJDBCSection.
java:1049)
at
COM.ibm.db2os390.sqlj.jdbc.DB2SQLJJDBCSection.execute_call(DB2SQLJJDBCSect
ion.java:874)
at
COM.ibm.db2os390.sqlj.jdbc.DB2SQLJCallableStatement.execute(DB2SQLJCallabl
eStatement.java:116)
at jecall_Query_oi_summ.main(jecall_Query_oi_summ.java:86)

116 DB2 Java Stored Procedures: Learning by Example


Solution

The number of parameters the client sent to DB2 does not match the number
of parameters that DB2 understands the stored procedure to contain. This
often is caused by forgetting to set the number of ResultSets when defining
the stored procedure.

This is somewhat perplexing when comparing source code against the stored
procedure definition. The source code may show, for example, 5 parameters,
yet the stored procedure definition shows 4. The difference is in the
‘ResultSets’ value of the definition. Consequently, (the number of parameters
in the source code) should equal ((the number of parameters in the stored
procedure definition) + (the number of ResultSets in the stored procedure
definition)).

6.7.2.9 SQLCODE==> -471 SQLSTATE ==> 55023

Symptom

The client returns an error message similar to this:


ava.sql.SQLException: DB2JDBCSection Received Error in Method
execute_call:SQLCODE==> -471 SQLSTATE ==> 55023 Error Tokens ==> <<DB
2/OS390 V5.1 ANSI SQLJ-0/JDBC 1.0>> QUERY_OI_SUMM 00E79001 ^20^L
at
COM.ibm.db2os390.sqlj.jdbc.DB2SQLJJDBCSection.setError(DB2SQLJJDBCSection.
java:1049)
at
COM.ibm.db2os390.sqlj.jdbc.DB2SQLJJDBCSection.execute_call(DB2SQLJJDBCSect
ion.java:874)
at
COM.ibm.db2os390.sqlj.jdbc.DB2SQLJCallableStatement.execute(DB2SQLJCallabl
eStatement.java:116)
at jecall_Query_oi_summ.main(jecall_Query_oi_summ.java:86)

Solution

Recognize where the error is being seen: at the client, or when trying to
invoke the stored procedure. The SQLSTATE value (the Class Code value of
55) implies that the object is not in the prerequisite state. From a stored
procedure perspective, it means that a previous incarnation of the stored
procedure ended badly in the database, putting it into a state that prevents it
from being executed. Contact your DBA to determine the best method to
make it available again.

Chapter 6. Coding Java stored procedures 117


6.7.2.10 JNI panic during db2profc

Symptom

Error message from db2profc similar to:

[IBM][SQLJ Driver] SQJ0001W Customizing profile


"sscall_Add_customer_SJProfile0"

JNI panic: JNI received a null class at


COM.ibm.db2.sqlj.DB2SQLJInstaller.customizeProfile(DB2SQLJInstaller.j

ava:263)

at
COM.ibm.db2.sqlj.DB2SQLJInstaller.main(DB2SQLJInstaller.java:1204)

Solution

One cause may be special characters embedded within the SQL, such as
newlines. Carefully replace all whitespace within the SQL (or delete the
whitespace).

6.7.2.11 Cannot call a schema-qualified stored procedure

Symptom

During db2profc, an error message returns indicating that several stored


procedures match the name. (However, the source code has qualified the call
with a Schema).

The error message looks like:

sscall_Add_customer.sqlj:76.1-79.6: Error: Unable to resolve stored


procedure ACMESNS.ADD_CUSTOMER - 2 declarations match this call.

Total 1 error.

Solution

There may be a fix available for this error....investigate the IBM DB2 Web site
for availability. Alternatively, use a unique stored procedure name that is not
shared across schemas.

118 DB2 Java Stored Procedures: Learning by Example


Chapter 7. Preparing Java stored procedures

As with any programming language, there are steps required to transform the
source code into something that can be executed. This chapter describes the
steps required for Java stored procedure preparation.

7.1 Program preparation concepts


Preparing a Java stored procedure for DB2 requires the same basic steps
regardless of the platform:
1. Translate and customize (if stored procedure uses SQLJ — not required
for JDBC).
2. Bind extracted SQL into DB2 packages (if stored procedure uses SQLJ —
not required for JDBC).
3. Compile Java.
4. Package Java .class files into correct format for deployment platform.

The details of each step vary, depending upon the platform and the type of
source (JDBC or SQLJ), and are described in the following sections.

7.2 OS/390 Java stored procedure preparation


As WLM-managed stored procedure address spaces do not yet support a
Java Virtual Machine (JVM) environment, it is necessary to convert Java
.class files into OS/390 executable modules. This is done using the IBM High
Performance Java Compiler, part of VisualAge for Java Enterprise Edition for
OS/390.

OS/390 supports both JDBC and SQLJ stored procedures, and the
preparation process for each is described in the following sections. Note that
if a procedure uses both SQLJ and JDBC, the SQLJ preparation process
should be used.

7.2.1 Java stored procedure and DB2 package


Assuming that your Java stored procedure accesses DB2 in some way, the
program preparation process needs to produce either a DBRM or set of
DBRMs that can be bound into the DB2 package for the client issuing the
SQL CALL to the stored procedure.

© Copyright IBM Corp. 2000 119


For JDBC stored procedures, all that is required are the 4 generic JDBC DB2
packages that are bound at the time JDBC support is installed (called
DSNJDBC1, DSNJDBC2, DSNJDBC3 and DSNJDBC4).

For SQLJ stored procedures, 4 application specific DB2 packages will be


produced as part of the program preparation process.

See 9.1, “DB2 plans and packages” on page 167 for a discussion on how
these are used when binding client program plans.

7.2.2 DB2 authorization issues


This section describes some of the authorization issues you will need to
consider, both during the program preparation process and at run time.

Note that this section covers authorization issues from the stored procedure
perspective only. Additional considerations apply to client authorization, and
these are covered in 9.3, “Client authorization issues” on page 174.

7.2.2.1 SQLJ stored procedures


As SQLJ stored procedures use static SQL, authorization is relatively
straightforward.

Authorization checking is performed at the time the SQLJ DB2 packages for
the stored procedure are bound to DB2 (see 7.2.4, “OS/390 SQLJ program
preparation process” on page 129), and you may use any of the usual BIND
parameters (such as OWNER and QUALIFIER) to achieve the security environment
you need.

The authorization ID binding the client plan will require EXECUTE authority on
the stored procedure DB2 packages (see 9.1, “DB2 plans and packages” on
page 167).

7.2.2.2 JDBC stored procedures


As JDBC stored procedures use dynamic SQL, the authorization issues
become a lot more complex.

When trying to understand the DYNAMICRULES options discussed below, you


should remember that DB2 first attempts to use the option specified for the
generic JDBC stored procedure DB2 packages. If DYNAMICRULES is not
specified for the packages, DB2 will use the value specified in the client plan.

If you do not explicitly code a value for the DYNAMICRULES option at the time you
bind the JDBC generic DB2 packages (DSNJDBC1, DSNJDBC2, DSNJDBC3, and
DSNJDBC4) or the client plan, then by default DB2 will use run behavior.

120 DB2 Java Stored Procedures: Learning by Example


Authorization checking for any dynamic SQL statements executed by the
JDBC stored procedure will be conducted using the CURRENT SQLID of the client
application (which is set to the client’s primary authorization ID unless
explicitly changed with a SET CURRENT SQLID statement prior to the stored
procedure call). Therefore, all client authorization IDs must be given the
necessary access to any tables that may be used by the stored procedure,
which can be undesirable from a security and administration perspective.

Use of DYNAMICRULES(BIND) when binding the JDBC generic DB2 packages or


the client plan causes DB2 to use bind behavior. The authorization ID of the
DB2 package owner will be used for authorization checking, which removes
the requirement to give table access to each client authorization ID. Note that
use of this option will prevent the stored procedure from being able to use the
SQL GRANT, REVOKE, CREATE, ALTER, DROP and RENAME statements.

Two new options in DB2 for OS/390 V6 provide even more flexibility, due to
the implementation of stored procedure schema support.

Specifying DYNAMICRULES(DEFINEBIND) when binding the JDBC generic DB2


packages or the client plan causes DB2 to use define behavior. The
authorization ID of the owner (or schema) of the stored procedure will be
used for authorization checking. This allows a number of alternative security
strategies to be considered (for example, you could create the stored
procedure in the same schema as your DB2 tables, which would implicitly
give the stored procedure access to any tables in that schema).

DYNAMICRULES(DEFINERUN)
For stored procedure DB2 packages, use of the DYNAMICRULES(DEFINERUN)
option is equivalent to DYNAMICRULES(DEFINEBIND).

Specifying DYNAMICRULES(INVOKEBIND) when binding the JDBC generic DB2


packages or the client plan causes DB2 to use invoke behavior. If the CURRENT
SQLID is set to the primary authorization ID of the client process at the time of
the stored procedure call, both the primary authorization ID and all secondary
authorization IDs are used for authorization checking. Otherwise, just the
CURRENT SQLID is used.

Chapter 7. Preparing Java stored procedures 121


DYNAMICRULES(INVOKERUN)
For stored procedure DB2 packages, use of the DYNAMICRULES(INVOKERUN)
option is equivalent to DYNAMICRULES(INVOKEBIND).

For a full explanation of the DYNAMICRULES BIND option, refer to DB2 UDB
for OS/390 Command Reference , SC26-9006.

7.2.3 OS/390 JDBC program preparation process


If the source contains JDBC statements, the program preparation process is
as shown in Figure 14.

Java
Source 1
Bytecode 4
Java CREATE
prog.JAVA
Compiler Other PROCEDURE
prog.CLASS or
(JAVAC) CLASS files INSERT into
SYSPROCEDURES

3
JAR 2

HPJ
Compiler
DB2
Catalog

.JAR file
External
Link
JLL in
Optional Step
PDSE

Can run on any JDK


platform

Run on S/390
platform

Figure 14. OS/390 JDBC program preparation process

1. From within USS, Java-compile the source code (using the javac
command). This produces one or more .class files, which represent the
Java bytecode for your procedure.
2. If you wish, you may package multiple .class files into a single .jar file via
the jar command. This step is entirely optional, and as we are already
packaging multiple .class files into a single OS/390 executable in the HPJ
step next anyway, we elected to omit it.

122 DB2 Java Stored Procedures: Learning by Example


3. HPJ-compile the .class files produced in step 2 to create an OS/390 Java
DLL. This module resides in a PDSE data set, but HPJ also creates an
external link to the module, to allow it to be referenced from within the USS
environment.
4. Define the stored procedure to DB2 (via an INSERT into
SYSIBM.SYSPROCEDURES for DB2 for OS/390 V5, or via CREATE PROCEDURE if you
are using DB2 UDB for OS/390 V6). Unlike DB2 UDB for UNIX and DB2
UDB for Windows NT, DB2 for OS/390 allows you to perform this step
before the stored procedure exists.

Use of COLLID
We recommend that you explicitly specify the DB2 package collection
that your stored procedure DB2 packages will reside in.
For JDBC stored procedures, you will specify the DB2 package
collection that the 4 generic JDBC packages belong to (these generic
packages will have been created when JDBC support was installed,
using the db2genJDBC utility - see “JDBC Support” on page 59).
The way in which you can accomplish this depends upon the release of
DB2 UDB for OS/390 you are using:
- For DB2 UDB for OS/390 V5, you can provide a value for the COLLID
column when performing the INSERT into SYSIBM.SYSPROCEDURES.
- For DB2 UDB for OS/390 V6, you can specify the COLLID keyword on
the CREATE PROCEDURE statement.
If you do not do this, you will be forced to bind the 4 JDBC DBRMs into
DB2 packages belonging to the same collection as the client’s DB2
package. See 9.1, “DB2 plans and packages” on page 167 for more
details).

Development platform
Steps 1 and 2 of this process can be performed on any platform that
contains a suitable JDK. We performed them within UNIX Systems
Services (USS) within an S/390 environment.

Steps 3 and 4 must be performed on the S/390 platform.

Chapter 7. Preparing Java stored procedures 123


7.2.3.1 OS/390 JDBC detailed preparation example
The example JDBC stored procedure has been coded with this Java package
statement:
package ACMEJOS;

Java package statement


The use of package statements is obligatory on the S/390 platform.

To build this program, go up one directory from the source. For example, if
your source was in /U/DB2RES3/ACMEJOS/Add_customer.java, then you change
directory to /U/DB2RES3 to execute the build statements.

Start by compiling your Java source using the javac Java command, as
follows:
javac ACMEJOS/Add_customer.java

The resulting .class files are placed in the ACMEJOS subdirectory.

Next, you need to perform the HPJ compile. Here is the command as we
used:
hpj -o "//'SG245945.HPJSP.PDSE(ACMEJOS)'" \
-alias ACMEJOS.jll \
-O \
-jll \
-nofollow \
-t /u/sysadm/links \
ACMEJOS/Add_customer \
>hpj.map 2>&1

Refer to the VisualAge for Java Version 2.0 ET/390 Reference for a full
explanation of the hpj command parameters. Here is a brief description of the
main ones used in the command above:
• -o specifies the output PDSE data set that will contain the OS/390
executable. This data set must be allocated to your WLM address space
(see JCL procedure sample shown in 4.1.6.2, “JCL procedure of a Java
WLM-established address space” on page 67).
• -alias specifies the name of the alias to be created in the output PDSE
data set. This must correspond with the Java package name within your
stored procedure code.

124 DB2 Java Stored Procedures: Learning by Example


• -t specifies the name of the USS directory used to store links to the PDS
data set.

Upon completion of the compile, you should have an OS/390 executable and
alias within your PDSE data set, and a link to the executable within your USS
links library. For an overview of the runtime environment for an SQLJ stored
procedure, see Figure 13 on page 95.

If you have not done so already, you now need to define your stored
procedure to DB2. The location of your stored procedure is specified using
the format <package>.<class>.<method>, where <package> is the Java package
name, and <class> and <method> are the class and method names defined in
your code.

DB2 for OS/390 Version 5 requires you to manually insert a row into
SYSIBM.SYSPROCEDURES:
INSERT INTO SYSIBM.SYSPROCEDURES
(PROCEDURE,AUTHID,LUNAME,LOADMOD,LINKAGE,COLLID,
LANGUAGE,ASUTIME,STAYRESIDENT,IBMREQD,
RUNOPTS,
PARMLIST,
RESULT_SETS,WLM_ENV,PGM_TYPE, EXTERNAL_SECURITY,COMMIT_ON_RETURN)
VALUES(
'JS_ADD_CUSTOMER', '', '', '', 'N', 'DSNJDBC',
'COMPJAVA', 900, '','N',
'ACMEJOS/Add_customer.add_customer',
'CHAR(20) IN, CHAR(20) IN, CHAR(30) IN, INTEGER OUT, CHAR(40) OUT,
CHAR(240) OUT',
0,'WLM_JAVA_DB21','S','N','N'
);

Note
For DB2 for OS/390 Version 5, the RUNOPTS column of SYSPROCEDURES is used
to store the procedure name, and the LOADMOD column is ignored. This is
due to the fact that LOADMOD can only hold 8 characters.

DB2 UDB for OS/390 Version 6 provides full DDL and schema support for
stored procedures, so the equivalent command would be as follows:
CREATE PROCEDURE ACMEJOE.ADD_CUSTOMER
(
IN FIRSTNAME CHAR(20),
IN LASTNAME CHAR(20),
IN ADDRESS CHAR(30),
OUT CUSTNO INTEGER,

Chapter 7. Preparing Java stored procedures 125


OUT MARK CHAR(40)
OUT MARK_ERROR_TEXT CHAR(200)
)
FENCED
MODIFIES SQL DATA
LANGUAGE COMPJAVA
EXTERNAL NAME(ACMEJOE.Add_customer.add_customer)
PARAMETER STYLE JAVA
COLLID DSNJDBC
WLM ENVIRONMENT DBS1JAVAWLM
DYNAMIC RESULT SETS 0
PROGRAM TYPE SUB;

Use of COLLID
In the example above, we have specified a DB2 package collection of
DSNJDBC for the JDBC stored procedure. This is the name of the
collection we bound the 4 generic JDBC DBRMs into at the time JDBC
support was installed. See “JDBC Support” on page 59 for further details.

The stored procedure is now ready for execution.

7.2.3.2 Sample program preparation scripts


We used the scripts below for JDBC program preparation.

Note: These scripts can be found on the CD-ROM, in the SAMPLES\S390


UTILITIES\PROGRAM PREPARATION directory. Refer to Appendix E, “Using the
additional material” on page 347 for more information.

The entire process is invoked from the USS command line using a syntax
such as:
javaspj Add_customer ACMEJOS ACMEJOS acmes ACMEJOS

This can be found in script driver_josj.

Script javaspj — prepare JDBC stored procedure


This script performs the main program preparation tasks, and calls script
hpjsp to perform the HPJ compile.
# JDBC stored procedure with no SQLJ
# phase 1 javac
# phase 2 hpj
#
# Call format for shell is => javaspj pgm pkg mem qualifier pdsemem

126 DB2 Java Stored Procedures: Learning by Example


# Example => javaspj $1 $2 $3 $4
# $1= Java class name
# $2= Java package name
# << $3 Not used for JDBC only >>
# $3= Member package name used for binds - limit 7
# $4= Table qualifier
# $5= OS/390 PDSE member name - uppercase limit 8
#
pgm=$1
# pgm is the Java class name.
#
pkg=$2
# pkg is the used for the SP package collection, JAVA package,
# directory where the JAVA code is.
#
mem=$3
# Member package name used for binds - limit to 7 characters
#
qual=$4
# qual is the table qualifier
pdse=$5
# pdse is the OS/390 PDSE member name - uppercase limit to 8 characters
#
# set directory to Java code
#cd $pkg
#pgmuln=$1'_SJProfile0'
#echo $pgmuln

echo "Starting phase 1 - JDBC javac for" $pkg $pgm


javac $pkg/${pgm}.java

echo "Starting phase 2 - JDBC hpj compile"


hpjsp $pkg $pdse

#
echo "JDBC build for" $pkg $pgm "complete"

Chapter 7. Preparing Java stored procedures 127


Script hpjsp — perform HPJ compile
This script executes the HPJ compile process, to create an OS/390
executable module from the Java classes.
echo "Starting hpj for $1 $2"
U2=`echo $2 | tr 'a-z' 'A-Z'`
echo "current dir is `pwd`"
echo "building member in SG245945.HPJSP.$SSID.PDSE($U2)"
echo "building links in /u/$SSID/links"
CLASSES_TO_USE=`ls $1/*.class | sed 's/.class//'`
echo "using classes $CLASSES_TO_USE "
# -classpath .:/usr/lpp/hpj/lib/classes.zip \
hpj -o "//'SG245945.HPJSP.$SSID.PDSE($U2)'" \
-alias $1.jll \
-O \
-jll \
-nofollow \
-t /u/$SSID/links \
$CLASSES_TO_USE \
>hpj$1.map 2>&1
echo 'Ended hpj for ' $1 $2 ' - results'
more hpj$1.map

128 DB2 Java Stored Procedures: Learning by Example


7.2.4 OS/390 SQLJ program preparation process
If your Java stored procedure was written using SQLJ, or a combination of
SQLJ and JDBC, the program preparation process is somewhat more
complex, as shown in Figure 15.

SQLJ
Java
Source 1 Compiler Other
prog.JAVA prog.CLASS
(JAVAC) CLASS files
SQLJ
prog.SQLJ Translator

3
prog_
JAR
Profile 5 SJProfileKeys.class
Customiser prog_
(DB2PROFC) SJProfile0.ser
4
Serialized
Profile .JAR file
HPJ
DBRM
Compiler
DBRM Optional Step

External
DB2 BIND 6 Link
PACKAGE JLL in Can run on any JDK
PDSE platform
7 CREATE
PROCEDURE Run on S/390
or platform
DB2 INSERT into
SYSPROCEDURES
Catalog

Figure 15. OS/390 SQLJ program preparation process

1. From USS, translate your source code using the sqlj command. This will
extract all of the embedded SQL from your code and place it in an SQLJ
serialized profile (a kind of generic, database independent DBRM).
Serialized profiles are stored in .ser files. Your source code will be
modified, and placed in a .java file.
2. Java-compile the source code (using the javac command). This will
produce at least two .class files — one containing your code and one
containing the SQLJ access “stub”.

Chapter 7. Preparing Java stored procedures 129


Note
Unless you specifically request otherwise by specifying the
-compile=false option, javac will be automatically executed by sqlj and
there is no need to perform this step separately.

3. If you wish, you may package multiple .class (or .jar) files into a single
.jar file via the jar command. This step is entirely optional, and as we are
already packaging multiple .class files into a single OS/390 executable in
the HPJ step next anyway, we elected to omit it.
4. HPJ-compile the .class files produced in step 2 to create an OS/390
executable module. This module resides in a PDSE data set, but HPJ also
creates an external link to the module, to allow it to be referenced from
within the USS environment.
5. Execute the DB2 profile customizer using the db2profc command. This
translates the generic serialized profile created in step 1 into a set of 4
DB2 for OS/390 DBRMs (one for each type of isolation level: repeatable
read, read stability, cursor stability and uncommitted read).
6. Bind the 4 DBRMs produced by db2profc into DB2 packages using
standard DB2 for OS/390 BIND PACKAGE commands. The DB2 packages can
belong to any DB2 package collection - in our examples we named the
DB2 package collection after the Java package name.
7. Define the stored procedure to DB2 (via an INSERT into
SYSIBM.SYSPROCEDURES for DB2 for OS/390 V5, or via CREATE PROCEDURE if you
are using DB2 UDB for OS/390 V6).

130 DB2 Java Stored Procedures: Learning by Example


Use of COLLID
We recommend that you explicitly specify the DB2 package collection
that your stored procedure DB2 packages will reside in.
For SQLJ stored procedures, you will specify the DB2 package
collection that you bound your 4 application specific DBRMs into earlier.
The way in which you can accomplish this depends upon the release of
DB2 UDB for OS/390 you are using;
- For DB2 UDB for OS/390 V5, you can provide a value for the COLLID
column when performing the INSERT into SYSIBM.SYSPROCEDURES.
- For DB2 UDB for OS/390 V6, you can specify the COLLID keyword on
the CREATE PROCEDURE statement.
If you do not do this, you will be forced to bind the 4 SQLJ DBRMs into
DB2 packages belonging to the same collection as the client’s DB2
package. See 9.1, “DB2 plans and packages” on page 167 for more
details).

Development platform
Steps 1 to 3 of this process can be done on any platform that contains a
suitable JDK. We performed them within UNIX Systems Services (USS) in
an S/390 environment.

Steps 4 to 7 must be performed on the S/390.

7.2.4.1 OS/390 SQLJ detailed preparation example


The SQLJ stored procedure has been coded with this Java package
statement:
package ACMESOS;

The Java package statement


The use of package statements is obligatory on the S/390 platform.

To build this program, go up one directory from the source. For example, if
your source was in /U/DB2RES3/ACMESOS/Add_customer.java, then you change
directory to /U/DB2RES3 to execute the build statements.

Start by precompiling your SQLJ source program using the sqlj command, as
follows:

Chapter 7. Preparing Java stored procedures 131


sqlj ACMESOS/Add_customer.sqlj

Use of SQLJ command


Due to an oddity in our environment, we were forced to fully qualify the
location of the sqlj routine in order to get it to work with SQLJ source files
that were located in subdirectories. The command we used was:

/usr/lpp/db2/db2510/bin/sqlj ACMESOS/Add_customer.sqlj

This can be made more generic by using the whence command to return the
location of sqlj in your environment, like this:

`whence sqlj` $pkg/$pgm.sqlj

This is the command that appears in our sample preparation scripts.

By default, sqlj will also invoke javac (the Java compiler) to save you from
having to do this separately afterwards (to disable this and run javac yourself,
use the -compile=false option).

Assuming that you elected to automatically run javac as part of sqlj, the
output of the command will be:
• A .java file containing a modified version of your source. As this will be
immediately input to javac to produce .class files, the .java file plays no
further part in the program preparation process and may be considered an
intermediate temporary file.
• At least two Java .class files (one for your stored procedure code and one,
called <classname>_SJProfileKeys.class, for the SQLJ stub).
• A serialized profile, called <classname>_SJProfile0.ser. This contains the
SQL statements extracted by the sqlj process, in a generic database
independent format.

Next, we need to perform the HPJ compile. Here is the command we used
during our tests:
hpj -o "//'SG245945.HPJSP.PDSE(ACMESOS)'" \
-alias ACMESOS.jll \
-O \
-jll \
-nofollow \
-t /u/sysadm/links \
ACMESOS/Add_customer \
ACMESOS/Add_customer_SJProfileKeys \
>hpj.map 2>&1

132 DB2 Java Stored Procedures: Learning by Example


Refer to the VisualAge for Java Version 2.0 ET/390 Reference1, for a full
explanation of the hpj command parameters. Here is a brief description of the
main ones used in the commands above:
• -o specifies the output PDSE data set that will contain the OS/390
executable. This data set must be allocated to your WLM address space
(see JCL procedure sample shown in 4.1.6.2, “JCL procedure of a Java
WLM-established address space” on page 67).
• -alias specifies the name of the alias to be created in the output PDSE
data set. This must correspond with the Java package name within your
stored procedure code.
• -t specifies the name of the USS directory used to store links to the PDS
data set.

Including the correct class files


You need to include all of the .class files produced by the sqlj step in the
hpj compile, including the <classname>_SJProfileKeys.class stub.

Upon completion of the compile, you should have an OS/390 executable and
alias within your PDSE data set, and a link to the executable within your USS
links library. For an overview of the runtime environment for an SQLJ stored
procedure, see Figure 13 on page 95.

Next, you need to execute db2profc, which takes the serialized profile created
by sqlj above and creates four DB2 for OS/390 DBRMs. Below is an example
of how to invoke the db2proc:

db2profc -pgmname=ACMESOS ACMESOS/Add_customer_SJProfile0.ser

In our example, the DBRMs that would be generated are called ACMESOS1,
ACMESOS2, ACMESOS3 and ACMESOS4.These DBRMS are used to represent the
different isolation levels that could be used (UR, CS, RS and RR for
ACMESOS1 to 4 respectively).

The DBRMs will be placed in the PDS specified in the DB2SQLJDBRMLIB


parameter of your SQLJ properties data set (see 4.1.8, “Step 6: Set up the
JAVAENV data set” on page 69). In the examples below, the PDS is
SG246945.SAMPLIB.DBRM.

Now we have our DBRMs, we can BIND them. The DB2 packages we bind can
belong to any DB2 package collection. In our example we are using a DB2
1 At the time of writing, the ET/390 manuals did not have formal IBM publication numbers. However, they can be

downloaded from the Web in PDF format at http://www-4.ibm.com/software/ad/vajava/library.htm.

Chapter 7. Preparing Java stored procedures 133


package collection named after the Java package referenced in our stored
procedure:
BIND PACKAGE(ACMESOS)
MEMBER(ACMESOS1)
ACT(REP)
ISOLATION(UR)
VALIDATE(BIND)
LIBRARY('SG246945.SAMPLIB.DBRM')
QUALIFIER(ACMES)

BIND PACKAGE(ACMESOS)
MEMBER(ACMESOS2)
ACT(REP)
ISOLATION(CS)
VALIDATE(BIND)
LIBRARY('SG246945.SAMPLIB.DBRM')
QUALIFIER(ACMES)

BIND PACKAGE(ACMESOS)
MEMBER(ACMESOS3)
ACT(REP)
ISOLATION(RS)
VALIDATE(BIND)
LIBRARY('SG246945.SAMPLIB.DBRM')
QUALIFIER(ACMES)

BIND PACKAGE(ACMESOS)
MEMBER(ACMESOS4)
ACT(REP)
ISOLATION(RR)
VALIDATE(BIND)
LIBRARY('SG246945.SAMPLIB.DBRM')
QUALIFIER(ACMES)

If you have not done so already, you now need to define your stored
procedure to DB2. The location of your stored procedure is specified using
the format <package>.<class>.<method>, where <package> is the Java package
name, and <class> and <method> are the class and method names defined in
your code.

DB2 for OS/390 Version 5 requires you to manually insert a row into
SYSIBM.SYSPROCEDURES;
INSERT INTO SYSIBM.SYSPROCEDURES
(PROCEDURE,AUTHID,LUNAME,LOADMOD,LINKAGE,COLLID,
LANGUAGE,ASUTIME,STAYRESIDENT,IBMREQD,

134 DB2 Java Stored Procedures: Learning by Example


RUNOPTS,
PARMLIST,
RESULT_SETS,WLM_ENV,PGM_TYPE, EXTERNAL_SECURITY,COMMIT_ON_RETURN)
VALUES(
'SS_ADD_CUSTOMER', '', '', '', 'N', 'ACMESOS',
'COMPJAVA', 900, '','N',
'ACMESOS/Add_customer.add_customer',
'CHAR(20) IN, CHAR(20) IN, CHAR(30) IN, INTEGER OUT, CHAR(40) OUT,
CHAR(240) OUT',
0,'WLM_JAVA_DB21','S','N','N'
);

Note
For DB2 for OS/390 Version 5, the RUNOPTS column of SYSPROCEDURES is used
to store the procedure name. This is due to the fact that the LOADMOD column
can only hold 8 characters.

DB2 UDB for OS/390 Version 6 provides full DDL and schema support for
stored procedures, so the equivalent command would be as follows:
CREATE PROCEDURE ACMESOE.ADD_CUSTOMER
(
IN FIRSTNAME CHAR(20),
IN LASTNAME CHAR(20),
IN ADDRESS CHAR(30),
OUT CUSTNO INTEGER,
OUT MARK CHAR(40)
OUT MARK_ERROR_TEXT CHAR(200)
)
FENCED
MODIFIES SQL DATA
LANGUAGE COMPJAVA
EXTERNAL NAME(ACMEJOE.Add_customer.add_customer)
PARAMETER STYLE JAVA
COLLID ACMESOS
WLM ENVIRONMENT DBS1_JAVA_WLM
DYNAMIC RESULT SETS 0
PROGRAM TYPE SUB;

The stored procedure is now ready for execution.

7.2.4.2 Sample program preparation scripts


We used the scripts below for SQLJ program preparation. These scripts can
be found on the CD-ROM, in the SAMPLES\S390 UTILITIES\PROGRAM PREPARATION

Chapter 7. Preparing Java stored procedures 135


directory. Refer to Appendix E, “Using the additional material” on page 347
for more information.

The entire process is invoked from the USS command line using a syntax
such as:
javasp Add_customer ACMESOS addcust acmes ACMESOS

This can be found in script driver_sos.

Script javasp — prepare SQLJ stored procedure


This script performs the main program preparation tasks, and calls scripts
hpjsp to perform the HPJ compile and bindsp to create and execute the
necessary BIND statements.
# java stored procedure with SQL
# phase 1 SQLJ translator
# phase 2 db2profc create DBRMs
# phase 3 HPJ compile
# phase 4 bind packages
# phase 5 copy *.ser files
#
# Call format for shell is => javasp nam pkg mem qualifier pdsemem
# Example => javasp $1 $2 $3 $4
# $1= Java class name
# $2= Java package name
# $3= Member package name used for binds - limit 7
# $4= Table qualifier
# $5= OS/390 PDSE member name - uppercase limit 8
#
pgm=$1
# pgm is the Java class name.
pkg=$2
# pkg is the used for the SP package collection, JAVA package,
# directory where the JAVA code is, HPJ module name and DB2 package
# collection name
mem=$3
# mem package name used for binds - limit to 7 characters
qual=$4
# qual is the table qualifier
pdse=$5
# pdse is the OS/390 PDSE member name - uppercase limit to 8 characters
#

pgmuln=$1'_SJProfile0'
echo $pgmuln
echo "Starting phase 1 - SQLJ translator" $pkg $pgm

136 DB2 Java Stored Procedures: Learning by Example


`whence sqlj` $pkg/$pgm.sqlj

echo "Starting phase 2 - db2profc"


db2profc -pgmname=$mem $pkg/$pgmuln.ser
echo "Starting phase 3 - HPJ compile"
hpjsp $pkg $pdse
#
echo "Starting phase 4 - bind plans"

bindsp.rexx $mem $pkg $qual

umem=`echo $mem | tr 'a-z' 'A-Z'`


cat bind$SSID$umem.out | sed 's/ *$//'

#
# copy *.ser files to /u/$SSID/ser
#

echo "Starting phase 5 - copying *.ser files to /u/$SSID/ser"


cp $pkg/*.ser /u/$SSID/ser/$pkg
chmod 777 /u/$SSID/ser/$pkg/*

echo "Build for" $pkg $pgm "complete"

Script hpjsp — perform HPJ compile


See “Script hpjsp — perform HPJ compile” on page 128.

Script bindsp.rexx — generate/execute BIND PACKAGE commands


This script builds the bind statements and passed them to the TSO REXX
exec OEBIND.
/* rexx Unix System Services (USS) */
/* bindsp.rexx MEM PKG qual */
/* called by JAVA prep shell scripts to bind the stored procedure */
/* packages. */
/* */
/* 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. */
/* Written 03/05/200 by Michael J. Fischer */
/* */
/* Input parms: 3 */
/* MEM package base name */

Chapter 7. Preparing Java stored procedures 137


/* PKG Collection name (java Package
name) */
/* qual Table qualifier name used for
unqualified tables. */
/* MEM DBRM member name used for the
PDSE library */
/* PKG Package name for bind. */
/* qual Table qualifier name used for
unqualified tables. */
/* */
/* Calls TSOE rexx program "OEBIND" to run DSN in TSOE */
/* environment. This was done so the JAVA prep shell scripts */
/* can run in the OMVS or telnet environment. DSN will not run */
/* under telnet. */
/* */
/* To display help enter bindsp.rexx ? or bindsp.rexx '?' */
/* */
/* Note: In USS the ? is converted to a 2 */

arg MEM PKG qual

if MEM = "?" | MEM = 2 then do


do i = 1 while substr(sourceline(i),1,2) = "/*"
say sourceline(i)
end
return 0
end

if length(MEM) > 7 then do


say "ERROR**** Package base name must be 7 characters or less"
say "Unable to create BIND statements"
return 999
end
x=0

/* Find the DB2SQLJPROPERTIES environment variable and set it. */


/* If no DB2SQLJPROPERTIES variable set then default to */
/* db2sqljjdbc.properties in working directory */
do I = 1 to __environment.0
if substr(__environment.i,1,17) = 'DB2SQLJPROPERTIES' then do
DB2SQLJPROPERTIES =
substr(__environment.i,19,length(__environment.i)-18)
x=1
end
if substr(__environment.i,1,5) = 'TERM=' then do
termenv = substr(__environment.i,6,length(__environment.i)-5)
end
end
if x=0 then DB2SQLJPROPERTIES = 'db2sqljjdbc.properties'

/* Pick up the DB2 subsystem ID and DBRMLIB to use for the Binds */

138 DB2 Java Stored Procedures: Learning by Example


/* from the DB2SQLJPROPERTIES file. */
address syscall "readfile (DB2SQLJPROPERTIES) file."
if retval < 0 then do
say "ERROR*** The" DB2SQLJPROPERTIES "file does not exist"
say "Unable to create BIND statements"
return 999
end
else do i = 1 to file.0
if substr(file.i,8,4) = 'SSID' then
ssid = substr(file.i,13,length(file.i)-12)
if substr(file.i,8,7) = 'DBRMLIB' then
dbrmlib = substr(file.i,16,length(file.i)-15)
if substr(file.i,8,8) = 'PLANNAME' then
planname = substr(file.i,17,length(file.i)-16)
end

/* */
/* Build the BIND statements and save them in file BINDssidINPUT */
/* */

say '****** NOTE: ******'


say 'If this JAVA SP is called by a JAVA USS client make sure'
say 'collection' PKG||'.* is in PLAN' planname '. If this collection'
say 'is new to this plan, rebind it after adding collection.'
say '*******************'

b.0 = 5
b.1 ="BIND PACKAGE("PKG") MEMBER("MEM"1) ACT(REP) ISOLATION(UR) VALIDATE
(BIND) LIBRARY('"DBRMLIB"') QUALIFIER("QUAL")"
b.2 ="BIND PACKAGE("PKG") MEMBER("MEM"2) ACT(REP) ISOLATION(CS) VALIDATE
(BIND) LIBRARY('"DBRMLIB"') QUALIFIER("QUAL")"
b.3 ="BIND PACKAGE("PKG") MEMBER("MEM"3) ACT(REP) ISOLATION(RS) VALIDATE
(BIND) LIBRARY('"DBRMLIB"') QUALIFIER("QUAL")"
b.4 ="BIND PACKAGE("PKG") MEMBER("MEM"4) ACT(REP) ISOLATION(RR) VALIDATE
(BIND) LIBRARY('"DBRMLIB"') QUALIFIER("QUAL")"

b.5 ="END"

input = "BIND"||ssid||"INPUT"

address syscall "writefile ("||input||") 777 b."


if retval=-1 then do
"error*** writing bind input file" input
return 999
end

address syscall "getcwd cwd"

Chapter 7. Preparing Java stored procedures 139


if retval=-1 then do
"error*** getting current directory to save"
return 999
end

/* */
/* Call DSN on the tsoe os/390 to run. */
/* */
if termenv = 'vt100' then /* telnet */
"tso -t oebind" ssid cwd input mem
else
"tso oebind" ssid cwd input mem

/* */
/* Remove input file with BIND statements in */
/* */
"rm" input

/* */
/* make sure the directory exist for ser files in /u/ssid/ser/ */
/* */
address syscall
"chdir /u/"ssid"/ser/"pkg
if retval=-1 then do
"chdir /u/"ssid"/ser/"
if retval=-1 then do
say "error*** getting directory /u/"ssid"/ser"
return 999
end
"mkdir" pkg 777
if retval=-1 then do
say "error*** making directory /u/"ssid"/ser/"pkg
return 999
end
end
/* reset current directory */
"chdir" cwd
if retval=-1 then do
say "error*** reseting directory" cwd "to current"
return 999
end
RETURN

REXX exec OEBIND


The REXX exec executes the BIND statements and send the bind output back
to the USS HFS.

140 DB2 Java Stored Procedures: Learning by Example


/* rexx TSOE BIND ssid path input */
/* */
/* Called from Unix System Services (USS) rexx programs "bindsp.rexx"*/
/* and 'bindcl_plan.rexx that built the BIND statements for the */
/* JAVA client or stored procedure programs. */
/* */
/* 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. */
/* Written 03/05/200 by Michael J. Fischer */
/* */
/* Input parms: 3 */
/* ssid DB2 subsystem group or member name. */
/* path USS HFS path name to store output file to. */
/* input USS HFS path and file name for BIND input file. */
/* pkg Java package name */
/* */
/* This REXX program will read the HFS file of BIND statements */
/* and put them to the REXX stack. It will then start the DB2 */
/* "DSN" program for the subsystem passed to process the Bind */
/* statements from the REXX stack. It will trap the output from */
/* the BINDs and copy them to a HFS file back on USS */
/* */
/* To call this REXX exec from OS/390 Unix System Services running*/
/* telnet, add the following statements to your .profile. */
/* */
/* .profile */
/* ##### Added for tso -t from telnet */
/* # Assign the DD names to allocate */
/* # */
/* export TSOALLOC=sysexec */
/* # */
/* # Allocate the OpenMVS EXEC data set to SYSEXEC */
/* # */
/* export sysexec=SYS1.OS390.EXEC <== library where you stored */
/* # this exec. */
/* */
/* For help enter: OEBIND ? or OEBND '?' */
parse arg ssid path input pkg .

if ssid = "?" | ssid = "'?'" then do


do i = 1 while substr(sourceline(i),1,2) = "/*"
say sourceline(i)

Chapter 7. Preparing Java stored procedures 141


end
return 0
end

l='abcdefghijklmnopqrstuvwxyz'
u='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
ssid = translate(ssid,u,l)
say "SSID is " ssid
patho = "'"||path||"/bind"||ssid||pkg||".out'"
input = "'"||path||"/"||input||"'"

/* allocate bind output file */


"alloc fi(bindout) da(dsn.bindout) unit(sysallda) new reuse,
space(16,16) tracks recfm(f,b) lrecl(131) blksize(13100)"

/* allocate bind input file to copy bind statements to */


"alloc fi(bindin) da(dsn.bindin) unit(sysallda) new reuse,
space(1,1) tracks recfm(v,b) lrecl(1024) blksize(13100)"

/* allocate bind input hfs file with bind statements in */


'alloc ddname(hfsin) path('input') pathopts(ordwr,ocreat)',
'pathmode(sirusr,siwusr)'

'ocopy indd(hfsin) outdd(bindin) text convert(no)'

'free fi(hfsin)'

"execio * diskr bindin (STEM in. FINIS"


do i = 1 to in.0
queue in.i
end

/* turn on outtrap to capture bind output statements from DSN */


x = OUTTRAP('VAR.')

"DSN SYSTEM("ssid")"

y = OUTTRAP('OFF')

/*write bind output statement to a file to copy to hfs file */


"EXECIO" var.0" DISKW bindout (STEM var. FINIS"

/* allocate bind output hfs file for bind */


'alloc ddname(hfsout) path('patho') pathopts(ordwr,ocreat)',
'pathmode(sirusr,siwusr)'

142 DB2 Java Stored Procedures: Learning by Example


/* copy bind output to hfs file from bind run
*/'ocopy indd(bindout) outdd(hfsout) text convert(no)'

'free fi(hfsout)'

'delete dsn.bindout'
'delete dsn.bindin'

return 0

7.2.5 Using UNIX System Services (USS)


The Java programs must be prepared in UNIX System Services (USS),
which is the UNIX variation of OS/390. It was formerly known as OpenEdition;
sometimes the ‘OE’ can be seen associated with USS, as can be seen on the
URL for the main USS Web site:
http://s390.ibm.com/oe/

7.2.5.1 If you are OS/390 fluent


If you are fluent in OS/390, you may need to learn a minimum set of UNIX
commands. The technical investigation for this book was completed by two
people fluent in OS/390 and one person fluent in UNIX. The OS/390 people
were able to do most of their work with the following set of UNIX commands:
• cd
• pwd
• ls
• oedit
• omvs
• whence
• env
• more
• cat
• chmod

Also necessary is an understanding of environment variables such as


CLASSPATH and how they are set in .profile..

More information about using these and other USS commands can be found
in the OS/390 UNIX System User’s Guide, SC28-1891. Alternatively, the early
adaptors in your organization will have opportunities to develop
mechanizations to hide UNIX from pure OS/390 devotees.

Chapter 7. Preparing Java stored procedures 143


7.2.5.2 If you are UNIX fluent
If you are UNIX fluent and are being asked to work on USS to access OS/390
DB2, most of your UNIX skillset will transfer immediately. The messages may
look a little different, but for the most part it behaves like any other UNIX. You
will be able to telnet or login into USS to use your favorite editor “vi”.

Your biggest difficulty may consist of those commands that must execute on
OS/390. ‘DSN’ was a major stumbling block for our group, requiring the
construction of an extensive Kshell and Rexx procedure. The early adaptors
in your organization will have opportunities to develop mechanizations to hide
OS/390 from pure UNIX devotees.

7.3 NT / AIX Java stored procedure preparation


A DB2 UDB for UNIX, Windows, or OS/2 Java stored procedure can be either
JDBC or SQLJ. These have different preparation procedures. When a stored
procedure mixes both, it goes through the SQLJ process.

Note
The examples used in this section are for the Windows NT platform.

Some minor changes (for example, the use of forward slashes (/) instead of
back slashes (\) for directory names) will need to be made for the AIX
platform.

7.3.1 NT / AIX JDBC program preparation process


If the source consists of JDBC statements, the program preparation for a
stored procedure consists the steps shown in Figure 16.2

2 From a programmer’s perspective, all work and all statements can be executed on a personal workstation. The define of

the procedure, the install of the JAR, and so on, can be executed through a connection to a remote database. The one
hitch is that the install and replace JAR routines require the JAR file to reside on the remote server.

144 DB2 Java Stored Procedures: Learning by Example


1
Java
Source Bytecode
Java
Compiler Other
prog.JAVA
(JAVAC) prog.CLASS CLASS files

JAR
3

SQLJ.INSTALL_JAR
package.JAR

JAR File package.JAR


in sqllib/function
JAR File
4
Can run on any JDK
platform
CREATE Run on NT or AIX
PROCEDURE DB2 deployment platform
Catalog

Figure 16. AIX and Windows NT JDBC program preparation process

1. Java Compile the source code (using the javac command). This produces
one or more .class files, which represent the Java bytecode for your
procedure.
2. Package the class file(s) produced in the previous into a single .jar file via
the jar command. This step is mandatory for applications using the Java
package statement. 3
3. Install the JAR file in the database using the sqlj.install_jar command.
This provides a DB2 name for the JAR file, enters details of the classes
contained within it to the SYSIBM.SYSJARCONTENTS catalog table, and
copies the file to a standard location so that DB2 is able to access it at run
time.
4. Define the stored procedure to DB2 using the CREATE PROCEDURE statement.
Note that the stored procedure cannot be defined until its associated JAR
file exists.

3 It is possible to avoid use of JAR files by leaving out the ‘package’ statement in the JAVA source. The resulting class
files are copied directly to the <DB2>/sqllib/function directory, as seen in the examples shipped with the database.
However, as discussed earlier in Chapter 5, “Designing Java stored procedures” on page 83, this creates a flat
namespace that may cause conflicts between different applications. We recommend using JAVA packages and JARs to
segregate applications.

Chapter 7. Preparing Java stored procedures 145


A word about JAR files
DB2 UDB for UNIX, Windows, OS/2 is very particular about the order in
which these steps are conducted when it comes to JAR files. For example,
it will not allow a procedure to be created until it exists in the referenced
JAR file, or allow you to remove or refresh a JAR file while procedures are
defined that refer to it. We found that the safest way to go about performing
steps 3 and 4 above was to do the following;
1. Drop all procedures in the Java package via the SQL DROP PROCEDURE
statement.
2. Call sqlj.remove_jar followed by sqlj.install_jar to re-install the JAR
file in the correct location.
3. Re-create the procedures via the SQL CREATE PROCEDURE statement.

This is the process that is used in our sample code.

The process can be reliably rerun when re-preparing amended procedures.


However, as all procedures in a given Java package have to be placed in
the same JAR file, using this process means that you have to build the Java
package gradually, procedure by procedure, in order to satisfy DB2’s many
consistency checks.

For example, let’s assume that we want to produce two procedures called
Add_customer and Add_order in a Java package called ACMEJNE.

We write the first procedure, Add_customer, and go through the SQLJ


program preparation process. Using the steps above we first drop the
procedure (which will not yet exist), remove the JAR definition (which will
not exist), install the JAR (which should work) and then define the
Add_customer procedure to DB2 via SQL CREATE PROCEDURE statement.

When we write the second procedure, Add_order, we will need to drop both
procedures, remove and re-install the JAR definition, and then define both
procedures to DB2.

If we try to perform the steps in any other order, or if we try to create the
Add_order procedure before there is a definition for it within the JAR file,
the process will fail.

146 DB2 Java Stored Procedures: Learning by Example


7.3.1.1 NT / AIX JDBC preparation example
In the DB2 UDB for UNIX, Windows, or OS/2 JDBC detailed preparation
example, the JDBC stored procedure has been coded with this Java package
statement:
package ACMEJNS;

Note
Although use of Java packages is not essential on the UNIX or Windows
platforms, it is currently required on the OS/390 platform.

If Java stored procedure portability is important to you, we recommend that


you use Java packages when you code your stored procedures.

To build this program, go up one directory from the source. For example, if
your source was in C:\apps\ACMEJNS\Add_customer.java, then you change
directory to C:\apps to execute the build statements.
• Start by compiling your Java source using the javac Java command:
javac ACMEJNS\Add_customer.java
The resulting .class files are placed in the ACMEJOS subdirectory.
• Create the JAR file to be made available to the database, as follows:
jar cvf ACMEJNS.jar ACMEJNS\*.class

Note
We use *.class to ensure that we pick up the class files for any other
procedures within the Java package that may have been prepared

Note
Issue the following statements from a DB2 Command Line Processor
(CLP) session.

• Drop all procedures in the Java package:


DROP PROCEDURE ACMESNE.Add_customer ;
DROP PROCEDURE ACMESNE.Add_order ;
• Install the JAR file in the database. As a precaution, we recommend that
you drop it first, to allow for re-runs:
CALL SQLJ.REMOVE_JAR('ACMEJNS.ACMEJNS');

Chapter 7. Preparing Java stored procedures 147


CALL SQLJ.INSTALL_JAR('file:s:/sg245945/ACMEJNS/ACMEJNS.jar',
'ACMEJNS.ACMEJNS');

The first parameter of sqlj.install_jar or sqlj.replace_jar defines the


location of the JAR file you created previously.
The second parameter provides an identifer that you will use when
referring to the JAR file from within DB2 commands. Note that we have
qualified this identifier — DB2 uses this qualifier to determine which
subdirectory it will copy the JAR file to.
In our example, DB2 will register the JAR file and copy it to
sqllib\function\jar\ACMEJNS\ACMEJNS.jar.

Now that DB2 knows about the JAR, we can define the stored procedure to
DB2. Note that trying to define the procedure before the JAR has been
registered will result in an error.
CREATE PROCEDURE ACMEJNS.Add_customer
(
IN IN_CUST_FIRSTNAME CHAR(20),
IN IN_CUST_LASTNAME CHAR(20),
IN IN_CUST_ADDRESS CHAR(30),
OUT OUT_CUST_NO INT,
OUT MARK CHAR(40),
OUT MARK_ERROR_TEXT CHAR(200)
)
EXTERNAL NAME 'ACMEJNS.ACMEJNS:ACMEJNS.Add_customer.add_customer'
RESULT SETS 0
LANGUAGE JAVA
PARAMETER STYLE JAVA
FENCED
NO DBINFO ;

Note
As we dropped all of the procedures in the Java package earlier, you must
remember to recreate all of them here, not just the one you are working on!

The stored procedure is now ready for execution.

7.3.1.2 Sample program preparation scripts


Although not nearly as sophisticated as the examples we created for the
OS/390 platform, we did create some scripts for performing this program
preparation process for Windows NT and UNIX. Samples can be found in the
appendix.

148 DB2 Java Stored Procedures: Learning by Example


7.3.2 NT / AIX SQLJ program preparation process
If the source contains SQLJ statements (or a combination of SQLJ and JDBC
statements), the program preparation for a stored procedure consists of the
steps shown in Figure 17.

Modfied Java
2
Source Bytecode
SQLJ
Java
Source 1 Compiler Other
prog.JAVA prog.CLASS
(JAVAC) CLASS files
SQLJ
prog.SQLJ Translator

3
prog_ JAR
SJProfileKeys.class

prog_
4 SJProfile0.ser

Profile Serialised
Customiser Profile package.jar
(DB2PROFC) 5
JAR File
SQLJ.INSTALL_JAR
package.JAR

JAR File
in sqllib/function
6
Can run on any JDK
platform
DB2 CREATE
Catalog PROCEDURE Run on S/390
platform

Figure 17. AIX and Windows NT SQLJ program preparation process

1. Precompile your source code using the sqlj command. This will extract all
of the embedded SQL from your code and place it in an SQLJ serialized
profile (a kind of generic, database independent DBRM). Serialised
profiles are stored in .ser files. Your source code will be modified, and
placed in a .java file.
2. Java-compile the source code (using the javac command). This will
produce at least two .class files — one containing your code and one
containing the SQLJ access “stub”.

Chapter 7. Preparing Java stored procedures 149


Note
Unless you specifically request otherwise by specifying the
-compile=false option, javac will be automatically executed by sqlj and
there is no need to perform this step separately.
However, you may wish to split these processes if you are encountering
problems with the sqlj process (see 6.7.2.5, “The sqlj command hangs”
on page 115)

3. Package the class file(s) produced in the previous into a single .jar file via
the jar command. This step is mandatory if using the Java package
statement.
4. Execute the DB2 profile customizer using the db2profc command. This
takes the generic serialized profile created in step 1 and binds it directly to
the DB2 database you specify.
Note
If you wish, you can specify the bindfile option in the -prepoptions
parameter for db2profc. This will result in a standard .bnd file being
produced, which you can then use to manually bind to DB2.
By default, db2profc will execute the bind directly.

5. Install the JAR in the database (using the sqlj.install_jar command). This
provides a DB2 name for the JAR file, enters details of the classes
contained within it to the SYSIBM.SYSJARCONTENTS catalog table, and
copies the file to a standard location4 so that DB2 is able to access it at
run time.
6. Define the stored procedure to DB2 using the CREATE PROCEDURE statement.
Note that the stored procedure cannot be defined until its associated JAR
file exists.

4
The path is specified by the DB2INSTPROF parameter. The default value for this is sqllib/function.

150 DB2 Java Stored Procedures: Learning by Example


A word about JAR files
DB2 UDB for UNIX, Windows, OS/2 is very particular about the order in
which these steps are conducted when it comes to JAR files. For example,
it will not allow a procedure to be created until it exists in the referenced
JAR file, or allow you to remove or refresh a JAR file while procedures are
defined that refer to it. We found that the safest way to go about performing
steps 5 and 6 above was to do the following;
1. Drop all procedures in the Java package via the SQL DROP PROCEDURE
statement
2. Call sqlj.remove_jar followed by sqlj.install_jar to re-install the JAR file
in the correct location.
3. Re-create the procedures via the SQL CREATE PROCEDURE statement

This is the process that is used in our sample code.

The process can be reliably rerun when re-preparing amended procedures.


However, as all procedures in a given Java package have to be placed in
the same JAR file, using this process means that you have to build the Java
package gradually, procedure by procedure, in order to satisfy DB2’s many
consistency checks.

For example, let’s assume that we want to produce two procedures called
Add_customer and Add_order in a Java package called ACMEJNE.

We write the first procedure, Add_customer, and go through the SQLJ


program preparation process. Using the steps above we first drop the
procedure (which won’t yet exist), remove the JAR definition (which won’t
exist), install the JAR (which should work), and then define the Add_customer
procedure to DB2 via CREATE PROCEDURE.

When we write the second procedure, Add_order, we will need to drop both
procedures, remove and re-install the JAR definition, and then define both
procedures to DB2.

If we try to perform the steps in any other order, or if we try to create the
Add_order procedure before there is a definition for it within the JAR file,
the process will fail.

Chapter 7. Preparing Java stored procedures 151


Note
Steps 1 to 3 of this process can be done on any platform that contains a
suitable JDK. We performed them within UNIX Systems Services (USS) in
an S/390 environment.

Steps 4 to 6 must be performed on the AIX or Windows NT platform you will


be deploying the stored procedure on.

7.3.2.1 NT / AIX SQLJ detailed preparation example


The example SQLJ stored procedure has been coded with this Java package
statement:
package ACMESOS;

Note
Although use of Java packages is not essential on the Windows or UNIX
platforms, it is currently required on the OS/390 platform.

If Java stored procedure portability is important to you, we recommend that


you use Java packages when you code your stored procedures.

To build this program, go up one directory from the source. For example, if
your source was in C:\apps\ACMESOS\Add_customer.sqlj, then you change
directory to C:\apps to execute the build statements.

Start by precompiling your SQLJ source file. By default, the sqlj command
also executes javac to Java compile your procedure. The resulting files (Java
.class files and an SQLJ serialized profile) are placed in the same directory
as your source.
sqlj ACMESOS\Add_customer.sqlj

If you want to save the output messages, redirect them to files as in the
following example. The ‘>’ references standard output , the ‘2>’ references
standard error.
sqlj ACMESOS\Add_customer.sqlj > outsqlj.txt 2>outsqlj2.txt

Execute db2profc, which takes the serialized profile created by the sqlj
command and binds the SQL it contains to DB2.
db2profc -prepoptions="qualifier acmes package using addcust"
-url=jdbc:db2:ACMES ACMESNS\Add_customer_SJProfile0

152 DB2 Java Stored Procedures: Learning by Example


Use of pre-compile options
Use of the qualifier precompile option allows you to specify an identifier
for DB2 to use for all unqualified table references in the procedure.

The package using option allows you to name the DB2 package that
db2profc will generate, which is essential if you have multiple procedures
within one package.

Other precompile options (such as specifying the plan owner) can also be
used — refer to the PRECOMPILE PROGRAM command in the DB2 UDB
Command Reference.

Create the JAR file to be made available to the database (note that we are
including multiple class files and the serialized profile in the JAR).

jar cvf ACMESOS/ACMESOS.jar ACMESOS\*.class ACMESOS\*.ser

.Note
We use *.class to ensure that we pick up the class files for any other
procedures within the Java package that may have been prepared

Note
Issue the following statements from a DB2 Command Line Processor
(CLP) session.

Drop all procedures in the Java package:


DROP PROCEDURE ACMESNE.Add_customer ;
DROP PROCEDURE ACMESNE.Add_order ;

Install the JAR file in the database. As a precaution, it is a good idea to drop it
first to allow for re-runs:
CALL SQLJ.REMOVE_JAR('ACMESNS.ACMESNS');
CALL SQLJ.INSTALL_JAR('file:s:/sg245945/ACMESNS/ACMESNS.jar',
'ACMESNS.ACMESNS');

The first parameter of sqlj.remove_jar or sqlj.install_jar defines the


location of the JAR file you created previously.

Chapter 7. Preparing Java stored procedures 153


The second parameter provides an identifer that you will use when referring
to the JAR file from within DB2 commands. Note that we have qualified this
identifier — DB2 uses this qualifier to determine which subdirectory it will
copy the JAR file to.

In our example, DB2 will register the JAR file and copy it to
sqllib\function\jar\ACMEJOS\ACMESNS.jar.

Now that DB2 knows about the JAR, we can define the stored procedure to
DB2. Note that trying to define the procedure before the JAR has been
registered will result in an error.
CREATE PROCEDURE ACMESNS.Add_customer
(
IN IN_CUST_FIRSTNAME CHAR(20),
IN IN_CUST_LASTNAME CHAR(20),
IN IN_CUST_ADDRESS CHAR(30),
OUT OUT_CUST_NO INT,
OUT MARK CHAR(40),
OUT MARK_ERROR_TEXT CHAR(200)
)
EXTERNAL NAME 'ACMESNS.ACMESNS:ACMESNS.Add_customer.add_customer'
RESULT SETS 0
LANGUAGE JAVA
PARAMETER STYLE JAVA
FENCED
NO DBINFO
NULL CALL MODIFIES SQL DATA;

Note
As we dropped all of the procedures in the Java package earlier, you must
remember to recreate all of them here, not just the one you are working on!

The stored procedure is now ready for execution.

7.3.2.2 Sample program preparation scripts


Although not nearly as sophisticated as the examples we created for the
OS/390 platform, we did create some scripts for performing this program
preparation process for Windows NT and UNIX. These can be found in the
appendix.

154 DB2 Java Stored Procedures: Learning by Example


7.3.3 The sqlj.install_jar and sqlj.replace_jar routines
The routines used to install (and replace) the JAR files have strict syntax
requirements. They also produce sometimes inscrutable error messages.

You can find some documentation on the SQLJ JAR routines within the
section on Java Stored Procedures and UDFs in the DB2 UDB Application
Development Guide, SC09-2845-00.

Important: Observe the following cautions:


• Never remove a JAR from the database manually
The JAR files register to the database via the sqlj ar routines. These JAR
files then can be seen at sqllib\function\jar\<schema>. Never delete a JAR
file manually. Always remove a JAR file using the sqlj.remove_jar routine.
• Log in as schema owner
Within Command Center, the sqlj jar routines fail to recognize a ‘set
schema ACMES’. You must connect at the beginning using the schema, as
in 'connect to sample user ACMES'.
• EXTERNAL NAME in create procedure statement
The EXTERNAL NAME clause in create procedure is case-sensitive.
The first part of the name refers to the schema. In the following example,
ACMES is the schema:
EXTERNAL NAME '"ACMES"."ACMESOS":ACMESOS.Add_customer.add_customer'

Chapter 7. Preparing Java stored procedures 155


156 DB2 Java Stored Procedures: Learning by Example
Chapter 8. Deployment and execution

This chapter takes a look as some of the deployment and execution issues to
be considered once you have written and tested your Java stored procedures.

8.1 Deployment
One of the great advantages of developing stored procedures in Java is the
fact that you are able to write and test them on one platform, then easily
deploy them on another with few or no changes being required.

Even if you are developing and deploying on a single platform, you will
probably want separate development and production environments, and there
are issues you need to be aware of and manage.

8.1.1 Migrating between environments on S/390


If you are developing and deploying your stored procedures completely on the
S/390 platform, we strongly recommend that you establish entirely separate
development and production environments (consisting of separate DB2
subsystems/data sharing groups, USS HFS systems, OS/390 libraries, and
everything else). If this is not possible, try to separate out as much as
possible (using different schemas within DB2, separate directories within
HFS, and so on).

In the following discussions, we assume that you have two entirely separate
environments for development and production. You should be able to handle
any number of variations (additional environments such as Unit Test and
System Test, a lesser degree of physical separation between environments,
and so on) using the same basic approach.

There are two approaches commonly used for moving applications between
development and production:
• Source-centric. Only program source files are moved between
environments, and the program preparation process is re-executed within
the production environment. This is the approach adopted by sites that
use source management tools such as CA Endevor.
• Executable-centric. Only executable modules are moved between
development and production, with no program preparation being executed
within the production environment.

© Copyright IBM Corp. 2000 157


These two approaches are discussed in the following sections. In both cases,
only the application specific aspects of the migration process are considered
— it has been assumed that the system setup (as described in 4.1, “OS/390
system setup” on page 57) has been addressed for both the source and
target environments.

8.1.1.1 Source-centric migration


The migration process using the source-centric approach is relatively simple,
as shown in Figure 18.

Development Environment Production Environment

Source Source
prog.JAVA prog.JAVA

Java Compiler Java Compiler

Java Java
Bytecode prog.CLASS prog.CLASS Bytecode

HPJ Compiler HPJ Compiler

External External
JLL in JLL in
Link Link
PDSE PDSE

DB2 DB2
DDL DDL
Catalog Catalog

Figure 18. Source-centric migration for a JDBC application

In this situation, all that needs to be migrated is:


• The Java source code for the procedure. This can be accomplished using
a simple FTP command to copy the source from the development HFS
system to the production one. Note that Java source files should be FTPed
in text format.

158 DB2 Java Stored Procedures: Learning by Example


• The DDL containing the CREATE PROCEDURE (for Version 6) or INSERT INTO
SYSPROCEDURES (for Version 5) statements, plus any other DDL associated
with the application. Assuming that the development and production
environments use shared DASD, this can be accomplished with a simple
IEBCOPY, or a dedicated DB2 object management tool.

Once these two items have been moved, all that would be required is to
re-perform the program preparation process within the production
environment to create a new executable, and submit the necessary DDL to
define the procedure to DB2.

SQLJ procedures
Figure 18 on page 158 shows a JDBC migration for simplicity. Migration of
an SQLJ procedure would use an identical approach, with only the program
preparation steps differing.

8.1.1.2 Executable-centric migration


The migration process for the executable-centric migration approach is
simpler still, as shown in Figure 19.

The following items must be copied from the source to the target
environment:
• The HPJ compiled executable module. As this is a simple PDSE member,
this can be accomplished using a utility such as IEBCOPY.
• The DDL containing the CREATE PROCEDURE (for Version 6) or INSERT INTO
SYSPROCEDURES (for Version 5) statements, plus any other DDL associated
with the application. Again, this can be accomplished with a simple
IEBCOPY, or a dedicated DB2 object management tool.

Once these items have been moved, all that would be required is the creation
of a external link in the relevant HFS directory, to point to the newly moved
PDSE executable.

This can be accomplished using the USS ln command, as shown in the


example below:
ln -e ACMESOS ACMESOS.jll

Chapter 8. Deployment and execution 159


Development Environment Production Environment

Source
prog.JAVA

Java Compiler

Java
Bytecode prog.CLASS

HPJ Compiler
Create Link

External External
JLL in JLL in
Link Link
PDSE PDSE

DB2 DB2
DDL DDL
Catalog Catalog

Figure 19. Executable-centric migration for a JDBC application

SQLJ procedures
Figure 19 shows a JDBC migration for simplicity. Migration of an SQLJ
procedure would use a very similar approach, but the DBRMs generated by
the db2profc process on the target system would also have to be moved to
the target environment, and then bound to the production DB2 system.

8.1.2 Migrating between environments on UNIX/NT


As the UNIX and Windows NT environments do not have the additional
complexity of the HPJ step, the process for moving applications between
environments is somewhat simpler than for OS/390.

160 DB2 Java Stored Procedures: Learning by Example


8.1.2.1 Source-centric migration
The source-centric migration uses the same concepts as shown previously.
You can move the JDBC or SQLJ source files from the source environment to
the target environment along with the necessary INSTALL_JAR and CREATE
PROCEDURE statements (using FTP or some other utility), and then re-run the
entire program preparation process on the target platform.

8.1.2.2 Executable-centric migration


For JDBC procedures, you can migrate between environments by executing
the following steps:
1. Move the JAR file containing the procedure code and the DDL defining the
procedures to the target environment.
2. Define the JAR file to DB2 using the sqlj.install_jar statement.
3. Execute the CREATE PROCEDURE commands to define the procedures to DB2.

The process for SQLJ is slightly more involved:


1. Move the JAR file containing the procedure code, the DDL defining the
procedures and the serialized profile generated by the sqlj command to
the target environment.
2. Define the JAR file to DB2 using the sqlj.install_jar statement.
3. Execute the CREATE PROCEDURE commands to define the procedures to DB2.
4. Execute db2profc in the target environment to create the necessary DB2
packages in the target DB2 system.

8.1.3 Porting between UNIX/NT and S/390


You may want to prototype and develop your procedures within UNIX or
Windows NT, and then port them to the S/390 platform for subsequent use.

Although it is perfectly possible to port Java bytecode, in the guise of .class


files or .jar files between the two environments, it is likely that further
development may be required. Therefore, we recommend that you stick to
porting source files.

There are a few considerations you should be aware of when porting between
these platforms. We cover these in the following sections.

Chapter 8. Deployment and execution 161


8.1.3.1 Changing Class.forName method and connection
As there is no need for specific references to drivers or connections within
stored procedures themselves, they can be ported with absolutely no
amendments to the code. We proved this several times in the development of
the examples within this book.

However, client code will have such references, so a couple of minor changes
will be necessary.

The Class.forName method is used to load a specific driver, which differs


between UNIX/NT and OS/390 as follows:
• COM.ibm.db2os390.sqlj.jdbc.DB2SQLJDriver for OS/390
• COM.ibm.db2.jdbc.app.DB2Driver for AIX and Windows NT

Similarly, the connection URL used within JDBC clients differs as follows:
• jdbc:db2os390sqlj:DB21 for OS/390
Here, DB21 is the subsystem name.
• jdbc:db2:ACMES for AIX and Windows NT
Here, ACMES is the database name.

8.1.3.2 Code translation


There are some issues associated with the translation of certain ASCII and
EBCDIC characters between the environments that will be well known to C
and C++ programmers.

Detailed exploration of this issue is beyond the scope of this book, but here
are a couple of practical pointers:
• Java code makes extensive use of square brackets (‘[‘ and ‘]’). When a
program is ported to the USS environment, these characters appear to be
corrupted, as there is no EBCDIC equivalent for them (they appear as
x’AD’ and x’BD’ respectively in USS). However, although this issue makes
the code look somewhat messy within the USS environment, it has
absolutely no impact on the execution of Java programs from within a JVM
or HPJ environment.
• Good coding practices encourage the use of tabs in source code as a
readability aid. Unfortunately, these are not always translated correctly
and often appear as unprintable characters in USS. Again, this can be
ignored, but it is a good idea to format code using hard space characters
rather than tabs if you will be frequently porting between platforms.

162 DB2 Java Stored Procedures: Learning by Example


8.2 Execution
The following sections describe some execution considerations, depending
on which platform you are using.

8.2.1 OS/390 execution considerations


8.2.1.1 Refreshing a changed procedure
Once a Java stored procedure is called, the OS/390 executable can be
cached by the WLM. If you subsequently call the same procedure again, the
version from the cache is used, and not the one from the disk.

Do this to refresh a Java stored procedure after changes have been made:
1. Re-prepare the stored procedure, as described in 7.2, “OS/390 Java
stored procedure preparation” on page 119.
2. Issue a V WLM,APPLENV=xxx,REFRESH command on the system console to
refresh the .jlls containing the code (where applenv is the WLM application
environment name).

8.2.2 UNIX and Windows NT execution considerations


Here we provide various execution considerations for these environments.

8.2.2.1 Refreshing a changed procedure


Once a Java stored procedure is called, its bytecode is cached by the class
loader. Then, if you call the same step again, the version from the cache is
used, and not the one from the disk.

To refresh a Java stored procedure after changes have been made, do the
following:
1. Re-prepare the stored procedure, as described in 7.3, “NT / AIX Java
stored procedure preparation” on page 144.
2. Issue the following command to replace the JAR file:
call sqlj.replace_jar ('file:/aaakirk/Acme/Acme.jar','Acme');
3. Issue the following command to refresh the classes:
call sqlj.refresh_classes (void);

Chapter 8. Deployment and execution 163


8.3 Stored procedure management and version control on OS/390
With the new schema support in DB2 UDB for OS/390 V6 (see Chapter 12,
“DB2 UDB for OS/390 schema support” on page 233), it is now possible to
more effectively provide version control for DB2 stored procedures. In this
section we will discuss how stored procedures can be managed with
versions.

8.3.1 Source code control


DB2 for OS/390 doesn't really “store” the stored procedures source code, so
change management is basically left up to the installation. When the Stored
Procedure Builder is used, the source is stored in the OS/390 catalog tables,
but only the current version is kept.

To separate test and production source code, they both would be stored in
separate PDSs. You would use your current source code management tools
to management the movement of the source code from test to production.

8.3.2 Version control


The capability to execute different versions of a stored procedure is controlled
by AUTHID in V5 and SCHEMA in V6. This allows the same stored procedure
name to be used to invoke different load modules: in V5, the executing
AUTHID is used to find the right catalog entry; and in V6, the SCHEMA is
used to qualify the name. The number of parameters passed are also
matched up. You may also accomplish version control by using the 'set
current packageset' special register from inside the stored procedure to direct
DB2 to the correct COLLECTION ID.

WLM provides us with a seamless way to deploy a new version of the load
module that is loaded and run when a stored procedure is invoked. When
running in GOAL mode, a 'V WLM,APPLENV=x,REFRESH' command allows
currently executing CALL statements to complete against the 'old' version of the
load module, and a new address space is brought up for any new requests, so
they pick up the new version of the load module.

The calling application doesn't need to qualify the CALL statement on


schema name. If it is not specified, it is determined from the
CURRENT_PATH special register (if the SQL CALL statement specifies the
stored procedure name in a host variable) or the PATH bind option (if the SQL
CALL statement specifies the stored procedure name as a literal.)

164 DB2 Java Stored Procedures: Learning by Example


8.3.3 Sample of a test and production version
Here is an example of using SCHEMA to control a test and production version
of a stored procedure.

The production version has schema PROD, so its qualified name is


PROD.PROCA. The test version has schema TEST, so its qualified name is
TEST.PROCA.

The calling application uses the SQL statement “CALL PROCA” to invoke the
stored procedure. This DB2 package was bound with PATH(PROD), so when
it executes, it calls PROD.PROCA.

The developer creates another PROCA in schema TEST, so it's qualified


name is TEST.PROCA. Its load module name is the same as PROD.PROCA,
and is stored in a different load library in a different WLM application
environment.

Example: WLM application environment Test_Payroll and Prod_Payroll are


both executing load module PAY0200. But they both have WLM start a
different WLM-established JCL procedure with the different load library in it.

Calling applications to use the test version are bound with PATH(TEST) or
fully use the qualified TEST.PROCA. Using the bind parameter PATH(TEST)
is a better solution, since there would be no application code change.
1. When it is ready to roll into production, copy the PROD version, -1 version,
off to another load library.
2. Copy the TEST version into PROD library.
3. Rebind the stored procedure with PATH(PROD).
4. Issue the WLM refresh for the PROD application to make these changes
visible.

If you have problems with this new code in production, you can simply move
the old version of the load module back to the PROD library. Then reissue the
WLM refresh. This way, the calling application never has to change, or even
be rebound, to pick up a new or old version of its load module.

8.3.4 Running two versions in the same DB2 subsystem


Now, with SCHEMA in V6, you can now have two or more versions of a stored
procedure in the same DB2 subsystem accessing different tables. To do this,
you bind the application with both the PATH and OWNER option. The
OWNER option is used to point to a different copy of a table, and the PATH
option used to point to a different stored procedure.

Chapter 8. Deployment and execution 165


166 DB2 Java Stored Procedures: Learning by Example
Chapter 9. Client applications invoking Java stored procedures

This chapter describes some of the issues that you need to be aware of when
coding clients to invoke Java stored procedures.

9.1 DB2 plans and packages


As your client application contains at least one SQL statement (the CALL to
the stored procedure), it will need to be prepared using the standard program
preparation process.

For an SQLJ client application, this involves running the sqlj precompiler,
db2profc profile customizer, binding DB2 packages, and running a Java
compile. For a JDBC client, all that is required is the Java compile step. Note
that as the client application runs in the USS JVM, no HPJ compile will be
required in either case.

When the client is invoked (whether it is JDBC or SQLJ), the


DB2SQLJPROPERTIES environment variable is used to find the name of the SQLJ
properties file. This file contains the setting for the DB2SQLJPLANNAME parameter,
which is the name of the plan DB2 uses when running the client (we used the
default name of SQLJPLAN). For simplicity, we will refer to this plan as SQLJPLAN
in the following paragraphs.

9.1.1 JDBC client requirements


For a JDBC client, SQLJPLAN must refer to the 4 generic JDBC DBRMs
DSNJDBC1, DSNJDBC2, DSNJDBC3 and DSNJDBC4. You can do this by directly binding
the DBRMs into SQLJPLAN, but we recommend binding them into a generic DB2
package collection (we used DSNJDBC, for example) and including this DB2
package collection in the DB2 package list for SQLJPLAN.

In addition, you need to ensure that SQLJPLAN contains the necessary


references to the DB2 packages for the stored procedure you will be invoking
(if necessary). See 9.1.3, “Stored procedure requirements” on page 168 for
details.

9.1.2 SQLJ client requirements


For an SQLJ client application, the SQLJPLAN must refer to the 4 client DBRMs
created by db2profc when you went through the program preparation process
for the client. You can do this by directly binding the DBRMs into SQLJPLAN, but
we recommend binding them into a DB2 package collection (we used a DB2

© Copyright IBM Corp. 2000 167


package collection called CLIENT, for example) and including this DB2 package
collection in the DB2 package list for SQLJPLAN.

In addition, you need to ensure that SQLJPLAN contains the necessary


references to the DB2 packages for the stored procedure you will be invoking
(if necessary). See 9.1.3, “Stored procedure requirements” on page 168 for
details.

9.1.3 Stored procedure requirements


In 7.2.3, “OS/390 JDBC program preparation process” on page 122 and
7.2.4, “OS/390 SQLJ program preparation process” on page 129, we
recommended that you explicitly specify a DB2 package collection to be
associated with your stored procedure. If you followed this recommendation,
you need do nothing else to ensure that the correct JDBC or SQLJ DB2
packages can be invoked at run time.

If you chose not to explicitly specify the DB2 package collection, you will need
to ensure that the 4 generic JDBC DBRMs (for a JDBC stored procedure) or
the 4 application-specific DBRMs (for a SQLJ stored procedure) are bound
into DB2 packages that belong to the same DB2 package collection as the
client DB2 package/plan.

9.1.4 Summary
Table 10 contains a summary of the requirements for SQLJPLAN according to
the type of client and stored procedure, if our recommendations concerning
the use of COLLID are followed.
Table 10. Contents of SQLJPLAN by client and SP type using COLLID

Called Stored Procedure Type

JDBC Stored Procedure SQLJ Stored Procedure

JDBC Client Collection containing the 4 Collection containing the 4


generic JDBC packages generic JDBC packages
DSNJDBC1, DSNJDBC2, DSNJDBC1, DSNJDBC2, DSNJDBC3
DSNJDBC3 and DSNJDBC4 (e.g. and DSNJDBC4 (e.g. DSNJDBC).
DSNJDBC).

168 DB2 Java Stored Procedures: Learning by Example


Called Stored Procedure Type

JDBC Stored Procedure SQLJ Stored Procedure

SQLJ Client Collection (any name), Collection (any name),


containing the 4 packages containing the 4 packages
produced by db2profc when produced by db2profc when
preparing the SQLJ client. preparing the SQLJ client.

Table 11 contains a summary of the requirements for SQLJPLAN according to


the type of client and stored procedure, if COLLID is not explicitly supplied
when defining the stored procedures. This approach is considerably more
restrictive.
Table 11. Contents of SQLJPLAN by client and SP type not using COLLID

Called Stored Procedure Type

JDBC Stored Procedure SQLJ Stored Procedure

JDBC Client Collection containing the 4 Collection containing the 4


generic JDBC packages generic JDBC packages
DSNJDBC1, DSNJDBC2, DSNJDBC1, DSNJDBC2, DSNJDBC3
DSNJDBC3 and DSNJDBC4 (e.g. and DSNJDBC4 (e.g. DSNJDBC).
DSNJDBC).
Same collection must also
contain the 4 packages
produced by db2profc when
preparing the SQLJ stored
procedure.

SQLJ Client Collection (any name), Collection (any name),


containing the 4 packages containing the 4 packages
produced by db2profc when produced by db2profc when
preparing the SQLJ client. preparing the SQLJ client.

Same collection must also Same collection must also


contain the 4 generic JDBC contain the 4 packages
packages DSNJDBC1, produced by db2profc when
DSNJDBC2, DSNJDBC3 and preparing the SQLJ stored
DSNJDBC4. procedure.

Chapter 9. Client applications invoking Java stored procedures 169


9.1.5 Usage recommendations
As can be seen from Table 10 on page 168 and Table 11 on page 169,
SQLJPLAN is central to the operation of both SQLJ and JDBC clients and stored
procedures, and as such you should carefully consider the way in which it will
be used in your environment.

For instance, use of a single SQLJPLAN will result in an ever-increasing list of


packages for DB2 to search through at runtime, which may start to negatively
impact performance. In addition, there are practical limitations with rebinding
SQLJPLAN every time a new DB2 package collection has to be added to the
DB2 package list.

For these reasons, we recommend that you consider creating several plans,
splitting them according to development area, business unit, application or
some other attribute suited to your environment.

Each version of SQLJPLAN will be pointed to by a separate SQLJ properties file,


which in turn must be pointed to by the DB2SQLJPROPERTIES environment
variable. We suggest setting this for each user within the .profile script
(possibly in response to a question regarding which environment they would
like to be set up for). See 4.1.9.2, “SQLJ properties file” on page 71 and
4.1.4, “Step 2: Provide .profile for users” on page 63 for further details.

9.2 Client coding considerations


The following sections describe some of the issues that you need to be aware
of when coding client applications invoking Java stored procedures.

9.2.1 General client coding considerations


In this section, we present some general client coding considerations that
apply to both JDBC and SQLJ clients.

9.2.1.1 Coding the connect statement


Your client will need to use the getConnection method to create a connection
to the desired DB2 subsystem or data sharing group, such as the one in the
example below:
url = "jdbc:db2os390sqlj:DBZ1";
con = DriverManager.getConnection(url);

The last component of the connection string (DBZ1 in the example) should
refer to the location name of the system you are trying to connect to (which is
defined in the DDF Communication Record in the BSDS for that subsystem).

170 DB2 Java Stored Procedures: Learning by Example


You may either specify a local location name (for a subsystem on the same
OS/390 system as the client) or a remote one (for a subsystem on different
OS/390 system). If you specify a remote system, that system must be defined
in the communications database (CDB) for the local DB2.

Refer to section 3.3 of DB2 Application Programming Guide and Reference


for Java, SC26-9018-01 for further information.

9.2.1.2 The SQL CALL statement


Due to an oddity in the drivers we used, we were forced to code all stored
procedure names within CALL statements in upper case, as shown in the
following JDBC and SQLJ examples:
procName = "ADD_CUSTOMER";
String sql = "CALL " + procName + "(?,?,?,?,?,?)";

#sql [myconn] { CALL ADD_CUSTOMER


( :IN lastname, :IN firstname, :IN address, :OUT cust_no,
:OUT returned_mark, :OUT returned_mark_error_text)
};

Attempts to use any lower case characters in the stored procedure name
resulted in a -113 SQLCODE, indicating invalid characters in the prepared
statement string.

So, using the following statements:


procName = "add_customer";
String sql = "CALL " + procName + "(?,?,?,?,?,?)";

or:
#sql [myconn] { CALL add_customer
( :IN lastname, :IN firstname, :IN address, :OUT cust_no,
:OUT returned_mark, :OUT returned_mark_error_text)
};

will result in a runtime error similar to the one below:


java.sql.SQLException: DB2JDBCSection Received Error in Method execute_call
:SQLCODE==> -113 SQLSTATE ==> 42602
Error Tokens ==> <<DB2/OS390 V5.1 ANSI SQLJ-0/JDBC 1.0>> add_customer 000 -
atCOM.ibm.db2os390.sqlj.jdbc.DB2SQLJJDBCSection.setError(DB2SQLJJDBCSection.java:1049)
at COM.ibm.db2os390.sqlj.jdbc.DB2SQLJJDBCSection.execute_call
(DB2SQLJJDBCSection.java:874)
at COM.ibm.db2os390.sqlj.jdbc.DB2SQLJCallableStatement.execute
(DB2SQLJCallableStatement.java:116)
at jscall_Add_customer.main(jscall_Add_customer.java:84)

Chapter 9. Client applications invoking Java stored procedures 171


Therefore, we recommend that you code all client calls using upper case
names only.

COBOL clients
This issue did not appear to affect COBOL clients, and we able to
successfully invoke Java stored procedures from within COBOL clients
using a mixture of upper and lower case names.

9.2.2 JDBC client coding considerations


Invoking a stored procedure using JDBC requires a specific set of steps to be
followed:
1. Creating the string containing the SQL CALL statement, using parameter
markers in place of the stored procedure parameters
2. Preparing the SQL string for execution
3. Setting the input parameters
4. Registering the output parameters, to allow them to be accessed after the
CALL
5. Executing the call to the stored procedure
6. Retrieving the vales of the output parameters

The code fragments shown in the following sections illustrate these steps.

9.2.2.1 Create SQL string


First, a string must be defined containing the SQL CALL statement to invoke
the stored procedure. The syntax of the CALL statement is normal, other than
the fact that each reference to a parameter (normally represented by a host
variable of some sort) is replaced by a ? character. In the example below, we
are invoking a procedure called JS_ADD_CUSTOMER which has 6 parameters
(3 input parameters and 3 output parameters).

procName = "JS_ADD_CUSTOMER";
String sql = "CALL " + procName + "(?,?,?,?,?,?)";

Note that the stored procedure name in the call is in upper case — see
9.2.1.2, “The SQL CALL statement” on page 171.

172 DB2 Java Stored Procedures: Learning by Example


9.2.2.2 Prepare string for execution
Now that we have built the SQL string, it needs to be passed to DB2 for
preparation. This is done using the prepareCall method, as shown in the
example below:
callStmt = con.prepareCall(sql);

9.2.2.3 Set input parameters


Next, we need to tell DB2 what values to pass for the input parameters when
the stored procedure is invoked. The following lines of code allocate the three
parameters passed to the client program to parameters 1, 2 and 3 of the
stored procedure, using the argv function.
callStmt.setString (1, argv[0]); // firstname
callStmt.setString (2, argv[1]); // lastname
callStmt.setString (3, argv[2]); // address

Note that in common with many other aspects of Java, the argv function
defines the first parameter as argv[0], even though the setString method
refers to the first stored procedure parameter as number 1.

9.2.2.4 Register output parameters


In order to access the output parameters after the call, they must be
associated with the call statement using the registerOutParameter method. In
the example below, we are defining parameters 4, 5 and 6 according to their
respective data types:
callStmt.registerOutParameter (4, Types.INTEGER); // generated Cust no
callStmt.registerOutParameter (5, Types.CHAR); // mark
callStmt.registerOutParameter (6, Types.CHAR); // mark_error_text

9.2.2.5 Call stored procedure


Now, we are ready to call the stored procedure using the simple syntax
shown below:
callStmt.execute();

9.2.2.6 Retrieve output parameters


Finally, we need to retrieve the previously registered output parameters and
place them into host variables so that they are accessible to the client
program:
int returned_cust_no = callStmt.getInt(4);
String returned_mark = callStmt.getString(5);
String returned_mark_error_text = callStmt.getString(6);

Chapter 9. Client applications invoking Java stored procedures 173


9.2.3 SQLJ client coding considerations
Coding an SQLJ call to a stored procedure is simpler and less verbose than
its JDBC equivalent. The CALL statement is embedded directly within the
stored procedure call, and can use host variable names for the input and
output parameter names within the call.

The code fragment below shows a call to the same stored procedure
discussed in the JDBC section earlier:
#sql [myconn] { CALL ADD_CUSTOMER
( :IN lastname, :IN firstname, :IN address, :OUT cust_no,
:OUT returned_mark, :OUT returned_mark_error_text)
};

Note that the stored procedure name in the call is in upper case — see
9.2.1.2, “The SQL CALL statement” on page 171.

9.3 Client authorization issues


Section 7.2.2, “DB2 authorization issues” on page 120 covered DB2 security
issues related to stored procedures themselves. This section looks at some
additional authorization considerations from the client’s perspective.

9.3.1 JDBC client authorization


Most of the authorization issues covered in 7.2.2.2, “JDBC stored
procedures” on page 120 also apply to JDBC clients. It is possible to alter the
way in which authorization checking is performed using the DYNAMICRULES
parameter when binding the client’s generic JDBC packages or plan.

9.3.2 DB2 for OS/390 stored procedure execute authority


When invoking a stored procedure that resides on the S/390 platform, the
authority needed to execute the procedure varies depending upon whether
the procedure was created prior to DB2 UDB for OS/390 Version 6 or not.

Prior to Version 6, the client only requires execute authority on the DB2
packages used by the stored procedure.

However, invoking a procedure created since Version 6 was installed requires


a specific EXECUTE privilege on the stored procedure itself, in addition to the
DB2 package privileges described above. The EXECUTE privilege is implicitly
held if you are the owner of the stored procedure or a SYSADM, or may be
explicitly granted using the new GRANT EXECUTE ON PROCEDURE... SQL
statement.

174 DB2 Java Stored Procedures: Learning by Example


Refer to the description of the CALL statement in the DB2 UDB for OS/390
SQL Reference, SC26-9014 for a full description.

9.4 Sample Java client preparation scripts


We used the scripts below for Java client program preparation.

Note: These scripts can be found on the CD-ROM, in the SAMPLES\S390


UTILITIES\PROGRAM PREPARATION directory. Refer to Appendix E, “Using the
additional material” on page 347 for more information.

The entire process is invoked from the USS command line using a syntax
such as:
javacl sscall_Add_customer acmecl sscalac acmes

This can be found in script driver_cl.

9.4.1 Sample javacl script


This script will translate the SQLJ, create the DBRMs with db2profc, and bind
the DB2 packages.
# SQLJ client with SQL
# phase 1 SQLJ translator
# phase 2 db2profc create DBRMs
# phase 3 bind packages
#
# Call format for shell is => javacl pgm pkg mem qualifier
# Example => javacl $1 $2 $3 $4
# $1= Java class name
# $2= Java package name
# $3= Member package name used for binds - limit 7
# $4= Table qualifier
#
pgm=$1
# pgm is the Java class name.
pkg=$2
# pkg is the used for the SP package collection, JAVA package,
# directory where the JAVA code is.
mem=$3
# mem package name used for binds - limit to 7 characters
qual=$4
# qual is the table qualifier
#
pgmuln=$1'_SJProfile0'
echo $pgmuln

Chapter 9. Client applications invoking Java stored procedures 175


echo "Starting phase 1 - SQLJ translator" $pgm $pkg
`whence sqlj` $pkg/$pgm.sqlj

echo "Starting phase 2 - db2profc"


db2profc -pgmname=$mem $pkg/$pgmuln.ser

echo "Starting phase 3 - bind plans"


# bindcl.rexx $mem $pkg $qual $spcol
bindsp.rexx $mem $pkg $qual

umem=`echo $mem | tr 'a-z' 'A-Z'`


cat bind$SSID$umem.out | sed 's/ *$//'
echo "Build for" $pgm $pkg "complete"

9.4.2 Sample bindcl.rexx script


This script builds the bind statements and passed them to the TSO REXX
exec OEBIND. It will only bind the DB2 packages, and the plan will have to be
manually bound.
/* rexx Unix System Services (USS) */
/* bindcl_plan.rexx MEM PKG qual spcol */
/* called by JAVA prep shell scripts to bind the client plan and */
/* packages. */
/* */
/* 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. */
/* Written 03/05/200 by Michael J. Fischer */
/* */
/* Input parms: 4 */
/* MEM DBRM member name used for the PDSE library. */
/* PKG Client package name for bind. */
/* qual Table qualifier name used for unqualified tables. */
/* spcol Stored procedure package collection name to use */
/* in Plan. */
/* */
/* Calls TSOE rexx program "OEBIND" to run DSN in the tsoe */
/* environment. This was done so the JAVA prep shell scripts */
/* can run in the OMVS or telnet environment. DSN will not run */
/* under telnet. */
/* */
/* To display help enter bindcl_plan.rexx ? or bindcl_plan.rexx '?' */

176 DB2 Java Stored Procedures: Learning by Example


/* */
/* Note: In USS a ? is converted to a 2. */

arg MEM PKG qual spcol .

if MEM = "?" | MEM = 2 then do


do i = 1 while substr(sourceline(i),1,2) = "/*"
say sourceline(i)
end
return 0
end

if length(MEM) > 7 then do


say "ERROR**** Member name can not be greater then 7 characters"
say "Unable to create BIND statements"
return 999
end

x=0

/* */
/* Find the DB2SQLJPROPERTIES environment variable and set the */
/* rexx DB2SQLJPROPERTIES variable to it. */
/* If no DB2SQLJPROPERTIES variable set then default to */
/* db2sqljjdbc.properties in working directory */
/* */
do I = 1 to __environment.0
if substr(__environment.i,1,17) = 'DB2SQLJPROPERTIES' then do
DB2SQLJPROPERTIES = substr(__environment.i,19,length(__environment.1)-18)
x=1
end
if substr(__environment.i,1,5) = 'TERM=' then do
termenv = substr(__environment.i,6,length(__environment.i)-5)
end
end
if x=0 then DB2SQLJPROPERTIES = 'db2sqljjdbc.properties'

/* Pick up the DB2 subsystem ID and DBRMLIB to use for the Binds */
/* db2sqljplanname */
/* from the DB2SQLJPROPERTIES file. */
address syscall "readfile (DB2SQLJPROPERTIES) file."
if retval < 0 then do
say "ERROR*** The" DB2SQLJPROPERTIES "file does not exist"
say "Unable to create BIND statements"
return 999
end

Chapter 9. Client applications invoking Java stored procedures 177


else do i = 1 to file.0
if substr(file.i,8,4) = 'SSID' then
ssid = substr(file.i,13,length(file.i)-12)
if substr(file.i,8,7) = 'DBRMLIB' then
dbrmlib = substr(file.i,16,length(file.i)-15)
if substr(file.i,8,8) = 'PLANNAME' then
planname = substr(file.i,17,length(file.i)-16)
end

/* */
/* Build the BIND statements and save them to the stack. */
/* */

say '****** NOTE: ******'


say 'If this JAVA client calls a JAVA SP, make sure the SP's'
say 'collection along with this clients collection'
say PKG||'.* is in PLAN' planname 'and rebind this PLAN'
say '*******************'

b.0 = 5
b.1 ="BIND PACKAGE("PKG") MEMBER("MEM"1) ACT(REP) ISOLATION(UR) VALIDATE
(BIND) LIBRARY('"DBRMLIB"') QUALIFIER("QUAL")"
b.2 ="BIND PACKAGE("PKG") MEMBER("MEM"2) ACT(REP) ISOLATION(CS) VALIDATE
(BIND) LIBRARY('"DBRMLIB"') QUALIFIER("QUAL")"
b.3 ="BIND PACKAGE("PKG") MEMBER("MEM"3) ACT(REP) ISOLATION(RS) VALIDATE
(BIND) LIBRARY('"DBRMLIB"') QUALIFIER("QUAL")"
b.4 ="BIND PACKAGE("PKG") MEMBER("MEM"4) ACT(REP) ISOLATION(RR) VALIDATE
(BIND) LIBRARY('"DBRMLIB"') QUALIFIER("QUAL")"
b.5 ="END"

input = "BIND"||ssid||"INPUT"

address syscall "writefile ("||input||") 777 b."


if retval=-1 then do
"error*** writing bind input file" input
return 999
end

address syscall "getcwd cwd"


if retval=-1 then do
"error*** getting current directory to save"
return 999
end

/* */
/* Call "oebind" to run DSN on the tsoe OS/390 environment. */
/* */

178 DB2 Java Stored Procedures: Learning by Example


if termenv = 'vt100' then /* telnet */
"tso -t oebind" ssid cwd input mem
else
"tso oebind" ssid cwd input mem

/* */
/* Remove input file with BIND statements in */
/* */
"rm" input

/* */
/* make sure the directory exist for ser files in /u/"ssid"/ser/ */
/* */
address syscall
"chdir /u/"ssid"/ser/"pkg
if retval=-1 then do
"chdir /u/"ssid"/ser/"
if retval=-1 then do
say "error*** getting directory /u/"ssid"/ser"
return 999
end
"mkdir" pkg 777
if retval=-1 then do
say "error*** making directory /u/"ssid"/ser/"pkg
return 999
end
end
/* reset current directory */
"chdir" cwd
if retval=-1 then do
"error*** reseting directory" cwd "to current"
return 999
end
RETURN

Chapter 9. Client applications invoking Java stored procedures 179


180 DB2 Java Stored Procedures: Learning by Example
Chapter 10. Migration of DB2 for OS/390 Version 5 to Version 6

Migration to DB2 Universal Database for OS/390 Version 6 eliminates all Type
1 indexes, shared read-only data, data set passwords, and use of host
variables without the colon; and it changes the usage of the RECOVER INDEX
command.

You can migrate to Version 6 only from a Version 5 subsystem, and you must
convert all type 1 indexes to type 2 indexes. Shared read-only data has to be
removed, and all data set passwords must be removed. For stored
procedures, the table SYSIBM.SYSPROCEDURES is migrated to two new tables,
SYSIBM.SYSROUTINES and SYSIBM.SYSPARMS.

In the following sections we cover some additional migration considerations


that apply specifically to DB2 stored procedures.

10.1 Stored procedures


In earlier releases of DB2, columns AUTHID and LUNAME of catalog table
SYSIBM.SYSPROCEDURES were used to uniquely identify multiple instances of a
stored procedure. After migrating to Version 6, you should use the SCHEMA
column in the SYSIBM.SYSROUTINES catalog table, the CURRENT PATH special
register, and the PATH bind option to identify multiple instances of a procedure
(see Chapter 11, “DB2 UDB for OS/390 network computing enhancements”
on page 187, Chapter 12, “DB2 UDB for OS/390 schema support” on page
233 and Chapter 13, “DB2 UDB for OS/390 stored procedures
enhancements” on page 243 for background information).

During the migration process, DB2 generates CREATE PROCEDURE statements


which populate SYSIBM.SYSROUTINES and SYSIBM.SYSPARMS. Rows in
SYSIBM.SYSROUTINES that contain non-blank values for columns AUTHID or LUNAME
are not used to generate the CREATE PROCEDURE statements. You can identify
those rows by using the following statement:
SELECT * FROM SYSIBM.SYSPROCEDURES WHERE AUTHID <> ' ' OR LUNAME <> ' ';

DB2 also copies rows in SYSIBM.SYSPROCEDURES into table SYSIBM.SYSPARMS and


propagates information from the PARMLIST column of SYSIBM.SYSROCEDURES into
SYSIBM.SYSROUTINES and SYSIBM.SYSPARMS.

© Copyright IBM Corp. 2000 181


Stored procedures migrated from Version 5 do not have an owner, because
they were not created with the CREATE PROCEDURE statement. This means that
the authorization rules don't change from V5. If you subsequently DROP and
CREATE the stored procedure, now it has an OWNER, so the caller must have
EXECUTE ON PROCEDURE authority to invoke it. DB2 authorization treats these
migrated procedures differently than procedures created with CREATE
PROCEDURE. The authorization for migrated procedures is unchanged.

Migrated stored procedures have SCHEMA set to SYSPROC. This means that to
invoke them, SYSPROC has to be in the concatenation of schemes that DB2
uses in resolution.

The catalog table SYSIBM.SYSPROCEDURES is not used in Version 6 to define


stored procedures to DB2. The SYSCAT.PROCEDURES view of catalog table
SYSIBM.SYSPROCEDURES is not used to list the stored procedures registered in
DB2. Although these tables are no longer used in Version 6, DB2 does not
drop them during migration because they are needed for fallback and data
sharing coexistence.

For more information, refer to DB2 Application Programming and SQL Guide,
SC26-9004.

10.1.1 SYSIBM.SYSPROCEDURES no longer used


Catalog table SYSIBM.SYSPROCEDURES is no longer used to define stored
procedures to DB2 in Version 6. During catalog migration, all rows in
SYSIBM.SYSPROCEDURES are automatically migrated to the new
SYSIBM.SYSROUTINES catalog table and to SYSIBM.SYSPARMS.

In Version 6, you use the CREATE and ALTER PROCEDURE statement to define
stored procedures. To prepare for fallback, or to run in a coexistence
environment for data sharing, you must modify the SYSPROCEDURES catalog table
to match the updates to SYSROUTINES and SYSPARMS that those CREATE
statements make.

10.1.2 Java stored procedures under Version 5


If you used Java stored procedures in release 5, you stored the Java
classname and methodname in the RUNOPTS column. After migrating to Version
6, the catmaint job has moved the contents of RUNOPTS for COMPJAVA programs
to the External Name column. Therefore, in Version 6, the Java stored
procedure will use the External Name column for the Java classname.

182 DB2 Java Stored Procedures: Learning by Example


10.1.3 DB2 catalog maintenance
Make sure you have a stand-alone copy of your DB2 subsystem, BSDSs,
logs, catalog, directory, and libraries before you start your Version 5
subsystem with the new Version 6 libraries and run the catmaint job. This is to
ensure that you have a fallback if you run into problems when running the
catmaint job.

If you run into errors with step 2, DNSTITC2, of the catmaint job DSNTIJCT, this
step is restarted. The SYSIBM.SYSPROCEDURES is available in Version 6 to update,
so you can correct any problems you might have with a stored procedure. You
then can rerun the catmaint job DSNTIJTC at step 2, DSNTITC2. You will get -601
SQLCODE on the procedures that have already been defined to Version 6 and a
return code of 4 on the job when you rerun it. The -601 is caused by a
duplicate row on the catmaint job trying to insert a row that is already been
defined to SYSIBM.SYSROUTINES from the first run. These -601 errors can be
ignored.

Note
Remember to check that you have removed all data set passwords, any
views on SYSIBM.SYSCOLDIST and SYSIBM.SYSCOLDISTSTATS, and convert all
indexes to type 2. The sample database DSN8 is created with some type 1
indexes and has passwords on its data sets. Remember to change the
passwords by following these steps:
1. Stop the database, using the -STOP DATABASE command.
2. Remove the password on all associated data sets by using VSAM
access method services ALTER data.set NULLIFY(MASTERPW) command.
3. Change the password, using the DSETPASS clause of the ALTER TABLESPACE
statement or the ALTER INDEX statement to a space. You must use the
same password for all data sets for the same table space or index
space.
4. Start the database again, using the -START DATABASE command.

Chapter 10. Migration of DB2 for OS/390 Version 5 to Version 6 183


10.1.4 Fallback considerations from Version 6 to Version 5
If you created stored procedures with the Version 6 statement CREATE
PROCEDURE, you will not be able to access those stored procedures if you need
to fall back to Version 5. You will receive SQLCODE -204 if you try to access a
Version 6 stored procedure after fallback, because the procedure name is not
in catalog SYSIBM.SYSPROCEDURES. You will need to manually keep track of your
changes to SYSIBM.SYSROUTINES and SYSIBM.SYSPARMS, because on fallback to
Version 5, the SYSIBM.SYSPROCEDURES table is not updated with any changes or
newly created stored procedures. You will have to manually create the
updates to SYSIBM.SYSPROCEDURES before you migrate, or you must have kept
the DDL in a PDS that you can run and update SYSIBM.SYSPROCURES table after
falling back to Version 5.

184 DB2 Java Stored Procedures: Learning by Example


Part 3. DB2 UDB for OS/390 V6 — various enhancements

© Copyright IBM Corp. 2000 185


186 DB2 Java Stored Procedures: Learning by Example
Chapter 11. DB2 UDB for OS/390 network computing enhancements

This chapter describes the enhancements and new support provided by DB2
UDB for OS/390 for network computing solutions that can help you to improve
the development, performance, and security of your client/server
applications.

11.1 DRDA support for three-part names


The following sections describe the three-part name support.

11.1.1 Three-part names prior to Version 6


With prior versions of DB2 (and with DB2 Version 6) you can use either
DRDA or DB2 private protocol when making distributed calls. Prior to Version
6, the way DB2 would know which protocol to use is based on the provision of
a three-part name (or an alias for a three-part name) for private protocol, or
the use of the SQL CONNECT statement for DRDA. See Figure 20.

Figure 20. Three-part names — prior to DB2 for OS/390 Version 6

Some of the differences between private protocol and DRDA are listed below.
These differences still exist in Version 6.

© Copyright IBM Corp. 2000 187


• Private protocol always uses dynamic SQL. There is no way for you to
specify static SQL when using private protocol. With DRDA, you can use
static and dynamic SQL.
• Private protocol has restrictions in terms of the SQL that can be executed
on the remote server. You are basically limited to DML SQL statements.
With DRDA, in addition to DML, you can execute DCL and DDL
statements at the remote server.
• Private protocol limits the server type to DB2 on the MVS platform. With
DRDA, you can send/receive SQL statements to any platform that
supports DRDA.
• Private protocol can use only SNA connections. With DB2 for OS/390
Version 5 and higher, DRDA can use SNA and TCP/IP connections.
• With DB2 Version 6, you have support for UDTs and LOBs. This support is
only available if the underlying protocol is DRDA.
LOBs can be accessed from a client only when using the DRDA protocol.
Because a typical use of LOBs is on some type of workstation, DRDA is
enhanced to allow a LOB value to be sent across the network. In this way,
LOB values and LOB locators can be passed back and forth between a
DRDA AR and AS. Both DB2 on the workstation and DB2 for OS/390
provide support for these DRDA enhancements, allowing a DB2
application to access and manipulate LOB values anywhere in the DRDA
network.
DB2 on the workstation, however, supports the file reference variables
whereby a LOB value can be selected or inserted without the requirement
for a contiguous piece of application storage to contain it.
When a DRDA client sees a reference to a file reference variable in the
VALUES clause of an INSERT statement or the SET clause of an UPDATE
statement the DRDA client will read the file’s contents on the wire as a
single LOB value. Similarly, when a DRDA client sees a reference to a file
reference variable in the INTO clause of a SELECT or FETCH statement,
the DRDA client will place the LOB value it receives from the server into
the specified file. If you try to pass UDTs or LOBs using private protocol,
the statement fails, and a -728 SQLCODE is returned.
• Stored procedures are supported only when using DRDA. See Table 12.

188 DB2 Java Stored Procedures: Learning by Example


Table 12. Private protocol v DRDA access

Category Private Protocol DRDA

Use of static/dynamic SQL Dynamic only Dynamic and static

SQL Type DML only DML, DCL and DDL

Remote server support DB2 for OS/390 only Any DRDA AS

Protocol support SNA only SNA and TCP/IP

Support for Object No Yes


Relational extensions
(such as UDTs and LOBs)

Support for stored No Yes


procedures

11.1.2 Three-part names in Version 6


Although DB2 Version 6 still supports the use of private protocol, it will not be
enhanced in the future. Application programs using a remote three-part
name, or an alias for a table with a remote three-part name, can now use the
DRDA protocol if they are explicitly bound for DRDA by the use of the new
BIND/REBIND option, DBPROTOCOL(DRDA).

With this option, DB2 will implicitly use the DRDA protocol for remote access.
Existing applications that previously resulted in private protocol flows, but are
now rebound to DRDA, will not have to be rewritten.

Not only can you have your existing programs converted to a DRDA flow, but
new programs can be coded with less of the connection management
inherent to DRDA.

For example, a current DRDA program may execute these statements:


CONNECT to local;
CONNECT to remote_site1;
CONNECT to remote_site2;
CONNECT to remote_site3;
SELECT * from table3; -- (table3 in remote_site3)
SET CONNECTION to remote_site2;
SELECT * from table2; -- (table2 in remote_site2)
SET CONNECTION to remote_site1;
SELECT * from table1; -- (table1 in remote_site1)
SET CONNECTION to local;
SELECT * from table0; -- (table0 in local)

Chapter 11. DB2 UDB for OS/390 network computing enhancements 189
The same statements can be written as:
SELECT * from remote_site3.userid.table1;
SELECT * from remote_site2.userid.table1;
SELECT * from remote_site1.userid.table1;
SELECT * from userid.table0;

For an illustration of these concepts, refer to Figure 21.

Figure 21. Three-part name — Version 6

So, besides the advantage of minimal impact to exiting programs, the new
DBPROTOCOL option produces another major advantage; coding is
simplified because there is less of it. Also, if you use alias for remote tables,
you achieve location transparency; if a table has to be moved from one
location to the other, you do not have to change your application. It is enough
to change the alias to point to another location and rebind/copy the package
to that location.

190 DB2 Java Stored Procedures: Learning by Example


11.1.3 Package requirements
To effect the change at the requester, you have to rebind the local package or
plan specifying DBPROTOCOL(DRDA). You have also to bind the same
package (with this or another name) at the remote servers you are accessing,
and include the remote server’s packages in the package list of the local plan
(the same way that you already do for remote packages). Once this is done,
the programs that were previously using the private protocol will use DRDA. If
DRDA execution is attempted, but no package is found at the remote site, a
-805 SQLCODE is issued.

When accessing tables using three-part names and DRDA, access to the
remote server can be dynamic or static, depending on how you code your
application. You can use CONNECT 1 or CONNECT 2, although you are
strongly recommended to use CONNECT 2 (see Figure 22). Refer to DB2
UDB for OS/390 Version 6 SQL Reference, SC26-901, for detailed
information about CONNECT (Type 1) and CONNECT (Type 2).

Figure 22. Package requirements

Chapter 11. DB2 UDB for OS/390 network computing enhancements 191
11.1.4 How it works
Figure 23 summarizes the flow that DB2 uses to identify the correct server.

LOC1
SELECT * FROM
DRDA
LOC1.USER.TAB

1 - Check CURRENT SERVER


2 - CONNECT / SET CONNECTION TO LOC1
3 - SET CONNECTION back
4 - LOC1 is DORMANT

Figure 23. How it works

Following are the details of the steps shown in Figure 23:


1. DB2 first checks the value of the CURRENT SERVER special register.
2. DB2 will implicitly issue a connect or a SET CONNECTION statement to
the remote location. If the program was precompiled with
SQLRULES(STD) and the connection to the remote location was already
established, DB2 issues the SET CONNECTION statement. Otherwise,
DB2 issues the CONNECT statement.
3. Once the statement coded in the application program finishes execution,
DB2 issues the SET CONNECTION statement to the previously saved
value of the CURRENT SERVER special register.
4. The remote site will remain in the connection set (to maximize
performance), but will be marked as a DORMANT connection.

The connection management is handled automatically by DB2. There is no


need for the application programmer to be concerned about SQLRULES
(DB2 or STD). DB2 knows when to do a SET CONNECTION or a CONNECT.

When this conversion is accomplished, the concern about having a private


connection and a DRDA connection to the same location (SQLCODE -842) is
eliminated.

192 DB2 Java Stored Procedures: Learning by Example


11.1.5 DBPROTOCOL bind option
These are the defaults for the DBPROTOCOL bind option:
• BIND PLAN/PACKAGE
If not specified, this defaults to what was specified in the DSNTIP5 panel
of the installation process. If you do not change it on the panel, the default
is DRDA.
• REBIND PLAN/PACKAGE
The default is what was specified the last time you bound the plan or
package.
• Remote BIND
If you specify a three-part name (LOC2.USER1.TABLE1), and in the
remote system LOC2, USER1.TABLE1 is an alias for
LOC3.USER1.TABLE1, then when you bind the package to LOC2, the
protocol used by LOC2 to get to LOC3 is the installation default for LOC2.
You have to bind the package to LOC2, and LOC3. When you bind the
package to LOC2, LOC2 will not automatically create a package in LOC3.

There is a new column DBPROTOCOL in SYSPACKAGE and SYSPLAN,


which indicates the DBPROTOCOL bind option of PRIVATE (‘P’) or DRDA
(‘D’).

11.1.6 Stored procedures — considerations


The CALL statement to invoke a stored procedure already supported the
three-part name, but at the time of the call, you had to be connected to the
server specified in the stored procedure name. With Version 6, you do not
have to issue the CONNECT or SET CONNECTION statement to the location
where the stored procedure resides. DB2 will automatically connect to the
remote location of the stored procedure.

11.1.6.1 Result sets


The DESCRIBE PROCEDURE and ASSOCIATE LOCATORS statements can
specify a three-part name for a remote stored procedure, and will now be
executed with respect to the site specified in the three-part name. This will be
done regardless of the DBPROTOCOL bind parameter.

Similarly, the statements ALLOCATE CURSOR, DESCRIBE CURSOR,


FETCH cursor, and CLOSE cursor require that the application be connected
to the site where the stored procedures declaring the cursor are executed.
Note that the FETCH and CLOSE cursor statements also apply when a stored
procedure is not being used.

Chapter 11. DB2 UDB for OS/390 network computing enhancements 193
These statements, in their syntax, contain result set locators which uniquely
identify a cursor. So, although a three-part name is not contained in these
statements, there is no ambiguity as to which cursor is being referenced.
Therefore, the restriction about site connection has been removed for the
ALLOCATE CURSOR and DESCRIBE CURSOR statements, regardless of
the BIND option.

Note
When using DESCRIBE PROCEDURE and other SQL statements for
accessing result sets, you should ensure that the procedure name is
specified exactly as it is on the CALL statement (including the number of
qualifiers used for the procedure name).
See the description of the DESCRIBE PROCEDURE statement in the
DB2 SQL Reference, SC26-9014 for further details.

11.1.7 Hopping
This section describes the possible hopping (three-part name) usage
scenarios, which are summarized in Figure 24.

Figure 24. Hopping

194 DB2 Java Stored Procedures: Learning by Example


11.1.7.1 DRDA and private protocol
The maximum level of hopping is two hops, if one of the protocols involved is
private. For example, if you use a three-part name on SITE1, that refers to
SITE2, and in SITE 2, this is an alias for an object residing in SITE 3. This
object must be a local view or table in SITE 3; it cannot be an alias for a
remote table.

In this scenario, the DRDA protocol is used in the connection between SITE 1
and SITE 2, and the private protocol is used in the connection between SITE
2 and SITE 3. The private protocol cannot be used in both.

11.1.7.2 Only DRDA protocol


If you use only DRDA, there is no limit on the number of sites that you can
hop, as long as there are packages at the target site. As a consequence, a
middle site (SITE 2 or SITE 3 in the diagram) cannot tell how many levels
have been nested.

11.1.7.3 Loop back


Consider the following scenario:
On SITE 1: rtable is synonym of site2.user1.table1
On SITE 2: table1 is synonym of site1.user1.table1

In this scenario, the loop back would be possible.

However, there are some scenarios where DB2 detects and avoids loop back
connections. For example:
On SITE 1: rtable is synonym of site2.user1.rtable
On SITE 2: rtable is synonym of site1.user1.rtable

DB2 does not allow another hop on a connection that matches the LUWID of
another existing DRDA thread. So, if SITE 1 has a thread “to” SITE 2, and a
thread “from” SITE 2, the incoming thread from SITE 2 will be marked so that
no further hops are performed.

Another example is:


On SITE 1: rtable is synonym of site2.user1.rtable
On SITE 2: rtable is synonym of site3.user1.rtable
On SITE 3: rtable is synonym of site1.user1.rtable

For the example above, a -904 SQLCODE with reason code 00D31052 is
returned.

Chapter 11. DB2 UDB for OS/390 network computing enhancements 195
Figure 25 summarizes these scenarios.

Figure 25. Loop back

11.1.8 Advantages
Following are some more advantages of using this new enhancement:
• Better performance at execution time, because binding occurs when the
package is bound, not during program execution.
• Better performance due to the fact that static statement information is not
destroyed at COMMIT time. If a cursor is not specified WITH HOLD, a
COMMIT will cause DB2 to discard all the statement information. If the
statement is dynamic, subsequent re-execution causes another PREPARE
(or REBIND) of the statement to take place.

Note
It is important to emphasize that the options available for Version 5 for
truly dynamic statements, such as KEEPDYNAMIC and statement
caching, also apply to Version 6.

• Allows access to DRDA servers that are not DB2 for OS/390 systems
through the use of a three-part name (or alias).

196 DB2 Java Stored Procedures: Learning by Example


• Permits hopping to non-DB2 for OS/390 systems (see 11.1.7, “Hopping”
on page 194).
• Access to new DB2 functions such as stored procedures, which were
added only to DRDA processing.
• Take advantage of DRDA DDF enhancements, such as the chained
PREPARE/DESCRIBE/ pre-OPEN performance enhancements.

11.1.9 Impacts
There are some minor impacts associated with conversion to DRDA
three-part table names. These include:
• No support for continuous block fetch. Although Version 6 provides for
similar function, the OPTIMIZE FOR clause is specified.
See 11.2, “DRDA query block size” on page 198 for details.
• Loop back is not allowed. See 11.1.7.3, “Loop back” on page 195 for
details.
• The current restriction with CREATE, ALTER, DROP, GRANT, REVOKE,
COMMENT ON, LABEL ON, RENAME is not removed. These statements
(whether or not three-part name were used in coding) are excluded from
private protocol. This restriction remains with the new three-part name
DRDA protocol implementation.
In general, only the same statements as for private protocol (DML) are
allowed when using DRDA with three-part names. In addition, most SET
local statements are propagated to the remote sites through the new
DRDA codepoint.
• Only package authorization information is passed to non OS/390 DRDA
servers.
Authorization to a DB2 for OS/390 server (hop site) should be identical to
the authorization as it currently exists. Once a server other than DB2 for
OS/390 is encountered, however, only the package information will flow to
that site or to downstream sites.
For example, between two DB2 for OS/390 systems, the plan
authorization is passed. The above is valid for DRDA and private and will
continue be like that. Once DB2 hops to a non-DB2 for OS/390 system,
such as DB2 UDB on the workstation, only package authorization is
passed.

Chapter 11. DB2 UDB for OS/390 network computing enhancements 197
11.2 DRDA query block size
In DRDA level 1 and level 2, the amount of query data returned on each
network transmission is governed by the DRDA query block size, specified by
the application requester (AR). The maximum value for the DRDA query
block size is 32 KB, so the amount of data exchanged between the client and
the server on each data transmission is relatively small.

The 32 KB limit for the DRDA query block size is a performance bottleneck
for applications that need to move large amounts of data around (such as
Data Propagator Relational (DPropR) and Visual Warehouse) especially
when the client and the server are connected by relatively slow network
connections.

Because in a DRDA environment there is only one conversation, continuous


block fetching (used in private protocol) cannot be deployed when using
DRDA.

DB2 UDB for OS/390 Version 6 implements DRDA level 3, which provides
support for returning multiple DRDA query blocks on each network
transmission. Although this does not remove the 32 KB limit on a single
DRDA query block, it bypasses the limitation by allowing the DRDA server to
send multiple 32 KB blocks in each network transmission.

There are two new installation parameters, EXTRA BLOCK REQ and EXTRA BLOCK
SRV, that specify the maximum number of extra negotiated query blocks to be
used when the OPTIMIZE FOR n ROWS clause is coded (see 11.2.1,
“OPTIMIZE FOR n ROWS clause enhancements” on page 198).

When the client supports DRDA level 3, DRDA allows the client to specify the
limit on the number of extra DRDA query blocks. The DRDA default for extra
block is zero, which results in the flows that are identical to DRDA level 1 or
level 2.

11.2.1 OPTIMIZE FOR n ROWS clause enhancements


Some enhancements to the OPTIMIZE FOR n ROWS clause were introduced
in Version 5 to minimize the impact of sending a large block of data when just
a few rows of the result set were relevant to the client application. So in
general, the OPTIMIZE FOR n ROWS clause has been used only where a
small number of rows are expected.

198 DB2 Java Stored Procedures: Learning by Example


With DB2 UDB for OS/390 Version 6, OPTIMIZE FOR n ROWS is also used
when the result set that must be returned to the client exceeds the negotiated
block size.

If a DRDA client (or a stored procedure at a server) declares the cursor with
the OPTIMIZE FOR n ROWS clause, the client can request extra blocks from
the server, who may then send up to 32 K DRDA query blocks in one network
transmission.

Additionally, network I/O and SQL operations can be performed in parallel


when OPTIMIZE FOR n ROWS is specified and the SQL consists of FETCH
requests against the OPTIMIZE FOR n ROWS query. For example, the DRDA
requester can issue an asynchronous receive operation for the next DRDA
query block, while the SQL operation is processing rows from the current
DRDA query block (see Figure 26).

CLIENT
OPTIMIZE FOR 10000000 ROWS

PROCESS ROWS SYNCHRONOUS


BLOCK 1
ASYNCHRONOUS
BLOCK 2

Figure 26. OPTIMIZE FOR large number

The first block is sent synchronously. The remaining blocks are sent
asynchronously.

The minimum between EXTRA BLOCK SRV and EXTRA BLOCK REQ is negotiated.
DRDA allows the negotiation to be conducted either at connection or at
statement execution time. DB2 UDB for OS/390 Version 6 as a requester only
does this at connection time, while as a server it supports negotiation either
at connection or statement execution time.

This allows DRDA applications to gain many of the benefits currently


available in the DB2’s private protocol block fetch function.

Chapter 11. DB2 UDB for OS/390 network computing enhancements 199
11.2.2 How it works
For the client, the installation parameter EXTRA BLOCK REQ specifies the
maximum number of extra DRDA query blocks that this client can request.
For the server, the installation parameter EXTRA BLOCK SRV specifies the
maximum number of extra DRDA query blocks that this server is allowed to
transmit.

When the client application is coded with OPTIMIZE FOR n ROWS, where “n”
is a large number, the following happens:
1. If the result set fits in a block, the block is sent.
2. If the result set does not fit in a block, and the client requests extra DRDA
query blocks, the minimum of EXTRA BLOCK REQ and EXTRA BLOCK
SRV is evaluated.
3. The extra blocks evaluated in step 2 are sent.
4. If these extra blocks are not enough (that is, there are still rows to be sent)
these rows will be sent upon the next request from the client.

Figure 27 shows that flow.

CLIENT SERVER

EXTRA BLOCK REQ EXTRA BLOCK SRV

Y Rows fit in
SEND
one block?

N
MINIMUM
EXT REQ EXT SRV

SEND
EXTRA BLOCKS

N
END More rows?

Y
SEND on new
client request

Figure 27. OPTIMIZE FOR — how it works

200 DB2 Java Stored Procedures: Learning by Example


11.2.3 Usage recommendations
The OPTIMIZE FOR n ROWS clause should only be used to increase the
number of DRDA query blocks in applications that have the following
attributes:
• The application fetches a large number of rows from a read-only query.
• The application rarely closes the SQL cursor before reaching the end of
the query answer set.
• The application does not issue statements other than FETCH to the DB2
server while the SQL cursor is open.

In Figure 28, the DRDA client opens a cursor and fetches rows from the
cursor using the OPTIMIZE FOR 1000 ROWS clause. Both the DRDA client
and the DB2 server are configured to support multiple DRDA query blocks. At
some point prior to the end of the query answer set, the application issues an
SQL INSERT. Since OPTIMIZE FOR is being used, the DRDA connection is
not available when the SQL INSERT is issued (that is, the connection is still
being used to receive the DRDA query block for 1000 rows).

This causes two performance problems:


• Application elapsed time is increased if the DRDA client has to wait for a
large query answer set to be transmitted, before the DRDA connection can
be used for other SQL statement.
• If the SQL applications closes the cursor before fetching all of the rows in
the SQL answer set, the server may fetch a large number of rows
unnecessarily.

Chapter 11. DB2 UDB for OS/390 network computing enhancements 201
CLIENT SERVER
..OPTIMIZE FOR 1000 ROW S;

OPEN C1; CURSOR IS OPENED

Query block with 100 rows returned


FETC H C1 INTO...
Query block with 100 rows returned
FETC H C1 INTO... Query block with 100 rows returned
Query block with 100 rows returned
Query block with 100 rows returned
INSERT INTO .... Query block with 100 rows returned
Query block with 100 rows returned
Query block with 100 rows returned
Query block with 100 rows returned
Query block with 100 rows returned

Server processes INSERT statement

Figure 28. Potential issue when using OPTIMIZE FOR n ROWS

11.3 DDF connection pooling


This is another very important feature of DB2 UDB for OS/390 that allows a
DRDA requester to reuse a connection for new client applications. For this
support there is a new type of thread, identified as a type 2 inactive thread,
which uses less storage for each thread, thus improving the throughput in a
distributed environment.

Following are the benefits provided by this function:


• DB2 can perform connection pooling between thousands of TCP/IP or
SNA connections and a small number of database access threads. There
are150,000 inactive threads per subsystem (but 4.8 million for Parallel
Sysplex)
• The lower CPU cost for creating DDF threads is particularly important for
workloads, such as Web Common Gateway Interface (CGI) applications,
which connect and disconnect to DB2 very frequently.
• There is now reduced storage necessary per DDF.
• RELEASE(DEALLOACTE) is supported for inactive DDF threads.
• DB2 allows new DRDA transactions to reuse database threads (similar to
CICS and IMS).

202 DB2 Java Stored Procedures: Learning by Example


DB 2 Connect Inactive thread pool Active thread pool
Enterprise
Edition

AIX
HP -UX
Solaris
Sinix

OS /2 W INDOW
3.x, 95, NT

AIX
HP-UX
S olaris
O S/2 Sinix

WINDOW
3.x, 95, NT

Figure 29. DDF connection pooling

11.4 STOP DDF MODE(SUSPEND) command


DB2 for OS/390 Version supports a new command that quiesces the DDF
workload:
-STOP DDF MODE(SUSPEND)

Using this DB2 command, you can make DDLs or other changes without
breaking the connections to your DDF clients. This feature is very important
and helpful to improve the overall server availability for e-business and
client/server applications. When the DB2 command, -STOP DDF MODE(SUSPEND)
is issued, it has the following effects:
• Holds INACTIVE threads in INACTIVE state, until a -START DDF command
is issued.
• Terminates all DDF pool threads.
• Prevents the initiation of all inbound DDF work.
• Waits for ACTIVE threads to reach the INACTIVE state.
• After completion, no DDF user will hold locks on any DB2 object.

Chapter 11. DB2 UDB for OS/390 network computing enhancements 203
MODE(SUSPEND) is intended to be used at a DB2 for OS/390 DRDA server,
especially one that has DDF THREADS = INACTIVE when there are locking
conflicts between DDL and client access to the data. This function will
quiesce DDF activity and terminate the DDF pool of data base access threads
used to service the client requests, thus making the database available for
maintenance, including DDL.

The fact that MODE(SUSPEND) completes successfully does not guarantee


that database resources are not still held if there is any activity other than
inbound DDF processing being performed. It may be necessary to use
-CANCEL THREAD to terminate other processing that is being performed in
order to free the database resources.

See Table 13 for a description of the actions taken when a START DDF or a
STOP (DB2 or DDF) command is issued depending on the current DDF state.

Table 13. START / STOP command versus DDF status

Command

DDF status START DDF STOP STOP FORCE STOP DDF


(DB2 or DDF) (DB2 or DDF) MODE(SUSPEND)

Starting Error Error Error Error

Started Error OK (stop) OK (stop) OK (suspend)

Stopping Error Error Error Error

Stopped OK (start) Error Error Error

Suspending OK (resume) OK (stop) OK (stop) Error

Suspended OK (resume) OK (stop) OK (stop) Error

11.4.1 Command syntax


This command allows that requests received by DB2, that would normally
cause DDF work to be dispatched, including requests for new connections,
are instead queued. Outbound DDF processing is not affected by this
command.

204 DB2 Java Stored Procedures: Learning by Example


Following is the command syntax:
>>--STOP DDF---------------------------------------------><
| |
|--MODE-----( QUIESCE )------------------|
| |
|--( FORCE )----------------|
| |
|--(SUSPEND)------------------|
| |
|--CANCEL(n)--|
| |
|--WAIT(n)----|

If CANCEL or WAIT are not specified, then this command waits for all active
DDF database access threads to terminate. If this is not the desired affect,
then how long the command will wait and what action will be taken after a
specified time period can be controlled by the CANCEL and WAIT optional
keywords.
• CANCEL
If suspend processing has not completed successfully in n seconds,
cancel all active DDF database access threads. CANCEL has a valid
range of 0-9999 seconds.
• WAIT
If suspend processing has not completed successfully in n seconds,
resume DDF processing again. WAIT has a valid range of 0-9999 seconds.
The affect of the WAIT option is the same as if a -START DDF command was
issued after n seconds if the suspend process has not completed
successfully during that period.

Note:
See Appendix A, “New messages and error codes” on page 285 for new
messages and error codes provided to support this feature.

11.5 Declared Global Temporary Tables


DB2 for OS/390 Version 5 provides support for the function, CREATE Global
Temporary Tables. The way that this support was implemented did address
some customer needs, such as for Business Intelligence (BI) solutions and
porting applications from Oracle, Sybase, and SQL Server.

Chapter 11. DB2 UDB for OS/390 network computing enhancements 205
With BI, there are many cases when you need to pull data out of the
database, process the data, and then use it for subsequent join operations.

With customers moving their application from Sybase, Oracle, or SQL Server
to DB2, we found out that those products had a particular style that was
different from that expected by our global temporary table support. DB2 UDB
for OS/390 Version 6 provides support for declared global temporary tables,
which has the same style, to provide easy porting from Oracle, Sybase, and
SQL Server, as well as providing functions that simplify its use for BI.

The main enhancements for declared global temporary tables are these:
• Support for indexes
This will be helpful when you use temporary tables for join operations.
Without indexes, DB2 would have to do a table space scan. When the
create index statement is issued, DB2 records that information in memory;
there is no catalog activity.
• Tables do not have to be predefined in the DB2 catalog
Basically, in the middle of your program you just have to issue a new
statement DECLARE GLOBAL TEMPORARY TABLE, which is a dynamic SQL
statement. It does not go out to the catalog and change it. When you issue
the statement, DB2 does this in memory, so only your execution can see it.
The temporary table description is not shared across application
processes. Each application process that uses the declare global
temporary table can define the same qualified table name, with a possibly
unique description for the temporary table.
In addition, when issuing the DECLARE GLOBAL TEMPORARY TABLE statement,
the columns definitions can be implicitly defined as a result of a SELECT
statement. This means that you can populate your temporary table
through the same one SQL statement used to define its columns.
• Full support for delete and update operations
Declared global temporary tables are like regular tables. You can delete
the rows, update the rows. This was not supported with Global Temporary
Tables; only insert and massive delete were supported.
• No catalog contention at runtime
This is very important for BI solutions. Using global temporary tables for
the intermediate tables, you will not have the catalog contention that you
would have with regular create of a real table, where operations such as
creating indexes, huge volume of applications running in parallel update
the catalog simultaneously.

206 DB2 Java Stored Procedures: Learning by Example


11.5.1 Usability considerations
Global temporary tables can be very helpful. They are recommended for use
in scenarios such as: BI applications; e-business and client/server
applications in which you want to move query data into an area that does not
interfere with the OLTP processing; staging data extracted from an IMS
database; and making such data accessible to ODBC clients.

The additional facilities offered by declared global temporary tables make


them a more attractive option than created global temporary tables under
most circumstances. However, there are some situations where created
temporary tables may still be preferable. For example, an application that had
to support very high insert rates into the temporary table, but did not need any
of the additional facilities provided by declared temporary tables, could
realize performance gains due to the lack of logging for inserts to created
temporary tables.

Following are some considerations of using declared global temporary tables:


• Logging
There is logging for declared temporary tables, providing the ability of
doing rollback or UNDO logging up to the last COMMIT point. There is no
need for the REDO recovery ability.
• Persistence
Declared global temporary tables will typically persist for the life of your
transaction until you issue a commit or roll it back. However, there is a
clause with which you can specify that you want that this table to exist
beyond the commit, for allocate duration, or to explicitly drop it.
• Qualifier
The qualifier for a global temporary table is always SESSION. You do not
have any flexibility on choice of a schema name. The word SESSION
becomes a special name that we can easily recognize. When you say
SESSION, you are talking about global temporary tables.

Note:
We recommend that you do not use the word SESSION as one of your
schema names.

Chapter 11. DB2 UDB for OS/390 network computing enhancements 207
• Workfiles
Global temporary tables do not use the regular workfiles (DSNDB07). This
means that they will not compete with your regular workload. Segmented
table spaces in a special temporary database are used as the space for
the table.
• Authorization
You do not need any special authorization privilege to create or declare a
temporary table. Every user automatically has the privilege to create these
on their own.

11.6 Savepoints
A savepoint represents the state of data and schema at a particular point in
time. An application may set named savepoints within a transaction, then as
dictated by application logic, roll back subsequent data and schema changes
without affecting the overall outcome of the transaction. The scope of a
savepoint is the DBMS on which it is set.

Savepoints enable the coding of contingency or what-if logic and could be


useful in the following scenarios.
• Programs with sophisticated error recovery.
• To undo stored procedure updates when an error is detected. With no
savepoints taken in the calling application, a rollback in a stored procedure
will roll back the entire unit of recovery, including all work done by the
caller prior to the stored procedure being invoked. A savepoint taken
immediately prior to the stored procedure call could be used to allow the
stored procedure to rollback in the event of a problem being encountered,
without also undoing any of the changes made by the caller within the
same unit of work.

You can set savepoints by using the SAVEPOINT syntax documented in the
DB2 UDB for OS/390 Version 6 SQL Reference, SC26-9014-01. The
savepoint name can be up to 128 characters, and we suggest that you use a
meaningful name. You can use the UNIQUE OPTION to assert that the
savepoint name will not be reused within the transaction. If you omit the
UNIQUE option and reuse the savepoint name, the old savepoint will be
destroyed. Note that this is different from using the RELEASE SAVEPOINT
statement, which will release all savepoints with that name.

208 DB2 Java Stored Procedures: Learning by Example


When you issue the SAVEPOINT statement, DB2 writes an external
savepoint log record. Savepoints that you create are often termed external
(as opposed to internal) because DB2 already uses internal savepoints as its
mechanism for backing out specific units of recovery. Internal savepoints are
used by DB2 only, cannot be accessed through an application, and may be
liable to change in future releases or as a result of applying maintenance. In
contrast, you have full control over external savepoints.

To roll back to an external savepoint you have set, use the ROLLBACK TO
SAVEPOINT svptname statement. This will back out all data and schema
changes that were made after the savepoint. The following will not be backed
out:
• Any updates outside of the local DBMS (such as remote DB2s, VSAM,
CICS, IMS)
• Changes to created temporary tables (however, changes to declared
temporary tables are backed out)
• The opening and closing of cursors
• Changes in cursor positioning
• The acquisition and release of locks
• The caching of the rolled back statements

11.6.1 Connecting to other DB2 systems


While there are outstanding savepoints, you cannot access a remote DBMS
using DB2 private protocol access or DRDA using aliases or three-part
names. For example, if there is a savepoint set at location A, location A
cannot connect to location B using either of these two ways to access data.

DRDA access using a CONNECT statement is allowed; however, the


savepoints are local to their site. For example, location A can connect to
location B, but the savepoint set at A is unknown to B and does not cover any
operations performed at location B.

You should note that a savepoint set prior to a CONNECT is known only at
the local site, and a savepoint set after a connect is known only at the remote
site. Consequently, we recommend that the processing at the alternate site to
where the savepoint is known should be read-only.

Chapter 11. DB2 UDB for OS/390 network computing enhancements 209
DB2 does not restrict the use of aliases and three-part names to connect to a
remote site when there are outstanding savepoints at the remote site.
However, we do not recommend this; because you will not necessarily know,
when you access a three-part name, whether it is local or remote. Also, the
location of the data may change without knowledge of the application. It
follows, therefore, that the outcome of a rollback to savepoint will be
uncertain for the application.

We recommend that you code the RELEASE SAVEPOINT savepoint name


statement to release savepoints that are no longer required for clarity and to
reenable the operation of SQL that resolves to remote locations.

11.6.2 Restrictions on using savepoints


You cannot use savepoints in global transactions, triggers, user-defined
functions, or in stored procedures that are nested within triggers or
user-defined functions.

11.6.3 Savepoint performance


The overhead of maintaining a savepoint is minimal. The measurements
performed show that the cost of taking a savepoint is equivalent to a DML
instruction.

11.7 Identity columns


A common requirement for many relational database applications is the
generation of unique key values when inserting rows into a table. In the
absence of any DB2 feature to support this requirement, many users have
been forced to implement their own solutions (such as generating keys based
on reversed timestamp values1 , or using a single-row table that contains the
highest used key value2).

Many other relational databases provide the ability to automatically generate


these key values, based upon parameters specified at the time the table is
created. This functionality, which DB2 terms identity columns, has been
added to DB2 for OS/390 Version 6 via APAR PQ306523 , and is also
available within DB2 for UNIX, Windows and OS/2 as part of Version 7.

1 This solution is not guaranteed to generate unique values.


2
This solution has the potential to cause serious performance bottlenecks, due to lock waits on the 1-row table. These
are exacerbated in a data sharing environment.
3 If you intend to unload tables containing ID columns we recommend that you also look at PQ38493. See 11.7.4, “Utility
issues” on page 218 for details.

210 DB2 Java Stored Procedures: Learning by Example


The remainder of this chapter describes DB2’s implementation of this
important new feature, which can greatly reduce the amount of work required
to port some applications from other vendor’s database products to DB2
UDB. Unless otherwise specified, all references are to the DB2 for OS/390
product. A section at the end of this chapter deals with the major
implementation differences between the OS/390 and UNIX, Windows NT, and
OS/2 products.

11.7.1 Overview
DB2’s implementation of this feature fulfills the following design objectives:
• Guarantee uniqueness, both within an individual subsystem and across a
data sharing group (if applicable).
• Provide the ability for an application to either specify an explicit value for
an identity column during INSERT, or have DB2 generate the value if
required4 .
• Minimize the resource usage and elapsed time overheads required to
generate the value in a highly concurrent environment.
• Provide recoverability in the event of a DB2 system failure by
reconstructing the last value before the outage, thereby ensuring that
uniqueness is maintained.

At the time a table is created, you may specify a single numeric column within
the table as being an identity column. Included in this specification is the
columns’ start value and increment/decrement value, and whether DB2 is to
allow explicit values to be supplied.

11.7.2 Data definition issues


This section looks at the DDL issues associated with creating and altering
tables containing identity columns.

11.7.2.1 Creating tables with identity columns


The AS IDENTITY attribute can be specified as part of the table definition on
the CREATE TABLE statement or when adding a column with the ALTER
TABLE statement to create an identity column. In addition, when a table is
being created like another table that contains an identity column, a new
option on the LIKE clause can be used to specify whether the identity column
attributes are inherited.

4
Intended for use in data propagation environments.

Chapter 11. DB2 UDB for OS/390 network computing enhancements 211
+----------------------------------------------------------+
| COLUMN-DEFINITION: |
| |--column-name--data-type--.----------------.----------| |
| '-column-options-' |
| COLUMN-OPTIONS: |
| <-----------------------------------------------< |
| |---.---------------------------------------------.----| |
| |-NOT NULL------------------------------------| |
| |-.-UNIQUE------.-----------------------------| |
| | '-PRIMARY KEY-' | |
| |-FIELDPROC--program-name--.----------------.-| |
| | | <-,------< | | |
| | '-(--constant--)-' | |
| |-references-clause---------------------------| |
| |-check-constraint----------------------------| |
| '-generated-column-spec-----------------------' |
| GENERATED-COLUMN-SPEC: |
| |-+--------------------------------------------------+-| |
| | +-WITH-+ | |
| |-'------'--DEFAULT--.----------------.------------| |
| | '-default-clause-' | |
| | | |
| +-GENERATED--.-ALWAYS-----.--.------------------.--+ |
| '-BY DEFAULT-' '-as-identity-spec-' |
| AS-IDENTITY-SPEC: |
| |-AS IDENTITY-+---------------------------------------+-||
| | <-,-----------------------------< | |
| | +---1----+ | | |
| | | | | | |
| +-(---+-START WITH--+-nconst-+---+--+-)-+ |
| | | |
| | +---1----+ | |
| | | | | |
| |-INCREMENT BY--+-nconst-+-+ |
| | | |
| | +-CACHE 20------+ | |
| | | | | |
| +-+-NO CACHE------+--------+ |
| | | |
| +-CACHE-integer-+ |
| LIKE-clause (CREATE TABLE) |
| |-----LIKE--+--table-name--+------------------------>> |
| | | |
| +--view-name---+ |
| >>--+---------------------------------------------+---| |
| | | |

212 DB2 Java Stored Procedures: Learning by Example


| | +-COLUMN ATTRIBUTES-+ | |
| | | | | |
| +--INCLUDING IDENTITY--+-------------------+--+ |
+----------------------------------------------------------+

GENERATED

Specifies that DB2 generates values for the column. You must specify
GENERATED if the column is to be considered an identity column, or if the
data type of the column is a ROWID (or a distinct type that is based on a
ROWID).

ALWAYS

Specifies that DB2 always generates a value for the column when a row is
inserted into the table.

BY DEFAULT

Specifies that DB2 generates a value for the column when a row is inserted
into the table unless a value is specified.

BY DEFAULT is the recommended value only when you are using data
propagation.

AS IDENTITY

Specifies that the column is an identity column for the table.

A table can have only one identity column. AS IDENTITY can be specified only if
the data type for the column is an exact numeric type with a scale of zero
(SMALLINT, INTEGER, DECIMAL with a scale of zero, or a distinct type based on one
of these types).

An identity column is implicitly NOT NULL.

START WITH numeric-constant

Specifies the first value for the identity column. The value can be a positive or
negative value that could be assigned to the column, as long as there are no
non-zero digits to the right of the decimal point. The default is 1.

Chapter 11. DB2 UDB for OS/390 network computing enhancements 213
INCREMENT BY numeric-constant

Specifies the interval between consecutive values of the identity column. This
value can be any positive or negative value that is not 0, does not exceed the
value of a large integer constant, and could be assigned to this column, as
long as there are no non-zero digits to the right of the decimal point. The
default is 1.

If the value is positive, the sequence of values for the identity column
ascends. If the value is negative, the sequence of values for the identity
column descends.

CACHE or NO CACHE

Specifies whether to keep some preallocated values in memory. Preallocating


and storing values in the cache improves performance for inserting rows into
a table that has an identity column.

CACHE integer

Specifies the number of values of the identity column sequence that DB2
preallocates and keeps in memory. The minimum value that can be specified
is 2, and the maximum is the largest value that can be represented as an
integer. The default is 20.

During a system failure, all cached identity column values that are yet to be
assigned are lost and, thus, will never be used. Therefore, the value specified
for CACHE also represents the maximum number of values for the identity
column that could be lost during a system failure.

In a data sharing environment, each member gets its own range of <integer>
consecutive values to assign.

NO CACHE

Specifies that caching is not to be used.

LIKE-clause (for CREATE TABLE)

Specifies that the columns of the table have exactly the same name and
description as the columns of the identified table or view. However, for an
identity column, the new table inherits only the data type of the identity
column; none of the other column attributes are inherited unless the new
INCLUDING IDENTITY clause is specified.

214 DB2 Java Stored Procedures: Learning by Example


INCLUDING IDENTITY COLUMN ATTRIBUTES

Specifies that the new table inherits all of the column attributes of the identity
column. If the table identified by LIKE does not have an identity column, the
INCLUDING IDENTITY clause is ignored.

If the identified object of LIKE is a view, INCLUDING IDENTITY COLUMN ATTRIBUTES


cannot be specified.

11.7.2.2 Adding an identity column to an existing table


The ALTER TABLE ADD COLUMN statement can be used to add an ID column to an
existing table. Unless the table is empty, DB2 will place it in reorg pending
status (if the table is partitioned, then all partitions are reorg pending).

Running REORG will materialize the ID column values for all rows in the table
(again, if the table is partitioned, REORG must be run against the entire table
space and not just one partition). The order in which DB2 will allocate the ID
column values is system determined.

11.7.2.3 Altering an identity column


To alter the attributes of an existing identity column, you must drop and
recreate the table (using your normal procedures for conserving the table
data, indexes, authorities, and other dependent objects).

When re-creating the table, you should ensure that the START WITH value that
is specified is set to the next value that you want DB2 to generate after the
table is reloaded with data. See 11.7.2.4, “Copying tables between
subsystems” on page 216 for an SQL statement that can be used to
determine this.

Also, as you will be using the LOAD utility to reload the table data after it is
recreated, you must specify GENERATED BY DEFAULT so that LOAD is allowed to
reuse the previously allocated identity column values. Once this is done,
there is no way to go back to GENERATED ALWAYS.

Note
See 11.7.4, “Utility issues” on page 218 for further considerations when
unloading and loading tables containing identity columns.

Chapter 11. DB2 UDB for OS/390 network computing enhancements 215
Note
Under very specific circumstances, it may be possible to retain the
GENERATED ALWAYS attribute by doing the following:
1. Make the table unavailable to prevent further INSERT/LOAD activity.
2. Unload the table in ID column order.
3. Drop and re-create the table as required, specifying GENERATED ALWAYS for
the ID column and the original value for the START WITH attribute.
4. LOAD the data back into the table, excluding the unloaded ID column
values from load operation, and thereby allowing DB2 to regenerate
them during the load operation.

However, if you want to ensure that the ID column key values remain the
same (essential if the ID column is a primary key, and referenced as a
foreign key in another table) you need to be very careful. Be absolutely
sure that:
• No gaps appear in the ID column sequence (for example, if the
increment is 1 and the start value is 1, the table must contain rows with
values 1, 2, 3, 4, and so on, with no gaps in the series). Note that it is
very likely that gaps will exist, for example, due to caching in a data
sharing environment, or rollbacks of failed units of work.
• No one else is able to LOAD or INSERT into the table in between the time
you re-create it and the time the LOAD operation is conducted.

11.7.2.4 Copying tables between subsystems


Special consideration has to be given to avoiding overlaps when copying
tables with ID columns between subsystems.

Consider the following procedure:


1. Stop the table space containing the table on the source subsystem, to stop
any new rows from being inserted.
2. Run the following catalog query to determine the start value and increment
for the CREATE TABLE statement on the target system:
SELECT B.DCREATOR,
B.DNAME,
B.DCOLNAME,
A.INCREMENT+A.MAXASSIGNEDVAL AS NEW_START_VALUE,
A.INCREMENT

216 DB2 Java Stored Procedures: Learning by Example


FROM SYSIBM.SYSSEQUENCES A INNER JOIN
SYSIBM.SYSSEQUENCESDEP B
ON A.SEQUENCEID = B.BSEQUENCEID
WHERE B.DCREATOR = 'ACMEE'
AND B.DNAME = 'CUSTOMER';
In these statements, the values for B.DCREATOR and B.DNAME predicates are
replaced with your own table creator and table name.
3. Create the table on the target subsystem, using the start and increment
values determined from the previous step.
4. Stop the table space on the target system, to prevent rows from being
inserted until it is populated.
5. Copy the data from the source to the target (using DSN1COPY or similar)
6. Start the table on the target subsystem (and also the source if required).

11.7.3 Data manipulation issues


This section covers the implications of executing INSERT and UPDATE SQL
statements against tables containing ID columns.

11.7.3.1 Insert
If a table has an ID column defined as GENERATED ALWAYS, you may not explicitly
specify a value for that column during INSERT processing (any attempt to do so
will result in SQLSTATE 428C9, SQLCODE -798). You must therefore either
omit the column entirely from the INSERT statement, or use the SQL
DEFAULT clause.

For example, if table CUSTOMER has three columns: CUST_NO,


CUST_FIRSTNAME and CUST_LASTNAME, where CUST_NO is a
GENERATED ALWAYS ID column, an insert could be performed with either of
the two methods shown below:
INSERT INTO CUSTOMER
(CUST_FIRSTNAME, CUST_LASTNAME)
VALUES (‘John’, ‘Doe’);

INSERT INTO CUSTOMER


(CUST_NO, CUST_FIRSTNAME, CUST_LASTNAME)
VALUES (DEFAULT, ‘John’, ‘Doe’);

For GENERATED BY DEFAULT ID columns, you may either use the above syntax to
allow DB2 to generate the value, or explicitly specify a value in the normal
way. As previously noted, DB2 does not do any checking for explicitly

Chapter 11. DB2 UDB for OS/390 network computing enhancements 217
supplied ID column values, so you should consider defining a unique index on
the column if you wish to enforce uniqueness.

11.7.3.2 Update
UPDATE statements are not allowed against GENERATED ALWAYS ID columns
(SQLSTATE 42808, SQLCODE -151).

If an ID column is defined as GENERATED BY DEFAULT, updates are


allowed. However, as for INSERT operations, DB2 will not do any validation of
the updated column value.

11.7.4 Utility issues


This section covers the implications of executing DB2 utilities against tables
containing ID columns.

11.7.4.1 REORG
As mentioned previously, adding an ID column to an existed table that
contains data using the ALTER TABLE ADD COLUMN statement will result in the
table space being placed in reorg pending status. Running reorg will cause
DB2 to generate the ID column values (in a system-determined order) and
remove the REORP status.

APAR PQ38493 - Unloading Tables Containing Identity Columns


APAR PQ38493 introduces additional features to support the unload and
load of identity columns.

With the APAR applied, DB2 will include a dummy field called DSN_IDENTITY
to represent the identity column within the LOAD statement produced by
REORG UNLOAD EXTERNAL and REORG DISCARD. A new option called IGNOREFIELDS
will also be present in the LOAD deck.

When loading into a table with a GENERATED ALWAYS identity column, the
IGNOREFIELDS option will cause LOAD to ignore the DSN_IDENTITY field, allowing
LOAD to generate its own values. To load the data into a table with a
GENERATED BY DEFAULT identity column (or no identity column) the
IGNOREFIELDS option should be removed from the LOAD deck and the
DSN_IDENTITY field renamed to point to the corresponding column in the
target table. The unloaded data values will then be used.

If the APAR has not been applied, the utility will omit field specifications for
GENERATED ALWAYS ID columns.

218 DB2 Java Stored Procedures: Learning by Example


Identity Columns and RI
Some complications arise when a table has been altered to add an ID
column and the table is part of a referential set. If that table is recovered to
a point in time after the ALTER but before the REORG, it is possible for the table
space to be in both check pending and reorg pending state.

To resolve this situation, you can now run REORG with both CHECKP and REORP
states set. After completion, CHECKP will still be set, but this can be removed
by running CHECK DATA as usual.

11.7.4.2 LOAD
Running the LOAD utility against a table containing ID columns will result in
the same rules being applied as for INSERT processing when generating data
values.

Where the ID column has been defined as GENERATED ALWAYS, DB2 will
generate a value for that column as the row is loaded. You may not explicitly
include ID columns in the field specification. When loading data produced
from a REORG UNLOAD external operation with PQ38493 applied you can use the
new IGNOREFIELDS keyword to instruct DB2 to ignore any identity column fields
in the unloaded data (see description in previous section).

For GENERATED BY DEFAULT, you may include the ID column in the field
specification. If you do so, the supplied value in the input data file will be
used. Otherwise, the value is generated by DB2. The DEFAULTIF clause can be
used to get DB2 to generate a value if required. When loading data produced
from a REORG UNLOAD external operation with PQ38493 applied you should
remove the IGNOREFIELDS keyword to instruct DB2 to use the unloaded values
(see description in previous section).

For partitioned tables, you may not run the load against a single partition via
LOAD INTO TABLE PART if the ID column in part of the partitioning key.

If a table space has been placed in reorg pending state by using ALTER TABLE
ADD COLUMN to add an ID column to a populated table, you may use LOAD
REPLACE to reset the status if you wish to reload the table rather than
reorganize it.

Chapter 11. DB2 UDB for OS/390 network computing enhancements 219
11.7.4.3 RECOVER
As mentioned in the note above, some complications can arise when using
RECOVER to restore a table space to an earlier point in time when an ID column
has been added.

If the table space is recovered to a point in time between the ALTER TABLE and
the subsequent REORG, the REORP status will be set upon completion of the
RECOVER.

Some issues can also arise regarding the highest generated value following a
recovery. If a table is recovered to a prior point in time, DB2 will not reset the
highest generated value for the table. This can lead to large gaps in the series
of generated values, which may cause problems for some types of
applications.

For example, a table has an ID column defined as START WITH 1 INCREMENT BY


1, and has 1000 rows in it. The table is then recovered to an earlier point in
time, where only 500 rows existed. The next INSERT operation generates a
value of 1001, as DB2 will continue to use the previously generated high
value, and there will be a gap in the generated values between 501 and 999.

11.7.5 Other properties


You should be aware of a number of restrictions and other properties of
identity columns:
• The identity column must have a numeric data type of SMALLINT, INTEGER, or
DECIMAL with a scale of zero (or a distinct type based on one of these
types), and cannot be nullable.
• Only one identity column is allowed per table, and that column may not
have an edit procedure specified for it.
• You cannot specify an edit procedure for a table containing an identity
column.
• There is no guarantee that DB2 will allocate numbers sequentially. If a
given transaction increments an identity counter twice, it is possible that
the two generated values will not be sequential (possibly due to other
transactions inserting into the same table). If sequential numbers are
absolutely necessary, you may want to consider taking an exclusive lock
on the table, but this can have a negative impact on application
concurrency5.

5 And in a data sharing environment, explicitly locking the table also introduces the possibility of an exclusive retained

lock on the table if the member fails.

220 DB2 Java Stored Procedures: Learning by Example


• There may be gaps in the generated column values. This can happen if a
transaction is rolled back after allocating a new value, or (in a data sharing
environment) if a subsystem fails and had not used all of the numbers
reserved in its cache.
• In a data sharing environment with caching enabled, identity column
values may not be inserted into the table in numeric order, as each
member will allocate the next unused value in its own cache. For example,
if member DB2A caches numbers 1-20 and member DB2B caches 21-40,
it is possible that an INSERT from DB2B will use a value of 26, to be
followed by an INSERT from DB2A with a value of 14.
• Global temporary tables may not contain identity columns.

11.7.6 DB2 catalog table considerations


In this section we provide some considerations on DB2 catalog tables.

11.7.6.1 New catalog tables


Two new catalog tables (and associated indexes) have been introduced to
DB2 for OS/390 to support ID columns:
• SYSIBM.SYSSEQUENCES contains one row for each ID column, and
records attributes such as the internal DB2 name for the column
(SEQUENCEID), its defined start (START) and increment (INCREMENT) values, and
the currently used high value (MAXASSIGNEDVAL).
• SYSIBM.SYSSEQUENCESDEP contains one row for each identity
column, and links an ID column definition on SYSSEQUENCES (via BSEQUENCEID)
to its corresponding definition in SYSCOLUMNS (via DNAME and DCOLNAME).

Both of these tables reside in their own table spaces, called SYSEQ and SYSSEQ2
respectively. On other platforms, only the SYSIBM.SYSSEQUENCES table exists, but
this contains mostly the same information as the S/390 implementation.

11.7.6.2 Changed catalog tables


The usage of the DEFAULT column in SYSIBM.SYSCOLUMNS has been altered for ID
columns as follows:
• Set to I if column is an ID column and is GENERATED ALWAYS
• Set to J if column is an ID column and is GENERATED BY DEFAULT

Note that the UPDATES column is always set to Y for ID columns, but as
previously noted, GENERATED ALWAYS columns cannot be updated.

Chapter 11. DB2 UDB for OS/390 network computing enhancements 221
11.7.6.3 Catalog recovery issues
As part of the DB2 catalog, the new tables must be included in your routine
catalog backup and recovery jobs.

When recovering the catalog to a prior point in time, you should be aware of
the implications this will have for tables containing ID columns. Recovery of
SYSIBM.SYSSEQUENCES to a previous point in time may result in duplicate values
being generated. To avoid this, consider one of the following options:
• Recover all table spaces containing tables with ID columns to the same
point in time as the catalog is recovered to.
• Following the catalog recovery, determine the highest used ID column
value within all ID column tables, then drop and recreate the table with a
new START WITH value as described in 11.7.2.3, “Altering an identity
column” on page 215.

11.7.7 Usage recommendations


In this section we provide some usage recommendations for indexing.

11.7.7.1 Indexing
Use of the GENERATED BY DEFAULT clause allows you to optionally specify an
explicit value for an identity column at the time the row is inserted. In order to
guarantee uniqueness, DB2 will force you to create a unique index on the
identity column in this situation.

However, given that identity columns will commonly be used as primary keys
within a table, you should create a unique index on the column, even where
GENERATED ALWAYS is used.

11.7.7.2 Retrieving generated values


One of the issues you will need to be aware of when using identity columns is
retrieving the unique value generated by DB2 following an insert.

For example, where a referential relationship exists between two tables, it is


common to use the primary key of the parent table as a foreign key in the
dependent table, as shown in Figure 30.

222 DB2 Java Stored Procedures: Learning by Example


CUSTOMER (Parent Table) ORDER (Dependent Table)
CUST_NO FIRSTNAME LASTNAME ORDER_NO CUST_NO ORDER_DATE

Figure 30. Typical parent / dependent relationship

Let’s assume that the CUST_NO column of the parent table and the ORDER_NO
column of the dependent table are both defined as identity columns, and that
we wish to insert new rows into both tables.

We may insert a row into the CUSTOMER table using the following SQL
statement:
INSERT INTO CUSTOMER
(FIRSTNAME, LASTNAME)
VALUES (‘John’, ‘Doe’);

The INSERT into the parent table is successful, with DB2 automatically
generating a value for CUST_NO based upon the parameters we specified when
the table was created. However, when we want to insert an associated row
into the dependent table, we don’t know what value to use for the CUST_NO
column.

This issue is being addressed via an APAR enhancement to DB2 that


implements a new built-in function to return the most recently generated ID
column value within the current unit of work. However, there are some
requirements that this enhancement cannot address, so you may also need to
consider alternative solutions.

Note
Both of the solutions presented below assume you will be using “singleton
inserts”. The techniques will not work with mass insert operations (for
example, an INSERT with embedded SELECT).

Chapter 11. DB2 UDB for OS/390 network computing enhancements 223
Use of IDENTITY_VAL_LOCAL function
APAR PQ36328 introduces a new built-in function called IDENTITY_VAL_LOCAL.
This function returns the most recently generated ID column value for a
single-row insert within the current unit of work at the current processing
level6 . The function returns a DECIMAL(31,0) value, regardless of the data type
of the underlying ID column.

To use the previous example, our program successfully inserts a row into the
CUSTOMER table using the following SQL:
INSERT INTO CUSTOMER
(FIRSTNAME, LASTNAME)
VALUES (‘John’, ‘Doe’);

We will then be able to handle the subsequent insert into the ORDER table using
the following SQL:
INSERT INTO ORDER
(CUST_NO, ORDER_DATE)
VALUES (IDENTITY_VAL_LOCAL(), CURRENT DATE);

Expressions in a VALUES clause are evaluated before the actual insert takes
place. Therefore, the most recent generated ID column value within the
processing level is for the previous insert into the CUSTOMER table, and the
IDENTITY_VAL_LOCAL function within the subsequent insert into ORDER will work.

There are a number of important caveats and restrictions to the use of this
function, which you should be aware of:
• If possible, use the function immediately after the INSERT statement that
generates the required ID column value. Any subsequent inserts will make
it impossible to retrieve the value using this function.
• Where a suitable INSERT has not been performed at the current processing
level, or a COMMIT or ROLLBACK has occurred since the most recent INSERT, a
null value is returned.
• You need to take special care when using triggers in conjunction with this
function. For instance, before-insert triggers will not be able to retrieve the
generated value, and after-insert triggers can only retrieve values for
inserts performed within the trigger body itself.
• Ensure that the original INSERT operation was successful before invoking
the IDENTITY_VAL_LOCAL function, as the value returned following a failed
INSERT is unpredictable.

6 In this context, a
processing level is all of the code within a single program, or trigger, or stored procedure. Therefore,
a program calling a stored procedure which executes some SQL that invokes a trigger consists of three processing levels.

224 DB2 Java Stored Procedures: Learning by Example


Use of an after-insert trigger
If you are unable to use the IDENTITY_VAL_LOCAL function, you may want to
consider the use of a simple after-insert trigger to capture the generated
value.

To use this technique, you should:


1. Create a global temporary table like the one shown in Figure 31 to hold the
generated value.

CREATE GLOBAL TEMPORARY TABLE GTT_CUST_NO


(
CUST_NO INTEGER NOT NULL
);

Figure 31. Example DDL for a global temporary table

2. Create an after-insert trigger on the table with the ID column, to retrieve


the generated ID column value and insert it into the global temporary
table. An example of this is shown in Figure 32 below.

CREATE TRIGGER CUST_IA


AFTER INSERT
ON CUSTOMER
REFERENCING NEW AS NEWROW
FOR EACH ROW
MODE DB2SQL
BEGIN ATOMIC
INSERT INTO GTT_CUST_NO
(CUST_NO)
VALUES (NEWROW.CUST_NO);
END;

Figure 32. Example DDL for an after-insert trigger

Chapter 11. DB2 UDB for OS/390 network computing enhancements 225
Note
If you use SPUFI to create your triggers, you will probably encounter an
error, due to the fact that SPUFI mistakes any semicolons in the BEGIN
ATOMIC section as the end of the CREATE TRIGGER statement.

To avoid this problem, you can terminate all statements within the SPUFI
file (except the ones in the BEGIN ATOMIC section of your triggers!) with
another character (a colon, for example) and update your SPUFI defaults to
use this as the statement terminator.

3. From within your application program, INSERT the row into the table
(thereby invoking the trigger).
4. SELECT the generated value from the global temporary table after the
INSERT.
5. If further inserts will be done within the same unit of work, the row should
then be deleted from the global temporary table ready for the process to
be repeated.

This technique is illustrated in Figure 33.

226 DB2 Java Stored Procedures: Learning by Example


Your program
...
INSERT INTO CUSTOMER CUSTOMER
(FIRSTNAME, LASTNAME) CUST_NO
FIRSTNAME LASTNAME
VALUES ('JOHN', 'DOE') (ID column)

... 1 0010 JOHN DOE


SELECT CUST_NO
FROM GTT_CUST_NO
....

2
1. Program inserts row into table
3
and DB2 generates CUST_NO
value.
2. Trigger is fired, and inserts
CUST_NO generated CUST_NO value into
global temporary table.
0010 3. Program retrieves CUST_NO
value from global temporary
GTT_CUST_NO table.

Figure 33. After-insert trigger to retrieve the generated value of an id-column

Chapter 11. DB2 UDB for OS/390 network computing enhancements 227
11.7.8 Use of identity columns versus ROWID columns
DB2 V6 introduced a new data type called ROWID. ROWID columns and ID
columns share some characteristics, but have also a number of important
differences. The two options are compared in Table 14.
Table 14. Comparison of Identity and ROWID columns

Attribute Identity ROWID


columns columns

Supports DB2 generated or user-supplied valuesa Yes Yes

DB2 guarantees uniqueness of generated values Yesb Yes

Regularly ascending or descending according to Yes No


user-defined rules

Supported data types SMALLINT, VARCHAR(40)


INTEGER or
DECIMAL

Easily understood external representation of Yes No


generated values?

Comparable with other data types? Yes No

Can be used to reference LOB columns? No Yes

Can be used for direct row accessc? No Yes


a. User specified values only allowed where columns has been defined with
GENERATED BY DEFAULT clause
b. For GENERATED ALWAYS columns, or GENERATED BY DEFAULT columns with
unique index defined.
c. Direct row access is a new feature in DB2 for OS/390 that allows an application
to directly access a given row in the table if it can supply a value for the row’s
ROWID in the query.

In general, you should consider using ID columns for the generation of key
values that may need to be presented to the user, or be meaningful in their
own right.

In contrast, ROWID columns are most useful when direct retrieval and
manipulation of the generated value is not required, such as dealing with LOB
columns and using direct row access.

228 DB2 Java Stored Procedures: Learning by Example


11.7.9 Data propagation considerations
If a source table in a one-way data propagation environment contains an ID
column with the GENERATED ALWAYS attribute, you should define the
corresponding ID column on the target table with GENERATED BY DEFAULT to
allow the propagation process to explicitly supply a value for the column.

For two-way replication, both source tables must use GENERATED BY DEFAULT for
the same reason. Also, if unique values are required, you should take care
when specifying the START WITH and INCREMENT BY values for the two tables to
prevent the same value being generated at each site.

For instance, you may decide to have one value generating odd values (using
START WITH 1 INCREMENT BY 2) and one generating even values (using START
WITH 2 INCREMENT BY 2).

This scenario is described in Figure 34.

Site A Site B
CREATE TABLE .... CREATE TABLE ....
(COLA INTEGER (COLA INTEGER
GENERATED BY DEFAULT GENERATED BY DEFAULT
START WITH 2 START WITH 1
INCREMENT BY 2 INCREMENT BY 2
COLB ... COLB ...

COLA COLB COLC COLA COLB COLC


(ID) (ID)
1 ... ... 2
1 ... ...
2 ... ... 2 ... ...
3 ... ... 3 ... ...
4 3
1

INSERT INSERT

Figure 34. Identity column data propagation issues

Chapter 11. DB2 UDB for OS/390 network computing enhancements 229
The following is a description of the process illustrated above:
1. Process at Site A inserts a row into table (without specifying a value for
COLA), and DB2 generates a value of 2.
2. Replication takes place, and row 2 is replicated to Site B (with the value for
COLA being specified). As Site B only generates odd-numbered values for
COLA, there is no conflict.
3. Process at Site B inserts a row into the table (without specifying a value
for COLA), and DB2 generates a value of 3.
4. Replication takes place, and row 3 is replicated to Site A (with the value for
COLA being specified). As Site A only generates even-numbered values
for COLA, there is no conflict.

11.7.10 Influencing insert order in a data sharing environment


Some applications have a requirement that an ever-increasing key value is
generated. As previously described, in a data sharing environment it is
possible for rows to be inserted out of sequence, due to the way in which
each member of the data sharing group caches a range of values.

In order to prevent this issue, you may use the NOCACHE option (see 11.7.2.1,
“Creating tables with identity columns” on page 211 for a description of this
parameter). However, use of NOCACHE may negatively impact performance and
should only be used if necessary to the application.

11.7.11 Differences in implementation across the DB2 Family


This section summarizes the major differences between DB2 UDB for
OS/390’s implementation of the ID columns feature and that of the DB2 UDB
for UNIX, Windows NT, or OS/2 Version 7 products.

11.7.11.1 Retrieving generated values


DB2 UDB for UNIX, Windows NT, or OS/2 does not yet support the new
IDENTITY_VAL_LOCAL built-in function. Therefore, you should consider
using an after-insert trigger to retrieve generated ID column values, as
described in “Use of an after-insert trigger” on page 225.

11.7.11.2 Support for col=DEFAULT during update


DB2 UDB for UNIX, Windows NT, or OS/2 already supported the use of the
SET col = DEFAULT syntax for use with NOT NULL WITH DEFAULT columns.
This capability also applies to ID columns, where DB2 will generate a value.

DB2 UDB for OS/390 does not support this syntax. However, as the clause is
essentially redundant, it can simply be omitted if SQL portability is an issue.

230 DB2 Java Stored Procedures: Learning by Example


11.7.11.3 Support for ALTER ADD ID column
DB2 UDB for UNIX, Windows NT, or OS/2 does not support the ALTER TABLE
ADD COLUMN of an identity column to an existing table. Identity columns may
only be defined as part of a CREATE TABLE statement.

11.7.11.4 Parallel processing support


DB2 UDB for UNIX, Windows NT, or OS/2 does not yet support the use of
identity columns in the Enterprise Extended Edition (EEE) of the product,
which is designed to run on highly parallel hardware. In contrast, the DB2
UDB for OS/390 implementation offers support for data sharing
environments.

Chapter 11. DB2 UDB for OS/390 network computing enhancements 231
232 DB2 Java Stored Procedures: Learning by Example
Chapter 12. DB2 UDB for OS/390 schema support

A schema is an identifier (such as a user id or an application identifier) to help


group together a set of DB2 objects. A schema can be owned by an
individual, and the owner can control access to the data and the objects
within it. You can think of a schema as being an extension of the table
qualifier concept, which now encompasses new objects such as stored
procedures, user defined functions, and triggers.

A schema is also an object in the database and, like a package collection, it is


created automatically when the first object in a schema is created.

A schema name is used as the first part of a two-part object name. When an
object is created, you can assign it to a specific schema by specifying the
schema as the first part of the object name. If you do not specify a schema, it
is assigned to the default schema, whose name is usually the CURRENT
SQLID at the time the object is created.

The second part of the two-name is the name of the object. For example, a
user named JOHN might have a stored procedure named JOHN.PROC_1.

As in prior releases, the qualifier, or schema name, for an object may or may
not represent the creator of the object. However, additional authority
(administrative authority) is required to create an object with a schema name
other than the SQL authorization ID of the process.

All objects qualified by the same schema name can be thought of as a group
of related objects. Figure 35 shows 4 schemas (JOHN, SMITH, PROD1, and
TEST) and objects contained in these schemas. The type of objects
contained in these schemas are UDFs, UDTs, triggers, and stored
procedures.

JOHN SMITH PROD1 TEST

SP1 SP2 SP1 SP4 SPCALC


SPCALC
UDF1 TRIG2 UDF1 TRIG2 UDF_SALCI
UDF_SALCI
UDT3 SP3 UDT3 SP3 US_DOLLARS
US_DOLLARS
UDF1 UDF1 UDF2 UDF3 TRIGGER1
TRIGGER1
UDT2 SP3 UDT1 SP5 UDT2 SP3
UDT2 SP3

Figure 35. What is a schema?

© Copyright IBM Corp. 2000 233


A schema can also be used for versioning. As shown in Figure 35, a version
of UDF1 exists in schema JOHN and another UDF1 exists in schema SMITH
(see 8.3.2, “Version control” on page 164 for a practical example of how this
facility could be used for versioning stored procedures).

12.1 Schema characteristics


Following are some characteristics related to schemas:
• There is no DDL to create a schema. A schema is created when the first
object qualified by this schema name is created.
• There are new privileges related to schemas. You have now the following
GRANT and REVOKE statements:
GRANT CREATEIN|ALTERIN|DROPIN ON schema TO grantee WITH GRANT OPTION
REVOKE CREATEIN|ALTERIN|DROPIN ON schema FROM grantee
When an authorization ID matches a schema name, the authorization ID is
said to be the schema owner. The schema owner can issue the above
commands to grant/revoke the privileges on the schema for other users.
• There is a new SET CURRENT PATH statement to specify the value of the
CURRENT PATH special register. This register is used to specify one or
more schema names that are used to resolve unqualified data type names
and function names in dynamically prepared SQL statements. It is also
used to resolve unqualified procedure names that are specified as host
variables in SQL CALL statements (CALL host-variable).
• There is a new option in the BIND command to specify the value of the
PATH to be used during BIND operations.

12.2 How schemas are used


In this section we explain how schemas are used.

12.2.1 Explicit specification


Schemas are used in the following situations (refer to Figure 36):
• When you issue the CREATE, ALTER, DROP, or COMMENT ON
statement for a trigger, UDF, UDT, or stored procedure, you can explicitly
specify a schema name.
• The schema name specified can be any primary or secondary
authorization ID associated with the process.

234 DB2 Java Stored Procedures: Learning by Example


• If the schema name specified is not the primary or a secondary
authorization ID associated with the process, the primary or one of the
secondary authorization IDs associated with the process must have either
the CREATEIN, ALTERIN, or DROPIN privilege for the specified schema.
To use COMMENT ON the specified object, the authorization ID (primary
or secondary) associated with the process must have ALTERIN privilege
on the SCHEMA. SYSADM and SYSCTRL implicitly have these privileges.

CREATE ALTER DROP COMMENT ON

object-type JOHN.object_name
JOHN

object_name

* Schema name can be any authorization ID of the process


* Schema name can be any name if SYSADM, SYSCTRL, or
user has appropriate privilege on the schema name

Figure 36. How a schema is used — explicit specification

12.2.2 Implicit specification


When you issue the CREATE, ALTER, DROP, or COMMENT ON statement
for a trigger, UDF, UDT, or stored procedure, you can omit a schema name.
In this case, a schema name is assumed, as follows (refer to Figure 37):
• If the CREATE, ALTER, DROP, or COMMENT ON statement is embedded
in an application program (static SQL), the implicit schema name is the
authorization ID of the QUALIFIER (explicit or default) specified during the
BIND for this application.
• If the CREATE, ALTER, DROP, or COMMENT ON statement is issued
dynamically, the value of the CURRENT SQLID special register is the
implicit qualifier, unless you specified DYNAMICRULES(BIND) when the
application was bound. If DYNAMICRULES(BIND) was specified, then the
implicit qualifier is the authorization ID of the QUALIFIER (explicit or
default) specified during the BIND for this application. Note that CREATE
and DROP do not allow the DYNAMICRULES(BIND) specification, that is,

Chapter 12. DB2 UDB for OS/390 schema support 235


they cannot be issued dynamically when DYNAMICRULES(BIND) was
specified during BIND.

CREATE ALTER DROP COMMENT ON

object-type object_name
JOHN

object_name

* Static: Schema name is the authorization ID BIND QUALIFIER


* Dynamic: Schema name is CURRENT SQLID
(Except for DYNAMICRULES(BIND) ==> if allowed)

Figure 37. How a schema is used — implicit specification

12.3 Schemas and the CURRENT PATH special register


When you invoke a stored procedure or UDF, activate a trigger, or have a
reference to a UDT, and you don't specify the schema name, name resolution
occurs according to the PATH bind option or CURRENT PATH special register
from left to right until it finds a schema name for which there exists a stored
procedure definition with the name in the CALL statement. DB2 uses the
schema names from the PATH bind option for CALL statements of the form:
CALL literal

For CALL statements of the form:


CALL host-variable

DB2 uses schema names from the CURRENT PATH special register. Name
resolution is object-specific.

When DB2 finds a stored procedure definition, DB2 executes that stored
procedure if the following conditions are true:
• The caller is authorized to execute the stored procedure.
• The stored procedure has the same number of parameters as in the CALL
statement.

236 DB2 Java Stored Procedures: Learning by Example


If both conditions are not true, DB2 continues to go through the list of
schemas until it finds a stored procedure that meets both conditions or
reaches the end of the list.

If DB2 cannot find a suitable stored procedure, it returns a -440 SQL error
code for the CALL statement.

For the following discussion, refer to Figure 38.

The CURRENT PATH special register is a VARCHAR string with the


maximum length of 254 bytes. It contains an ordered list of schema names.
The schema names SYSIBM, SYSFUN and SYSPROC are always included
in the list before any other schema name, therefore you don't have to specify
them. You can specify them, to override the order of the search.

The schema SYSIBM already contains objects in it. Users cannot create
objects in SYSIBM or SYSFUN schemas.

The CURRENT PATH special register is used to resolve unqualified object


names.

"RES1", "RES2", "PROD"

"SYSIBM", "SYSFUN", "SYSPROC","RES1","RES2","PROD"

"RES1", "SYSIBM", "RES2", "SYSPROC"

"SYSFUN", "RES1","SYSIBM","RES2","SYSPROC"

Figure 38. CURRENT PATH special register

12.3.1 SET CURRENT PATH


The CURRENT PATH special register is set to the BIND path option at startup
of the stored procedure. The SET CURRENT PATH statement changes the
value of the CURRENT PATH special register; for example:
- SET CURRENT PATH = SCHEMA1, SCHEMA2, SYSIBM
- SET CURRENT PATH = :hostvariable
- SET CURRENT PATH = USER
- SET CURRENT PATH = SYSTEM PATH

Chapter 12. DB2 UDB for OS/390 schema support 237


The SET CURRENT PATH statement has the following characteristics:
• It can be used in dynamic SQL.
• No special authorization is required.
• It can be static or dynamic.
• Schema existence is not checked.
• It is classified as a non-local SET statement in DRDA.

The CURRENT PATH special register is used to resolve unqualified


user-defined distinct types and functions in dynamic SQL statements. The
CURRENT PATH special register is used to resolve unqualified stored
procedure names when the SQL CALL statement specifies a host variable for
the procedure name, and to resolve UDFs and stored procedures that appear
in a trigger body. It is not used for the trigger itself.
• Invocation:
This statement can be embedded in an application program or issued
interactively. It is an executable statement that can be dynamically
prepared.
• Authorization:
No authorization is required to execute this statement.

Syntax: For the following discussion, refer to Figure 39.

_=_ <_,____________________
>>__SET__ _ __________________________ __ PATH_ __ | __ | ___ _schema-name_________
| |_CURRENT__ ___________ _ | | |_SYSTEM PATH________
| |_FUNCTION_| | |_USER______________
|_CURRENT_PATH_____________________| |_ _ _________________
| |_CURRENT__ _____
|
|_host-variable_________
|_string-constant________

Figure 39. SET CURRENT PATH — syntax

- Description:
• schema-name

238 DB2 Java Stored Procedures: Learning by Example


Identifies a schema. DB2 for OS/390 does not validate the
existence of the schema. If a schema-name is, for example,
misspelled, it will not be noted and it could affect the way
subsequent SQL operates.
• SYSTEM PATH
This value is the same as specifying the schema name "SYSIBM"
followed by "SYSFUN", followed by "SYSPROC". SYSTEM PATH
can only be specified once (SQLSTATE 42732, SQLCODE -585).
• USER
The value of the USER special register. USER can only be specified
once (SQLSTATE 42732, SQLCODE -585).
• host-variable
A variable of type CHAR or VARCHAR. The value of the
host-variable must represent a valid schema-name and cannot be
set to null. If the host-variable has an associated indicator variable,
the value of that indicator variable must not indicate a null value
(SQLSTATE 42815, SQLCODE -713).
The schema name must:
- Be left justified within the host variable
- Be padded on the right with blanks if its length is less than that of
the host variable
• string-constant
A character string constant which represents a valid schema-name.
Note: If the schema name specified here as a string-constant will
also be specified in other SQL statements and the schema name
does not conform to the rules for ordinary identifiers, then in the
other SQL statements the schema name must be specified as a
delimited identifier.
Notes:
- A schema name appears more than once in the path (SQLSTATE
01625, SQLCODE +585).
- The number of schemas that can be specified is limited by the total
length of the CURRENT PATH special register.
- The special register string is built by taking each schema name
specified and removing trailing blanks, adding two delimiters around it,
and adding one comma after each schema except the last one.

Chapter 12. DB2 UDB for OS/390 schema support 239


- The length of the resulting string cannot exceed 254 bytes (SQLSTATE
42907, SQLCODE -586).
- The schemas SYSIBM, SYSFUN and SYSPROC do not need to be
specified. If one is not included in the path, it is implicitly assumed as
the first schema (in this case, it is not included in the CURRENT PATH
special register). If more than one is not included in the path, SYSIBM
is put first in the path followed by SYSFUN and then SYSPROC. If
SYSIBM, SYSFUN or SYSPROC is not specified, it is not included in
the 254 byte length limit.
• SET CURRENT PATH is executed by the application server and is
therefore classified as a non-local SET statement in DRDA.

12.3.2 PATH bind option


The new bind option PATH is applicable to BIND PLAN, BIND PACKAGE,
REBIND PLAN and REBIND PACKAGE. It determines the path to be used in
resolving unqualified UDTs, UDFs, and procedure names (in CALL
statements) in static SQL. If this option is not specified on BIND, the default
path is "SYSIBM", followed by "SYSFUN", followed by "SYSPROC", followed
by the userid of the owner of the package or plan. If this option is not
specified on REBIND, the previous value is retained.

For plans, the value of PATH applies only to the DBRMs bound directly to the
plan (named in the MEMBER option on BIND PLAN), and has no affect on
PKLIST names.

The bind option has no affect on dynamic SQL statements which use the
value of the CURRENT PATH special register.

The syntax is:


PATH (schema-name1 schema-name2 ..

where:
• schema-name
Identifies a schema. No validation is done to determine whether the
schema actually exists at precompile or at bind time. The same schema
cannot appear more than once in the path (DSNT205). The number of
schemas that can be specified is limited by the length of the resulting path,
which cannot exceed 254 bytes.
The length is calculated by taking the length of each schema, adding two
for delimiters around each schema and adding one for a comma after each
schema except for the last one.

240 DB2 Java Stored Procedures: Learning by Example


The SYSIBM, SYSFUN and SYSPROC schemas do not need to be
explicitly specified. They are assumed implicitly to be at the beginning of
the list. The implicitly added schemas are added in the order listed above.
Furthermore, if SYSIBM, SYSFUN, or SYSPROC are not specified, they
are not included in the 254 byte length
The schema names are not folded by DB2. Therefore, specify schema
names which are ordinary (non-delimited) identifiers in uppercase. Failure
to do this results in these schema names being essentially ignored in the
path (DB2 only matches them with schemas in the database if they are
specified in uppercase). The default (that is, if this option is not specified)
is as follows:
- BIND PLAN:
SYSIBM, SYSFUN, SYSPROC, <I>plan or package /I>>owner
- BIND PACKAGE:
SYSIBM, SYSFUN, SYSPROC, >plan or package /I>>owner
- REBIND PLAN:
use existing value
- REBIND PACKAGE:
use existing value

Note: DB2I BIND/REBIND panels support the new PATH option.

Chapter 12. DB2 UDB for OS/390 schema support 241


242 DB2 Java Stored Procedures: Learning by Example
Chapter 13. DB2 UDB for OS/390 stored procedures enhancements

In this chapter we discuss stored procedure enhancements.

13.1 Stored procedures: an overview


Stored procedures are user-written programs that are stored at the DB2
server and can be invoked by client applications. A stored procedure can
contain most statements that an application program usually contains. Stored
procedures can execute SQL statements at the server as well as application
logic for a specific function.

A stored procedure can be written in many different languages, such as


COBOL, OO COBOL, C, C++, PL/I, FORTRAN, Assembler, REXX, Java, and
SQL Procedures (refer to Developing Cross-Platform DB2 stored Procedures
— SQL Procedures and the Stored Procedure Builder, SG24-5485 for more
details).

The language in which stored procedures can be written depends on the


platform where the DB2 server is installed.

Local client applications, remote DRDA, or remote data services (private


protocol) can invoke the stored procedure by issuing the SQL CALL
statement. The SQL CALL statement is part of the ISO/ANSI (SQL:1999), an
open solution for invoking stored procedures among database management
system vendors that support the SQL ISO/ANSI standard.

The calling program can pass parameters to the stored procedure and
receive parameters back from the stored procedure. The calling application
can also access and process result sets generated by the stored procedure.
In addition, the client program and the stored procedure do not have to be
written in the same programming language. For example, a C client program
can invoke a COBOL stored procedure or an SQL stored procedure.

The following DB2 servers currently support DRDA stored procedures:


• DB2 UDB for OS/2
• DB2 UDB for AIX
• DB2 UDB for Windows NT
• DB2 UDB for HP-UX
• DB2 UDB for Solaris
• DB2 UDB for AS/400
• DB2 UDB for OS/390

© Copyright IBM Corp. 2000 243


13.1.1 Why use stored procedures?
In previous releases of DRDA, the client system performed all application
logic. The server was responsible only for SQL processing on behalf of the
client. In such an environment, all database accesses must go across the
network, resulting in poor performance in some cases.

This is a relatively simple model, which makes the application program easy
to design and implement. Because all application code resides at the client, a
single application programmer can take responsibility for the entire
application. However, there are some disadvantages to using this approach.

Because the application logic runs only at the client, additional network
input/output (I/O) operations are required for most SQL requests. These
additional operations can result in poor performance. This approach also
requires the client program to have detailed knowledge of the server’s
database design. Thus, every change in the database design at the server
requires a corresponding change in all client programs accessing the
database. Also, because the programs run at the client workstations, it is
often complicated to manage and maintain the copies at the clients.

Stored procedures enable you to encapsulate many of your application’s SQL


statements into a program that is stored at the DB2 server. The client can
invoke the stored procedure by using only one SQL statement, thus reducing
the network traffic to a single send and receive operation for a series of SQL
statements. It is also easier to manage and maintain programs that run at the
server than it is to manage and maintain many copies at the client machines.
See Figure 40.

244 DB2 Java Stored Procedures: Learning by Example


OS/390 System

DRDA CLIENT STORED PROC


OR
DB2 ADDRESS SPACE
LOCAL CLIENT
SCHEDULE PROGX PROGX

PERFORM SQL EXEC SQL SELECT

EXEC SQL PERFORM SQL EXEC SQL UPDATE


CALL PROGX

PERFORM SQL EXEC SQL CREATE

RETURN VALUES
TO CLIENT PROGX ENDS

PROGY

Figure 40. Stored procedures — overview

In addition, stored procedures enable you to split the application logic


between the client and the server. You can use this technique to prevent the
client application from manipulating the contents of sensitive server data. You
can also encapsulate business logic into programs at the server.

Stored procedures also enable access to features that exist only on the
database server. These features include commands that run only on the
server, software installed only on the server that can be accessed by the
stored procedure, and the computing resources of the server, such as
memory and disk space.

Because stored procedures are defined in DRDA, they also take advantage of
DRDA features, such as data transformation between platforms, database
security and accounting, and two-phase commit support.

Chapter 13. DB2 UDB for OS/390 stored procedures enhancements 245
13.1.2 SQL CALL — processing flow
Following is the processing flow of the SQL CALL statement within DB2 for
OS/390.
1. A thread must be created for each application that needs DB2 services. If
the application is local, the thread is created when the first SQL statement
is executed. If the request comes from a remote client, the thread is
created when the client application issues the SQL CONNECT statement.
After the thread is created, SQL statements can be executed.
2. When a client application issues an SQL CALL statement, the stored
procedure name and the I/O parameters are passed to DB2 via the
Distributed Data Facility (DDF) address space.
3. When DB2 receives the SQL CALL statement, it searches in the DB2
catalog for a row associated with the stored procedure name. From this
table, DB2 obtains the load module associated with the stored procedure
and other information related to it.
4. Stored procedures are executed in address spaces. For DB2 for OS/390
Version 4, there is only one address space available, which is called the
DB2-established address space. Since Version 5, in addition to the
DB2-established address space, you can have several work load manager
(WLM) established address spaces.
For DB2-established or WLM-established address spaces, you can
specify a number of task control blocks (TCBs) in this address space
available for stored procedures. Each stored procedure is executed under
one TCB. After searching the DB2 catalog, DB2 searches for a procedure
address space in which to execute the stored procedure.
5. When DB2 notifies the stored procedure address space to execute a
stored procedure, the thread that was created for the client application is
reused for an execution. This has the following implications:
- CPU cost is low because DB2 does not create a new thread.
- Accounting is on behalf of the client application.
- For static SQL the OWNER of the client program must have EXECUTE
privilege on the stored procedure package. For dynamic SQL issued by
the stored procedure, security is checked against the user of the client
program, unless the DYNAMICRULES(BIND) option was specified
when binding the package for the stored procedure. No sign-on or
connection processing is required.
- Any processing done by the stored procedure is considered a logical
continuation of the client application’s unit of work. Thus, locks

246 DB2 Java Stored Procedures: Learning by Example


acquired by the stored procedure are released when the client
application commits or rolls back.
6. The stored procedure address space uses the LE/370 product libraries to
load and execute the stored procedure. Through the DB2 catalog, you can
pass run-time parameters for LE/370 when the stored procedure is
executed.
7. Control is passed to the stored procedure along with the input and output
parameters. The stored procedure can issue most SQL statements. It also
has access to non-DB2 resources (however, such updates are outside the
unit of work if the stored procedure is being executed within a
DB2-established address space).
8. Before terminating, the stored procedure assigns values to the output
parameters and returns the control to DB2.
9. DB2 copies the output parameters received from the stored procedure to
the client application parameter area and returns control to the client
application.
10.The calling program receives the output parameters and continues the
same unit of work.
11.The client application implicitly issues the COMMIT statement. With DB2
Version 5, the client application can implicitly commit as soon as the
stored procedure returns the control to the client application. If the client
application and the stored procedure used during this execution update at
different sites, the two-phase commit protocol is used.

Although stored procedures are primarily used from DRDA remote clients,
they are also supported locally. If a local application issues the SQL CALL
statement, the distributed data facility (DDF) is not involved and need not be
started.

13.1.3 Stored procedures — time line characteristics


Starting with Version 4, in this section and its subsection we will describe the
characteristics of DB2 stored procedures.

13.1.3.1 In Version 4
Most of the Version 4 characteristics apply to Version 6, but Version 6
introduced a number of enhancements, as we will describe later in this
section and show in the examples presented in this book.

Chapter 13. DB2 UDB for OS/390 stored procedures enhancements 247
• Static or dynamic SQL
The stored procedure can issue static or dynamic SQL statements. Data
definition language (DDL) statements, most data manipulation language
(DML) statements, and data control language (DCL) statements can be
coded in a stored procedure.
The DRDA architecture allows SQL CALL statements to use static or
dynamic SQL. For the current version of the DB2 products, the SQL CALL
statement must be a static SQL. Nevertheless, parameters in the CALL
statement, including the stored procedure name, can be supplied at
execution time. Thus, you can use the SQL CALL statement to
dynamically invoke any procedure supported by DB2.
These characteristics have not changed in Version 6.
• Ability to use three-part names over private protocol
You can reference aliases or three-part names in a stored procedure.
Although for Version 4 and Version 5 you cannot issue an SQL CALL
statement in your stored procedure, you can call other programs or
routines from a stored procedure by using standard programming
language facilities.
If you must access the same remote location from a client program that
uses CONNECT TYPE 2, you can issue an SQL RELEASE statement for
the remote location, followed by an SQL COMMIT statement. These
statements must be executed before or after the stored procedure,
depending on when you want to connect to the remote location. If you use
these statements, you terminate your unit of work. If you do not want to
terminate your unit of work, but still want to access tables at the remote
location, you can use system-directed access in your client program to the
same remote location that the stored procedure is accessing. In this case
use a three-part name and do not issue the SQL CONNECT statement.
For client programs using CONNECT TYPE 1, you must issue an SQL
COMMIT before or after the call to the stored procedure. Unlike DB2 on
OS/390, if your client program is running in the workstation platform using
CONNECT TYPE 2, you can connect in the same unit of work to the same
remote location that is accessed by the stored procedure.
Note that a new thread is created when you issue the CONNECT
statement. When the stored procedure executes the SQL statement with
the three-part name specification, another thread is created in DB2 for the
same unit of work. In this scenario, be careful when updates are made
from the client program and the stored procedure on the same data. You
might get into a lock problem situation because the threads are different.

248 DB2 Java Stored Procedures: Learning by Example


If you have precompiled your program with CONNECT TYPE 1, you must
issue an SQL COMMIT statement before or after the call to the stored
procedure that is using system-directed access. If you do not commit, your
client program receives an SQLCODE -30090 when trying to call the
stored procedure or in the SQL CONNECT statement.
• IFI call and DB2 commands
You can use IFI calls and issue commands from the stored procedure.
Note that DRDA supports only SQL statements, not commands. If, for
example, you need to monitor the DB2 environment from a workstation,
you can invoke a stored procedure that issues DB2 commands and
returns results to the workstation.
• Access to non-DB2 resources
You can access VSAM files and IMS databases or invoke CICS
transactions from a stored procedure. To access an IMS database, you
have the following options:
- Invoke a CICS transaction
- Invoke an APPC application
- Use MQ Series
- Use DRA (new support in IMS, and must use DB2 Version 5 or higher)
• Restricted SQL operations
For DB2 Version 4 and Version 5, the following SQL statements cannot be
used in a stored procedure:
- CALL
- COMMIT
- CONNECT
- RELEASE
- ROLLBACK
- SET CONNECTION
- SET CURRENT SQLID
If you try to use any of the unsupported SQL statements, your stored
procedure and the client program receive a -751 SQLCODE. This is an
exceptional case where the client program directly receives the failing
SQLCODE that the stored procedure receives. When your stored
procedure receives a -751 SQLCODE, the DB2 thread associated with it is
placed in a “must rollback” state.

Chapter 13. DB2 UDB for OS/390 stored procedures enhancements 249
When the client program receives control back from the stored procedure,
it must issue a successful SQL ROLLBACK statement before it can
continue processing. If the client program does not issue the SQL
ROLLBACK statement and terminate, DB2 automatically rolls back the
unit of work.
If, because an error condition, you want to ensure a rollback in the unit of
work, you can code the following ROLLBACK statement in your stored
procedure:
IF error-condition THEN
EXEC SQL ROLLBACK END-EXEC.
Because ROLLBACK is an invalid SQL statement for stored procedures,
your unit of work is placed in a “must rollback” state.

13.1.3.2 In Version 5
DB2 Version 5 supports WLM-established stored procedures address spaces
in addition to the DB2-established address space, which was already
supported in DB2 Version 4.

DB2 for OS/390 Version 5 (with OS/390 release 3 or above) enables you to
run multiple WLM-managed stored procedures address spaces. With
WLM-established address spaces, you can:
• Access non-DB2 resources with two-phase commit.
• Execute stored procedures based on individual transaction priorities.
• Achieve workload balancing across multiple stored procedure address
spaces.
• Utilize the increased flexibility to group or isolate applications.
• Do a RACF check to non-DB2 resources based on the client authorization.

For WLM-established address spaces, you can use the primary authorization
ID related to the client application. To do this, you must specify the value Y for
the EXTERNAL_SECURITY column of SYSIBM.SYSPROCEDURES. You
should only specify this option if you access non-DB2 resources and you
want to check the privileges of the client authorization ID instead of the
WLM-established address space. The following considerations apply if you
specify Y for the EXTERNAL_SECURITY column:
• If you have inbound translation, the translated authorization ID is used.
• The RACF ID and group name that you select must have authority to run
the Recoverable Resource Manager Services Attachment Facility
(RRSAF) application programs.

250 DB2 Java Stored Procedures: Learning by Example


Recoverable Resource Manager Services Attachment Facility
An application program can use RRSAF to connect to DB2 to process SQL
statements, commands, or instrumentation facility interface (IFI) calls.
Programs that run in MVS batch, TSO foreground, and TSO background can
use RRSAF.

RRSAF uses OS/390 Transaction Management and Recoverable Resource


Manager Services (OS/390 RRS). With RRSAF, you can coordinate DB2
updates with updates made by all other resource managers that also use
OS/390 RRS in an MVS system.

WLM-established address space must use RRSAF, therefore you may update
non-DB2 resources that register with RRS using the two-phase commit
protocol. IMS and APPC are examples of RRS enabled resource managers.

Multiple result sets in DB2 for OS/390


DB2 for OS/390 has implemented support to multiple result sets as both client
and server.

If your stored procedure is executing on DB2 for OS/390, your stored


procedure can return multiple result sets to a local or remote client
application. These code points are supported by DB2 CONNECT.

If the stored procedure is executing on a remote DRDA application server, the


remote DRDA application server must support DRDA code points used to
return multiple result sets.

To implement multiple result sets for each result set you want returned, your
stored procedure must:
• Declare a cursor with the WITH RETURN option
• Open the cursor
• Leave the cursor open

When the stored procedure ends, DB2 return the rows in the query result
when the client issues a FETCH statement.

The RESULT_SETS column of the row associated with your stored procedure
in the catalog table SYSIBM.SYSPROCEDURES must contain the maximum
number of result sets that the stored procedure will be allowed to return to the
caller.

For example, if you want to return a result set that contains entries for all
employees in department D11, you should code your stored procedure as
follows:

Chapter 13. DB2 UDB for OS/390 stored procedures enhancements 251
1. The stored procedure declares a cursor that describes this subset of
employee:
EXEC SQL DECLARE CURSOR-EMP CURSOR WITH RETURN FOR
SELECT EMPNO, FIRSTNAME, MIDINT, LASTNAME, PHONENO
FROM DSN8510.EMP
WHERE WORKDEPT=’D11’;
END EXEC
2. Then it opens the cursor:
EXEC SQL OPEN CURSOR-EMP END-EXEC.
3. It ends without closing the cursor or fetching rows from this cursor.
If the stored procedure fetches rows, the fetched rows are not returned to
the client. In general, there are no reasons for the stored procedure to
fetch the row, but sometimes there might be. Following is an example of a
real use for fetching rows from the cursor prior to returning to DB2:
The customer has a Web application that can only display 50 rows of
data on each page. Web applications are stateless, so they are not
able to keep the cursor open to fetch more than 50 rows of data on any
given series of Web clicks.
To get around this problem, they implemented the query inside a stored
procedure. The Web user clicks on a button that indicates whether they
want:
• The first 50 rows
• The second group of 50 rows
• The third group of 50 rows
• And so on
If the user wants the second group of 50 rows, the stored procedure
issues the SELECT statement specifying WITH RETURN and
OPTIMIZE FOR 50 ROWs. The stored procedure then issues 50
FETCH calls, so that the cursor is positioned on row 51. At this point,
the stored procedure returns to DB2. DB2 will transmit row 51-100 to
the Web server, giving the user what they wanted.
In this application, rarely are more than 50 rows returned from a query,
so this was a simple way to implement the support.

You should use meaningful cursor names for returning result sets, because
the name of the cursor that is used to return result sets is available to the
client application through extensions to the DESCRIBE statement.

252 DB2 Java Stored Procedures: Learning by Example


You can use any of these objects in the SELECT statement associated with
the cursor for a result set:
• Tables, synonyms, views, temporary tables, and aliases defined at local
DB2 system.
• Tables, synonyms, views, temporary tables, and aliases defined at remote
DB2 on OS/390 systems that are accessible through DB2 private protocol
access.

You can use a temporary table to return result sets from a stored procedure.
This capability can be used to return nonrelational data sets such as IMS,
VSAM, or QSAM, to a DRDA client. For example, you can access IMS data
from a stored procedure in the following way:
• Access the IMS database.
• Receive the IMS reply message, which contains data that should be
returned to the client.
• Insert the data from the reply message into a global temporary table.
• Open a cursor against the temporary table. When the stored procedure
ends, the rows from the temporary table are available to the client.

Using this approach, you can join information contained in the global
temporary table obtained from non-relational data to your DB2 data and
return it to the client.

You can code your multiple result sets stored procedure in any languages
supported to code stored procedures. In addition, the stored procedure can
be written using the DB2 for OS/390 ODBC/CLI interface. As with a normal
stored procedure, it must use LE/370.

Multiple result sets stored procedures are supported in the DB2-established


address space and in the WLM-established address spaces.

If your application program calls a stored procedure that returns result sets,
you must include code in your application to receive each of the result sets.

Result sets are only available from read-only client applications. You cannot
use the UPDATE OR DELETE for multiple result sets in your client
application. Stored procedure result set are always marked “read only”, so
update or delete operations fail if you issue them. This implies that UPDATE
or DELETE WHERE CURRENT CURSOR is not allowed in the stored
procedure or in the client application.

Chapter 13. DB2 UDB for OS/390 stored procedures enhancements 253
Unlike DB2 UDB for workstations, your DB2 for OS/390 client application can
be written in any supported language and can use the DB2 for OS/390
ODBC/CLI interface.

If the client application is not using ODBC/CLI, there are the following
extensions in the SQL language:
• A result set locator SQL data type
• An ASSOCIATE LOCATORS SQL statement
• An ALLOCATE CURSOR SQL statement
• A DESCRIBE PROCEDURE SQL statement
• A DESCRIBE CURSOR SQL statement

COMMIT_ON_RETURN
DB2 for OS/390 Version 5 has introduced a new column,
COMMIT_ON_RETURN. If you specify N for this column. all updates
performed by the unit of work are committed when the client application
commits. This is the default.

If you specify Y for this column, all updates performed by the unit of work are
committed when control returns to the client application if the SQLCODE for
the CALL statement is zero or has a positive value. This implies that updates
performed before the stored procedure is invoked, are also committed. Those
updates can be updates done by the stored procedure locally or remotely
(through a three-part name or using RRSAF), or done locally or remotely by
the client application before invoking the stored procedure.

Any updates performed by the client application after execution of the stored
procedure are part of another unit of work. The client application does not
need to code the commit statement. This is valid for DB2-established or
WLM-established address spaces, regardless of whether the client
application is using COMMIT 1 or COMMIT 2. If the application updated other
DRDA servers before invoking the stored procedure, those updates are also
committed upon successful execution of the stored procedure.

The advantage of committing automatically is that all locks acquired


previously are released, except for locks acquired for opened cursors
declared with both the WITH HOLD and WITH RETURN options.

If the stored procedure is coded to return result sets, you must declare the
cursors for the result sets with the WITH RETURN and WITH HOLD options;
otherwise the cursors are closed when control returns to the client
application. For one result set, you only need to specify WITH HOLD if
COMMIT_ON_RETURN is 'Y'.

254 DB2 Java Stored Procedures: Learning by Example


If the stored procedure is connected to a location, for which updates are not
allowed, the client application gets a -426 SQLCODE.

DLI support
Because IMS does not support multiple TCBs for batch processing and
requires that the IMS region controller be the module in control, you cannot
access IMS databases directly from the stored procedures address spaces
using the batch region facility.

There are several ways that you can access IMS databases:
• Using the database resource adapter (DRA) callable interface.
• Including APPC code in the stored procedure. An IMS or CICS transaction
can be invoked by APPC.
• Using the MQI interface to access CICS transaction.
• Using the EXCI interface.
• Using the MQI interface to place a transaction on the IMS message
queue.

Depending on the method and the level of product you use, you can have
different combinations of:
• Commitment control
• Complexity of the code
• Performance

Once you have accessed IMS databases, you can pass IMS information
through output parameters, or you can insert information obtained from IMS
databases in a global temporary table, and pass this information to the client
application using multiple result sets.

Here we describe a method using the DRA callable interface (see Figure 41).

The IMS-supplied DRA-callable interface is a facility available in IMS Version


6 as an APAR. The DRA-callable interface allows an OS/390 application
execution environment (AEE), such as a stored procedures address spaces,
access to IMS database through the IMS database control system (DBCTL).

Chapter 13. DB2 UDB for OS/390 stored procedures enhancements 255
A stored procedure has access to the IMS database using DRA connection to
DBCTL in a CICS environment and connection to the IMS control region in an
IMS TM environment, because in an IMS TM environment, DBCTL services
are provided in the IMS control region. The architecture of DRA, the callable
interface, resides in the DB2 stored procedure address space, and is
recognized by IMS as an application execution region (AER).

Using the DRA-callable interface the stored procedure can access full
function DL/I databases and fast path data entry databases (DEDB). The
DRA-callable interface allows DBCTL and OS/390 application programs,
such as stored procedures, to be developed, installed, and maintained
independently of each other.

M V S S y s te m

DRDA
D B 2 S to re d
C lien t P roc e du re s R e gio n
EXEC SQL
CALL PRO GX DB2

S c h ed P R O G X P R O G X:

C ALL C OB T D LI
"A P SB "

C ALL C OB T D LI D L IS A S
DBCTL
"G U "
R etu rn v a lu es
to D R D A u s e r

EXEC SQL
C O M M IT
MVS RRS

D L /I c a lls c a n b e is s u e d fro m a s to re d p ro c e d u re
R R S c o o rd in a te s th e c o m m it b e tw e e n D B 2 a n d IM S V 6
G lo b a l te m p o ra ry ta b le s c a n b e u s e d to re tu rn IM S d a ta in a s to re d
p ro c e d u re q u e ry re s u lt s e t
R e q u ire s O S /3 9 0 R 3 a n d IM S V 6 R 1 A P A R th a t e n a b le s R R S s u p p o rt

Figure 41. DB2 stored procedures access DL/I databases

The IMS DRA-callable interface provides new modules packaged with


existing IMS Version 6 DRA modules to support the new callable interface to
DBCTL.

256 DB2 Java Stored Procedures: Learning by Example


Because the interface requires OS/390 RRS, you can use the interface only
in the WLM-established address space. Note that OS/390 R3 or later is
required, due to RRS. As a consequence, the minimum level of DB2 that
allows you to use the DRA-callable interface is DB2 for OS/390 Version 5.
Because Version 4 supports only DB2-established address spaces, you
cannot access an IMS database using the DRA-callable interface with DB2
Version 4.

You cannot execute a stored procedure as an IMS batch application, because


the batch does not connect to DBCTL.

You access IMS databases using the language CALL statement.

The CALLs that are available are the CALLs to the AERTDLI interface or the
AIBTDLI interface. The following function calls are supported by DRA-callable
interface: APSB, CIMS, DEQ, DLET, DPSB, FLD, GU, GHU, GN, GHN,
GMSG, ICMD, INIT, INQY, ISRT, LOG, POS, RCMD, REPL, ROLS, SETS,
SETU, SNAP, STAT, OPEN, and CLSE.

13.1.3.3 In Version 6
This section describes the stored procedures enhancements introduced in
DB2 UDB for OS/390 Version 6.

CREATE PROCEDURE
In Version 6, the SYSIBM.SYSPROCEDURES catalog table is no longer
used. Stored procedures are defined using the CREATE PROCEDURE DDL
statement. The CREATE PROCEDURE statement updates other catalog
tables, such as SYSIBM.SYSROUTINES and SYSIBM.SYSPARMS.

As consequence of the CREATE PROCEDURE statement, there are also the


ALTER PROCEDURE and DROP PROCEDURE DDL statements.

The SQL GRANT and REVOKE statements are enhanced to allow users to
manage the privileges to execute stored procedures.

The CURRENT PATH special register and the PATH bind option are used to
determine the schema name of unqualified stored procedures (see Chapter
12, “DB2 UDB for OS/390 schema support” on page 233 for more details
about schemas).

Stored procedures share with User Defined Functions (UDFs) the same
catalog tables for CREATE/ALTER/GRANT and REVOKE.

Chapter 13. DB2 UDB for OS/390 stored procedures enhancements 257
Three-part name usage
In prior release of DB2, the stored procedure name was composed of three
parts. If the first part was specified, it had to match the location of the current
server. If the second part was specified, it had to match exactly SYSPROC.
The third part had to match the PROCEDURE column of
SYSIBM.SYSPROCEDURE table.

In Version 6, the first part can match any LOCATION name specified in the
SYSIBM.LOCATIONS catalog table. An implicit CONNECT statement is
issued to that location, using DRDA. This provides an enhanced degree of
flexibility. You can invoke a remote procedure as long as you have DRDA
connectivity to the location where the stored procedure resides.

Usage of schemas
In Version 6, the second part of the name does not need to be SYSPROC. it
can be any schema name. Again, this provides a greater degree in
management of stored procedures. You may want to group all related stored
procedures under the same schema. See Chapter 12, “DB2 UDB for OS/390
schema support” on page 233 for more details about schemas.

Some DML restrictions lifted


SQL statements such as CALL, CONNECT, SET CONNECTION and
RELEASE are now allowed within a stored procedure. This allows for nesting
of stored procedures and flexibility to manage the connections.

Authorization enhancements
Because the stored procedure is now created using SQL CREATE statement,
the authorization ID that creates the stored procedure is the OWNER of the
stored procedure and owns it. In previous versions, if the stored procedure
had no SQL, then a package was not required, and you could not directly
prevent the execution of the stored procedure.

Now the owner of the stored procedure can prevent execution of the stored
procedure even if the stored procedure does not require a package.

Also, when you create the stored procedure, you can specify several levels of
DML SQL statements that can be issued by the stored procedure.

UDFs
You can invoke a UDF from a stored procedure and you can invoke a stored
procedure from within a UDF. With the support for the SQL CALL statement in
a stored procedure, you can nest stored procedures and UDFs. UDFs
execute the same way that stored procedures do, in the WLM-established

258 DB2 Java Stored Procedures: Learning by Example


address space. Stored procedures can also be invoked from triggers.
Transition tables can be passed to the stored procedure from triggers.

Note:
In version 6, UDFs cannot be written in Java.

LOBs
You can use LOCATORs, BLOB, CLOB, DBCLOB as input or output
parameters to the stored procedures.

Note:
In version 6, LOBs, LOCATORs and ROWID cannot be defined as
parameters to stored procedures written in Java.

UDTs
The built-in as well as the UDT are supported for the data type of stored
procedure input/output parameters.

13.2 The CREATE PROCEDURE DDL statement


The CREATE PROCEDURE statement can be embedded in an application
program or issued dynamically. It is an executable statement that can be
dynamically prepared. However, if the bind option DYNAMICRULES(RUN) is
not specified explicitly or implicitly, the statement cannot be dynamically
prepared.

This is an example of the insert statement to SYSIBM.SYSPROCEDURES for


Version 5:
INSERT INTO SYSIBM.SYSPROCEDURES
(PROCEDURE,AUTHID,LUNAME,LOADMOD,LINKAGE,COLLID,
LANGUAGE,ASUTIME,STAYRESIDENT,IBMREQD,
RUNOPTS,
PARMLIST,
RESULT_SETS,WLM_ENV,PGM_TYPE, EXTERNAL_SECURITY,COMMIT_ON_RETURN)
VALUES(
'ADD_CUSTOMER', '', '', '', 'N', 'ACMESOE',
'COMPJAVA', 900, '','N',
'ACMESOE/Add_customer.add_customer',
'CHAR(20) IN, CHAR(20) IN, CHAR(30) IN, INTEGER OUT, CHAR(40) out,
CHAR(200) out',

Chapter 13. DB2 UDB for OS/390 stored procedures enhancements 259
1,'WLMJAVADBS1','S','N','N'
);

This is an example of the CREATE PROCEDURE statement for Version 6:


CREATE PROCEDURE ACMESOE.ADD_CUSTOMER
(
IN FIRSTNAME CHAR(20),
IN LASTNAME CHAR(20),
IN ADDRESS CHAR(30),
OUT CUSTNO INTEGER,
OUT MARK CHAR(40),
OUT MARK_ERROR_TEXT CHAR(200))
FENCED
MODIFIES SQL DATA
LANGUAGE COMPJAVA
EXTERNAL NAME 'ACMESOE/Add_customer.add_customer'
PARAMETER STYLE JAVA
WLM ENVIRONMENT WLMJAVADBS1
RUN OPTIONS 'ACMESOE/Add_customer.add_customer'
DYNAMIC RESULT SETS 0
PROGRAM TYPE SUB;

Note that there are new options, modified options, and options that are
unmodified from previous versions. Following are the new options available in
Version 6:
• NOT DETERMINISTIC | DETERMINISTIC
This optional clause specifies whether the stored procedure will always
return the same result from successive calls with identical input
arguments.
• CONTAINS SQL | READS SQL DATA | MODIFIES SQL DATA | NO SQL
This optional clause specifies whether the stored procedure issues any
SQL statement, and if so, what type of SQL statements.
• DBINFO | NO DBINFO
Specifies whether specific information known by DB2 is to be passed to
the stored procedure as an additional invocation time argument.

Following are the options that were enhanced in Version 6:


• PARAMETER STYLE
Identifies the linkage convention used to pass parameters to the stored
procedure. All of the linkage conventions provide arguments to the stored
procedure containing the parameters specified on the SQL CALL

260 DB2 Java Stored Procedures: Learning by Example


statement. Some of the linkage conventions pass additional arguments to
the stored procedure that provide more information to the stored
procedure.
• NO WLM ENVIRONMENT | WLM ENVIRONMENT (name,*)
Specifies if this stored procedure is to execute in the DB2-established
stored procedure address space or in the WLM-established stored
procedure address space.
• EXTERNAL SECURITY
Specifies how this stored procedure interacts with an external security
product (such as RACF) to control access to non-DB2 resources.

The following options were already specifiable through the


SYSIBM.SYSPROCEDURE catalog table and have not changed for this
version of DB2. Following is a brief explanation of the various options:
• LANGUAGE
Specifies the language in which this stored procedure is coded.
• EXTERNAL NAME
Specifies the name of the load module for this stored procedure
• COLLID
Identifies the package collection to use when the stored procedure is
executed.
• ASUTIME
Specifies the total amount of CPU that a single invocation of a stored
procedure can run, in CPU service units.
• RUN OPTIONS
Specifies the LE/370 run-time options to be passed to the stored
procedure.
• STAY RESIDENT
Specifies whether the stored procedure load module remains resident in
memory when the stored procedure ends.
• PROGRAM TYPE
Specifies whether the stored procedure runs as a main routine or as a
subroutine. If the CREATE statement is embedded in a program, the
default for this option depends on the value of the SQLRULES option:
- If SQLRULES(DB2) is specified, the default for PROGRAM TYPE is
MAIN.

Chapter 13. DB2 UDB for OS/390 stored procedures enhancements 261
- If SQLRULES(STD) is specified, the default for PROGRAM TYPE is
SUB.

If the CREATE statement is issued dynamically, the default for this option
depends on the value of the CURRENT RULES special register:
• If the CURRENT RULES special register is DB2, the default for
PROGRAM TYPE is MAIN.
• If the CURRENT RULES special register is STD, the default for
PROGRAM TYPE is SUB.

RESULT SET n

Specifies the maximum number of result sets that can be returned by the
stored procedure.

COMMIT ON RETURN

Indicates whether the transaction should be committed immediately upon


return from a successful execution of the stored procedure.

Note that in Version 6, there is no specification equivalent to AUTHID and


LUNAME. These were most likely used for versioning. You can still control
the versioning by placing the same stored procedure definition under different
schemas. In this case, you should also specify that the stored procedure
executes in different WLM-established stored procedure address spaces
(different WLM application environments), if the load module name is equal
for both versions, each one in a different load module library.

Note:
The stored procedures with the same name but different schemas can
have different EXTERNAL NAME and be in the same WLM environment,
they only have to be in different ones if they have the same EXTERNAL
NAME (load module).

13.2.1 Parameter definitions


As mentioned before, stored procedures support as INPUT, OUTPUT, or
INPUT-OUTPUT, parameters for the new built-in data types (rowid, BLOB,
CLOB, DBCLOB), or user defined distinct data type (see Figure 42).

262 DB2 Java Stored Procedures: Learning by Example


IN | OUT | INOUT parname datatype

V5 and...
[schema.]udt | built_in
rowid
BLOB
CLOB AS LOCATOR

DBCLOB

Figure 42. Stored procedures: parameters definition

Only a LOB data type, or a distinct type based on a LOB data type, can
specify AS LOCATOR.

Note that for Version 6, in the SQL CALL statement, you can pass a special
register, an operator (+, -, *, /, CONCAT, !!), a CASE expression, a CAST
specification, or a function besides a constant, a host variable, and the NULL
value. A table can also be passed, if the SQL CALL statement is issued from
a trigger. Each column of the table comes in as a separate parameter,
described by an SQLDA.

Note:
In version 6, LOBs, LOCATORs and ROWID cannot be defined as
parameters to stored procedures written in Java.

13.2.2 New options


This section describes in more detail the new options available in Version 6.
• FENCED
Specifies that the stored procedure runs in an external address space to
prevent DB2 storage from being corrupted. This is an optional
specification because the architecture of stored procedure in DB2 has
always been that the stored procedure runs in address spaces that are
external to DB2. The reason for this specification is for compatibility with
DB2 UDB in the workstation, when you can have stored procedures that
are fenced and unfenced.

Chapter 13. DB2 UDB for OS/390 stored procedures enhancements 263
• DETERMINISTIC
The stored procedure always returns the same result from successive
calls with identical input arguments. For example, if you issue the
following CALL:
CALL TOTAL_SALES_96(itemnumber)
This is deterministic, because no matter how many times you invoke the
stored procedure the total sales for a passed year will always be the same
for a particular item. On the other hand, if you issue the following CALL:
CALL CURRENT_SALES(itemnumber)
This is not deterministic, because depending upon when you invoked the
stored procedure, the sales for a particular item might have changed.
Note that DB2 does not check if the stored procedure is consistent with
the specification of DETERMINISTIC or NOT DETERMINISTIC. The
specification is intended for documentation purposes. In the future, this
might be used for optimization (not to actually call the stored procedure, if
we already know what the answer will be).
• NO SQL
No SQL statements are allowed in the stored procedure.
If the stored procedure attempts to execute any SQL statements, then an
error (SQLCODE-487) is raised at run time.
Nevertheless, the stored procedure can perform complex calculations,
access non-DB2 resources, or trigger events outside of DB2, such as to
broadcast an e-mail.
• CONTAINS SQL
If the stored procedure attempts to execute COMMIT, DELETE,
DESCRIBE PREPARE, ROLLBACK, SELECT and INSERT SQL
statements, then an error (SQLCODE-579) is raised at run time. This is
the default when you create a procedure. The restriction applies to all SQL
(cursors or singleton SQL).
• READS SQL DATA
If the stored procedure attempts to execute COMMIT, DELETE, INSERT,
ROLLBACK, and UPDATE SQL statements, then an error
(SQLCODE-577) is raised at run time.
• MODIFIES SQL DATA
If the stored procedure attempts to execute COMMIT, AND ROLLBACK
SQL statements, then an error (SQLCODE-751) is raised at run time. If
this was for a ROLLBACK statement, the whole unit of work is placed in a

264 DB2 Java Stored Procedures: Learning by Example


"must rollback state". The SYSIBM.SYSPROCEDURES (Version 5)
catalog entries will be migrated to be 'MODIFIES SQL DATA', not the
default CONTAINS SQL.

Note:
NO SQL, CONTAINS SQL, READS SQL DATA, and MODIFIES SQL DATA
are (by ANSI rules) supposed to 'cascade' such that nested procedures
obey the strictest rule specified by any parent (calling) procedure.

• DB2INFO
When DB2INFO is specified (NO DB2INFO is the default), an additional
argument is passed on invocation of the stored procedure. This
specification is compatible with UDFs, therefore some of the information
will be blank for stored procedures. The argument is a structure which
contains the following information:
- Location name length
- Location name of where the stored procedure was invoked
- Application run-time authorization ID, regardless of the nested routines
in between this routine and the application
- CCSID of the DB2 subsystem
- Schema-name — blank for stored procedures
- Table name length, blank for stored procedures
- Table name, blank for stored procedures.
- Column name blank for stored procedures
- Column name, blank for stored procedures
- Database release level of where the stored procedure was invoked
- Database version number of where the stored procedure was invoked
- Operating system platform of where the stored procedure was invoked

13.2.3 Enhanced options


This section describes in more detail the enhanced options available in
Version 6.
• PARAMETER STYLE DB2SQL
In addition to GENERAL (in previous versions SIMPLE for the LINKAGE
column of SYSPROCEDURES) and GENERAL WITH NULLS (in previous

Chapter 13. DB2 UDB for OS/390 stored procedures enhancements 265
versions SIMPLE WITH NULLS for the LINKAGE column of
SYSPROCEDURES), the DB2SQL option can be specified. When
DB2SQL is specified, additional arguments are passed to/from the stored
procedure:
- A null indicator for each parameter on the CALL statement
- The SQLSTATE to be returned to DB2 upon completion of the stored
procedure
- The qualified name of the stored procedure
(location.schema.procname)
- The specific name of the stored procedure
- Currently DB2 does not support multiple procedures with the same
name in the same schema, so the specific name is the same as the
procedure name
- The SQL diagnostic string to be returned to DB2

Migrated stored procedures will have GENERAL or GENERAL WITH NULLS


depending on the value of LINKAGE.
• EXTERNAL SECURITY DEFINER
In addition to DB2 (in previous versions NO for the
EXTERNAL_SECURITY column of SYSPROCEDURES) and USER (in
previous versions YES for the EXTERNAL SECURITY column of
SYSPROCEDURES), the DEFINER option can be specified. When
DEFINER is specified, an external security environment should be
established for the stored procedure. If the stored procedure accesses
resources protected by an external security product, that access will be
performed using the authorization ID of the person that created the stored
procedure. This specification is valid only for WLM-established stored
procedure address spaces.
• WLM ENVIRONMENT (name,*)
When the stored procedure is called directly by an SQL application
program, name specifies the WLM application environment used to run the
stored procedure.
If the stored procedure is called by another stored procedure or UDF
(nested CALL to a stored procedure), this stored procedure will run in the
environment used by the calling stored procedure or user-defined
function.

266 DB2 Java Stored Procedures: Learning by Example


WLM will try to schedule the stored procedure to run in the same address
space as the calling stored procedure or UDF. But if for any reason it
cannot (for example, maximum number of TCBs exceeded, requirement to
schedule another address space), the stored procedure will still run using
the application environment of the caller, but will run in another address
space. WLM uses the current workload and the priority of the thread to
decide whether to schedule another address space. The stored procedure
will run in the same application environment as the caller if the ,* is
specified after name.
Note also that to prevent users from moving a stored procedure or a UDF
to a sensitive WLM application environment, DB2 invokes the external
security manager (for example, RACF), to determine if the user is allowed
to issue ALTER statements that reference the specified WLM
environment. The RACF command below authorizes a DB2 user
(DB2USER1) to CREATE or ALTER stored procedures on DB2 subsystem
DB2A that specify the WLM environment PAYROLL:
PERMIT DB2A.WLMENV.PAYROLL CLASS(DSNR) ID(DB2USER1) ACCESS(READ)

13.2.4 Advantages of DDL


Following are the implications, resulting from the use of DDL to create
stored procedures, as opposed to inserting rows directly into
SYSIBM.SYSPROCEDURES.
• CREATE
A better method of control over the stored procedure is now available.
Although SYSIBM.SYSPROCEDURES is a catalog table, DB2 had no
control over the information placed there other than the normal verification
(column data type). Using DDL, DB2 can register dependencies between
stored procedure and other objects. Dependencies in any packages that
make a CALL to the procedure, and in triggers that invoke the stored
procedure, are registered, but the stored procedure package is not tied to
the UDF.
DB2 now validates the parameter list at CREATE time. LE/370 run options
are not validated at CREATE time, but LE/370 does that when DB2 passes
the string to it. There are validations (not really new) between the options,
such as which options are valid with NO WLM ENVIRONMENT.
- SYSROUTINES and SYSPARMS
When you create a stored procedure, DB2 places information in the
new catalog tables SYSROUTINES and SYSPARMS. These tables
also contain information related to UDFs.

Chapter 13. DB2 UDB for OS/390 stored procedures enhancements 267
- Privileges
To CREATE a stored procedure, one of the following privileges is
required:
• CREATE IN schema
• SYSADM or SYSCTRL authority.
• Usage of schemas
The following sections describe some considerations related to the usage
of schemas and stored procedures. Note that the CREATE IN schema is
implicit in your own USERID.
• ALTER
You can ALTER any of the options of a stored procedure. The altered
definition and the original definition are both cached in memory. Only the
application that performed the ALTER sees the altered definition. Once the
application that performed the ALTER commits, the old definition is
deleted and the new definition is available.
- Privilege
To ALTER a stored procedure, one of the following privileges is
required:
• Ownership of the stored procedure
• ALTER IN schema
• SYSADM or SYSCTRL authority
- CALL packages are invalidated
Any program (client, UDFs, or another stored procedure that has a
CALL for the altered procedure) have their packages invalidated. On
the next invocation of the altered stored procedure, the packages are
automatically rebound.
• DROP
The keyword RESTRICT must be specified. All packages containing a
CALL to the stored procedure are invalidated, but RESTRICT only applies
to trigger packages. The stored procedure is not dropped if a trigger
definition contains a CALL to this stored procedure.

268 DB2 Java Stored Procedures: Learning by Example


- Privilege
To DROP a stored procedure, one of the following privileges is
required:
• Ownership of the stored procedure
• DROP IN schema
• SYSADM or SYSCTRL authority
• COMMENT ON PROCEDURE
You can use the COMMENT ON PROCEDURE procname to add
comments to an existing stored procedure. These comments are
registered in the REMARKS columns of the corresponding row of
SYSROUTINES.

13.2.5 Schema name: CREATE PROCEDURE


When you create a stored procedure, you can specify a schema name, as for
example:
CREATE schema.procname...

In this case, the schema can be the same as any authorization IDs of the
process. However, if the specified name includes a qualifier that is not the
same as one of these authorization IDs, then one of the following must be
met:
• The privilege set includes SYSADM or SYSCTRL
• The authorization ID of the process has the CREATE IN privilege on the
specified schema.

If the procedure name is unqualified, as, for example:


CREATE procname....

and the statement is embedded in a program, the schema name of the


procedure is the authorization ID in the QUALIFIER bind option when the plan
or package was created or last rebound. If QUALIFIER was not used, the
schema name of the procedure is the owner of the plan or package.

If the procedure name is unqualified and the statement is dynamically


prepared, the SQL authorization ID contained in the CURRENT SQLID
special register is the schema name of the stored procedure.

Chapter 13. DB2 UDB for OS/390 stored procedures enhancements 269
13.2.6 Schema name: CALL statement
When the CALL statement is executed, the stored procedure must identify a
stored procedure that exists at the application server for which the application
is connected or in the location specified in the three-part name.

When you code the client application, you have the following options:
• Specify a literal for the stored procedure name with the schema name.
• Specify a literal for the stored procedure name without a schema name.
• Specify a host variable for the stored procedure name.

If you specify a literal for the stored procedure name with the schema name,
the procedure being invoked must have already been added to the
SYSROUTINES catalog table via CREATE PROCEDURE or via migration to
Version 6.

If the stored procedure is not found, you will get SQLCODE -440. If
VALIDATE(RUN) is specified, the -440 SQLCODE does not cause the BIND
to fail.

If the remote DB2 is Version 4 or Version 5, no schema resolution will be


done; the procedure name will be checked in SYSIBM.SYSPROCEDURES.

If a qualified name (where the schema name is not SYSPROC) is sent to a


Version 4 or Version 5 system, the CALL statement will fail there, just as it
does today on Version 4 or Version 5. If the remote system is Version 6, the
qualification is made there as described. See the other platform specifications
for how they handle a CALL statement.

Figure 43 shows a summary of the flow during bind:


• Does the schema contain the stored procedure?
- If YES, that is OK.
- If NO, during the bind a -440 SQLCODE is returned.
- BIND will succeed or fail on what was specified for VALIDATE.

270 DB2 Java Stored Procedures: Learning by Example


V4/V5 ===> SYSPROC

CALL schema.procname

V6 ===> Any name


procname in schema?

NO YES ===>OK
SQLCODE -440

BIND VALIDATE

RUN=>OK BIND=>FAIL

Figure 43. Schema name: CALL statement 1/2

You should use VALIDATE(RUN) with a remote call or the local BIND will fail,
since the stored procedure will most likely not exist at the calling site. Note
that there was not any such validation in Version 4 or 5.

If you specify a literal for the stored procedure name without a schema name,
then name resolution occurs at bind time based on the PATH bind option
specification.

If you specify a host variable for the stored procedure name, then name
resolution occurs at the execution time based on the value of the CURRENT
PATH special register. Note that all CALLs issued by ODBC, JDBC, or CLI
are resolved at execution time. This is because each of these drivers map the
CALL onto a “CALL :hv” in the driver package.

DB2 searches the schema name using the CURRENT PATH special register
or the PATH bind option from left to right. It qualifies the specified procedure
name starting with the first schema name of CURRENT PATH or PATH bind
option until a match is found. If a matching schema.procname is found, but
the caller is not authorized to it, or if the number of parameters in the
procedure definition does not match the number of parameters specified in
the CALL statement, the next schema.procname combination is tried until
one is found that the caller is authorized to execute and has a matching
number of parameters, or until the list of schemas is exhausted. If the

Chapter 13. DB2 UDB for OS/390 stored procedures enhancements 271
procedure name cannot be resolved a -440 SQLCODE is returned. Figure 44
summarizes this flow.

C A L L p ro c 1 P A T H b in d o p tio n

C A L L :h o s tv a r C U R R E N T P A T H s p e c re g
N e x t s c h e m a ? = = = = > N O = = = = = > -4 4 0

p ro c 1 fo u n d ?

NO
U s e r is a u t h o ri z e d ?

M a tc h i n g n u m b e r o f p a rm s ?

T h a t's th e o n e !!!

Figure 44. Schema name: CALL statement 2/2

13.3 Lifted DML restrictions


You can now code CONNECT, SET CONNECTION and RELEASE within a
stored procedure.

It is strongly recommended that the stored procedure and the caller be


precompiled with CONNECT 2. Because statements in a stored procedure
can go to distributed sites, and COMMITs are not allowed in a stored
procedure, type 1 connect would therefore be a problem.

Also, you can now invoke a local or remote stored procedure from a stored
procedure. With the new DRDA support for three-part names and aliases for
tables, together with the nested capabilities of stored procedures, you can
use DB2 to construct N-tier client/server applications, where SQL and stored
procedures RPC are used to communicate between sites.

DataJoiner has DRDA server capability. Today, that means a DB2 requester
can issue a SELECT to DataJoiner, and obtain query results from Oracle,
Sybase, and so on. In Version 6 you will be able to issue queries to
DataJoiner from a DB2 stored procedure to collect data from many servers in
the network, and return this data to the client as a stored procedure answer
set.

272 DB2 Java Stored Procedures: Learning by Example


Note that if the stored procedure is used for complex logic and complex
calculation but no data access, you can have code reuse. For example,
assume you have a workstation that invokes a stored procedure on one DB2,
whose hardware capability is not fitted for heavy calculations. This stored
procedure can invoke a remote stored procedure just for this purpose.

Figure 45 shows an example of nested SQL CALLs. See 13.4, “Nested stored
procedures: characteristics” on page 274 for more details about nested
stored procedures.

CALL PROC1
PROC1

CALL PROC2
PROC2

CALL
L2.SCX.PR3 DRDA
PR3

CALL PR4 PR4

Figure 45. SQL CALL statement (nesting)

In addition, as mentioned before, if you use the three-part name, then the
location name does not need to match the location of the current server. It
can be any location specified in the SYSIBM.SYSLOCATIONs catalog table.

Note that if you specify a location that refers to a DB2 on OS/390 prior to
Version 6, you should code for the second part SYSPROC.

DB2 UDB supports schema names for stored procedures. No particular


DRDA level required. The schema.procname is buried within the execute
SQL statement DDM message.

Chapter 13. DB2 UDB for OS/390 stored procedures enhancements 273
13.4 Nested stored procedures: characteristics
In Version 6 you are allowed to use nested stored procedures. Following are
the characteristics of this feature:
• Environment saved/restored on each nested call
The following special registers are saved before the SQL CALL is
executed from the caller stored procedure and restored when the control
is returned from the called stored procedure:
- CURRENT DATE
- CURRENT DEGREE
- CURRENT PACKAGESET
- CURRENT PATH
- CURRENT RULES
- CURRENT SERVER
- CURRENT TIME
- CURRENT TIMESTAMP
- CURRENT TIMEZONE
- CURRENT USER
• No COMMIT ON RETURN
A stored procedure with the COMMIT ON RETURN attribute cannot be
nested. In other words, a stored procedure, user-defined function, or
trigger cannot issue a CALL to a stored procedure defined with the
COMMIT ON RETURN attribute (SQLCODE -729). However, a client can
invoke a stored procedure that has COMMIT ON RETURN specified, and
this stored procedure CALLs other stored procedures for which COMMIT
ON RETURN was NOT specified.
A stored procedure that executes in a WLM-established address space
cannot be nested with a stored procedure that executes in a
DB2-established address space. You can nest DB2-established with
DB2-established and WLM-established with WLM-established, but you
cannot nest the two with each other.
• Result sets
Result sets are returned only to the previous levels.

274 DB2 Java Stored Procedures: Learning by Example


• Up to 16 levels of nesting
You can nest stored procedures, UDFs and triggers up to 16 levels. Note
that if you use a three-part name to invoke a procedure at a remote
location, the nesting level starts over at that new server. Also, if there is a
loop back to the first server, it is again reset, but the remote chain will stop
there because that server cannot nest to another location. The nesting
level is any combination of stored procedures, UDFs, and triggers.
• Can use alias for three-part name tables
This capability is no different than in previous versions of DB2. However,
DRDA can now be used as the protocol; therefore, you can also access
tables at non-DB2 for OS/390 remote sites from a stored procedure.

13.5 Authorization
Figure 46 shows the authorization required to issue the CALL statement for a
stored procedure, depending on the caller, as follows:
• The client application that has a CALL coded must have a package
created (if the client is remote, the package is enough), or must have a
plan that includes a package, or the DBRM was bound directly in plan.
• The stored procedure, in turn, must have a package if it has SQL
statements coded.
• The stored procedure can invoke another program (or stored procedure),
which, in turn, must have a package if the routine has SQL statements.

To execute the plan (or package for remote clients), one of the following
privileges is required:
• EXECUTE on plan or package of the client application
• Ownership of the plan or package of the client application
• PACKADM on the collection where the package for client application was
bound
• SYSADM authority

Chapter 13. DB2 UDB for OS/390 stored procedures enhancements 275
C LIEN T SP1
PG M 1
CA LL S P 1
C ALL P G M 1

S P1 PGM1
P LA N
P A CK A G E P A CK A G E
C LIE N T
P AC K A G E

To execute the package/plan m ust:


EX E CU TE on plan/package
Ownership of plan/package O wner (definer) of S P m ust:
PA C K AD M on collection E X E CU TE on package(s) (S P 1 and P GM 1)
SY S A DM O wnership of package(s)
P A C KA D M on collection
Owner of client package/authid of client m us t:
S Y S A DM
E X E CU TE on S P
O wnership of S P
S Y S A DM

Figure 46. Authorization — CALL

For static SQL calls that specify a literal for a procedure name, the owner of
the package for the client application (OWNER bind specification) must have
one of the following privileges:
• EXECUTE on the stored procedure
• Ownership of the stored procedure
• SYSADM authority

The owner of the stored procedure (owner is the definer, who issued the
CREATE PROCEDURE statement, in turn, must have one of the following
privileges:
• EXECUTE on the stored procedure package and packages for invoked
routines from the stored procedure (packages SP1 and PGM1 as shown in
Figure 46)
• Ownership of the stored procedure package and packages for invoked
routines from the stored procedure (packages SP1 and PGM1 as shown in
Figure 46)
• PACKADM on the collection of the stored procedure and on the collection
where the packages for invoked routines from the stored procedure
(packages SP1 and PGM1 as shown in Figure 46)
• SYSADM authority

276 DB2 Java Stored Procedures: Learning by Example


13.5.1 Who has EXECUTE privilege on a stored procedure?
The following rules determine who is checked for EXECUTE privilege on a
stored procedure:
• If a literal is specified, the owner of the package associated with the client
application is checked.
• If a host variable or parameter marker is used, then checking for the
privilege to execute the stored procedure depends on the
DYNAMICRULES bind option as follows:
- RUN — The authorization ID is the primary or any secondary
authorization ID associated with the client application process.
- BIND — The authorization ID is the owner of the package or plan of the
client application.
- DEFINE — If the SQL CALL is issued from a stored procedure or a
UDF, the authorization ID is the owner of the stored procedure or UDF.
Otherwise, the authorization ID is the owner of the package plan of the
client application.
- INVOKE — If the SQL CALL is issued from stored procedure or a UDF,
the authorization ID is the invoker of the stored procedure or UDF.
Otherwise the authorization ID is the primary or any secondary
authorization ID associated with the client application process.

Figure 47 summarizes the checking process.

Chapter 13. DB2 UDB for OS/390 stored procedures enhancements 277
CLIENT SP1
PGM1
CALL SP1
CALL PGM1

PLAN SP1 PGM1


PACKAGE PACKAGE
CLIENT
PACKAGE

* Literal:owner of the package/plan of the client


* Host variable: depends on DYNAMICRULES:
RUN =>primary/sec AUTHID associated with the client
BIND=>owner of package/plan containing CALL
DEFINE=> equal BIND, or owner of SP/UDF
INVOKE=> equal RUN, or invoker of SP/UDF

Figure 47. Authorization — who is checked?

Let us now guide you though an example: Assume that a stored procedure
(SP1) invokes another routine (PGM1). There is a client application with a
CALL statement for this stored procedure. Three packages are invoked:
• PKG1 for the routine
• PKG2 for the stored procedure
• PKG3 for the client application

Also assume the following:


• The owner of PKG1 is USER1.
• The owner of PKG2 is USER2.
• The owner of the stored procedure is USER3.
• The owner of the package of the client application is USER4.
• USER5 wants to execute the client application.

Under these conditions:


• USER3, the owner of the stored procedure, must have EXECUTE
privilege on PKG1.

278 DB2 Java Stored Procedures: Learning by Example


USER1:
GRANT EXECUTE ON PKG1 TO USER3
• USER5 must have EXECUTE privilege on the package of the client
application:
USER4:
GRANT EXECUTE ON PKG3 TO USER5
- For static SQL programs that specify a literal, the owner of the client
application (USER4) must have EXECUTE privilege on the stored
procedure:
USER3:
GRANT EXECUTE ON PROCEDURE SP1 TO USER4
- For static SQL that specifies a host variable or parameter marker the
authorization ID that will be checked for the execution of the stored
procedure will be USER5 or USER4 depending on the
DYNAMICRULES bind option. If DYNAMICRULES bind option is RUN,
the privilege is checked against USER5:
USER3:
GRANT EXECUTE ON PROCEDURE SP1 TO USER5
If DYNAMICRULES bind option is BIND, the privilege is checked
against USER4:
USER3:
GRANT EXECUTE ON PROCEDURE SP1 TO USER4

Figure 48 summarizes this example.

SP1 USER3
PGM1
USER5 CALL SP1
CALL PGM1

PKG3 USER4 PKG2 USER2 PKG1 USER1

USER1: GRANT EXECUTE ON PACKAGE PKG1 TO USER3


USER2: GRANT EXECUTE ON PACKAGE PKG2 TO USER3

USER4: GRANT EXECUTE ON PACKAGE PKG3 TO USER5


IN ADDITION

CALL SP1 ===> USER3: GRANT EXECUTE ON PROCEDURE SP1 TO USER4


CALL :HV ===> USER3: GRANT EXECUTE ON PROCEDURE SP1 TO USER5 (DYNAMICRULES RUN)
CALL :HV ===> USER3: GRANT EXECUTE ON PROCEDURE SP1 TO USER4 (DYNAMICRULES BIND)

Figure 48. Authorization — example

Chapter 13. DB2 UDB for OS/390 stored procedures enhancements 279
13.6 DISPLAY PROCEDURE command
Note that the DISPLAY PROCEDURE command accepts the qualified stored
procedure name as parameter and now displays the schema name and the
WLM_ENV information. See Figure 49.

-DISPLAY PROCEDURE(PAYROLL.*, HRPROD.*)

DSNX940I csect - DISPLAY PROCEDURE REPORT FOLLOWS-

------ SCHEMA=PAYROLL
PROCEDURE STATUS ACTIVE QUEUED MAXQUE TIMEOUT WLM_ENV
PAYRPRC1 STARTED 0 0 1 0 PAYROLL
PAYRPRC2 STOPQUE 0 5 5 3 PAYROLL
PAYRPRC3 STARTED 2 0 6 0 PAYROLL
USERPRC4 STOPREJ 0 0 1 0 SANDBOX

------ SCHEMA=HRPROD
PROCEDURE STATUS ACTIVE QUEUED MAXQUE TIMEOUT WLM_ENV
HRPRC1 STARTED 0 0 1 0 HRPROCS
HRPRC2 STOPREJ 0 0 1 0 HRPROCS
DISPLAY PROCEDURE REPORT COMPLETE

Figure 49. DISPLAY PROCEDURE command

The DISPLAY PROCEDURE does not use the current path to determine
schema. It works the same way from an application program as from the
console. The argument to display with schema can be:
• Procedure name — displays the named stored procedure in schema
SYSPROC
• (*.*) — displays information for all stored procedures in all schemas that
have been accessed by DB2 applications, since DB2 was started. This is
the default.

You must have DISPLAY privilege, SYSOPR, SYSCTRL, or SYSADM


authority for all schemas to issue DISPLAY PROCEDURE with this option.
Note that the owner of a stored procedure can DISPLAY their stored procedures
status.

280 DB2 Java Stored Procedures: Learning by Example


13.7 Migration considerations
During migration to DB2 for OS/390 Version 6, DB2 will copy the rows from
the existing SYSIBM.SYSPROCEDURES and will populate
SYSIBM.SYSPARMS and SYSIBM.SYSROUTINES (with appropriate
reformatting), where SCHEMA column is set to SYSPROC.

DB2 will not copy rows that contain non-blank values for the AUTHID or
LUNAME. Although not used in Version 6, DB2 does not drop the
SYSIBM.SYSPROCEDURES catalog table, DB2 needs it for data sharing
coexistence and fallback.

Stored procedures migrated from Version 4 and Version 5 will not have an
owner. DB2 authorization will treat these migrated procedures differently that
those created by the CREATE PROCEDURE statement. The migrated rows
with no owner will follow the same authorization rules. Refer to Chapter 10,
“Migration of DB2 for OS/390 Version 5 to Version 6” on page 181 for more
information about migration.

Chapter 13. DB2 UDB for OS/390 stored procedures enhancements 281
282 DB2 Java Stored Procedures: Learning by Example
Part 4. Appendices

© Copyright IBM Corp. 2000 283


284 DB2 Java Stored Procedures: Learning by Example
Appendix A. New messages and error codes

This appendix presents some of the new messages and error codes for DB2
UDB for OS/390 version 6.

A.1 STOP DDF MODE SUSPEND


DSNL065I DSNL065I csect CURRENT DDF STATE DOES NOT PERMIT
STOP DDF MODE(SUSPEND)

Explanation: The current DDF state does not allow suspend processing to be
initiated. DDF must be started for normal processing in order for suspend
processing to be initiated.

System Action: The command is not executed.


_____________________________________________________________

DSNL066I DSNL066I csect STOP DDF MODE(SUSPEND) COMPLETE

Explanation: DDF suspend processing has completed successfully. DDF has


suspended all inbound activity.

System Action: Processing continues normally.


_____________________________________________________________

DSNL067I DSNL067I csect CURRENT DDF STATE DOES NOT PERMIT


START DDF

Explanation: The current DDF state does not allow START DDF processing to
be initiated.

System Action: The command is not executed.


_____________________________________________________________

DSNL068I DSNL068I csect START DDF (RESUME PROCESSING)


COMPLETE

Explanation: DDF has resumed normal processing.

System Action: Processing continues normally.


_____________________________________________________________

DSNL069I DSNL069I csect DDF IS SUSPENDING

© Copyright IBM Corp. 2000 285


Explanation: DDF has initiated suspend processing.

System Action: Processing continues normally.


_____________________________________________________________

DSNL070I DSNL070I csect DDF IS RESUMING

Explanation: DDF has initiated resume processing.

System Action: Processing continues normally.


_____________________________________________________________

DSNL071I DSNL071I csect WAIT OR CANCEL REQUIRES KEYWORD


SUSPEND

Explanation: The WAIT(n) or CANCEL(n) key words require that


MODE(SUSPEND) be specified.

System Action: The command is not executed.


_____________________________________________________________

DSNL072I DSNL072I csect WAIT TIME EXPIRED, DDF RESUME


PROCESSING INITIATED

Explanation: The DDF suspend process has not completed successfully in


the period of time specified for the WAIT key word and so DDF resume
processing has been initiated.

System Action: DDF resume processing has been initiated.


_____________________________________________________________

DSNL073I DSNL073I csect CANCEL TIME EXPIRED, CANCEL ACTIVE


DBAT PROCESSING HAS BEEN INITIATED.

Explanation: The DDF suspend process has not completed successfully in


the period of time specified for the CANCEL key word and so DDF is
cancelling all active data base access threads (DBATS).

System Action: DDF is attempting to terminate all active data base access
threads.

286 DB2 Java Stored Procedures: Learning by Example


Appendix B. Sample code, DDL, and preparation scripts

This appendix contains information to help you build the stored procedure
samples listed in the book. You can also find all of the items within this
section in electronic format on the accompanying CD-ROM (see Appendix E,
“Using the additional material” on page 347).

B.1 Sample DDL


Below are the DDL files used to create the ACME SOFTWARE CO sample
application referred to throughout this book.

The DDL for each of the platforms we cover is listed separately (however,
since the DDL for Windows NT and AIX is exactly the same, it is listed only
once. Within each of these sections, the standard and enhanced DDL is
shown (for a definition of these terms, refer to 3.3, “Sample application
components” on page 21).

B.1.1 DB2 UDB for OS/390 DDL


This section contains the sample DDL for the OS/390 platform.

B.1.1.1 Standard DDL

--------------------------------------------------------
-- --
-- DDL FOR ACME SOFTWARE CO EXAMPLE --
-- --
-- SQL LEVEL: STANDARD (NO ENHANCED V6 FEATURES) --
-- --
--------------------------------------------------------

--------------------------------------------------------
-- CREATE DATABASE --
--------------------------------------------------------

--DROP DATABASE DACMES ;


COMMIT ;

CREATE DATABASE DACMES ;

--------------------------------------------------------
-- CREATE TABLESPACES/TABLES/INDEXES --
--------------------------------------------------------

© Copyright IBM Corp. 2000 287


--
-- CUSTOMER
--

CREATE TABLESPACE SCUST


IN DACMES
USING STOGROUP SYSDEFLT;

CREATE TABLE ACMES.CUSTOMER


(
CUST_NO INTEGER NOT NULL
PRIMARY KEY,
CUST_FIRSTNAME CHAR(20) NOT NULL,
CUST_LASTNAME CHAR(20) NOT NULL,
CUST_ADDRESS CHAR(30)
)
IN DACMES.SCUST;

CREATE UNIQUE INDEX ACMES.P_CUSTOMER


ON ACMES.CUSTOMER
(CUST_NO);

--
-- PRODUCT
--

CREATE TABLESPACE SPRODUCT


IN DACMES
USING STOGROUP SYSDEFLT;

CREATE TABLE ACMES.PRODUCT


(
PROD_NO INTEGER NOT NULL
PRIMARY KEY,
PROD_DESC CHAR(30) NOT NULL,
PROD_PRICE DECIMAL(10,2) NOT NULL,
PROD_IN_STOCK INTEGER NOT NULL
)
IN DACMES.SPRODUCT;

CREATE UNIQUE INDEX ACMES.P_PRODUCT


ON ACMES.PRODUCT
(PROD_NO);

--

288 DB2 Java Stored Procedures: Learning by Example


-- ORDER
--

CREATE TABLESPACE SORDER


IN DACMES
USING STOGROUP SYSDEFLT;

CREATE TABLE ACMES.ORDER


(
ORD_NO INTEGER NOT NULL
PRIMARY KEY ,
ORD_DATE DATE NOT NULL,
ORD_CUST_NO INTEGER NOT NULL,
FOREIGN KEY (ORD_CUST_NO)
REFERENCES ACMES.CUSTOMER(CUST_NO) ON DELETE CASCADE
)
IN DACMES.SORDER;

CREATE UNIQUE INDEX ACMES.P_ORDER


ON ACMES.ORDER
(ORD_NO);

CREATE INDEX ACMES.F_ORDER_1


ON ACMES.ORDER
(ORD_CUST_NO);

--
-- ORDER ITEM
--

CREATE TABLESPACE SORDITEM


IN DACMES
USING STOGROUP SYSDEFLT;

CREATE TABLE ACMES.ORDER_ITEM


(
ORD_ITEM_NO INTEGER NOT NULL
PRIMARY KEY,
ORD_ITEM_ORD_NO INTEGER NOT NULL,
ORD_ITEM_PROD_NO INTEGER NOT NULL,
ORD_ITEM_QTY INTEGER NOT NULL,
FOREIGN KEY (ORD_ITEM_ORD_NO)
REFERENCES ACMES.ORDER(ORD_NO) ON DELETE CASCADE,
FOREIGN KEY (ORD_ITEM_PROD_NO)
REFERENCES ACMES.PRODUCT(PROD_NO) ON DELETE CASCADE
)
IN DACMES.SORDITEM;

Appendix B. Sample code, DDL, and preparation scripts 289


CREATE UNIQUE INDEX ACMES.P_ORDER_ITEM
ON ACMES.ORDER_ITEM
(ORD_ITEM_NO);

CREATE INDEX ACMES.F_ORDER_ITEM_1


ON ACMES.ORDER_ITEM
(ORD_ITEM_ORD_NO);

CREATE INDEX ACMES.F_ORDER_ITEM_2


ON ACMES.ORDER_ITEM
(ORD_ITEM_PROD_NO);

--
-- HI_CUST_NO
--

CREATE TABLESPACE SHICUST


IN DACMES
USING STOGROUP SYSDEFLT;

CREATE TABLE ACMES.HI_CUST_NO


(
HI_CUST_NO INTEGER NOT NULL
)
IN DACMES.SHICUST;

INSERT INTO ACMES.HI_CUST_NO


VALUES(1);

--
-- HI_ORD_NO
--

CREATE TABLESPACE SHIORD


IN DACMES
USING STOGROUP SYSDEFLT;

CREATE TABLE ACMES.HI_ORD_NO


(
HI_ORD_NO INTEGER NOT NULL
)
IN DACMES.SHIORD;

INSERT INTO ACMES.HI_ORD_NO


VALUES(1);

290 DB2 Java Stored Procedures: Learning by Example


B.1.1.2 Enhanced DDL

Note
If you intend to submit the following DDL using SPUFI, ensure that the
termination character is set to ‘:’ in the SPUFI defaults panel (see
explanatory text in DDL for details).

--------------------------------------------------------
-- --
-- DDL FOR ACME SOFTWARE CO EXAMPLE --
-- --
-- --
-- SQL LEVEL: ENHANCED (USES ENHANCED V6 FEATURES) --
-- --
-- NOTE: THE COLON (':') CHARACTER IS USED INSTEAD --
-- OF THE SEMICOLON (';') CHARACTER FOR --
-- TERMINATING COMMNANDS, DUE TO THE PRESENCE --
-- OF CREATE TRIGGER STATEMENTS. --
-- --
-- IF THIS FILE IS SUBMITTED USING SPUFI, --
-- ENSURE THAT THE TERMINATION CHARACTER IS --
-- SET TO ':' IN THE SPUFI DEFAULTS PANEL. --
-- --
--------------------------------------------------------

--------------------------------------------------------
-- CREATE DATABASE --
--------------------------------------------------------

--DROP DATABASE DACMEE :


COMMIT :

CREATE DATABASE DACMEE :

--------------------------------------------------------
-- CREATE TABLESPACES/TABLES/INDEXES --
--------------------------------------------------------

--
-- CUSTOMER
--

Appendix B. Sample code, DDL, and preparation scripts 291


CREATE TABLESPACE SCUST
IN DACMEE
USING STOGROUP SYSDEFLT:

CREATE TABLE ACMEE.CUSTOMER


(
CUST_NO INTEGER NOT NULL
PRIMARY KEY
GENERATED ALWAYS AS IDENTITY
(START WITH 1,
INCREMENT BY 1,
CACHE 10),
CUST_FIRSTNAME CHAR(20) NOT NULL,
CUST_LASTNAME CHAR(20) NOT NULL,
CUST_ADDRESS CHAR(30) NOT NULL
)
IN DACMEE.SCUST:

CREATE UNIQUE INDEX ACMEE.P_CUSTOMER


ON ACMEE.CUSTOMER
(CUST_NO):

--
-- PRODUCT
--

CREATE TABLESPACE SPRODUCT


IN DACMEE
USING STOGROUP SYSDEFLT:

CREATE TABLE ACMEE.PRODUCT


(
PROD_NO INTEGER NOT NULL
PRIMARY KEY,
PROD_DESC CHAR(30),
PROD_PRICE DECIMAL(10,2) NOT NULL,
PROD_IN_STOCK INTEGER NOT NULL
)
IN DACMEE.SPRODUCT:

CREATE UNIQUE INDEX ACMEE.P_PRODUCT


ON ACMEE.PRODUCT
(PROD_NO):

--

292 DB2 Java Stored Procedures: Learning by Example


-- ORDER
--

CREATE TABLESPACE SORDER


IN DACMEE
USING STOGROUP SYSDEFLT:

CREATE TABLE ACMEE.ORDER


(
ORD_NO INTEGER NOT NULL
PRIMARY KEY
GENERATED ALWAYS AS IDENTITY
(START WITH 1,
INCREMENT BY 1,
CACHE 10),
ORD_DATE DATE NOT NULL,
ORD_CUST_NO INTEGER NOT NULL,
FOREIGN KEY (ORD_CUST_NO)
REFERENCES ACMEE.CUSTOMER(CUST_NO) ON DELETE CASCADE
)
IN DACMEE.SORDER:

CREATE UNIQUE INDEX ACMEE.P_ORDER


ON ACMEE.ORDER
(ORD_NO):

CREATE INDEX ACMEE.F_ORDER_1


ON ACMEE.ORDER
(ORD_CUST_NO):

--
-- ORDER ITEM
--

CREATE TABLESPACE SORDITEM


IN DACMEE
USING STOGROUP SYSDEFLT:

CREATE TABLE ACMEE.ORDER_ITEM


(
ORD_ITEM_NO INTEGER NOT NULL
PRIMARY KEY
GENERATED ALWAYS AS IDENTITY
(START WITH 1,
INCREMENT BY 1,
CACHE 10),
ORD_ITEM_ORD_NO INTEGER NOT NULL,

Appendix B. Sample code, DDL, and preparation scripts 293


ORD_ITEM_PROD_NO INTEGER NOT NULL,
ORD_ITEM_QTY INTEGER NOT NULL,
FOREIGN KEY (ORD_ITEM_ORD_NO)
REFERENCES ACMEE.ORDER(ORD_NO) ON DELETE CASCADE,
FOREIGN KEY (ORD_ITEM_PROD_NO)
REFERENCES ACMEE.PRODUCT(PROD_NO) ON DELETE CASCADE
)
IN DACMEE.SORDITEM:

CREATE UNIQUE INDEX ACMEE.P_ORDER_ITEM


ON ACMEE.ORDER_ITEM
(ORD_ITEM_NO):

CREATE INDEX ACMEE.F_ORDER_ITEM_1


ON ACMEE.ORDER_ITEM
(ORD_ITEM_ORD_NO):

CREATE INDEX ACMEE.F_ORDER_ITEM_2


ON ACMEE.ORDER_ITEM
(ORD_ITEM_PROD_NO):

--------------------------------------------------------
-- CREATE GLOBAL TEMP TABLES --
-- --
-- THESE ARE USED BY THE AFTER-INSERT TRIGGERS THAT --
-- ARE DEFINED BELOW. THE TRIGGERS INSERT THE PRIMARY --
-- KEY VALUE OF THE NEW ROW INTO THE GLOBAL TEMP --
-- TABLE TO ALLOW IT TO BE ACCESSED BY THE CALLING --
-- APP. --
-- --
--------------------------------------------------------

CREATE GLOBAL TEMPORARY TABLE ACMEE.GTT_CUST_NO


(
CUST_NO INTEGER NOT NULL
):

CREATE GLOBAL TEMPORARY TABLE ACMEE.GTT_ORDER_NO


(
ORDER_NO INTEGER NOT NULL
):

--------------------------------------------------------
-- CREATE TRIGGERS --
--------------------------------------------------------

294 DB2 Java Stored Procedures: Learning by Example


CREATE TRIGGER ACMEE.CUST_IA
AFTER INSERT
ON ACMEE.CUSTOMER
REFERENCING NEW AS NEWROW
FOR EACH ROW
MODE DB2SQL
BEGIN ATOMIC
INSERT INTO ACMEE.GTT_CUST_NO
(CUST_NO)
VALUES (NEWROW.CUST_NO);
END:

CREATE TRIGGER ACMEE.ORD_IA


AFTER INSERT
ON ACMEE.ORDER
REFERENCING NEW AS NEWROW
FOR EACH ROW
MODE DB2SQL
BEGIN ATOMIC
INSERT INTO ACMEE.GTT_ORDER_NO
(ORDER_NO)
VALUES (NEWROW.ORD_NO);
END:

--------------------------------------------------------
-- Create Temporary Table Used For Summary Query--
--------------------------------------------------------
create global temporary table acmee.order_item_summ
(
PROD_DESC CHAR(30) ,
QTY_1_TO_5 CHAR(1) NOT NULL,
QTY_6_TO_10 CHAR(1) NOT NULL,
QTY_11_PLUS CHAR(1) NOT NULL
):
--------------------------------------------------------
-- POPULATE PRODUCT TABLE --
--------------------------------------------------------
INSERT INTO ACMEE.PRODUCT
(PROD_NO, PROD_DESC, PROD_PRICE, PROD_IN_STOCK)
VALUES (1,'Acme Word Processor',19.99,200):
INSERT INTO ACMEE.PRODUCT
(PROD_NO, PROD_DESC, PROD_PRICE, PROD_IN_STOCK)
VALUES (2,'Acme Speadsheet',29.99,12):
INSERT INTO ACMEE.PRODUCT
(PROD_NO, PROD_DESC, PROD_PRICE, PROD_IN_STOCK)
VALUES (3,'Acme Presentation Graphics',29.99,101):
INSERT INTO ACMEE.PRODUCT

Appendix B. Sample code, DDL, and preparation scripts 295


(PROD_NO, PROD_DESC, PROD_PRICE, PROD_IN_STOCK)
VALUES (4,'Acme E-Mail Client',39.99,240):
INSERT INTO ACMEE.PRODUCT
(PROD_NO, PROD_DESC, PROD_PRICE, PROD_IN_STOCK)
VALUES (5,'Acme Office Suite',49.99,12):
INSERT INTO ACMEE.PRODUCT
(PROD_NO, PROD_PRICE, PROD_IN_STOCK)
VALUES (6,69.99,678):

--------------------------------------------------------
-- POPULATE CUSTOMER --
--------------------------------------------------------

INSERT INTO ACMEE.CUSTOMER


(cust_firstname, cust_lastname, cust_address)
VALUES ('John Q.', 'Public', '111 1st St., San Jose, CA '):

--------------------------------------------------------
-- POPULATE ORDER --
--------------------------------------------------------
INSERT INTO ACMEE.ORDER
(ord_date, ord_cust_no)
VALUES (CURRENT DATE, 1):

INSERT INTO ACMEE.ORDER


(ord_date, ord_cust_no)
VALUES (CURRENT DATE - 1 DAY, 1):

--------------------------------------------------------
-- POPULATE ORDER ITEM --
--------------------------------------------------------
Insert into ACMEE.ORDER_ITEM
(ORD_ITEM_ORD_NO, ORD_ITEM_PROD_NO,ORD_ITEM_QTY)
VALUES(1,1,1):

Insert into ACMEE.ORDER_ITEM


(ORD_ITEM_ORD_NO, ORD_ITEM_PROD_NO,ORD_ITEM_QTY)
VALUES(1,2,2):

Insert into ACMEE.ORDER_ITEM


(ORD_ITEM_ORD_NO, ORD_ITEM_PROD_NO,ORD_ITEM_QTY)
VALUES(1,3,3):

Insert into ACMEE.ORDER_ITEM


(ORD_ITEM_ORD_NO, ORD_ITEM_PROD_NO,ORD_ITEM_QTY)

296 DB2 Java Stored Procedures: Learning by Example


VALUES(1,4,4):

Insert into ACMEE.ORDER_ITEM


(ORD_ITEM_ORD_NO, ORD_ITEM_PROD_NO,ORD_ITEM_QTY)
VALUES(1,5,5):

Insert into ACMEE.ORDER_ITEM


(ORD_ITEM_ORD_NO, ORD_ITEM_PROD_NO,ORD_ITEM_QTY)
VALUES(2,1,2):

Insert into ACMEE.ORDER_ITEM


(ORD_ITEM_ORD_NO, ORD_ITEM_PROD_NO,ORD_ITEM_QTY)
VALUES(2,2,4):

Insert into ACMEE.ORDER_ITEM


(ORD_ITEM_ORD_NO, ORD_ITEM_PROD_NO,ORD_ITEM_QTY)
VALUES(2,3,6):

Insert into ACMEE.ORDER_ITEM


(ORD_ITEM_ORD_NO, ORD_ITEM_PROD_NO,ORD_ITEM_QTY)
VALUES(2,4,8):

Insert into ACMEE.ORDER_ITEM


(ORD_ITEM_ORD_NO, ORD_ITEM_PROD_NO,ORD_ITEM_QTY)
VALUES(2,5,10):

Insert into ACMEE.ORDER_ITEM


(ORD_ITEM_ORD_NO, ORD_ITEM_PROD_NO,ORD_ITEM_QTY)
VALUES(2,6,22):

B.1.2 DB2 UDB for AIX and Windows DDL


This section contains the sample DDL for the AIX and Windows NT platforms.

B.1.2.1 Standard DDL


--------------------------------------------------------
-- --
-- DDL FOR ACME SOFTWARE CO EXAMPLE --
-- --
-- SQL LEVEL: STANDARD (NO ENHANCED V6 FEATURES) --
-- --
--------------------------------------------------------
-- to load:
-- db2 -tvf ddls.txt

Appendix B. Sample code, DDL, and preparation scripts 297


--------------------------------------------
-- CREATE TABLES/INDEXES --
--------------------------------------------
CONNECT TO ACMES;
--
-- CUSTOMER
--

CREATE TABLE ACMES.CUSTOMER


(
CUST_NO INTEGER NOT NULL
PRIMARY KEY,
CUST_FIRSTNAME CHAR(20) NOT NULL,
CUST_LASTNAME CHAR(20) NOT NULL,
CUST_ADDRESS CHAR(30)
)
;

CREATE UNIQUE INDEX ACMES.P_CUSTOMER


ON ACMES.CUSTOMER
(CUST_NO);

--
-- PRODUCT
--

CREATE TABLE ACMES.PRODUCT


(
PROD_NO INTEGER NOT NULL
PRIMARY KEY,
PROD_DESC CHAR(30) NOT NULL,
PROD_PRICE DECIMAL(10,2) NOT NULL,
PROD_IN_STOCK INTEGER NOT NULL
)
;

CREATE UNIQUE INDEX ACMES.P_PRODUCT


ON ACMES.PRODUCT
(PROD_NO);

--
-- ORDER
--

CREATE TABLE ACMES.ORDER

298 DB2 Java Stored Procedures: Learning by Example


(
ORD_NO INTEGER NOT NULL
PRIMARY KEY ,
ORD_DATE DATE NOT NULL,
ORD_CUST_NO INTEGER NOT NULL,
FOREIGN KEY (ORD_CUST_NO)
REFERENCES ACMES.CUSTOMER(CUST_NO) ON DELETE CASCADE
)
;

CREATE UNIQUE INDEX ACMES.P_ORDER


ON ACMES.ORDER
(ORD_NO);

CREATE INDEX ACMES.F_ORDER_1


ON ACMES.ORDER
(ORD_CUST_NO);

--
-- ORDER ITEM
--

CREATE TABLE ACMES.ORDER_ITEM


(
ORD_ITEM_NO INTEGER NOT NULL
PRIMARY KEY,
ORD_ITEM_ORD_NO INTEGER NOT NULL,
ORD_ITEM_PROD_NO INTEGER NOT NULL,
ORD_ITEM_QTY INTEGER NOT NULL,
FOREIGN KEY (ORD_ITEM_ORD_NO)
REFERENCES ACMES.ORDER(ORD_NO) ON DELETE CASCADE,
FOREIGN KEY (ORD_ITEM_PROD_NO)
REFERENCES ACMES.PRODUCT(PROD_NO) ON DELETE CASCADE
)
;

CREATE UNIQUE INDEX ACMES.P_ORDER_ITEM


ON ACMES.ORDER_ITEM
(ORD_ITEM_NO);

CREATE INDEX ACMES.F_ORDER_ITEM_1


ON ACMES.ORDER_ITEM
(ORD_ITEM_ORD_NO);

CREATE INDEX ACMES.F_ORDER_ITEM_2


ON ACMES.ORDER_ITEM
(ORD_ITEM_PROD_NO);

Appendix B. Sample code, DDL, and preparation scripts 299


--
-- HI_CUST_NO
--

CREATE TABLE ACMES.HI_CUST_NO


(
HI_CUST_NO INTEGER NOT NULL
)
;

INSERT INTO ACMES.HI_CUST_NO


VALUES(1);

--
-- HI_ORD_NO
--

CREATE TABLE ACMES.HI_ORD_NO


(
HI_ORD_NO INTEGER NOT NULL
)
;

INSERT INTO ACMES.HI_ORD_NO


VALUES(1);

--
-- Create Procedures
--

-- Note that all CREATE PROCEDURE statements are within the


-- prep BAT files for each procedure. This is due to the fact
-- that the JAR file for the procedure must exist before the
-- procedure can be defined to DB2
--

B.1.2.2 Enhanced DDL


--------------------------------------------------------
--
-- Works for Version 7 of DB2/UDB for NT
--------------------------------------------------------
--
-- DDL FOR ACME SOFTWARE CO EXAMPLE --
-- --

300 DB2 Java Stored Procedures: Learning by Example


-- --
-- SQL LEVEL: ENHANCED (USES ENHANCED FEATURES) --
-- --
-- NOTE: THE COLON (':') CHARACTER IS USED INSTEAD --
-- OF THE SEMICOLON (';') CHARACTER FOR --
-- TERMINATING COMMNANDS, DUE TO THE PRESENCE --
-- OF CREATE TRIGGER STATEMENTS. --
-- --
-- IF THIS FILE IS SUBMITTED USING CLP, --
-- ENSURE THAT THE TERMINATION CHARACTER IS --
-- SET TO ':' as in the following:
-- --
-- db2 -td: -vf ddle.txt --
--------------------------------------------------------

CONNECT TO ACMEE:

--------------------------------------------------------
-- CREATE TABLES/INDEXES --
--------------------------------------------------------

--
-- CUSTOMER
--

CREATE TABLE ACMEE.CUSTOMER


(
CUST_NO INTEGER NOT NULL
PRIMARY KEY
GENERATED ALWAYS AS IDENTITY
(START WITH 1,
INCREMENT BY 1,
CACHE 10),
CUST_FIRSTNAME CHAR(20) NOT NULL,
CUST_LASTNAME CHAR(20) NOT NULL,
CUST_ADDRESS CHAR(30) NOT NULL
)
:

CREATE UNIQUE INDEX ACMEE.P_CUSTOMER


ON ACMEE.CUSTOMER
(CUST_NO):

--

Appendix B. Sample code, DDL, and preparation scripts 301


-- PRODUCT
--

CREATE TABLE ACMEE.PRODUCT


(
PROD_NO INTEGER NOT NULL
PRIMARY KEY,
PROD_DESC CHAR(30) ,
PROD_PRICE DECIMAL(10,2) NOT NULL,
PROD_IN_STOCK INTEGER NOT NULL
)
:

CREATE UNIQUE INDEX ACMEE.P_PRODUCT


ON ACMEE.PRODUCT
(PROD_NO):

--
-- ORDER
--

CREATE TABLE ACMEE.ORDER


(
ORD_NO INTEGER NOT NULL
PRIMARY KEY
GENERATED ALWAYS AS IDENTITY
(START WITH 1,
INCREMENT BY 1,
CACHE 10),
ORD_DATE DATE NOT NULL,
ORD_CUST_NO INTEGER NOT NULL,
FOREIGN KEY (ORD_CUST_NO)
REFERENCES ACMEE.CUSTOMER(CUST_NO) ON DELETE CASCADE
)
:

CREATE UNIQUE INDEX ACMEE.P_ORDER


ON ACMEE.ORDER
(ORD_NO):

CREATE INDEX ACMEE.F_ORDER_1


ON ACMEE.ORDER
(ORD_CUST_NO):

--
-- ORDER ITEM

302 DB2 Java Stored Procedures: Learning by Example


--

CREATE TABLE ACMEE.ORDER_ITEM


(
ORD_ITEM_NO INTEGER NOT NULL
PRIMARY KEY
GENERATED ALWAYS AS IDENTITY
(START WITH 1,
INCREMENT BY 1,
CACHE 10),
ORD_ITEM_ORD_NO INTEGER NOT NULL,
ORD_ITEM_PROD_NO INTEGER NOT NULL,
ORD_ITEM_QTY INTEGER NOT NULL,
FOREIGN KEY (ORD_ITEM_ORD_NO)
REFERENCES ACMEE.ORDER(ORD_NO) ON DELETE CASCADE,
FOREIGN KEY (ORD_ITEM_PROD_NO)
REFERENCES ACMEE.PRODUCT(PROD_NO) ON DELETE CASCADE
)
:

CREATE UNIQUE INDEX ACMEE.P_ORDER_ITEM


ON ACMEE.ORDER_ITEM
(ORD_ITEM_NO):

CREATE INDEX ACMEE.F_ORDER_ITEM_1


ON ACMEE.ORDER_ITEM
(ORD_ITEM_ORD_NO):

CREATE INDEX ACMEE.F_ORDER_ITEM_2


ON ACMEE.ORDER_ITEM
(ORD_ITEM_PROD_NO):

--------------------------------------------------------
-- CREATE GLOBAL TEMP TABLES --
-- --
-- THESE ARE USED BY THE AFTER-INSERT TRIGGERS THAT --
-- ARE DEFINED BELOW. THE TRIGGERS INSERT THE PRIMARY --
-- KEY VALUE OF THE NEW ROW INTO THE GLOBAL TEMP --
-- TABLE TO ALLOW IT TO BE ACCESSED BY THE CALLING --
-- APP. --
-- --
--------------------------------------------------------

CREATE TABLE ACMEE.GTT_CUST_NO


(

Appendix B. Sample code, DDL, and preparation scripts 303


CUST_NO INTEGER NOT NULL
):

CREATE TABLE ACMEE.GTT_ORDER_NO


(
ORDER_NO INTEGER NOT NULL
):

--------------------------------------------------------
-- CREATE TRIGGERS --
--------------------------------------------------------

CREATE TRIGGER ACMEE.CUST_IA


AFTER INSERT
ON ACMEE.CUSTOMER
REFERENCING NEW AS NEWROW
FOR EACH ROW
MODE DB2SQL
BEGIN ATOMIC
DELETE FROM ACMEE.GTT_CUST_NO;
INSERT INTO ACMEE.GTT_CUST_NO
(CUST_NO)
VALUES (NEWROW.CUST_NO);
END:

CREATE TRIGGER ACMEE.ORD_IA


AFTER INSERT
ON ACMEE.ORDER
REFERENCING NEW AS NEWROW
FOR EACH ROW
MODE DB2SQL
BEGIN ATOMIC
DELETE FROM ACMEE.GTT_ORDER_NO;
INSERT INTO ACMEE.GTT_ORDER_NO
(ORDER_NO)
VALUES (NEWROW.ORD_NO);
END:

--------------------------------------------------------
-- POPULATE PRODUCT TABLE --
--------------------------------------------------------
INSERT INTO ACMEE.PRODUCT
(PROD_NO, PROD_DESC, PROD_PRICE, PROD_IN_STOCK)
VALUES (1,'Acme Word Processor',19.99,200):
INSERT INTO ACMEE.PRODUCT
(PROD_NO, PROD_DESC, PROD_PRICE, PROD_IN_STOCK)
VALUES (2,'Acme Speadsheet',29.99,12):

304 DB2 Java Stored Procedures: Learning by Example


INSERT INTO ACMEE.PRODUCT
(PROD_NO, PROD_DESC, PROD_PRICE, PROD_IN_STOCK)
VALUES (3,'Acme Presentation Graphics',39.99,101):
INSERT INTO ACMEE.PRODUCT
(PROD_NO, PROD_DESC, PROD_PRICE, PROD_IN_STOCK)
VALUES (4,'Acme E-Mail Client',49.99,240):
INSERT INTO ACMEE.PRODUCT
(PROD_NO, PROD_DESC, PROD_PRICE, PROD_IN_STOCK)
VALUES (5,'Acme Office Suite',59.99,12):
INSERT INTO ACMEE.PRODUCT
(PROD_NO, PROD_PRICE, PROD_IN_STOCK)
VALUES (6,69.99,678):

--------------------------------------------------------
-- POPULATE CUSTOMER --
--------------------------------------------------------

INSERT INTO ACMEE.CUSTOMER


(cust_firstname, cust_lastname, cust_address)
VALUES ('John Q.', 'Public', '111 1st St., San Jose, CA '):

--------------------------------------------------------
-- POPULATE ORDER --
--------------------------------------------------------
INSERT INTO ACMEE.ORDER
(ord_date, ord_cust_no)
VALUES (CURRENT DATE, 1):

INSERT INTO ACMEE.ORDER


(ord_date, ord_cust_no)
VALUES (CURRENT DATE - 1 DAY, 1):

--------------------------------------------------------
-- POPULATE ORDER ITEM --
--------------------------------------------------------
Insert into ACMEE.ORDER_ITEM
(ORD_ITEM_ORD_NO, ORD_ITEM_PROD_NO,ORD_ITEM_QTY)
VALUES(1,1,1):

Insert into ACMEE.ORDER_ITEM


(ORD_ITEM_ORD_NO, ORD_ITEM_PROD_NO,ORD_ITEM_QTY)
VALUES(1,2,2):

Insert into ACMEE.ORDER_ITEM


(ORD_ITEM_ORD_NO, ORD_ITEM_PROD_NO,ORD_ITEM_QTY)

Appendix B. Sample code, DDL, and preparation scripts 305


VALUES(1,3,3):

Insert into ACMEE.ORDER_ITEM


(ORD_ITEM_ORD_NO, ORD_ITEM_PROD_NO,ORD_ITEM_QTY)
VALUES(1,4,4):

Insert into ACMEE.ORDER_ITEM


(ORD_ITEM_ORD_NO, ORD_ITEM_PROD_NO,ORD_ITEM_QTY)
VALUES(1,5,5):

Insert into ACMEE.ORDER_ITEM


(ORD_ITEM_ORD_NO, ORD_ITEM_PROD_NO,ORD_ITEM_QTY)
VALUES(2,1,2):

Insert into ACMEE.ORDER_ITEM


(ORD_ITEM_ORD_NO, ORD_ITEM_PROD_NO,ORD_ITEM_QTY)
VALUES(2,2,4):

Insert into ACMEE.ORDER_ITEM


(ORD_ITEM_ORD_NO, ORD_ITEM_PROD_NO,ORD_ITEM_QTY)
VALUES(2,3,6):

Insert into ACMEE.ORDER_ITEM


(ORD_ITEM_ORD_NO, ORD_ITEM_PROD_NO,ORD_ITEM_QTY)
VALUES(2,4,8):

Insert into ACMEE.ORDER_ITEM


(ORD_ITEM_ORD_NO, ORD_ITEM_PROD_NO,ORD_ITEM_QTY)
VALUES(2,5,10):

Insert into ACMEE.ORDER_ITEM


(ORD_ITEM_ORD_NO, ORD_ITEM_PROD_NO,ORD_ITEM_QTY)
VALUES(2,6,22):
--------------------------------------------------------
-- Create Temporary Table Used For Summary Query--
--------------------------------------------------------
create table acmee.order_item_summ
(
PROD_DESC CHAR(30) ,
QTY_1_TO_5 CHAR(1) NOT NULL,
QTY_6_TO_10 CHAR(1) NOT NULL,
QTY_11_PLUS CHAR(1) NOT NULL
):

306 DB2 Java Stored Procedures: Learning by Example


B.2 Sample stored procedure definitions
The sections that follow contain the stored procedure definitions used for the
examples within this book.

B.2.1 DB2 UDB for OS/390 stored procedure definitions


The following sections contain the stored procedure definitons for the OS/390
versions of the ‘simple’ and ‘enhanced’ samples used in this book.

Note
The simple version of the samples was designed to work on DB2 UDB for
OS/390 Version 5. The stored procedure defintitions therefore take the
form of INSERT statements into the SYSIBM.SYSPROCEDURES catalog table.

The enhanced version was intended for DB2 UDB for OS/390 Version 6,
and therefore uses the new CREATE PROCEDURE statements.

B.2.1.1 Simple stored procedure defintions


The stored procedure definitions for each of the ‘simple’ samples follow.

ACMECOS
-------------------------------------------------------------
-- --
-- SYSPROCEDURES INSERT FOR SG24-5945 --
-- --
-- Package ACMECOS --
-- --
-- SQL Type: COBOL/static SQL --
-- Platform: OS/390 --
-- SQL Level: Standard --
-- --
-------------------------------------------------------------

--
-- Delete old rows if they exist
--
DELETE FROM SYSIBM.SYSPROCEDURES
WHERE PROCEDURE LIKE 'CS%';

--
-- Add_customer
--

Appendix B. Sample code, DDL, and preparation scripts 307


INSERT INTO SYSIBM.SYSPROCEDURES
(PROCEDURE,AUTHID,LUNAME,LOADMOD,LINKAGE,COLLID,
LANGUAGE,ASUTIME,STAYRESIDENT,IBMREQD,
RUNOPTS,
PARMLIST,
RESULT_SETS,WLM_ENV,PGM_TYPE, EXTERNAL_SECURITY,COMMIT_ON_RETURN)
VALUES(
'CS_ADD_CUSTOMER', '', '', 'ADDCUST', 'N', 'ACMECOS',
'COBOL', 900, '','N',
'',
'CHAR(20) IN, CHAR(20) IN, CHAR(30) IN, INTEGER OUT, CHAR(40) OUT,
CHAR(240) OUT',
0,'WLM_JAVA_DB21','S','N','N'
);

--
-- Check all OK
--
SELECT *
FROM SYSIBM.SYSPROCEDURES
WHERE PROCEDURE LIKE 'CS%';

ACMEJOS
-------------------------------------------------------------
-- --
-- SYSPROCEDURES INSERT FOR SG24-5945 --
-- --
-- Package ACMEJOS --
-- --
-- SQL Type: JDBC --
-- Platform: OS/390 --
-- SQL Level: Standard --
-- --
-------------------------------------------------------------

--
-- Delete old rows if they exist
--
DELETE FROM SYSIBM.SYSPROCEDURES
WHERE PROCEDURE LIKE 'JS%';

--
-- Add_customer
--
INSERT INTO SYSIBM.SYSPROCEDURES
(PROCEDURE,AUTHID,LUNAME,LOADMOD,LINKAGE,COLLID,

308 DB2 Java Stored Procedures: Learning by Example


LANGUAGE,ASUTIME,STAYRESIDENT,IBMREQD,
RUNOPTS,
PARMLIST,
RESULT_SETS,WLM_ENV,PGM_TYPE, EXTERNAL_SECURITY,COMMIT_ON_RETURN)
VALUES(
'JS_ADD_CUSTOMER', '', '', '', 'N', 'DSNJDBC',
'COMPJAVA', 900, '','N',
'ACMEJOS/Add_customer.add_customer',
'CHAR(20) IN, CHAR(20) IN, CHAR(30) IN, INTEGER OUT, CHAR(40) OUT,
CHAR(240) OUT',
0,'WLM_JAVA_DB21','S','N','N'
);

--
-- Check all OK
--
SELECT *
FROM SYSIBM.SYSPROCEDURES
WHERE PROCEDURE LIKE 'JS%';

ACMESOS
-------------------------------------------------------------
-- --
-- SYSPROCEDURES INSERT FOR SG24-5945 --
-- --
-- Package ACMESOS --
-- --
-- SQL Type: SQLJ --
-- Platform: OS/390 --
-- SQL Level: Standard --
-- --
-------------------------------------------------------------

--
-- Delete old rows if they exist
--
DELETE FROM SYSIBM.SYSPROCEDURES
WHERE PROCEDURE LIKE 'SS%';

--
-- Add_customer
--
INSERT INTO SYSIBM.SYSPROCEDURES
(PROCEDURE,AUTHID,LUNAME,LOADMOD,LINKAGE,COLLID,
LANGUAGE,ASUTIME,STAYRESIDENT,IBMREQD,
RUNOPTS,
PARMLIST,

Appendix B. Sample code, DDL, and preparation scripts 309


RESULT_SETS,WLM_ENV,PGM_TYPE, EXTERNAL_SECURITY,COMMIT_ON_RETURN)
VALUES(
'SS_ADD_CUSTOMER', '', '', '', 'N', 'ACMESOS',
'COMPJAVA', 900, '','N',
'ACMESOS/Add_customer.add_customer',
'CHAR(20) IN, CHAR(20) IN, CHAR(30) IN, INTEGER OUT, CHAR(40) OUT,
CHAR(240) OUT',
0,'WLM_JAVA_DB21','S','N','N'
);

--
-- Check all OK
--
SELECT *
FROM SYSIBM.SYSPROCEDURES
WHERE PROCEDURE LIKE 'SS%';

ACMEBOS
-------------------------------------------------------------
-- --
-- SYSPROCEDURES INSERT FOR SG24-5945 --
-- --
-- Package ACMEBOS --
-- --
-- SQL Type: SQLJ & JDBC Combined --
-- Platform: OS/390 --
-- SQL Level: Standard --
-- --
-------------------------------------------------------------

--
-- Delete old rows if they exist
--
DELETE FROM SYSIBM.SYSPROCEDURES
WHERE PROCEDURE LIKE 'BS%';

--
-- Add_customer
--
INSERT INTO SYSIBM.SYSPROCEDURES
(PROCEDURE,AUTHID,LUNAME,LOADMOD,LINKAGE,COLLID,
LANGUAGE,ASUTIME,STAYRESIDENT,IBMREQD,
RUNOPTS,
PARMLIST,
RESULT_SETS,WLM_ENV,PGM_TYPE, EXTERNAL_SECURITY,COMMIT_ON_RETURN)
VALUES(

310 DB2 Java Stored Procedures: Learning by Example


'BS_ADD_CUSTOMER', '', '', '', 'N', 'ACMEBOS',
'COMPJAVA', 900, '','N',
'ACMEBOS/Add_customer.add_customer',
'CHAR(20) IN, CHAR(20) IN, CHAR(30) IN, INTEGER OUT, CHAR(40) OUT,
CHAR(240) OUT',
0,'WLM_JAVA_DB21','S','N','N'
);

--
-- Check all OK
--
SELECT *
FROM SYSIBM.SYSPROCEDURES
WHERE PROCEDURE LIKE 'BS%';

B.2.1.2 Enhanced stored procedure definitons


The stored procedure definitions for each of the ‘enhanced’ samples follow.

ACMECOE
-------------------------------------------------------------
-- --
-- CREATE PROCEDURES FOR SG24-5945 --
-- --
-- Package ACMECOE --
-- --
-- SQL Type: COBOL --
-- Platform: OS/390 --
-- SQL Level: Enhanced --
-- --
-------------------------------------------------------------

--
-- Drop procedures if they exist
--
drop PROCEDURE ACMECOE.ADD_CUSTOMER RESTRICT;
drop PROCEDURE ACMECOE.ADD_ORDER RESTRICT;
drop PROCEDURE ACMECOE.ADD_CUST_ORDER RESTRICT;

--
-- Add_customer
--

CREATE PROCEDURE ACMECOE.ADD_CUSTOMER


(
IN FIRSTNAME CHAR(20),

Appendix B. Sample code, DDL, and preparation scripts 311


IN LASTNAME CHAR(20),
IN ADDRESS CHAR(30),
OUT CUSTNO INTEGER,
OUT MARK CHAR(40),
OUT MARK_ERROR_TEXT CHAR(200)
)
FENCED
MODIFIES SQL DATA
LANGUAGE COBOL
EXTERNAL NAME ADDCUST
PARAMETER STYLE DB2SQL
COLLID ACMECOE
WLM ENVIRONMENT WLMJAVADBZ2
RESULT SETS 0
PROGRAM TYPE SUB;

--
-- Add_order
--
CREATE PROCEDURE ACMECOE.ADD_ORDER
(
IN CUSTNO INTEGER,
IN NUM_ITEMS INTEGER,
IN ORDERDETS CHAR(80),
OUT ORDERNO INTEGER,
OUT MARK CHAR(40),
OUT MARK_ERROR_TEXT CHAR(200)
)
FENCED
MODIFIES SQL DATA
LANGUAGE COBOL
EXTERNAL NAME ADDORD
PARAMETER STYLE DB2SQL
COLLID ACMECOE
WLM ENVIRONMENT WLMJAVADBZ2
RESULT SETS 0
PROGRAM TYPE SUB;

--
-- Add_cust_order
--
CREATE PROCEDURE ACMECOE.ADD_CUST_ORDER
(
IN FIRSTNAME CHAR(20),
IN LASTNAME CHAR(20),
IN ADDRESS CHAR(30),
IN NUM_ITEMS INTEGER,

312 DB2 Java Stored Procedures: Learning by Example


IN ORDERDETS CHAR(100),
OUT CUSTNO INTEGER,
OUT ORDERNO INTEGER,
OUT MARK CHAR(40),
OUT MARK_ERROR_TEXT CHAR(200)
)
FENCED
MODIFIES SQL DATA
LANGUAGE COBOL
EXTERNAL NAME ADDCORD
PARAMETER STYLE DB2SQL
COLLID ACMECOE
WLM ENVIRONMENT WLMJAVADBZ2
RESULT SETS 0
PROGRAM TYPE SUB;

--
-- Check all OK
--
SELECT *
FROM SYSIBM.SYSROUTINES
WHERE SCHEMA = 'ACMECOE';

ACMEJOE
-------------------------------------------------------------
-- --
-- CREATE PROCEDURES FOR SG24-5945 --
-- --
-- Package ACMEJOE --
-- --
-- SQL Type: JDBC --
-- Platform: OS/390 --
-- SQL Level: Enhanced --
-- --
-- NOTE: Java package * class name duplicated in RUNOPTS --
-- due to current drivers ignoring EXTERNAL NAME. --
-- This should not be required in general release of --
-- the code, so RUNOPTS can be removed at that time. --
-- --
-------------------------------------------------------------

--
-- --drop procedures if they exist
--

Appendix B. Sample code, DDL, and preparation scripts 313


drop PROCEDURE ACMEJOE.ADD_CUSTOMER RESTRICT;
drop PROCEDURE ACMEJOE.ADD_ORDER RESTRICT;
drop PROCEDURE ACMEJOE.QUERY_OI_SUMM RESTRICT;

--
-- Add_customer
--

CREATE PROCEDURE ACMEJOE.ADD_CUSTOMER


(
IN FIRSTNAME CHAR(20),
IN LASTNAME CHAR(20),
IN ADDRESS CHAR(30),
OUT CUSTNO INTEGER,
OUT MARK CHAR(40),
OUT MARK_ERROR_TEXT CHAR(200)
)
FENCED
MODIFIES SQL DATA
LANGUAGE COMPJAVA
EXTERNAL NAME 'acmejoe/Add_customer.add_customer'
PARAMETER STYLE JAVA
COLLID DSNJDBC
WLM ENVIRONMENT WLMJAVADBZ2
RUN OPTIONS 'acmejoe/Add_customer.add_customer'
DYNAMIC RESULT SETS 0
PROGRAM TYPE SUB;

--
-- Add_order
--
CREATE PROCEDURE ACMEJOE.ADD_ORDER
(
IN CUSTNO INTEGER,
IN ORDERDETS CHAR(100),
OUT ORDERNO INTEGER,
OUT MARK CHAR(40),
OUT MARK_ERROR_TEXT CHAR(200)
)
FENCED
MODIFIES SQL DATA
LANGUAGE COMPJAVA
EXTERNAL NAME 'ACMEJOE/Add_order.add_order'
PARAMETER STYLE JAVA
COLLID DSNJDBC
WLM ENVIRONMENT WLMJAVADBZ2
RUN OPTIONS 'ACMEJOE/Add_order.add_order'

314 DB2 Java Stored Procedures: Learning by Example


DYNAMIC RESULT SETS 0
PROGRAM TYPE SUB;

--
-- Query Order item summary
--
CREATE PROCEDURE ACMEJOE.QUERY_OI_SUMM
(
IN IN_CUST_NO CHAR(10),
IN IN_ORDER_NO CHAR(10),
OUT MARK CHAR(40),
OUT MARK_ERROR_TEXT CHAR(200)
)
EXTERNAL NAME 'ACMEJOE/Query_oi_summ.query_oi_summ'
RESULT SETS 1
LANGUAGE COMPJAVA
PARAMETER STYLE JAVA
COLLID DSNJDBC
WLM ENVIRONMENT WLMJAVADBZ2
RUN OPTIONS 'ACMEJOE/Query_oi_summ.query_oi_summ'
FENCED
NO DBINFO
NULL CALL MODIFIES SQL DATA
PROGRAM TYPE SUB;

--
-- Check all OK
--
SELECT *
FROM SYSIBM.SYSroutines
WHERE schema = 'ACMEJOE';

ACMESOE
-------------------------------------------------------------
-- --
-- CREATE PROCEDURES FOR SG24-5945 --
-- --
-- Package ACMESOE --
-- --
-- SQL Type: SQLJ --
-- Platform: OS/390 --
-- SQL Level: Enhanced --
-- --
-- NOTE: Java package & class name duplicated in RUNOPTS --
-- due to current drivers ignoring EXTERNAL NAME. --
-- This should not be required in general release of --
-- the code, so RUNOPTS can be removed at that time. --

Appendix B. Sample code, DDL, and preparation scripts 315


-- --
-------------------------------------------------------------

--
-- Drop procedures if they exist
--
drop PROCEDURE ACMESOE.ADD_CUSTOMER RESTRICT;
drop PROCEDURE ACMESOE.ADD_ORDER RESTRICT;
drop PROCEDURE ACMESOE.QUERY_OI_SUMM RESTRICT;

--
-- Add_customer
--

CREATE PROCEDURE ACMESOE.ADD_CUSTOMER


(
IN FIRSTNAME CHAR(20),
IN LASTNAME CHAR(20),
IN ADDRESS CHAR(30),
OUT CUSTNO INTEGER,
OUT MARK CHAR(40),
OUT MARK_ERROR_TEXT CHAR(200)
)
FENCED
MODIFIES SQL DATA
LANGUAGE COMPJAVA
EXTERNAL NAME 'ACMESOE.Add_customer.add_customer'
PARAMETER STYLE JAVA
COLLID ACMESOE
WLM ENVIRONMENT WLMJAVADBZ2
RUN OPTIONS 'ACMESOE.Add_customer.add_customer'
DYNAMIC RESULT SETS 0
PROGRAM TYPE SUB;

--
-- Add_order
--
CREATE PROCEDURE ACMESOE.ADD_ORDER
(
IN CUSTNO INTEGER,
IN ORDERDETS CHAR(100),
OUT ORDERNO INTEGER,
OUT MARK CHAR(40),
OUT MARK_ERROR_TEXT CHAR(200)
)
FENCED
MODIFIES SQL DATA

316 DB2 Java Stored Procedures: Learning by Example


LANGUAGE COMPJAVA
EXTERNAL NAME 'ACMESOE.Add_order.add_order'
PARAMETER STYLE JAVA
COLLID ACMESOE
WLM ENVIRONMENT WLMJAVADBZ2
RUN OPTIONS 'ACMESOE.Add_order.add_order'
DYNAMIC RESULT SETS 0
PROGRAM TYPE SUB;

--
-- Query Order item summary
--
CREATE PROCEDURE ACMESOE.QUERY_OI_SUMM
(
IN IN_CUST_NO CHAR(10),
IN IN_ORDER_NO CHAR(10),
OUT MARK CHAR(40),
OUT MARK_ERROR_TEXT CHAR(200)
)
EXTERNAL NAME 'ACMESOE.Query_oi_summ.query_oi_summ'
RESULT SETS 1
LANGUAGE COMPJAVA
PARAMETER STYLE JAVA
COLLID ACMESOE
WLM ENVIRONMENT WLMJAVADBZ2
RUN OPTIONS 'ACMESOE.Query_oi_summ.query_oi_summ'
FENCED
NO DBINFO
NULL CALL MODIFIES SQL DATA
PROGRAM TYPE SUB;

--
-- Check all OK
--
SELECT *
FROM SYSIBM.SYSROUTINES
WHERE schema = 'ACMESOE';

B.2.2 DB2 UDB for AIX and Windows stored procedure definitions
Due to the nature of the process, the stored procedure definitions on the AIX
and Windows platforms have to be dropped and redefined as part of program
preparation (see 7.3.1, “NT / AIX JDBC program preparation process” on

Appendix B. Sample code, DDL, and preparation scripts 317


page 144 and 7.3.2, “NT / AIX SQLJ program preparation process” on page
149 for an explanation of why).

For this reason, the stored procedure definitions for these platfoms can be
found in B.5.2, “AIX program preparation scripts” on page 318 and B.5.3, “NT
program preparation scripts” on page 321.

B.3 Sample stored procedure code


The sample stored procedure code can be found in 3.5, “Sample stored
procedures — standard” on page 24 and 3.6, “Sample stored procedures —
enhanced” on page 34.

B.4 Sample client code


Some sample code for invoking the stored procedures described in this book
can be found in 3.7, “Sample Client Code” on page 45.

B.5 Sample program preparation scripts


The sections that follow provide example listings of the program prepration
scripts we developed while writing this book. For more information on how to
use them, refer to Chapter 7., “Preparing Java stored procedures” on page
119.

B.5.1 OS/390 program preparation scripts


The OS/390 program preparation scripts for JDBC and SQLJ procedures are
listed in sections 7.2.3.2, “Sample program preparation scripts” on page 126
and 7.3.1.2, “Sample program preparation scripts” on page 148.

B.5.2 AIX program preparation scripts


The UNIX platform ships with a strong scripting capability which at the
minimum is compliant to Bourne shell. The script shown here runs under
Bourne (or Korn). Another approach is to use a Makefile, which is seen in the
stored procedure examples shipped with the database. Complex applications
may want to use a Software Configuration Management product.

318 DB2 Java Stored Procedures: Learning by Example


B.5.2.1 Basic shell preparation of a JDBC stored procedure
The following demonstrates using a script to compile, JAR, and install the
JAR. If you choose not to use a JAR then you need to copy the resultant Java
classes to the function directory as performed in the shipped samples.

prep.sh
echo off
cls

if [ $1 ]
then
PKG=$1
else
PKG=ACMEJUS
fi
if [ $2 ]
then
PGM=$2
else
PGM=Add_customer
fi

JARHOME=/u/db2inst3/sqllib/function/jar
echo "setting PKG to $PKG"
echo "setting PGM to $PGM"

echo "Beginning javac"


javac ${PKG}/${PGM}.java

echo "Beginning JAR"


jar cvf ${PKG}.jar ${PKG}/*.class

echo "Updating DB2 environment"

if [ -f ${JARHOME}/${PKG}/${PKG}.jar ]
then
echo "found ${JARHOME}/${PKG}/${PKG}.jar "
db2 -tvf replace_jar.sql
else
echo "failed find of ${JARHOME}/${PKG}/${PKG}.jar "
db2 -tvf install_jar.sql
db2 -tvf define_sp_${PGM}.sql

Appendix B. Sample code, DDL, and preparation scripts 319


fi

define_sp_Add_customer.sql

--------------------------------------------------------------------------
-----
-- --
-- SQL statements to define or redefine stored procedure
--
-- --
-- Note that JAR file must exist before CREATE PROCEDURE is executed,
--
-- which is why we have put it in here rather than in the main DDL file.
--
-- --
--------------------------------------------------------------------------
-----

--
-- Connect to database
--
CONNECT TO ACMES;

--
-- Drop procedure and JAR files if they exist
--
DROP PROCEDURE ACMEJUS.Add_customer;
CALL SQLJ.REMOVE_JAR('ACMEJUS.ACMEJUS');

--
-- Define jar file to DB2
--
call sqlj.install_jar
('file:/data/db2inst7/apps/ACMEJUS/ACMEJUS.jar','ACMEJUS.ACMEJUS');

--
-- Create procedure
--
-- External name is in format ' "

CREATE PROCEDURE ACMEJUS.Add_customer


(
IN IN_CUST_FIRSTNAME CHAR(20),
IN IN_CUST_LASTNAME CHAR(20),
IN IN_CUST_ADDRESS CHAR(30),
OUT OUT_CUST_NO INT,

320 DB2 Java Stored Procedures: Learning by Example


OUT MARK CHAR(40),
OUT MARK_ERROR_TEXT CHAR(200)
)
EXTERNAL NAME 'ACMEJUS.ACMEJUS:ACMEJUS.Add_customer.add_customer'
RESULT SETS 0
LANGUAGE JAVA
PARAMETER STYLE JAVA
FENCED
NO DBINFO
NULL CALL MODIFIES SQL DATA
;

B.5.3 NT program preparation scripts


The NT platform ships with the ability to run .BAT (batch command) files,
which allows for limited scripting ability. Complex applications will want to use
a Makefile approach or a commercial Software Configuration Management
package,both of which necessitate acquiring software not shipped with
Windows NT.

B.5.3.1 Basic preparation of a JDBC stored procedure


The following shows a basic preparation routine for a simple JDBC stored
procedure. This preparation script performs no error checking. All values are
hardcoded.

The batch file prep.bat invokes DB2 UDB in a batch mode to define the stored
procedure and to install the JAR file.

Prep.bat
echo off
cls

echo Preparing ACMEJNS\Add_customer.java...


echo

echo Beginning Java compile...


javac ACMEJNS\Add_customer.java

echo Beginning JAR...


jar cvf ACMEJNS.jar ACMEJNS\Add_customer.class

echo Updating DB2 environment...


db2 -tvf define_sp.sql

echo Preparation complete!

Appendix B. Sample code, DDL, and preparation scripts 321


Define_sp.sql

--------------------------------------------------------------------------
-----
-- --
-- SQL statements to define or redefine stored procedure
--
-- --
-- Note that JAR file must exist before CREATE PROCEDURE is executed,
--
-- which is why we have put it in here rather than in the main DDL file.
--
-- --
--------------------------------------------------------------------------
-----

--
-- Connect to database
--
CONNECT TO ACMES;

--
-- Drop procedure and JAR files if they exist
--
DROP PROCEDURE ACMEJNS.Add_customer;
CALL SQLJ.REMOVE_JAR('ACMEJNS.ACMEJNS');

--
-- Define jar file to DB2
--
CALL SQLJ.INSTALL_JAR('file:S:\Kirk\Samples\Code - Stored
Procedures\JDBC\NT\acmejns\acmejns.jar','ACMEJNS.ACMEJNS');

--
-- Create procedure
--
-- External name is in format ' "

CREATE PROCEDURE ACMEJNS.Add_customer


(
IN IN_CUST_FIRSTNAME CHAR(20),
IN IN_CUST_LASTNAME CHAR(20),
IN IN_CUST_ADDRESS CHAR(30),
OUT OUT_CUST_NO INT,
OUT MARK CHAR(40),
OUT MARK_ERROR_TEXT CHAR(200)

322 DB2 Java Stored Procedures: Learning by Example


)
EXTERNAL NAME 'ACMEJNS.ACMEJNS:ACMEJNS.Add_customer.add_customer'
RESULT SETS 0
LANGUAGE JAVA
PARAMETER STYLE JAVA
FENCED
NO DBINFO
NULL CALL MODIFIES SQL DATA
;
CALL SQLJ.REFRESH_CLASSES(VOID);

B.5.3.2 SQLJ stored procedure preparation


The following shows a complex preparation script for SQLJ stored procedures
on NT.

Highlights of this script include:


• The SQLJ preparation step includes checking valid syntax against the
DBMS (by arguing the userid/password and the URL)
• The automatic JAVA compile step is turned off during the SQLJ step.
• The class files are collected into the JAR once, after everything has been
completed.
• Error checking within the batch file has been inserted where feasible.

Prep.bat

echo off
cls

echo Beginning SQLJ precompile/compile...Query_oi_summ


sqlj -user=drdares2/drdares2 -url=jdbc:db2:ACMEE -compile=false -status
ACMESNE\Query_oi_summ.sqlj
if errorlevel 1 goto error

echo Begin javac....


javac ACMESNE\Query_oi_summ.java
if errorlevel 1 goto error

echo Beginning profile customisation...


db2profc -url=jdbc:db2:ACMEE -prepoptions="package using ACMESNE"
ACMESNE\Query_oi_summ_SJProfile0

echo Beginning SQLJ precompile/compile...Add_customer

Appendix B. Sample code, DDL, and preparation scripts 323


sqlj -user=drdares2/drdares2 -url=jdbc:db2:ACMEE -compile=false -status
ACMESNE\Add_customer.sqlj
if errorlevel 1 goto error
javac ACMESNE\Add_customer.java
if errorlevel 1 goto error

echo Beginning profile customisation...


db2profc -url=jdbc:db2:ACMEE ACMESNE\Add_customer_SJProfile0

if errorlevel 1 goto error

echo Beginning JAR...


jar cvf ACMESNE.jar ACMESNE\Defi*.class ACMESNE\Qu*.class ACMESNE\Qu*.ser
ACMESNE\Add_c*.ser ACMESNE\Add_c*.class

if errorlevel 1 goto error

echo Updating DB2 environment...


db2 -tvf define_acmesne.sql

if errorlevel 1 goto error

echo Preparation complete!

goto exit

:error

echo Problem encountered!!!

:exit

define_acmesne.sql

--------------------------------------------------------------------------
-----
-- --
-- SQL statements to define or redefine stored procedure
--
-- --
-- Note that JAR file must exist before CREATE PROCEDURE is executed,
--
-- which is why we have put it in here rather than in the main DDL file.
--
-- --

324 DB2 Java Stored Procedures: Learning by Example


--------------------------------------------------------------------------
-----

--
-- Connect to database
--
CONNECT TO ACMEE ;

drop PROCEDURE ACMESNE.Query_oi_summ ;

drop PROCEDURE ACMESNE.Add_customer;

CALL SQLJ.remove_JAR('ACMESNE.ACMESNE');
CALL SQLJ.install_JAR('file:s:\Kirk\Samples\Code - Stored
Procedures\SQLJ\NT\Acmesne\ACMESNE.jar','ACMESNE.ACMESNE');

CREATE PROCEDURE ACMESNE.Query_oi_summ


(
IN IN_CUST_NO CHAR(10),
IN IN_ORDER_NO CHAR(10),
OUT MARK CHAR(40),
OUT MARK_ERROR_TEXT CHAR(200)
)
EXTERNAL NAME 'ACMESNE.ACMESNE:ACMESNE.Query_oi_summ.query_oi_summ'
RESULT SETS 1
LANGUAGE JAVA
PARAMETER STYLE JAVA
FENCED
NO DBINFO
NULL CALL MODIFIES SQL DATA
;

CREATE PROCEDURE ACMESNE.Add_customer


(
IN IN_CUST_FIRSTNAME CHAR(20),
IN IN_CUST_LASTNAME CHAR(20),
IN IN_CUST_ADDRESS CHAR(30),
OUT OUT_CUST_NO INT,
OUT MARK CHAR(40),
OUT MARK_ERROR_TEXT CHAR(200)
)
EXTERNAL NAME 'ACMESNE.ACMESNE:ACMESNE.Add_customer.add_customer'
RESULT SETS 0
LANGUAGE JAVA
PARAMETER STYLE JAVA

Appendix B. Sample code, DDL, and preparation scripts 325


FENCED
NO DBINFO
NULL CALL MODIFIES SQL DATA
;

call sqlj.refresh_classes(void);

B.5.3.3 SQLJ stored procedure preparation - parameter driven


Included here is parameter-driven preparation batch file for SQLJ stored
procedures on NT. This might be useful for programmers planning to build
one generic script to be applied to many stored procedures.

Prep.bat
echo off
REM
REM GENERIC SQLJ PREP ROUTINE
REM
REM File <package>.sql must exist, containing necessary CREATE PROCEDURE
REM and REFRESH_JAR commands
rem
rem Example call: prep Add_customer ACMEBNS ACMEBNS ACMES ACMES DEFINE

cls

echo.
echo SQLJ Prog Prep script
echo.
echo Input parms:
echo Class name = %1
echo Java Package\subdirectory name = %2
echo DB2 Package name = %3
echo Database name = %4
echo Table qualifier = %5
echo Action = %6
echo.

REM Check Valid Action


if %6 == DEFINE goto cont1
if %6 == REFRESH goto cont2
echo Error: Action must be DEFINE or REFRESH.

goto error

:cont1

326 DB2 Java Stored Procedures: Learning by Example


REM Check SQL define file exists
if exist define_%2.sql goto cont3

echo Error: file define_%2.sql not found....


echo File must exist, and contain the necessary SQL CREATE PROCEDURE and
echo REFRESH_JAR commands...
echo.
goto error

:cont2
REM Check SQL refresh file exists
if exist refresh_%2.sql goto cont3

echo Error: file refresh_%2.sql not found....


echo File must exist, and contain the necessary REPLACE_JAR commands...
echo.
goto error

:cont3
echo Preparing %2\%1...
echo.

echo Beginning SQLJ precompile/compile...

set CLASSPATH=.\%2;%CLASSPATH%
echo start sqlj compile
sqlj -compile=false %2\%1.sqlj
if errorlevel 1 goto error
echo start javac compile
javac %2\%1.java

if errorlevel 1 goto error

echo Beginning profile customisation...


db2profc -prepoptions="qualifier %5 package using %3" -url=jdbc:db2:%4
%2\%1_SJProfile0

if errorlevel 1 goto error

echo Beginning JAR...


jar cvf %2.jar %2\*.class %2\*.ser

if errorlevel 1 goto exit

echo Updating DB2 environment...


if %6 == DEFINE db2 -tvf define_%2.sql
if %6 == REFRESH db2 -tvf refresh_%2.sql

Appendix B. Sample code, DDL, and preparation scripts 327


echo Preparation complete!

goto exit

:error

echo Problem encountered!!!

:exit

328 DB2 Java Stored Procedures: Learning by Example


Appendix C. OS/390 Recoverable Resource Services (RRS)

OS/390 Recoverable Resource Services (RRS) is a feature of MVS that


coordinates two-phase commit processing of recoverable resources in an
MVS system. DB2 supports use of these services for DB2 applications that
use the RRS attachment facility provided with DB2. Use the RRS attachment
to access resources such as SQL tables, DL/I databases, MQSeries
messages, and recoverable VSAM files within a single transaction scope. If
your system does not have RRS running see the chapter “Implementing
OS/390 Resources Recovery Services (RRS)” in Getting Started with DB2
Stored Procedures , SG24-4693.

C.1 RRS attachment


The RRS attachment is required for stored procedures that run in a
WLM-established address space. The user ID associated with that address
space must be authorized to run the Recoverable Resource Manager
Services Attachment Facility (RRSAF) and is associated with the
ssnm.RRSAF profile. Control access to the DB2 subsystem through RRSAF
by performing the following steps:
1. If you have not already established a profile for controlling access from the
RRS, you need to define ssnm.RRSAF in the DSNR resource class with a
universal access authority of NONE.
2. Activate the resource class
“ SETROPTS RACLIST(DSNR) REFRESH”
3. Add user IDs that are associated with the stored procedures address
spaces to the RACF started procedures table:
DC CL8’DB21JAVA’ WLM-established stored procedure address space.
DC CL8’DB2STC’ USERID
DC CL8’DB2SYS’ GROUP NAME
DC X’00’ NO PRIVILEGED ATTRIBUTE
DC XL7’00’ RESERVED BYTES

Stored procedures address space entries are required in the RACF started
procedures table. The associated RACF user ID and group name do not need
to match those used for the DB2 address spaces, but they must be authorized
to run the call attachment facility (for the DB2-established stored procedure
address space) or RRSAF (for WLM-established stored procedure address
spaces).

© Copyright IBM Corp. 2000 329


Changing the RACF started-procedures table: To change the RACF
started-procedures table (ICHRIN03), change, reassemble, and link edit the
resulting object code to MVS.

330 DB2 Java Stored Procedures: Learning by Example


Appendix D. Define WLM stored procedure address space

OS/390 workload management provides a solution for managing workload


distribution, workload balancing, and distributing resources to competing
workloads. OS/390 workload management is the combined cooperation of
various subsystems (CICS, IMS/ESA, JES, APPC, TSO/E, OS/390 UNIX
System Services, DDF, DB2, SOM, LSFM, and Internet Connection Server)
with the OS/390 workload management (WLM) component. To workload
management, work is a demand for service, such as a batch job, an APPC,
CICS, DB2, or IMS transaction, a TSO/E logon, a TSO/E command, or a SOM
request. All work running the installation is divided into workloads.

D.1 Enable stored procedure support


Follow these steps if you already installed DB2 but did not enable
WLM-establish application environment stored procedure processing.

D.1.1 Step 1. Run the installation CLIST in INSTALL or MIGRATE mode.


• On panel DSNTIPA1, specify the input member that contains field values
for your current installation. In the remaining installation panels, leave the
existing values, except in the following cases:
• On panel DSNTIPT, choose a different name for TEMP CLIST LIBRARY
and SAMPLE LIBRARY to avoid overwriting your original libraries.
• On panel DSNTIPG, specify a data set name for LE/370 RUN TIME
LIBRARY data set names for PL/I for MVS & VM (you need PL/I for MVS
and VM to run the PL/I stored procedures sample applications)
• On panel DSNTIPX, fill in all fields for the type of stored procedure
environment you will use.
Note
WLM-established stored procedure address spaces are required if you
wish to write Java stored procedures. You cannot run Java stored
procedures in a DB2 established stored procedure address space.

• Member DSNTIJMV of data set DSN610.SDSNSAMP contains sample


JCL procedures for starting WLM-established address spaces. This will
have to be modified for the JAVA support.
• Define WLM application environments for groups of JAVA stored
procedures and associate a JCL start-up procedure with each application
environment.

© Copyright IBM Corp. 2000 331


D.1.2 Step 2. Edit DSNTIJUZ
• Edit job DSNTIJUZ to add or change values of the stored procedure
parameters: STORMXAB, STORPROC, and STORTIME
• Run DSNTIJUZ to assemble and link-edit the subsystem parameter
module.
• Restart DB2 with the new parameters.

For WLM-established stored procedures.


• Define JCL procedures for the stored procedures address spaces.
• Member DSNTIJMV of data set DSN610.SDSNSAMP contains sample
JCL procedures for starting.WLM-established address spaces.
• Define WLM application environments for groups of stored procedures and
associate a JCL startup procedure with each application environment.
• You can also use the variable &IWMSSNM for the DB2SSN parameter
( DB2SSN=&IWMSSNM). This variable represents the name of the subsystem for
which you are starting this address space. This variable is useful for using
the same JCL procedure for multiple DB2 subsystems, such as a data
sharing group. WLM will substitute the correct subsystem member attach
name when starting the address spaces for each member of the group.
1. Specify the WLM application environment name for the
WLM_ENVIRONMENT option on CREATE or ALTER PROCEDURE (or
FUNCTION) to associate a stored procedure (or user-defined function)
with an application environment.
2. Using the install utility in the WLM application, install the WLM service
definition that contains information about this application environment into
the couple data set.
3. Activate a WLM policy from the installed service definition.
4. Begin running stored procedures.

D.2 How to use the WLM ISPF application


Once you have made some decisions on at least one service policy and your
classification rules, you are ready to start using the WLM ISPF application.
Your service policies and classification rules make up a service definition. You
can store a service definition in the following kinds of data sets:
• WLM couple data set

332 DB2 Java Stored Procedures: Learning by Example


In order for all systems in a sysplex to process with an active service
policy, they must all be able to access a service policy. They all access the
policy from a WLM couple data set. To use workload management, you
must allocate a WLM couple data set, define it to the sysplex, and install
your service definition onto it. You can allocate the WLM couple data set
from the application.
Only one service definition can be installed on the WLM couple data set.
• MVS partitioned data set (PDS)
You do not need to preallocate the data sets. You specify a data set name,
and the application allocates it for you. You can save one service definition
per MVS PDS.

Note
If you use customized data sets in your installation, or if you use DFSMS,
you can use WLM application exits IWMAREX1 and IWMAREX2 to specify those
changes. The data set userid.WLM.SAVExx (where userid is the TSO ID
running the application and xx is some numeric value such as SAVE01) is
allocated by the WLM application for recovery and is deleted by WLM upon
exiting the application. This naming convention should therefore not be
used for a new service definition.

D.3 Starting the WLM application


The WLM application is shipped in the internal programming control facility
(IPCS) library. When you start the application, the system needs to
concatenate the WLM/IPCS data sets, allocate some data sets, and then
invoke the WLM panels.

To start the application, specify:


TSO ex ‘SYS1.SBLSCLI0(IWMARIN0)’

Or, issue the following command:


TSO WLM

If you have different data set conventions for your IPCS data sets, or if you
use storage managed data sets, you should use the WLM application exits
IWMAREX1 and IWMAREX2.

Within a workload, you group work with similar performance characteristics


into service classes; for example:

Appendix D. Define WLM stored procedure address space 333


• Performance goals
• Resource requirements
• Business importance to the installation

Because some work may have variable resource requirements, you can
define multiple periods for a service class. Periods are a way of defining
different goals for work depending on the amount of resources the work
consumes. Typically, periods are used to give shorter transactions more
aggressive goals and to give longer running work of the same type less
aggressive goals. If you have multiple periods, each period except the last
has a duration. Duration is the amount of resources, in service units, that the
work consumes before it is switched to the goals of the next period.

You can also group work into a service class based on resource
requirements. If you have a group of batch work that can consume vast
amounts of resources, and you want to limit it, you can define a service class
and assign it to a resource group with a maximum amount of capacity. If the
work exceeds that capacity, workload management slows the execution rate.
Also, if a certain group of work needs a minimum amount of processor
capacity, you can set up a service class and assign it to a resource group.

Classification rules are the rules workload management uses to associate a


performance goal and/or a resource group with work by associating incoming
work with a service class. Optionally, classification rules can also associate
incoming work with a report class, similar to a report performance group.
Classification rules work in much the same way as the IEAICSxx PARMLIB
member in compatibility mode (except that classification rules are more
flexible).

The classification rules for a subsystem are specified in terms of transaction


qualifiers such as job name or transaction class. These qualifiers identify
groups of transactions that should have the same performance goals and
importance. The attributes of incoming work are compared to these qualifiers
and, if there is a match, the rule is used to assign a service class to the work.
A subsystem can also have a default class for work that does not match any
of the rules.

D.4 Control of stored procedures in a WLM environment


Programs can be grouped together and isolated in different WLM
environments based on application security requirements. For example,
payroll applications might be isolated in one WLM environment, because they
contain sensitive data, such as employee salaries. To prevent users from

334 DB2 Java Stored Procedures: Learning by Example


creating a stored procedure in a sensitive WLM environment, DB2 invokes
RACF to determine if the user is allowed to create stored procedures in the
specified WLM environment.

The WLM ENVIRONMENT keyword on the CREATE PROCEDURE statement (for Version
6) or the WLM_ENV column of SYSIBM.SYSPROCEDURES for Version 5) identifies the
WLM environment to use for running a given stored procedure. Attempts to
create a procedure fail if the user is not properly authorized.

DB2 performs a resource authorization check using the DSNR RACF class as
follows:
• In a DB2 data sharing environment, DB2 uses the RACF resource name:
“ db2_groupname.WLMENV.wlm_environment”.
• In a non-data sharing environment, DB2 checks the RACF resource name:
“ db2_subsytem_id.WLMENV.wlm_environment”.

The RACF RDEFINE command can be used to create RACF profiles that
prevent users from creating stored procedures and user-defined functions in
sensitive WLM environments. For example, you can prevent all users on DB2
subsystem DB2A (non-data sharing) from creating a stored procedure or
user-defined function in the WLM environment named PAYROLL:
RDEFINE DSNR (DB2A.WLMENV.PAYROLL) UACC(NONE)

The RACF PERMIT command authorizes a user to create a stored procedure


or user-defined function in a WLM environment. For example, you can
authorize a DB2 user (DB2USER1) to create stored procedures on DB2
subsystem DB2A (non-data sharing) in the WLM environment named
WLMENV1.
PERMIT DB2A.WLMENV.WLMENV1 CLASS(DSNR) ID(DB2USER1) ACCESS(READ)

You must define a RACF user IDs for DB2 stored procedure started tasks —
as mention in the RRS section. You must associate each of these address
spaces with a RACF user ID. Each of them can also be assigned a RACF
group name.

D.5 Defining the application environment


You will need to define your Java application environment to WLM. This is
done with the WLM ISPF panels. It is recommended that you keep your Java
stored procedures in at least one separate application environment from your
other language stored procedures. This is because of the size of the Java
package. But before you do that you should see what policy you are running

Appendix D. Define WLM stored procedure address space 335


with the MVS command “d wlm”. This will give you the active service policy
and the related service definition name.

D WLM
HQX1900------------------ SDSF PRIMARY OPTION MENU -- COMMAND ISSUED
COMMAND INPUT ===> /d wlm SCROLL ===> PAGE
RESPONSE=SC53
IWM025I 12.00.02 WLM DISPLAY 790
ACTIVE WORKLOAD MANAGEMENT SERVICE POLICY NAME: SPSTPC
ACTIVATED: 2000/03/10 AT: 11:42:37 BY: DB2RES3 FROM: SC61
DESCRIPTION: serv pol for db2 stor proc resid
RELATED SERVICE DEFINITION NAME: DB2JODBA
INSTALLED: 2000/03/10 AT: 11:41:49 BY: DB2RES3 FROM: SC61
WLM VERSION LEVEL: LEVEL008

To set up your application environment definition, start up the WLM ISPF


panels with TSO command WLM. Follow these steps to define a new
application environment for your Java stored procedure.
1. Select option 2; Extract definition from WLM couple data set, from the
Choose Service Definition Panel.
2. Select option 9; Application Environments, from the Definition Menu Panel.
3. Select option 1; create in the Action column from the Application
Environment Selection List Panel.
4. PF3 to get back to the Definition Menu Panel.
5. Move the cursor to Utilities; on top of this panel, select option: 1. Install
definition and press Enter.
6. Move the cursor to Utilities; on top of this panel, select option: 3. Activate
service policy, and press Enter.
7. Select Policy to activate and press Enter.

Here is a sample WLM Application Environment Definition:


Appl Environment Name . . WLMJAVADB21
Description . . . . . . . Java application for DB21
Subsystem type . . . . . DB2
Procedure name . . . . . DB21JAVA
Start parameters . . . . APPLENV=CC51WLM1,NUMTCB=20,DB2SSN=&IWMSSNM
Limit on starting server address spaces for a subsystem instance
1 1. No limit

336 DB2 Java Stored Procedures: Learning by Example


2. Single address space per system
3. Single address space per sysplex

Verify that you have a DB2 workload defined, service class for DDF, and
classification rules defined to WLM for your Java stored procedure workload.
For additional information on setting up your WLM environment see the
chapter “WLM-Established Stored Procedures Address Spaces” in Getting
Started with DB2 Stored Procedures: Give Them a Call through the Network ,
SG24-4693. For a complete explanation of how to use and set up the OS/390
WLM, refer to OS/390 MVS Workload Management Services, GC28-1773.

To define an application environment specify the subsystem type under which


the applications are running. In this case, DB2 should be your subsystem
type

You can define whether requests can execute in multiple server address
spaces and on multiple systems, or single address space per system or
sysplex. If you wish workload management to automatically manage the
number of servers in goal mode, set the field for “Limit on starting server
address spaces for a subsystem instance” to 1, no limit.

In the PROCEDURE NAME field put the name of the JCL procedure you want
started. This JCL procedure member must reside in an accessible PROCLIB
library.

Any required start parameters can be passed by WLM. You can, for example,
pass as a parameter the number of TCBs that should be available in the
address space and the application environment name to use.

D.6 Refreshing the environment for stored procedures


If WLM is operating in goal mode, use the following MVS command to refresh
the Language Environment when you need to load a new version of a stored
procedure:
VARY WLM,APPLENV=name,REFRESH

In this command, name is the name of a WLM application environment


associated with a group of stored procedures. This means that when you
execute this command, you affect all stored procedures associated with the
application environment.

To stop all stored procedures address spaces associated with the WLM
application environment name, use the MVS command:

Appendix D. Define WLM stored procedure address space 337


VARY WLM,APPLENV=name,QUIESCE

To start all stored procedures address spaces associated with the WLM
application environment name, use the MVS command:
VARY WLM,APPLENV=name,RESUME

You also need to use the VARY WLM command with the RESUME option when
WLM puts an application environment in the unavailable state.

An application environment in which stored procedures run becomes


unavailable when WLM detects five abnormal terminations within 10 minutes.
When an application environment is in the unavailable state, WLM does not
schedule stored procedures for execution in it.

If WLM is operating in compatibility mode use the MVS command:


CANCEL “WLM address space name”

D.7 Using WLM application environments in compatibility mode


Using application environments in compatibility mode involves “manually”
managing the server address spaces for each application environment. To
accomplish this, the installation must:
• Know the proper number of address spaces to start for each application
environment.
• Manually start the server address spaces.
• Manually terminate server address spaces that are no longer needed.
• Monitor the server address space delay information to ensure the right
number of server address spaces are used.

The above tasks can be done by using the operator START and CANCEL
commands, or by using an automated operations facility like System
Automation for OS/390.

The VARY WLM,APPLENV command can be issued from a system that is in either
compatibility or goal mode, and the command takes effect for all systems in
the sysplex. However, the VARY WLM,APPLENV command has no effect on
application environment server address spaces started on a compatibility
mode system. This means that if you issue the quiesce or refresh options of
the VARY WLM,APPLENV command on a sysplex where some systems are running
in compatibility mode, the application environment state remains in the
QUIESCING or REFRESHING state until all servers for the application
environment on the compatibility mode systems are manually terminated.

338 DB2 Java Stored Procedures: Learning by Example


D.8 Using WLM application environments in goal mode
In goal mode, application environments can be manually controlled by the
installation or automatically controlled by workload management. All of the
applications in an application environment are supported by a single JCL
startup procedure. Defining the name of this startup JCL procedure to
workload management indicates that workload management should control
the server address spaces. This is called “automatic” control. If you omit the
name of the JCL procedure in the application environment definition, then
“manual” control is in effect.

Under “manual” control, the installation must create and delete, as needed,
the server address spaces for each application environment. Note that the
VARY WLM,APPLENV command can be used to terminate manually started server
address spaces (through the quiesce or refresh options), but it will not restart
them.

Under “automatic” control, workload management creates server address


spaces as started tasks using the JCL procedure specified in the application
environment definitions. The startup parameters may be contained in either
the JCL procedure defined for each application environment or in the
application environment definition. When the server address spaces are no
longer needed, workload management deletes them.

Under “automatic” control, the quantity of server address spaces is totally


controlled by workload management. If an operator or automation starts or
cancels the server address spaces under “automatic” control, workload
management will:
• Use servers not started by workload management as if they were started
by workload management.
• Terminate servers not started by workload management if they are not
needed.
• Replace a server address space that was unexpectedly cancelled.

Warning
You should use the VARY WLM,APPLENV command to manage application
environment servers rather than the CANCEL command. If there are more
than five server cancellations in 10 minutes, workload management stops
creating new servers for the application environment.

Appendix D. Define WLM stored procedure address space 339


Commands that can be used to perform actions on an application
environment:

An application environment initially enters the AVAILABLE state when the


service policy that contains its definition is activated.

AVAILABLE means the application environment is available for use, and


servers are allowed to be started for it. There are three options on the VARY
command that you can use to change the state of an application environment
after it has been made available:
• VARY WLM,APPLENV=xxxx,QUIESCE
The quiesce option causes workload management to request the
termination of server address spaces for the application environment upon
completion of any active requests. Additional work requests are not
handled by the servers, although work requests can continue to be
queued, waiting for a server. If you do not want work queued, use
subsystem functions to stop the queueing.
You can issue a quiesce action for an application environment that is in the
AVAILABLE state. When a quiesce action is issued for an application
environment, it first enters the QUIESCING state until all servers have
been requested to terminate. It then enters the QUIESCED state.
• VARY WLM,APPLENV=xxxx,RESUME
The resume option restarts an application environment that was previously
quiesced and is in the QUIESCED state. It indicates to workload
management that server address spaces can once again be started for
this application environment. The new servers process any queued
requests and all new requests. When a resume action is issued for an
application environment, it first enters the RESUMING state until all
systems in the sysplex have accepted the action. It then enters the
AVAILABLE state.
• VARY WLM,APPLENV=xxxx,REFRESH
The refresh option requests the termination of existing server address
spaces and starts new ones in their place. Existing servers finish their
current work requests and end. The new servers process any queued
requests and all new requests. You can issue a refresh action for an
application environment that is in the AVAILABLE state. When a refresh
action is issued for an application environment, it first enters the
REFRESHING state until all servers have been requested to terminate. It
then enters the AVAILABLE state.

340 DB2 Java Stored Procedures: Learning by Example


D.9 Restricting access
Following is an example of restricting access to application environment
servers. In this example, the installation has the following situation:
MVS JCL procedures for DB2 stored procedure servers are: PAY1, PAY2,
PER1, PER2. These are the JCL procedures that workload management
uses to start the DB2 servers that handle stored procedure calls.
DB2 subsystem names are: DB2A and DB2B. These are the subsystem
names used when the DB2 subsystem connects to workload
management.

In this example, the installation performs the following actions:


• Activates the STARTED and SERVER classes (if not already done):
SETR CLASSACT(STARTED) RACLIST(STARTED) GENERIC(STARTED)
SETR CLASSACT(SERVER) RACLIST(SERVER) GENERIC(SERVER)
• Establishes an arbitrary USERID to use in a subsequent RDEFINE
command to tie an MVS procedure name to a server:
ADDUSER DB2SERV
• Associates the USERID with the started task name:
RDEFINE STARTED PAY*.* STDATA(USER(DB2SERV) GROUP(SYS1))
RDEFINE STARTED PER*.* STDATA(USER(DB2SERV) GROUP(SYS1))
• Defines server profiles in the form: subsys_type.subsys_name.applenv
where, subsys_type is the subsystem type, as specified in the service
definition osubsys_name is the instance name of the subsystem
associated with this server. The subsystem uses this name when
establishing itself as the work manager for application environment server
requests. APPLENV is the application environment name, as specified in
the service definition:
RDEFINE SERVER DB2.DB2A.* UACC(NONE)
RDEFINE SERVER DB2.DB2B.* UACC(NONE)
• Permits the USERID to the servers. This completes the association
between the MVS procedure names and the servers:
PERMIT DB2.DB2A.* CLASS(SERVER) ID(DB2SERV) ACCESS(READ)
PERMIT DB2.DB2B.* CLASS(SERVER) ID(DB2SERV) ACCESS(READ)
• Refreshes the classes to refresh the RACF data base and make these
changes go into effect:
SETR RACLIST(STARTED) REFRESH
SETR RACLIST(SERVER) REFRESH

Appendix D. Define WLM stored procedure address space 341


D.10 Summary of service definition / service policy concepts
When you set up your service definition, you identify the workloads, resource
groups, service classes, service class periods, and goals based on your
performance objectives. Then you define classification rules and one or more
service policies. This information makes up the base service definition.

A two-step process is required before the sysplex starts using a new service
definition.
1. You install the service definition onto the WLM couple data set.
2. You activate one of the service policies from the definition.

With a service policy, you can override specific goals or resource groups in
your base service definition. In a typical scenario, you might define a base
service definition that is appropriate for your normal business hours.

Because you need to have at least one service policy defined, you might
create an empty service policy called NORMAL. While the NORMAL service
policy is in effect, there would be no overrides to the goals or resource groups
in the base service definition. If you have a special business need to change
your goals for off shift processing, you might then also create a service policy
called OFFSHIFT. If you were to activate this policy at the end of the business
day (either by invoking the VARY WLM,POLICY=policyname command or by
using the “Activating a Service Policy” panel in the ISPF application), then the
goal overrides in the OFFSHIFT service policy would be in effect until you
switched back to NORMAL the next morning.

Overrides
You can override only goals, number of periods, and resource group
assignments and values. All of the workloads, service class names,
classification rules, scheduling environments, and application
environments defined in the service definition remain the same for any
policy. If you need to change any of these, you will need to change the base
service definition, re-install the service definition, and then activate a policy
from that changed service definition.

342 DB2 Java Stored Procedures: Learning by Example


Policy Definition
You need to define all of your policies at the outset, while you are defining
the rest of the service definition. Once the service definition is installed,
then you can switch from one defined policy to another. If you need to
create a new policy or change the overrides in an existing policy, you will
need to re-install the service definition with the new or changed policy
definition before you can activate the new policy

Watch out for work defaulting to SYSOTHER . Work in subsystems that use
enclaves (DB2 is one) can suffer performance degradation if left unclassified
in the service definition. If you do not add classification rules for this work in
your service definition, then when you switch to goal mode, that work will be
assigned to the SYSOTHER service class, which has a discretionary goal.

Using the WLM application, you need to add classification rules to assign the
work to service classes with appropriate response time or velocity goals. As a
general rule, it’s a good idea to keep an eye on the SYSOTHER service class
through RMF or another monitor. Any service accumulating in the
SYSOTHER service class is a signal that you have unclassified work in your
system.

Workload management can dynamically manage the number of batch initiator


address spaces is a JES2 environment. You can selectively turn over control
of the batch initiator management to WLM for one or more job classes. WLM
will start new initiators, as needed, to meet the performance goals of this
work.

By specifying or defaulting MODE=JES on the JES2 JOBCLASS initiator


start, you indicate that the initiators for the job class should be JES-managed,
as in the past. By specifying MODE=JES, you keep the job class in
JES-managed mode. (JES will manage the batch initiators for that job class,
in the same way it has in prior releases.) By specifying MODE=WLM, you put
that class into WLM-managed mode. You can switch as many job classes to
WLM-managed mode as you wish. You can easily switch any job class back
to JES-managed mode by using the $TJOBCLASS JES2 command.

A service definition contains all of the information necessary for workload


management processing. Enter your service definition into the ISPF
administrative application. The service definition is the way to express your
installation’s business goals to your sysplex. In order to do this, you must
understand your installation’s business environment.

Appendix D. Define WLM stored procedure address space 343


D.11 Recommendations for full implementation of OS/390 WLM
If your installation is managing CICS, IMS, or DDF transactions according to
MVS WLM response time goals, and if you are set up to use
WLM-established stored procedures address spaces, use the following
service classes for velocity:

The default SYSSTC service class for:


• VTAM address space
• IRLM address space (IRLMPROC)

Note: The VTAM address space and the IRLM address space must always
have a higher dispatching priority than all of the DBMS address spaces, their
attached address spaces, and their subordinate address spaces. Do not allow
WLM to reduce the priority of VTAM or IRLM to or below that of the other
DBMS address spaces.

A high velocity goal for a service class whose name you define, such as
PRODREGN, for the following:
• DB2 (all address spaces including WLM-established stored procedures,
except for the DB2-established stored procedures address space)
• CICS (all region types)
• IMS (all region types except BMPs)

The velocity goals for WLM-established stored procedures, CICS and IMS
regions are only important during startup or restart. After transactions begin
running, WLM ignores the WLM-established stored procedures, CICS or IMS
velocity goals and assigns priorities based on the goals of the transactions or
packages that are running in the regions. A high velocity goal is good for
ensuring that startups and restarts are performed as quickly as possible. If a
CICS or IMS transaction calls a DB2 stored procedure, WLM will assign
priorities base on goals of the package running in the WLM-established
address space.

Similarly, when you set response time goals for DDF threads or for stored
procedures in a WLM-established address space, the only work controlled by
the DDF or stored procedure velocity goals are the DB2 service tasks (work
performed for DB2 that cannot be attributed to a single user). The user work
runs under separate goals for the enclave.

For the DB2-established stored procedures address space, use a velocity


goal that reflects the requirements of your distributed work. Depending on

344 DB2 Java Stored Procedures: Learning by Example


what type of distributed work you do, this might be equal to or lower than the
goal for PRODREGN. IMS BMPs can be treated along with other batch jobs,
or can be given a velocity goal, depending on what business and functional
requirements you have at your site.

D.12 Considerations for compatibility mode


In compatibility mode, threads are given a service class by the classification
rules in the active WLM service policy. The MVS ICS maps service classes
SRVCLASS) to a performance group number (PGN), which determines the
performance group of the enclave. When workload manager operates in
compatibility mode, take the following actions to establish performance
objectives for DDF threads:
1. Define MVS performance groups (PGNs) for DDF threads in the IPS
PARMLIB member. Do the same for WLM-established stored procedures
address spaces if you are using them.
2. Create MVS ICS PARMLIB definitions to map the service classes
assigned in the workload manager classification rules to the
corresponding performance groups, using SUBSYS=DDF and the
SRVCLASS keyword. The subsystem default performance group for
SUBSYS=DDF is ignored.
3. Create MVS PARMLIB definitions to assign a performance group to the
WLM-established stored procedures address spaces if you are using
them. The same performance group can be assigned to these stored
procedures address spaces as is assigned to DDF.
4. Activate the updated PARMLIB members (SET IPS=xx, ICS=yy). Each of
the PGN values in the MVS ICS must be defined in the IPS PARMLIB
member. The PGN definition can include information on the performance
period, which is used by SRM to change the performance objective of a
DDF thread based on the amount of processor resource the DDF thread
consumes.

D.13 Considerations for goal mode


In goal mode, threads are assigned a service class by the classification rules
in the active WLM service policy. Each service class period has a
performance objective (goal), and workload manager raises or lowers that
period’s access to system resources as needed to meet the specified goal.

For example, the goal might be “application APPL8 should run in less than 3
seconds of elapsed time 90% of the time.” Assign the DDF address space

Appendix D. Define WLM stored procedure address space 345


and any WLM-established address spaces for stored procedures and
user-defined functions to the same service class as the DB2 database
services address space (ssnmDBM1). Define this service class with a
velocity goal.

You can control which address spaces can be WLM-established server


address spaces that run stored procedures. To do this, use the server
resource class, which WLM uses to identify valid address spaces to which
work can be sent. If the server class is not defined or activated, then any
address space is allowed to connect to WLM as a server address space and
to identify itself as a server address space that runs stored procedures.To use
the server resource class, perform the following steps:
1. Run a version of RACF in which the resource class SERVER is included
as part of the predefined resource classes (RACF Version 2 Release 2
and subsequent releases).
2. Define a RACF profile for resource class SERVER: RDEFINE SERVER
(DB2.ssnm.applenv) where APPLENV is the name of the application
environment associated with the stored procedure.
3. Activate the SERVER resource class: SETROPTS RACLIST(SERVER)
REFRESH
4. Permit read access to the server resource name to the user IDs
associated with the stored procedures address space.
PERMIT DB2.DB2T.TESTPROC CLASS(SERVER) ID(SYSDSP) ACCESS(READ)
PERMIT DB2.DB2P.PAYROLL CLASS(SERVER) ID(SYSDSP) ACCESS(READ)
PERMIT DB2.DB2P.QUERY CLASS(SERVER) ID(SYSDSP) ACCESS(READ)

You can find additional information in the chapter “WLM_Established Stored


Procedures” in Getting Started with DB2 Stored Procedures, SG24-4693.

346 DB2 Java Stored Procedures: Learning by Example


Appendix E. Using the additional material

This redbook also contains additional material in CD-ROM format, and/or


Web material. See the appropriate section below for instructions on using or
downloading each type of material.

E.1 Using the CD-ROM


The CD-ROM that accompanies this redbook contains all of the sample files
referenced within the book.

Table 50 on page 348 shows the directory structure used for the samples.

Most of the directories include a readme.txt file, which contains a detailed


description of the samples contained within that directory.

© Copyright IBM Corp. 2000 347


Sample client code

Sample stored procedure code

S390 sample utilities

Sample SQL code


Figure 50. Sample files — directory structure

E.1.1 Sample client code


These files can be found in directory \Samples\Code_Clients

\Samples\Code_Clients\readme_clients.txt

E.1.1.1 OS/390 sample client code


These files can be found in directory \Samples\Code_Clients\OS390
\Samples\Code_Clients\OS390\cscallac.txt
\Samples\Code_Clients\OS390\jecall_Query_oi_summ.java
\Samples\Code_Clients\OS390\jscall_Add_customer.java
\Samples\Code_Clients\OS390\readme.txt

348 DB2 Java Stored Procedures: Learning by Example


\Samples\Code_Clients\OS390\sscall_Add_customer.sqlj

E.1.1.2 UNIX / NT Sample client code


These files can be found in directory \Samples\Code_Clients\Unix_and_NT
\Samples\Code_Clients\Unix_and_NT
\Samples\Code_Clients\Unix_and_NT\jecall_Query_oi_summ.java
\Samples\Code_Clients\Unix_and_NT\jscall_Add_customer.java
\Samples\Code_Clients\Unix_and_NT\prep.sh
\Samples\Code_Clients\Unix_and_NT\prep_sscall.bat
\Samples\Code_Clients\Unix_and_NT\sscall_Add_customer.sqlj

E.1.2 Sample stored procedure code


These files can be found in directory \Samples\Code_Stored_Procedures

\Samples\Code_Stored_Procedures\readme_procs.txt

E.1.2.1 COBOL sample stored procedure code


These files can be found in directory \Samples\Code_Stored_Procedures\COBOL
\Samples\Code_Stored_Procedures\COBOL\S390
\Samples\Code_Stored_Procedures\COBOL\S390\Acmecoe
\Samples\Code_Stored_Procedures\COBOL\S390\Acmecos
\Samples\Code_Stored_Procedures\COBOL\S390\Acmecos\addcust.txt

E.1.2.2 JDBC sample stored procedure code


These files can be found in directory \Samples\Code_Stored_Procedures\JDBC

\Samples\Code_Stored_Procedures\JDBC\readme_jdbc.txt

JDBC sample stored procedure code - NT


These files can be found in directory \Samples\Code_Stored_Procedures\JDBC\NT
\Samples\Code_Stored_Procedures\JDBC\NT\Acmejne
\Samples\Code_Stored_Procedures\JDBC\NT\Acmejns
\Samples\Code_Stored_Procedures\JDBC\NT\Acmejne\ACMEJNE
\Samples\Code_Stored_Procedures\JDBC\NT\Acmejne\define_sp.sql
\Samples\Code_Stored_Procedures\JDBC\NT\Acmejne\prep.bat
\Samples\Code_Stored_Procedures\JDBC\NT\Acmejne\ACMEJNE\Add_customer.java
\Samples\Code_Stored_Procedures\JDBC\NT\Acmejne\ACMEJNE\Add_order.java
\Samples\Code_Stored_Procedures\JDBC\NT\Acmejne\ACMEJNE\Query_oi_summ.java
\Samples\Code_Stored_Procedures\JDBC\NT\Acmejns\ACMEJNS
\Samples\Code_Stored_Procedures\JDBC\NT\Acmejns\define_sp.sql
\Samples\Code_Stored_Procedures\JDBC\NT\Acmejns\prep.bat
\Samples\Code_Stored_Procedures\JDBC\NT\Acmejns\ACMEJNS\Add_customer.java

Appendix E. Using the additional material 349


JDBC sample stored procedure code - S390
These files can be found in directory
\Samples\Code_Stored_Procedures\JDBC\S390
\Samples\Code_Stored_Procedures\JDBC\S390\ACMEJOS
\Samples\Code_Stored_Procedures\JDBC\S390\ACMEJOS\Add_customer.java

JDBC sample stored procedure code - UNIX


These files can be found in directory
\Samples\Code_Stored_Procedures\JDBC\UNIX
\Samples\Code_Stored_Procedures\JDBC\UNIX\ACMEJUE
\Samples\Code_Stored_Procedures\JDBC\UNIX\ACMEJUS
\Samples\Code_Stored_Procedures\JDBC\UNIX\ACMEJUE\ACMEJUE
\Samples\Code_Stored_Procedures\JDBC\UNIX\ACMEJUE\define_sp_Query_oi_summ.
sql
\Samples\Code_Stored_Procedures\JDBC\UNIX\ACMEJUE\install_jar.sql
\Samples\Code_Stored_Procedures\JDBC\UNIX\ACMEJUE\prep.sh
\Samples\Code_Stored_Procedures\JDBC\UNIX\ACMEJUE\replace_jar.sql
\Samples\Code_Stored_Procedures\JDBC\UNIX\ACMEJUE\ACMEJUE\Query_oi_summ.ja
va
\Samples\Code_Stored_Procedures\JDBC\UNIX\ACMEJUS\ACMEJUS
\Samples\Code_Stored_Procedures\JDBC\UNIX\ACMEJUS\define_sp_Add_customer.s
ql
\Samples\Code_Stored_Procedures\JDBC\UNIX\ACMEJUS\install_jar.sql
\Samples\Code_Stored_Procedures\JDBC\UNIX\ACMEJUS\prep.sh
\Samples\Code_Stored_Procedures\JDBC\UNIX\ACMEJUS\replace_jar.sql

\Samples\Code_Stored_Procedures\JDBC\UNIX\ACMEJUS\ACMEJUS\Add_customer.jav
a

E.1.2.3 SQLJ sample stored procedure code


These files can be found in directory \Samples\Code_Stored_Procedures\SQLJ

\Samples\Code_Stored_Procedures\SQLJ\readme.txt

SQLJ sample stored procedure code - NT


These files can be found in directory \Samples\Code_Stored_Procedures\SQLJ\NT
\Samples\Code_Stored_Procedures\SQLJ\NT\Acmesne
\Samples\Code_Stored_Procedures\SQLJ\NT\ACMESNS
\Samples\Code_Stored_Procedures\SQLJ\NT\Acmesne\acmesne
\Samples\Code_Stored_Procedures\SQLJ\NT\Acmesne\define_acmesne.sql
\Samples\Code_Stored_Procedures\SQLJ\NT\Acmesne\prep.bat
\Samples\Code_Stored_Procedures\SQLJ\NT\Acmesne\acmesne\Add_customer.sqlj
\Samples\Code_Stored_Procedures\SQLJ\NT\Acmesne\acmesne\Query_oi_summ.sqlj
\Samples\Code_Stored_Procedures\SQLJ\NT\ACMESNS\ACMESNS
\Samples\Code_Stored_Procedures\SQLJ\NT\ACMESNS\define_sp.sql

350 DB2 Java Stored Procedures: Learning by Example


\Samples\Code_Stored_Procedures\SQLJ\NT\ACMESNS\prep.bat
\Samples\Code_Stored_Procedures\SQLJ\NT\ACMESNS\refresh.bat
\Samples\Code_Stored_Procedures\SQLJ\NT\ACMESNS\refresh_sp.sql
\Samples\Code_Stored_Procedures\SQLJ\NT\ACMESNS\ACMESNS\Add_customer.sqlj

SQLJ sample stored procedure code - S390


These files can be found in directory
\Samples\Code_Stored_Procedures\SQLJ\S390
\Samples\Code_Stored_Procedures\SQLJ\S390\Acmesos
\Samples\Code_Stored_Procedures\SQLJ\S390\Acmesos\Add_customer.sqlj

SQLJ sample stored procedure code - UNIX


These files can be found in directory
\Samples\Code_Stored_Procedures\SQLJ\Unix
\Samples\Code_Stored_Procedures\SQLJ\Unix\ACMESUE
\Samples\Code_Stored_Procedures\SQLJ\Unix\ACMESUS
\Samples\Code_Stored_Procedures\SQLJ\Unix\ACMESUE\ACMESUE
\Samples\Code_Stored_Procedures\SQLJ\Unix\ACMESUE\define_sp_Query_oi_summ.
sql
\Samples\Code_Stored_Procedures\SQLJ\Unix\ACMESUE\install_jar.sql
\Samples\Code_Stored_Procedures\SQLJ\Unix\ACMESUE\prep.sh
\Samples\Code_Stored_Procedures\SQLJ\Unix\ACMESUE\replace_jar.sql
\Samples\Code_Stored_Procedures\SQLJ\Unix\ACMESUE\ACMESUE\Query_oi_summ.sq
lj
\Samples\Code_Stored_Procedures\SQLJ\Unix\ACMESUS\ACMESUS
\Samples\Code_Stored_Procedures\SQLJ\Unix\ACMESUS\define_sp_Add_customer.s
ql
\Samples\Code_Stored_Procedures\SQLJ\Unix\ACMESUS\install_jar.sql
\Samples\Code_Stored_Procedures\SQLJ\Unix\ACMESUS\prep.sh
\Samples\Code_Stored_Procedures\SQLJ\Unix\ACMESUS\replace_jar.sql

\Samples\Code_Stored_Procedures\SQLJ\Unix\ACMESUS\ACMESUS\Add_customer.sql
j

E.1.2.4 SQLJ & JDBC sample stored procedure code


These files can be found in directory \Samples\Code_Stored_Procedures\Both

\Samples\Code_Stored_Procedures\Both\readme.txt

SQLJ & JDBC sample stored procedure code - S390


These files can be found in directory
\Samples\Code_Stored_Procedures\Both\S390
\Samples\Code_Stored_Procedures\Both\S390\Acmebos
\Samples\Code_Stored_Procedures\Both\S390\Acmebos\Add_customer.sqlj

Appendix E. Using the additional material 351


SQLJ & JDBC sample stored procedure code - NT
These files can be found in directory \Samples\Code_Stored_Procedures\Both\NT
\Samples\Code_Stored_Procedures\Both\NT\ACMEBNS
\Samples\Code_Stored_Procedures\Both\NT\ACMEBNS\ACMEBNS
\Samples\Code_Stored_Procedures\Both\NT\ACMEBNS\define_acmebns.sql
\Samples\Code_Stored_Procedures\Both\NT\ACMEBNS\prep.bat
\Samples\Code_Stored_Procedures\Both\NT\ACMEBNS\refresh.bat
\Samples\Code_Stored_Procedures\Both\NT\ACMEBNS\refresh_acmebns.sql
\Samples\Code_Stored_Procedures\Both\NT\ACMEBNS\ACMEBNS\Add_customer.sqlj

SQLJ & JDBC sample stored procedure code - UNIX


These files can be found in directory
\Samples\Code_Stored_Procedures\Both\Unix
\Samples\Code_Stored_Procedures\Both\Unix\ACMEBUS
\Samples\Code_Stored_Procedures\Both\Unix\ACMEBUS\ACMEBUS
\Samples\Code_Stored_Procedures\Both\Unix\ACMEBUS\define_sp_Add_customer.s
ql
\Samples\Code_Stored_Procedures\Both\Unix\ACMEBUS\install_jar.sql
\Samples\Code_Stored_Procedures\Both\Unix\ACMEBUS\prep.sh
\Samples\Code_Stored_Procedures\Both\Unix\ACMEBUS\replace_jar.sql
\Samples\Code_Stored_Procedures\Both\Unix\ACMEBUS\ACMEBUS\Add_customer.sql
j

E.1.3 Sample S390 utilities


These files can be found in directory \Samples\S390_Utilities
\Samples\S390_Utilities\readme.txt

E.1.3.1 Sample S390 installation utilities


These files can be found in directory \Samples\S390_Utilities\Installation
\Samples\S390_Utilities\Installation\.profile
\Samples\S390_Utilities\Installation\db2jdbc.cursors
\Samples\S390_Utilities\Installation\db2sqljjdbc.properties
\Samples\S390_Utilities\Installation\dbz2java
\Samples\S390_Utilities\Installation\javaenv
\Samples\S390_Utilities\Installation\jdbcbind
\Samples\S390_Utilities\Installation\readme.txt
\Samples\S390_Utilities\Installation\sqljplan

Note:
The .profile file was recorded in the CD-ROM as profile (without the
dot). Once you have downloaded it, you need to rename the file to
.profile.

352 DB2 Java Stored Procedures: Learning by Example


E.1.3.2 Sample S390 program preparation utilities
These files can be found in
directory\Samples\S390_Utilities\Program_Preparation
\Samples\S390_Utilities\Program_Preparation\bindcl.rexx
\Samples\S390_Utilities\Program_Preparation\bindsp.rexx
\Samples\S390_Utilities\Program_Preparation\driver_bos
\Samples\S390_Utilities\Program_Preparation\driver_cl
\Samples\S390_Utilities\Program_Preparation\driver_joe
\Samples\S390_Utilities\Program_Preparation\driver_jos
\Samples\S390_Utilities\Program_Preparation\driver_soe
\Samples\S390_Utilities\Program_Preparation\driver_sos
\Samples\S390_Utilities\Program_Preparation\hpjcust
\Samples\S390_Utilities\Program_Preparation\hpjsp
\Samples\S390_Utilities\Program_Preparation\javacl
\Samples\S390_Utilities\Program_Preparation\javasp
\Samples\S390_Utilities\Program_Preparation\javaspj
\Samples\S390_Utilities\Program_Preparation\oebind
\Samples\S390_Utilities\Program_Preparation\readme.txt

E.1.4 Sample SQL


These files can be found in directory \Samples\SQL
\Samples\SQL\readme.txt

E.1.4.1 Sample SQL - S390


These files can be found in directory \Samples\SQL\S390
\Samples\SQL\S390\ddle.txt
\Samples\SQL\S390\ddls.txt
\Samples\SQL\S390\procbos.txt
\Samples\SQL\S390\proccoe.txt
\Samples\SQL\S390\proccos.txt
\Samples\SQL\S390\procjoe.txt
\Samples\SQL\S390\procjos.txt
\Samples\SQL\S390\procsoe.txt
\Samples\SQL\S390\procsos.txt
\Samples\SQL\S390\readme.txt

E.1.4.2 Sample SQL - UNIX and NT


These files can be found in directory \Samples\SQL\Unix_and_NT
\Samples\SQL\Unix_and_NT\ddle_nt_db2v7.txt
\Samples\SQL\Unix_and_NT\ddle_unix_db2v6.txt
\Samples\SQL\Unix_and_NT\ddls.txt

Appendix E. Using the additional material 353


E.2 Locating the additional material on the Internet
The samples contained on the CD-ROM associated with this redbook are
also available in softcopy on the Internet from the IBM Redbooks Web server.
Point your Web browser to:

ftp://www.redbooks.ibm.com/redbooks/SG245945

Alternatively, you can go to the IBM Redbooks Web site at:

http://www.redbooks.ibm.com/

Select the Additional materials and open the directory that corresponds with
the redbook form number.

E.3 Using the Web material


The additional Web material that accompanies this redbook includes the
following:
File name Description
SG245945.zip Zipped Code for all Samples in the book.

E.3.1 How to use the Web material


1. Download the zip file containing the samples from the IBM Redbooks Web
server, as described above.
2. Create a subdirectory (folder) on your workstation to hold the samples.
3. Unzip the sample material into this folder, using PKUNZIP or any other ZIP
utility. When you unzip the file, ensure that you select the relevant option
to retain the directory structure for the sample files. Refer to E.1, “Using
the CD-ROM” on page 347 for a detailed listing of the sample files.

354 DB2 Java Stored Procedures: Learning by Example


Appendix F. Special notices

This publication is intended to help system programmers, database


administrators, and application developers in understanding, assessing, and
utilizing the JDBC, SQLJ and Java stored procedures support of DB2 UDB
Server for OS/390 Version 6. The information in this publication is not
intended as the specification of any programming interfaces that are provided
by DB2 UDB Server for OS/390 Version 6. See the PUBLICATIONS section
of the IBM Programming Announcement for DB2 UDB Server for OS/390
Version 6 for more information about what publications are considered to be
product documentation.

References in this publication to IBM products, programs or services do not


imply that IBM intends to make these available in all countries in which IBM
operates. Any reference to an IBM product, program, or service is not
intended to state or imply that only IBM's product, program, or service may be
used. Any functionally equivalent program that does not infringe any of IBM's
intellectual property rights may be used instead of the IBM product, program
or service.

Information in this book was developed in conjunction with use of the


equipment specified, and is limited in application to those specific hardware
and software products and levels.

IBM may have patents or pending patent applications covering subject matter
in this document. The furnishing of this document does not give you any
license to these patents. You can send license inquiries, in writing, to the IBM
Director of Licensing, IBM Corporation, North Castle Drive, Armonk, NY
10504-1785.

Licensees of this program who wish to have information about it for the
purpose of enabling: (i) the exchange of information between independently
created programs and other programs (including this one) and (ii) the mutual
use of the information which has been exchanged, should contact IBM
Corporation, Dept. 600A, Mail Drop 1329, Somers, NY 10589 USA.

Such information may be available, subject to appropriate terms and


conditions, including in some cases, payment of a fee.

The information contained in this document has not been submitted to any
formal IBM test and is distributed AS IS. The information about non-IBM
("vendor") products in this manual has been supplied by the vendor and IBM
assumes no responsibility for its accuracy or completeness. The use of this
information or the implementation of any of these techniques is a customer

© Copyright IBM Corp. 2000 355


responsibility and depends on the customer's ability to evaluate and integrate
them into the customer's operational environment. While each item may have
been reviewed by IBM for accuracy in a specific situation, there is no
guarantee that the same or similar results will be obtained elsewhere.
Customers attempting to adapt these techniques to their own environments
do so at their own risk.

Any pointers in this publication to external Web sites are provided for
convenience only and do not in any manner serve as an endorsement of
these Web sites.

Any performance data contained in this document was determined in a


controlled environment, and therefore, the results that may be obtained in
other operating environments may vary significantly. Users of this document
should verify the applicable data for their specific environment.

This document contains examples of data and reports used in daily business
operations. To illustrate them as completely as possible, the examples
contain the names of individuals, companies, brands, and products. All of
these names are fictitious and any similarity to the names and addresses
used by an actual business enterprise is entirely coincidental.

Reference to PTF numbers that have not been released through the normal
distribution process does not imply general availability. The purpose of
including these reference numbers is to alert IBM customers to specific
information relative to the implementation of the PTF when it becomes
available to each customer according to the normal IBM PTF distribution
process.

The following terms are trademarks of the International Business Machines


Corporation in the United States and/or other countries:
AIX AS/400
AT C/MVS
CICS CT
DATABASE2 DB2
DB2 Connect DRDA
Enterprise Storage Server IBMâ
Language Environment Net.Data
Netfinity OS/390
Parallel Sysplex QMF
RACF RAMAC
RETAIN RMF
RS/6000 S/390
SP System/390
VisualAge VTAM
XT 400

356 DB2 Java Stored Procedures: Learning by Example


The following terms are trademarks of other companies:

Tivoli, Manage. Anything. Anywhere.,The Power To Manage., Anything.


Anywhere.,TME, NetView, Cross-Site, Tivoli Ready, Tivoli Certified, Planet
Tivoli, and Tivoli Enterprise are trademarks or registered trademarks of Tivoli
Systems Inc., an IBM company, in the United States, other countries, or both.
In Denmark, Tivoli is a trademark licensed from Kjøbenhavns Sommer - Tivoli
A/S.

C-bus is a trademark of Corollary, Inc. in the United States and/or other


countries.

Java and all Java-based trademarks and logos are trademarks or registered
trademarks of Sun Microsystems, Inc. in the United States and/or other
countries.

Microsoft, Windows, Windows NT, and the Windows logo are trademarks of
Microsoft Corporation in the United States and/or other countries.

PC Direct is a trademark of Ziff Communications Company in the United


States and/or other countries and is used by IBM Corporation under license.

ActionMedia, LANDesk, MMX, Pentium and ProShare are trademarks of Intel


Corporation in the United States and/or other countries.

UNIX is a registered trademark in the United States and other countries


licensed exclusively through The Open Group.

SET and the SET logo are trademarks owned by SET Secure Electronic
Transaction LLC.

Other company, product, and service names may be trademarks or service


marks of others.

Appendix F. Special notices 357


358 DB2 Java Stored Procedures: Learning by Example
Appendix G. Related publications

The publications listed in this section are considered particularly suitable for a
more detailed discussion of the topics covered in this redbook.

G.1 IBM Redbooks


For information on ordering these publications see “How to get IBM
Redbooks” on page 363.
• Java Programming Guide for OS/390, SG24-5619
• Getting Started with DB2 Stored Procedures: Give Them a Call through
the Network , SG24-4693
• Developing Cross-Platform DB2 Stored Procedures: SQL Procedures and
DB2 Stored Procedure Builder, SG24-5485
• DB2 UDB for OS/390 and Continuous Availability, SG24-5486

G.2 IBM Redbooks collections


Redbooks are also available on the following CD-ROMs. Click the CD-ROMs
button at ibm.com/redbooks for information about all the CD-ROMs offered,
updates and formats.
CD-ROM Title Collection Kit
Number
System/390 Redbooks Collection SK2T-2177
Networking and Systems Management Redbooks Collection SK2T-6022
Transaction Processing and Data Management Redbooks Collection SK2T-8038
Lotus Redbooks Collection SK2T-8039
Tivoli Redbooks Collection SK2T-8044
AS/400 Redbooks Collection SK2T-2849
Netfinity Hardware and Software Redbooks Collection SK2T-8046
RS/6000 Redbooks Collection (BkMgr) SK2T-8040
RS/6000 Redbooks Collection (PDF Format) SK2T-8043
Application Development Redbooks Collection SK2T-8037
IBM Enterprise Storage and Systems Management Solutions SK3T-3694

© Copyright IBM Corp. 2000 359


G.3 Other resources
These publications are also relevant as further information sources:
• DB2 UDB for OS/390 Version 6 What’s New, GC26-9017-02
• DB2 UDB for OS/390 Version 6 Application Programming and SQL Guide,
SC26-9004
• DB2 UDB for OS/390 Version 6 SQL Reference, SC26-9014-01
• DB2 UDB for OS/390 Version 6 Administration Guide, SC26-9003-01
• DB2 UDB for OS/390 Version 6 Installation Guide, SC26-9008-01
• D B2 UDB for OS/390 Version 6 Command Reference, SC26-9006-01
• DB2 UDB for OS/390 Version 6 Utility Guide and Reference,
SC26-9015-01
• DB2 UDB for OS/390 Version 6 ODBC Guide and Reference,
SC26-9005-01
• DB2 UDB for OS/390 Version 6 Application Programming and SQL Guide,
SC26-9004-01
• DB2 UDB for OS/390 Version 6 Messages and Codes, SC26-9011-01
• DB2 UDB Version 6 Application Development Guide, SC09-2845
• OS/390 V2R8.0 MVS Planning: Workload Management, GC28-1761-09
• OS/390 WLM refer to OS/390 MVS Workload Management Services,
GC28-1773
• OS/390 V2R8 MVS Programming: Resource Recovery, GC28-1739-05
• DB2 UDB Installation and Configuration Supplement V6 , GC09-2857
• Java Application Programming Guide and Reference for Java ,
SC26-9018-01
• DB2 for OS/390 Application Programming Guide and Reference for Java,
SC26-9547
• UNIX System Services User’s Guide, SC28-1891
• Using REXX and OS/390 UNIX System Services , SC28-1905-04

360 DB2 Java Stored Procedures: Learning by Example


G.4 Referenced Web sites
These Web sites are also relevant as further information sources:
• http://www-4.ibm.com/software/data/db2/java/
The most recent material about using JAVA with DB2.
• http://www.s390.ibm.com/oe/
OS/390 UNIX System Services home page.
• http://www.rs6000.ibm.com/cgi-bin/ds_form?config=/usr/share/man/info/
en_US/a_doc_lib/data/base.cfg
AIX documentation; many commands also work in UNIX System Services.
• http://service.software.ibm.com/db2/support/dbssup.html
DB2 software updates.
• http://www.sqlj.org
SQLJ home page.
• http://www.ibm.com/s390/corner/
Java on S/390.
• http://www.software.ibm.com/data/db2/
DB2 Family
• http://www.software.ibm.com/data/db2/os390/
DB2 for OS/390.
• http://www.ibm.com/software/db2os390/downloads.html
DB2 downloads.
• http://www.ibm.com/solutions/businessintelligence/teraplex/index.html
Teraplex Center.

Appendix G. Related publications 361


362 DB2 Java Stored Procedures: Learning by Example
How to get IBM Redbooks

This section explains how both customers and IBM employees can find out about IBM Redbooks,
redpieces, and CD-ROMs. A form for ordering books and CD-ROMs by fax or e-mail is also provided.
• Redbooks Web Site ibm.com/redbooks
Search for, view, download, or order hardcopy/CD-ROM Redbooks from the Redbooks Web site.
Also read redpieces and download additional materials (code samples or diskette/CD-ROM images)
from this Redbooks site.
Redpieces are Redbooks in progress; not all Redbooks become redpieces and sometimes just a few
chapters will be published this way. The intent is to get the information out much quicker than the
formal publishing process allows.
• E-mail Orders
Send orders by e-mail including information from the IBM Redbooks fax order form to:
e-mail address
In United States usib6fpl@ibmmail.com
Outside North America Contact information is in the “How to Order” section at this site:
http://www.elink.ibmlink.ibm.com/pbl/pbl
• Telephone Orders
United States (toll free) 1-800-879-2755
Canada (toll free) 1-800-IBM-4YOU
Outside North America Country coordinator phone number is in the “How to Order”
section at this site:
http://www.elink.ibmlink.ibm.com/pbl/pbl
• Fax Orders
United States (toll free) 1-800-445-9269
Canada 1-403-267-4455
Outside North America Fax phone number is in the “How to Order” section at this site:
http://www.elink.ibmlink.ibm.com/pbl/pbl

This information was current at the time of publication, but is continually subject to change. The latest
information may be found at the Redbooks Web site.

IBM Intranet for Employees


IBM employees may register for information on workshops, residencies, and Redbooks by accessing
the IBM Intranet Web site at http://w3.itso.ibm.com/ and clicking the ITSO Mailing List button.
Look in the Materials repository for workshops, presentations, papers, and Web pages developed
and written by the ITSO technical professionals; click the Additional Materials button. Employees may
access MyNews at http://w3.ibm.com/ for redbook, residency, and workshop announcements.

© Copyright IBM Corp. 2000 363


IBM Redbooks fax order form

Please send me the following:

Title Order Number Quantity

First name Last name

Company

Address

City Postal code Country

Telephone number Telefax number VAT number

Invoice to customer number

Credit card number

Credit card expiration date Card issued to Signature

We accept American Express, Diners, Eurocard, Master Card, and Visa. Payment by credit card not
available in all countries. Signature mandatory for credit card payment.

364 DB2 Java Stored Procedures: Learning by Example


Glossary

The following terms and abbreviations are AFC See Application Foundation Classes.
defined as they are used in the DB2 library. If allied address space. An area of storage
you do not find the term you are looking for, external to DB2 that is connected to DB2 and is
refer to the index or to IBM Dictionary of therefore capable of requesting DB2 services.
Computing. Also, it brings term and
abbreviations related to Java and other American National Standards Institute
products, mentioned in this book. (ANSI) . An organization consisting of
producers, consumers, and general interest
A groups, that establishes the procedures by
which accredited organizations create and
abstract class A class that provides common maintain voluntary industry standards in the
information for subclasses, and therefore cannot United States.
be instantiated. Abstract classes provide at
least one abstract method. ANSI. American National Standards Institute.

abstract method A method with a signature, API See Application Program Interface.
but no implementation. You provide the applet A Java program designed to run within
implementation of the method in the subclass of a Web browser. Contrast with application.
the abstract class that contains the abstract
method. application. (1) A program or set of programs
that perform a task; for example, a payroll
abstract window toolkit (AWT) The Abstract application. (2) In Java programming, a
Window Toolkit API provides a layer between self-contained, stand-alone Java program that
the application and the host’s windowing includes a static main method. It does not
system. It enables programmers to port Java require an applet viewer. Contrast with applet.
applications from one window system to
another. The AWT provides access to basic Application Foundation Classes (AFCs)
interface components such as events, color, Microsoft’s version on the Java Foundation
fonts, and controls such as button, scroll bars, Classes (JFCs). AFCs deliver similar functions
text fields, frames, windows, dialogs, panels, to JFCs but only work on Windows 32-bit
canvases, and check boxes. platforms.

actual parameter list Parameters specified in application plan. The control structure
a call to a method. See also formal parameter produced during the bind process and used by
list. DB2 to process SQL statements encountered
during statement execution.
address space. A range of virtual storage
pages identified by a number (ASID) and a application program interface (API) . A
collection of segment and page tables which functional interface supplied by the operating
map the virtual pages to real pages of the system or by a separately orderable licensed
computer's memory. program that allows an application program
written in a high-level language to use specific
address space connection. The result of data or functions of the operating system or
connecting an allied address space to DB2. licensed program.
Each address space containing a task
connected to DB2 has exactly one address application requester (AR) . See requester.
space connection, even though more than one AR. application requester. See requester.
task control block (TCB) can be present. See
AS. application server.
allied address space and task control block.

© Copyright IBM Corp. 2000 365


ASCII (1) American Standard Code for selected and some authorization checking is
Information Interchange.A standard assignment performed.
of 7-bit numeric codes to characters. See also
automatic bind. (More correctly automatic
Unicode. (2) An encoding scheme used to
rebind). A process by which SQL statements are
represent strings in many environments, typically
bound automatically (without a user issuing a
on PCs and workstations. Contrast with
BIND command) when an application process
EBCDIC.
begins execution and the bound application plan
attachment facility. An interface between DB2 or package it requires is not valid.
and TSO, IMS, CICS, or batch address spaces.
dynamic bind. A process by which SQL
An attachment facility allows application
statements are bound as they are entered.
programs to access DB2.
incremental bind. A process by which SQL
authorization ID. A string that can be verified for
connection to DB2 and to which a set of statements are bound during the execution of an
privileges are allowed. It can represent an application process, because they could not be
individual, an organizational group, or a function, bound during the bind process, and
but DB2 does not determine this representation. VALIDATE(RUN) was specified.
AWT See Abstract Window Toolkit. static bind. A process by which SQL statements
are bound after they have been precompiled. All
B static SQL statements are prepared for execution
at the same time. Contrast with dynamic bind.
base table. (1) A table created by the SQL
CREATE TABLE statement that is used to hold BLOB. A sequence of bytes, where the size of
persistent data. Contrast with result table and the sequence ranges from 0 bytes to 2 GB - 1.
temporary table. (2) A table containing a LOB Such a string does not have an associated
column definition. The actual LOB column data is CCSID. The size of binary large object values can
not stored along with the base table. The base be anywhere up to 2 GB - 1.
table contains a row identifier for each row and an
browser (1) In VisualAge for Java, a window
indicator column for each of its LOB columns.
that provides information on program elements.
Contrast with auxiliary table.
There are browsers for projects, packages,
base type In Java, a type establishes an classes, methods, and interfaces. (2) An
interface to anything inherited from itself. See Internet-based too that lets users browse Web
type, derived type . sites.
bean A definition or instance of a JavaBeans built-in function. A function that is supplied by
component. See JavaBeans. DB2. Contrast with user-defined function.
BeanInfo (1) A Java class that provides explicit business object (1) An object that represents
information about the properties, events, and a business function. Business objects contain
methods of a bean class. (2) In the VisualAge for attributes that define the state of the object, and
Java Integrated Development Environment, a methods that define the behavior of the object. A
page in the class browser that provides bean business object also has relationships with other
information. business objects. Business objects can be used
in combination to perform a desired task. Typical
binary large object (BLOB). See BLOB.
examples of business objects are Customer,
bind. The process by which the output from the Invoice, or Account. (2) In the Enterprise Access
DB2 precompiler is converted to a usable control Builder, a class that implements the
structure called a package or an application plan. IBusinessObject interface. Business objects are
During the process, access paths to the data are used to map interactions with an existing home.

366 DB2 Java Stored Procedures: Learning by Example


bytecode Machine-independent code class hierarchy The relationships between
generated by the Java compiler and executed by classes that share a single inheritance. All Java
the Java interpreter. classes inherit from the Object class.

C class method Methods that apply to the class as


a whole rather than its instances (also called a
CAF. Call attachment facility.
static method).
call attachment facility (CAF). A DB2
class path When running a program in
attachment facility for application programs
VisualAge for Java, a list of directories and JAR
running in TSO or MVS batch. The CAF is an
files that contain resource files or Java classes
alternative to the DSN command processor and
that a program can load dynamically at run time.
allows greater control over the execution
A program's class path is set in its Properties
environment.
notebook.
call level interface (CLI). A callable application
CLASSPATH In your deployment environment,
program interface (API) for database access,
the environment variable keyword that specifies
which is an alternative to using embedded SQL.
the directories in which to look for class and
In contrast to embedded SQL, DB2 CLI does not
resource files.
require the user to precompile or bind
applications, but instead provides a standard set class variable Variables that apply to the class
of functions to process SQL statements and as a whole rather than its instances (also called a
related services at run time. static field ).
cast function. A function used to convert CLI. See call level interface.
instances of a (source) data type into instances client. (1)A networked computer in which the
of a different (target) data type. In general, a cast
IDE is connected to a repository on a team
function has the name of the target data type. It
server. (2) See requester.
has one single argument whose type is the
source data type; its return type is the target data CLOB. A sequence of bytes representing
type. single-byte characters or a mixture of single and
double-byte characters where the size can be up
casting Explicitly converting an object or
to 2 GB - 1. Although the size of character large
primitive’s data type.
object values can be anywhere up to 2 GB - 1, in
catalog. In DB2, a collection of tables that general, they are used whenever a character
contains descriptions of objects such as tables, string might exceed the limits of the VARCHAR
views, and indexes. type.
catalog table. Any table in the DB2 catalog. codebase An attribute of the <APPLET> tag
that provides the relative path name for the
C++ Access Builder A VisualAge fro Java,
classes. Use this attribute when your class files
Enterprise Edition tool that generates beans and
reside in a different directory than your HTML
C++ wrappers that let your Java programs access
files.
C++ DLLs.
column function. An SQL operation that derives
character large object (CLOB) . See CLOB.
its result from a collection of values across one or
class An encapsulated collection of data and more rows. Contrast with scalar function.
methods to operate on the data. A class may be
commit. The operation that ends a unit of work
instantiated to produce an object that is an
by releasing locks so that the database changes
instance of the class.
made by that unit of work can be perceived by
other processes.

367
Common Connector Framework In the Console In VisualAge for Java, the window that
Enterprise Access Builder, interface and class acts as the standard input (System.in) and
definitions that provide a consistent means of standard output (System.out) device for programs
interacting with enterprise resources (for running in the VisualAge for Java environment.
example, CICS and Encina transactions) from constructor A method called to set up a new
any Java execution environment. instance of a class.
Common Object Request Broker Architecture constant . A language element that specifies
(CORBA) Common Object Request Broker anunchanging value. Constants are classified as
Architecture. A specification produced by the string constants or numeric constants. Contrast
Object Management Group (OMG) that presents with variable.
standards for various types of object request
container A component that can hold other
brokers (such as client-resident ORBs,
components. In Java, examples of containers
server-based ORBs, system-based ORBs, and
include applets, frames, and dialogs. In the Visual
library-based ORBs). Implementation of CORBA
Composition Editor, containers can be graphically
standards enables object request brokers from
represented and generated.
different software vendors to interoperate.
context. The application's logical connection to
Common RFC Interface for Java A set of Java
the data source and associated internal DB2
interfaces and classes that defines a
ODBC connection information that allows the
middleware-independent layer to access R/3
application to direct its operations to a data
systems from Java. If applications are built on top
source. A DB2 ODBC context represents a DB2
of this interface, they can leverage different
thread.
middleware at run time without recoding. The
generated beans are based on this interface and cookie (1) A small file stored on an individual's
provide the same flexibility. computer; this file allows a site to tag the browser
with a unique identification. When a person visits
common server. Describes the set of DB2
a site, the site's server requests a unique ID from
products that run on various platforms and have
the person's browser. If this browser does not
the same source code. These platforms include
have an ID, the server delivers one. On the Wintel
OS/2, Windows, and UNIX.
platform, the cookie is delivered to a file
component model An architecture and an API called'cookies.txt,' and on a Macintosh platform, it
that allows developers to define reusable is delivered to 'MagicCookie.' Just as someone
segments of code that can be combined to create can track the origin of a phone call with Caller ID,
a program. VisualAge for Java uses the companies can use cookies to track information
JavaBeans component model. about behavior. (2) Persistent data stored by the
client in the Servlet Builder.
composite bean A bean that can contain both
visual and nonvisual components. A composite CORBA Common Objects Request Broker
bean is composed of embedded beans. Architecture.
connection In the VisualAge for Java Visual Core API Part of the minimal set of APIs that
Composition Editor, a visual link between two form the standard Java Platform. Core APIs are
components that represents the relationship available on the Java Platform regardless of the
between the components. Each connection has a underlying operating system. The Core API
source, a target, and other properties. grows with each release of the JDK; the current
core API is based on JDK 1.1. Also called core
connection handle. The data object that
classes.
contains information associated with a
connection managed by DB2 CLI. This includes cursor. A named control structure used by an
general status information, transaction status, application program to point to a row of interest
and diagnostic information.

368 DB2 Java Stored Procedures: Learning by Example


within some set of rows, and to retrieve rows from derived type In Java, a type that overrides the
the set, possibly making updates or deletions. definitions of a base type to provide unique
behavior. The derived type extends the base
D type.
Data Access Bean In the VisualAge for Java dipping A metaphor, introduced by
Visual Composition Editor, a bean that accesses BeanExtender on alphaWorks, for modifying a
and manipulates the content of component by hooking a special kind of Java
JDBC/ODBC-compliant relational databases. bean onto it. Dipping lets you add new behavior
or modify the Java bean's existing behavior
Data Access Builder A VisualAge for Java
without having to manipulate the Java bean's
Enterprise tool that generates beans to access
code. A dip is a special kind of Java bean that
and manipulate the content of
can be hooked on to another Java bean; it is the
JDBC/ODBC-compliant relational databases.
new feature you want to add to the component.
database management system (DBMS). A Software examples of dips include printing and
software system that controls the creation, security. Dippable Java beans can have one or
organization, and modification of a database and more dips connected to them. Almost any Java
access to the data stored within it. bean or class can be made dippable by extending
data source. A local or remote relational or it, a process called morphing.
non-relational data manager that is capable of dip A special kind of Java bean that can be
supporting data access via an ODBC driver which hooked on to another Java bean; the new feature
supports the ODBC APIs. In the case of DB2 for you want to add to the component. Software
OS/390, the data sources are always relational examples of dips include printing and security.
database managers.
distributed processing Processing that takes
DBCLOB. A sequence of bytes representing place across two or more linked systems.
double-byte characters where the size can be up
distinct type. A user-defined data type that is
to 2 gigabytes. Although the size of double-byte
internally represented as an existing type (its
character large object values can be anywhere up
source type), but is considered to be a separate
to 2 gigabytes, in general, they are used
and incompatible type for semantic purposes.
whenever a double-byte character string might
exceed the limits of the VARGRAPHIC type. distributed relational database architecture
(DRDA). A connection protocol for distributed
DBMS. Database management system.
relational database processing that is used by
DB2 thread. The DB2 structure that describes IBM's relational database products. DRDA
an application's connection, traces its progress, includes protocols for communication between an
processes resource functions, and delimits its application and a remote relational database
accessibility to DB2 resources. and services. management system, and for communication
debugger A component that assists in between relational database management
analyzing and correcting coding errors. systems.

declaration Statement that creates an DLL (dynamic link library) A file containing
identifier and its attributes, but does not reserve executable code and data bound to a program at
storage or provide an implementation. load time or run time, rather than during linking.
The code and data in a dynamic link library can
definition Statement that reserves storage or be shared by several applications simultaneously.
provides an implementation. The DLLs. Enterprise Access Builders also
deprecation An obsolete component that may generate platform-specific DLLs for the
be deleted from a future version of a product. workstation and OS/390 platforms.

369
double-byte character large object (DBCLOB). encapsulation The grouping of both data and
See DBCLOB. operations into neat, manageable units that can
be developed, tested, and maintained
double precision A floating-point number that
independently of one another. Such grouping is a
contains 64 bits. See also single precision .
powerful technique for building better software.
DRDA. Distributed relational database The object manages its own resources and limits
architecture. their visibility.
dynamic SQL. SQL statements that are enclave. In Language Environment for MVS &
prepared and executed within an application VM, an independent collection of routines, one of
program while the program is executing. In which is designated as the main routine. An
dynamic SQL, the SQL source is contained in enclave is similar to a program or run unit.
host language variables rather than being coded
Enterprise Access Builder (EAB) Feature of
into the application program. The SQL statement
Visual Age for Java, Enterprise Edition, that
can change several times during the application
creates connectors to enterprise server products
program's execution.
such as CICS, Encina, IMS TOC, and MQSeries.
Enterprise Edition See VisualAge for Java,
E
Enterprise Edition .
EBCDIC. Extended binary coded decimal
Enterprise Java Includes Enterprise
interchange code. An encoding scheme used to
JavaBeans as well as open API specifications for:
represent character data in the MVS, VM, VSE,
database connectivity, naming and directory
and OS/400Ñ environments. Contrast with
services, CORBA/IIOP interoperability, pure Java
ASCII.
distributed computing, messaging services,
EAB See Enterprise Access Builder. managing system and network resources, and
e-business Either (a) the transaction of transaction services.
business over an electronic medium such as the Enterprise JavaBeans A cross-platform
Internet or (b) a business that uses Internet component architecture for the development and
technologies and network computing in their deployment of multi-tier, distributed, scalable,
internal business processes (via intranets), their object-oriented Java applications.
business relationships (via extranets), and the
Enterprise ToolKit A set of VisualAge for Java
buying and selling of goods, services, and
Enterprise tools that enable you to develop Java
information (via electronic commerce.)
code that is targeted to specific platforms, such
e-commerce The subset of e-business that as AS/400, OS/390, OS/2, AIX, and Windows.
involves the exchange of money for goods or
Entry Edition See VisualAge for Java, Entry
services purchased over an electronic medium
Edition.
such as the Internet.
equi-join. A join operation in which the
EmbeddedJava An API and application
join-condition has the form expression =
environment for high-volume embedded devices,
expression.
such as mobile phones, pagers, process control,
instrumentation, office peripherals, network event An action by a user, program, or system
routers and network switches. EmbeddedJava that may trigger specific behavior. In the JDK,
applications run on real-time operating systems events notify the relevant listener classes to take
and are optimized for the constraints of appropriate action.
small-memory footprints and diverse visual
environment. A collection of names of logical
displays.
and physical resources that are used to support
embedded SQL. SQL statements coded within the performance of a function.
an application program. See static SQL.

370 DB2 Java Stored Procedures: Learning by Example


environment handle. In DB2 ODBC, the data that uses TCP and Telnet services to transfer
object that contains global information regarding bulk-data files between machines or hosts.
the state of the application. An environment
foreign key. A key that is specified in the
handle must be allocated before a connection
definition of a referential constraint. Because of
handle can be allocated. Only one environment
the foreign key, the table is a dependent table.
handle can be allocated per application.
The key must have the same number of columns,
exception An exception is an object that has with the same descriptions, as the primary key of
caused some sort of new condition, such as an the parent table.
error. In Java, throwing an exception means
form data A generated class representing the
passing that object to an interested party; a
HTML form elements in a visual servlet.
signal indicates what kind of condition has taken
place. Catching an exception means receiving formal parameter list Parameters specified in
the sent object. Handling this exception usually a method's definition. See also actual parameter
means taking care of the problem after receiving list.
the object, although it might mean doing nothing FTP See File Transfer Protocol .
(which would be bad programming practice).
full outer join. The result of a join operation that
executable content Code that runs from within includes the matched rows of both tables being
an HTML file (such as an applet). joined and preserves the unmatched rows of both
extends A subclass or interface extends a tables. See also join.
class or interface if it add fields or methods, or function. A specific purpose of an entity or its
overrides its methods. See also derived type. characteristic action such as a column function or
external function. A function for which the body scalar function. (See column function and scalar
is written in a programming language that takes function.). Furthermore, functions can be
scalar argument values and produces a scalar user-defined, built-in, or generated by DB2. (See
result for each invocation. Contrast with sourced built-in function, cast function, user-defined
function and built-in function. function, external function, sourced function.)

F G
factory A bean that dynamically creates garbage collection Java's ability to clean up
instances of beans. inaccessible unused memory areas ("garbage")
on the fly. Garbage collection slows performance,
field A data object in a class; for example, a
but keeps the machine from running out of
variable.
memory.
first tier The client; the hardware and software
Graphical User Interface (GUI) A type of
with which the end user interacts.
computer interface consisting of a visual
framework A set of object classes that provide metaphor of a real-world scene, often of a
a collection of related functions for a user or desktop. Within that scene are icons,
piece of software. representing actual objects, that the user can
access and manipulate with a pointing device.
free-form surface In the VisualAge for Java
Visual Composition Editor, the large, open area
where you can work with visual and nonvisual
H
beans. You add, remove, and connect beans on handle. In DB2 CLI, a variable that refers to a
the free-form surface. data structure and associated resources. See
statement handle, connection handle, and
File Transfer Protocol (FTP) In the Internet
environment handle.
suite of protocols, an application layer protocol

371
hierarchy The order of inheritance in to exchange data with eSuite and other
object-oriented languages. Each class in the InfoBus-enabled applications. The 100% Pure
hierarchy inherits attributes and behavior from its Java release and the InfoBus specification are
superclass, except for the top-level Object class. available for free download from:
http://java.sun.com/beans/infobus
HotJava A Java-enabled Web and intranet
browser developed by Sun Microsystems, Inc. inheritance The ability to create a subclass
HotJava is written in Java. (Definition copyright that automatically inherits properties and
1996-1999 Sun Microsystems, Inc. All Rights methods from its superclass. See also hierarchy.
Reserved. Used by permission.)
initialization file. For DB2 ODBC applications, a
Hypertext Markup Language (HTML) A file file containing values that can be set to adjust the
format, based on SGML, for hypertext documents performance of the database manager.
on the Internet. Allows for the embedding of
inner join. The result of a join operation that
images, sounds, video streams, form fields and
includes only the matched rows of both tables
simple text formatting. References to other
being joined. See also join.
objects are embedded using URLs, enabling
readers to jump directly to the referenced Inspector In VisualAge for Java, a window in
document. which you can evaluate code fragments in the
context of an object, look at the entire contents of
Hypertext Transfer Protocol (HTTP) The
an object and its class, or access and modify the
Internet protocol, based on TCP/IP, used to fetch
fields of an object.
hypertext objects from remote hosts.
instance The specific representation of a class,
I also called an object.
IDE See Integrated Development Environment . instance method A method that applies and
operates on objects (usually called simply a
identifier The name of an item in a program.
method). Contrast with class method .
IDL (Interface Definition Language) In
instance variable A variable that defines the
CORBA, a declarative language that is used to
attributes of an object. The class defines the
describe object interfaces, without regard to
instance variable's type and identifier, but the
object implementation.
object sets and changes its values.
IDL Development Environment In VisualAge
Integrated Development Environment (IDE)
for Java, an integrated IDL and Java development
In VisualAge for Java, the set of windows that
environment. The IDL Development Environment
provide the user with access to development
allows you to work with IDL source code in the
tools. The primary windows are the Workbench,
multipane IDLs page and generate Java code
Log, Console, Debugger, and Repository
using an IDL-to-Java compiler.
Explorer.
IDL group A container used to hold IDL objects
interface A list of methods that enables a class
in the IDL Development Environment. It is similar
to implement the interface itself by using the
to a file system directory.
implements keyword. The Interfaces page in the
IIOP (Internet Inter-ORB Protocol) A Workbench lists all interfaces in the workspace.
communications standard for distributed objects
Internet Protocol (IP) In the Internet suite of
that reside in Web or enterprise computing
protocols, a connectionless protocol that routes
environments.
data through a network or interconnected
InfoBus A technology for flexible, networks. IP acts as an intermediary between the
vendor-independent data exchange which is used higher protocol layers and the physical network.
by eSuite and can be used by other applications However, this protocol does not provide error

372 DB2 Java Stored Procedures: Learning by Example


recovery and flow control and does not guarantee Machine, Java Class Libraries, Java Applet
the reliability of the physical network. Viewer, Java Debugger, and other tools.
Internet Inter-ORB Protocol (IIOP) Access Java Foundation Classes (JFC) Developed by
Builder A tool that edits and generates Netscape, Sun, and IBM, JFCs are building
CORBA-compliant Java modules. See Common blocks that are helpful in developing interfaces to
Object Request Broker Architecture (CORBA). Java applications. They allow Java applications to
interact more completely with the existing
interpreter A tool that translates and executes
operating systems. Also called Swing Set.
code line-by-line.
Java IDL Java IDL is a language-neutral way to
introspection For a JavaBean to be reusable
specify an interface between an object and its
in development environments, there needs to be
client on a different platform. Provides
a way to query what the bean can do in terms of
interoperability and integration with CORBA, the
the methods it supports and the types of event it
industry standard for distributed computing,
raises and listens for. Introspection allows a
allowing developers to build Java applications
builder tool to analyze how a bean works.
that are integrated with heterogeneous business
IP See Internet Protocol. information assets.
Java Management Application Programming
J
Interface (JMAPI) A specification proposed by
JAE See Java Application Environment. Sun Microsystems that defines a core set of
JAR file format JAR (Java Archive) is a application programming interfaces for
platform-independent file format that aggregates developing tightly integrated system, network,
many files into one. Multiple Java applets and and service management applications. The
their requisite components (.class files, images, application programming interfaces could be
sounds and other resource files) can be bundled used in diverse computing environments that
in a JAR file and subsequently downloaded to a encompass many operating systems,
browser in a single HTTP transaction. architectures, and network protocols.

Java An object-oriented programming Java Media and Communications APIs


language for portable, interpretive code that Allows developers to integrate a wide range of
supports interaction among remote objects. Java media types into their Web pages, applets, and
was developed and specified by Sun applications. Includes: Media, Sound, Animation,
Microsystems, Incorporated. The Java 2D, 3D, Telephony, Speech and Collaboration.
environment consists of the JavaOS, the Virtual Java Media Framework (JMF) Java Media
Machines for various platforms, the Framework API specifies a unified architecture,
object-oriented Java programming language, and messaging protocol and programming interface
several class libraries. for media players, capture and conferencing. JMF
Java Application Environment (JAE) The provides a set of building blocks useful by other
source code release of the Java (TM) areas of the Java Media API suite. For example,
Development Kit. (Definition copyright 1996-1999 the JMF provides access to audio devices in a
Sun Microsystems, Inc. All Rights Reserved. cross-platform, device-independent manner,
Used by permission.) which is required by both the Java Telephony and
the Java Speech APIs. JMF will be published as
Java Development Kit (JDK) The Java three APIs: the Java Media Player, Java Media
Development Kit is the set of Java technologies Capture, and Java Media Conference.
made available to licensed developers by Sun
Microsystems. Each release of the JDK contains Java Naming and Directory Interface (JNDI)
the following: the Java Compiler, Java Virtual A set of APIs that assist with the interfacing to
multiple naming and directory services.

373
(Definition copyright 1996-1999 Sun the server and administrative system resources
Microsystems, Inc. All Rights Reserved. Used by required for developers to quickly develop their
permission.) own Java servers.
Java Native Interface (JNI) A native Java Virtual Machine (JVM) A software
programming interface that allows Java code implementation of a central processing unit
running inside a Java Virtual Machine (VM) to (CPU) that runs compiled Java code (applets and
interoperate with applications and libraries applications).
written in other programming languages, such as
JavaBeans Java's component architecture,
C and C++.
developed by Sun, IBM, and others. The
Java Platform The Java Virtual Machine and components, called Java beans, can be parts of
the Java Core classes make up the Java Java programs, or they can exist as
Platform. The Java Platform provides a uniform self-contained applications. Java beans can be
programming interface to a 100%. Pure Java assembled to create complex applications, and
program regardless of the underlying operating they can run within other component
system. (Definition copyright 1996-1999 Sun architectures (such as ActiveX and OpenDoc).
Microsystems, Inc. All Rights Reserved. Used by
JavaDoc Sun's tool for generating HTML
permission.)
documentation on classes by extracting
Java Record Editor An editor that allows you comments from the Java source code files.
to construct and refine dynamic record types.
JDBC (Java Database Connectivity) In the
Java Record Framework A Java framework JDK, the specification that defines an API that
that describes and converts record data. enables programs to access databases that
comply with this standard.
Java Remote Method Invocation (RMI) Java
Remote Method Invocation is method invocation JavaObjs In Remote Method Invocation, the
between peers, or between client and server, name of the user-defined default file that contains
when applications at both ends of the invocation a list of server objects to be instantiated when the
are written in Java. Included in JDK 1.1. Remote Object Instance Manager is started.
Java Runtime Environment (JRE) A subset of JavaOS A basic, small-footprint operating
the Java Development Kit for end-users and system that supports Java. Java OS was
developers who want to redistribute the JRE. The originally designed to run in small electronic
JRE consists of the Java Virtual Machine, the devices like phones and TV remotes, but it is also
Java Core Classes, and supporting files. being targeted for use in network computers
(Definition copyright 1996-1999 Sun (NCs).
Microsystems, Inc. All Rights Reserved. Used by
JavaScript A scripting language used within an
permission.)
HTML page. Superficially similar to Java but
Java Security API A framework for developers JavaScript scripts appear as text within the HTML
to include security functionality in their applets page. Java applets, on the other hand, are
and applications. Includes: cryptography with programs written in the Java language and are
digital signatures, encryption, and authentication. called from within HTML pages or run as
An intermediate subset of the Security API known stand-alone applications.
as "Security and Signed Applets" is included in
JFC See Java Foundation Classes.
JDK 1.1.
JIT See Just-In-Time Compiler.
Java Server An extensible framework that
enables and eases the development of JMF See Java Media Framework.
Java-powered Internet and intranet servers. The JNDI See Java Naming and Directory Interface.
APIs provide uniform and consistent access to

374 DB2 Java Stored Procedures: Learning by Example


JNI See Java Native Interface. local . Refers to any object maintained by the
local DB2 subsystem. A local table, for example,
JRE See Java Runtime Environment.
is a table maintained by the local DB2 subsystem.
Just-In-Time compiler (JIT) A Contrast with remote.
platform-specific software compiler often
local variable A variable declared and used
contained within JVMs. JITs compile Java
within a method or block.
bytecodes on-the-fly into native machine
instructions, thereby reducing the need for Log In the VisualAge for Java IDE, the window
interpretation. that displays messages and warnings during
development.
JVM See Java Virtual Machine.

L M
member In the Java language, an item
large object (LOB) . See LOB.
belonging to a class, such as a field or method.
left outer join. The result of a join operation that
method A fragment of Java code within a class
includes the matched rows of both tables being
that can be invoked and passed a set of
joined, and preserves the unmatched rows of the
parameters to perform a specific task.
first table. See also join.
middleware A layer of software that sits
link-edit. To create a loadable computer
between a database client and a database
program using a linkage editor.
server, making it easier for clients to connect to
linker A computer program for creating load heterogeneous databases.
modules from one or more object modules or load
middle tier The hardware and software that
modules by resolving cross references among the
resides between the client and the enterprise
modules and, if necessary, adjusting addresses.
server resources and data. The software includes
In Java, the linker creates an executable from
a Web server that receives requests from the
compiled classes.
client and invokes Java servlets to process these
listener In the JDK, a class that receives and requests. The client communicates with the Web
handles events. server via industry standard protocols such as
load module. A program unit that is suitable for HTTP and IIOP.
loading into main storage for execution. The morphing The process of extending a Java
output of a linkage editor. bean to accept dips. Morphed Java beans are
LOB. A sequence of bytes representing bit data, called dippable Java beans and can have one or
single-byte characters, double-byte characters, or more dips connected to them. Almost any Java
a mixture of single and double-byte characters. A bean or class can be made dippable. See
LOB can be up to 2GB -1 byte in length. See also dipping.
BLOB, CLOB, and DBCLOB. multithreaded A program where different parts
LOB locator. A mechanism that allows an can run at the same time without interfering with
application program to manipulate a large object each other.
value in the database system. A LOB locator is a multithreading. Multiple TCBs executing one
fullword integer value that represents a single copy of DB2 ODBC code concurrently (sharing a
LOB value. An application program retrieves a processor) or in parallel (on separate central
LOB locator into a host variable; it can then apply processors).
SQL operations to the associated LOB value
mutex. Pthread mutual exclusion; a lock. A
using the locator.
Pthread mutex variable is used as a locking
mechanism to allow serialization of critical

375
sections of code by temporarily blocking the object The principal building block of
execution of all but one thread. object-oriented programs. Objects are software
programming modules. Each object is a
MVS/ESA. Multiple Virtual Storage/Enterprise
programming unit consisting of related data and
Systems Architecture.
methods.
N ODBC. See Open Database Connectivity.
native class Machine-dependent C code that ODBC driver. A dynamically-linked library (DLL)
can be invoked from Java. For multi-platform that implements ODBC function calls and
work, the native routines for each platform need interacts with a data source.
to be implemented.
Open Database Connectivity (ODBC) . A
NCF See Network Computing Framework. Microsoft database application programming
Network Computing Framework (NCF) An interface (API) for C that allows access to
architecture and programming model created to database management systems by using callable
help customer and industry software SQL. ODBC does not require the use of an SQL
development teams to design, deploy, and preprocessor. In addition, ODBC provides an
manage e-business solutions across the architecture that lets users add modules called
enterprise. database drivers that link the application to their
choice of database management systems at run
Network News Transfer Protocol (NNTP) In time. This means that applications no longer
the Internet suite of protocols, a protocol for the need to be directly linked to the modules of all the
distribution, inquiry, retrieval, and posting of news database management systems that are
articles that are stored in a central database. supported.
nonvisual bean A bean that is not visible to the outer join. The result of a join operation that
end user in the graphical user interface, but is includes the matched rows of both tables being
visually represented on the free-form surface of joined and preserves some or all of the
the Visual Composition Editor during unmatched rows of the tables being joined. See
development. Developers can manipulate also join.
nonvisual beans only as icons; that is, they
cannot edit them in the Visual Composition Editor ORB (Object Request Broker) In
as they can edit visual beans. Examples of object-oriented programming, software that
nonvisual beans include beans for business logic, serves as an intermediary by transparently
communication access, and database queries. enabling objects to exchange requests and
responses.
NNTP See Network News Transfer Protocol.
object-oriented design A software design
NUL. In C, a single character that denotes the method that models the characteristics of
end of the string. abstract or real objects using classes and
null. A special value that indicates the absence objects. Object-oriented design focuses on the
of information. data and on the interfaces to it. For instance, an
"object-oriented" carpenter would be mostly
NUL-terminated host variable. A varying-length concerned with the chair he was building, and
host variable in which the end of the data is secondarily with the tools used to make it; a
indicated by the presence of a NUL terminator. "non-object-oriented" carpenter would think
NUL terminator. In C, the value that indicates primarily of his tools. Object-oriented design is
the end of a string. For character strings, the NUL also the mechanism for defining how modules
terminator is X'00'. "plug and play." The object-oriented facilities of
Java are essentially those of C++, with
O

376 DB2 Java Stored Procedures: Learning by Example


extensions from Objective C for more dynamic prepared SQL statement. A named object that
method resolution. is the executable form of an SQL statement that
has been processed by the PREPARE statement.
overloading The ability to have different
methods with the same identifier, distinguished primary key. A unique, nonnull key that is part of
by their return type, and number and type of the definition of a table. A table cannot be defined
arguments. as a parent unless it has a unique key or primary
key.
overriding Implementing a method in a
subclass that replaces a method in a superclass. process A program executing in its own
address space, containing one or more threads.
P
Professional Edition See VisualAge for Java,
package A program element that contains Professional Edition.
classes and interfaces.
program In VisualAge for Java, a term that
part An existing, reusable software component. refers to both Java applets and applications.
All parts created with the Visual Composition
program element In VisualAge for Java, a
Editor conform to the JavaBeans component
generic term for a project, package, class,
model, and are referred to as beans. See visual
interface, or method.
bean and nonvisual bean .
project In VisualAge for Java, the topmost kind
persistence In object models, a condition that
of program element. A project contains Java
allows instances of classes to be stored
packages.
externally, for example in a relational database.
property An initial setting or characteristic of a
Persistence Builder In VisualAge for Java, a
bean, for example, a name, font, text, or
persistence framework for object models, which
positional characteristic.
enables the mapping of objects to information
stored in relational databases and also provides Pthread. The POSIX threading standard model
linkages to legacy data on other systems. for splitting an application into subtasks. The
Pthread standard includes functions for creating
plan. See application plan.
threads, terminating threads, synchronizing
plan name. The name of an application plan. threads through locking, and other thread control
POSIX. Portable Operating System Interface. facilities.
The IEEE operating system interface standard R
which defines the Pthread standard of threading.
See Pthread. RDBMS. Relational database management
system.
precompilation. A processing of application
programs containing SQL statements that takes relational database management system
place before compilation. SQL statements are (RDBMS). A relational database manager that
replaced with statements that are recognized by operates consistently across supported IBM
the host language compiler. Output from this systems.
precompilation includes source code that can be
reentrant . Executable code that can reside in
submitted to the compiler and the database
storage as one shared copy for all threads.
request module (DBRM) that is input to the bind
Reentrant code is not self-modifying and provides
process.
separate storage areas for each thread.
prepare. The first phase of a two-phase commit Reentrancy is a compiler and operating system
process in which all participants are requested to concept, and reentrancy alone is not enough to
prepare for commit. guarantee logically consistent results when
multithreading. See threadsafe.

377
reference An object's address. In Java, objects updated in the repository. See also SCM
are passed by reference rather than by value or repository and shared repository.
by pointers.
Repository Explorer In VisualAge for Java, the
remote. Refers to any object maintained by a window from which you can view and compare
remote DB2 subsystem; that is, by a DB2 editions of program elements that are in the
subsystem other than the local one. A remote repository.
view, for instance, is a view maintained by a
requester. Also application requester (AR). The
remote DB2 subsystem. Contrast with local.
source of a request to a remote RDBMS, the
remote debugger A debugging tool that system that requests the data.
debugs code on a remote platform.
resource file A non-code file that may be
Remote Function Call (RFC) SAP's open referred to from your Java program in VisualAge
programmable interface. External applications for Java. Examples include graphic and audio
and tools can call ABAB/4 functions from the SAP files.
System. You can also call third party applications
result set. The set of rows returned to a client
from the SAP System using RFC. RFC is a
application by a stored procedure.
means for communication that allows
implementation on all R/3 platforms. result set locator. A 4-byte value used by DB2
to uniquely identify a query result set returned by
Remote Method Invocation (RMI) RMI is a
a stored procedure.
specific instance of the more general term RPC.
RMI allows objects to be distributed over the result table. The set of rows specified by a
network; that is, a Java program running on one SELECT statement.
computer can call the methods of an object right outer join. The result of a join operation
running on another computer. RMI and java.net that includes the matched rows of both tables
are the only 100% pure Java APIs for controlling being joined and preserves the unmatched rows
Java objects in remote systems. of the second join operand. See also join.
Remote Object Instance Manager In Remote RMI (Remote Method Invocation) See
Method Invocation, a program that creates and Remote Method Invocation.
manages instances of server beans through their
associated server-side server proxies. RMI Access Builder A VisualAge for Java
Enterprise tool that generates proxy beans and
Remote Procedure Calls (RPC) RPC is a associated classes and interfaces so you can
generic term referring to any of a series of distribute code for remote access, enabling
protocols used to execute procedure calls or Java-to-Java solutions.
method calls across a network. RPC allows a
program running on one computer to call the RMI compiler The compiler that generates stub
services of a program running on another and skeleton files that facilitate RMI
computer. communication. This compiler can be
automatically invoked by the RMI Access Builder,
repository In VisualAge for Java, the and can also be invoked from the Tools menu
permanent storage area containing all open and item.
versioned editions of all program elements,
regardless of whether they are currently in the RMI registry A server program that allows
workspace. The repository contains the source remote clients to get a reference to a server
code for classes developed in (and provided with) bean.
VisualAge for Java, and the bytecode for classes rollback . The process of restoring data changed
imported from the file system. Every time you by SQL statements to the state at its last commit
save a method in the IDE, it is automatically point. All locks are freed. Contrast with commit.

378 DB2 Java Stored Procedures: Learning by Example


RPC See Remote Procedure Calls. serialization Turning an object into a stream,
and back again.
runtime system The software environment
where compiled programs run. Each Java runtime server The computer that hosts the Web page
system includes an implementation of the Java that contains an applet. The .class files that make
Virtual Machine. up the applet, and the HTML files that reference
the applet reside on the server. When someone
S on the Internet connects to a Web page that
contains an applet, the server delivers the .class
sandbox A restricted environment, provided by
files over the Internet to the client that made the
the Web browser, in which Java applets run. The
request. The server is also known as the
sandbox offers them services and prevents them
originating host.
from doing anything naughty, such as doing file
I/O or talking to strangers (servers other than the server bean The bean that is distributed using
one from which the applet was loaded). The RMI services and is deployed on a server.
analogy of applets to children led to calling the
servlet Server-side programs that execute on
environment in which they run the "sandbox."
and add function to Web servers. Java servlets
scalar function. An SQL operation that allow for the creation of complicated,
produces a single value from another value and is high-performance, cross-platform Web
expressed as a function name followed by a list of applications. They are highly extensible and
arguments enclosed in parentheses. See also flexible, making it easy to expand from client or
column function. single-server applications to multi-tier
applications.
SCM See Software Configuration Management.
SGML See Standardized Generalized Markup
SCM repository In VisualAge for Java, a
Language.
generic term for the data store of any external
software configuration management (SCM) tool. single precision A floating-point number that
Some SCM tools refer to this as an archive. contains 32 bits. See also double precision.
scope Determines where an identifier can be SmartGuide In IBM software products, an
used. In Java, instance and class variables have active form of help that guides you through
a scope that extends to the entire class. All other common tasks.
identifiers are local to the method where they are
Software Configuration Management (SCM)
declared.
The tracking and control of software
Scrapbook In VisualAge for Java, the window development. SCM tools typically offer version
from which you can write, edit, and test fragments control and team programming features.
of code without having to define an
sourced function. A function that is
encompassing class or method.
implemented by another built-in or user-defined
Secure Socket Layer (SSL) SSL is a security function already known to the database manager.
protocol which allows communications between a This function can be a scalar function or a column
browser and a server to be encrypted and (aggregating) function; it returns a single value
secure. SSL prevents eavesdropping, tampering from a set of values (for example, MAX or AVG).
or message forgery on your Internet or intranet Contrast with external function and built-in
network. function.
security Features in Java that prevent applets source type. An existing type that is used to
downloaded off the Web from deliberately or internally represent a distinct type.
inadvertantly doing damage. One such feature is
the digital signature, which ensures that an applet
came unmodified from a reputable source.

379
SQL Structured Query Language. A language stored procedure. A user-written application
used by database engines and servers for data program, that can be invoked through the use of
acquisition and definition. the SQL CALL statement.
SQL authorization ID (SQL ID). The stream A communication path between a
authorization ID that is used for checking source of information and its destination.
dynamic SQL statements in some situations.
Structured Query Language (SQL) . A
SQL Communication Area (SQLCA). A standardized language for defining and
structure manipulating data in a relational database.
used to provide an application program with subclass A class that inherits all the methods
information about the execution of its SQL and variables of another class (its superclass). Its
statements. superclass might be a subclass of another class
in the hierarchy.
SQL Descriptor Area (SQLDA). A structure that
describes input variables, output variables, or the subtype A type that extends another type (its
columns of a result table. supertype ).
SQLCA. SQL communication area. superclass A class that defines the methods
and variables inherited by another class (its
SQLDA. SQL descriptor area.
subclass).
SQL/DS. SQL/Data System. Also known as DB2
supertype A type that is extended by another
for VSE & VM.
type (its subtype).
SSL See secure socket layer.
Swing Set A group of lightweight, ready-to-use
Standardized Generalized Markup Language components developed by JavaSoft. The
An ISO/ANSI/ECMA standard that specifies a components range from simple buttons to
way to annotate text documents with information full-featured text areas to tree views and tabbed
about types of sections of a document. folders.
statement handle. In DB2 ODBC, the data synchronized This Java keyword specifies that
object that contains information about an SQL only one thread can run inside a method at once.
statement that is managed by DB2 CLI. This
includes information such as dynamic arguments, T
bindings for dynamic arguments and columns,
table. A named data object consisting of a
cursor information, result values and status
specific number of columns and some number of
information. Each statement handle is associated
unordered rows. Synonymous with base table or
with the connection handle.
temporary table.
static field See class variable.
task control block (TCB). A control block used
static method See class method. to communicate information about tasks within an
address space that are connected to DB2. An
static SQL. SQL statements, embedded within a
address space can support many task
program, that are prepared during the program
connections (as many as one per task), but only
preparation process (before the program is
one address space connection. See address
executed). After being prepared, the SQL
space connection.
statement does not change (although values of
host variables specified by the statement might TCB. MVS task control block.
change).
TCP/IP See Transmission Control Protocol
based on IP.

380 DB2 Java Stored Procedures: Learning by Example


temporary table. A table created by the SQL Transmission Control Protocol based on IP
CREATE GLOBAL TEMPORARY TABLE (1) A network communication protocol used by
statement that is used to hold temporary data. computer systems to exchange information
Contrast with result table. across telecommunication links. (2) An Internet
protocol that provides for the reliable delivery of
thin client Thin client usually refers to a system
streams of data from one host to another.
that runs on a resource-constrained machine or
that runs a small operating system. Thin clients type In VisualAge for Java, a generic term for a
don't require local system administration, and class or interface.
they execute Java applications delivered over the
network. U
third tier The third tier, or back end, is the UDF. User-defined function
hardware and software that provides database UDT. User-defined data type
and transactional services. These back-end
services are accessed through connectors Uniform Resource Locator (URL) The unique
between the middle-tier Web server and the address that tells a browser how to find a specific
third-tier server. Though this conceptual model Web page or file.
depicts the second and third tier as two separate Unicode A 16-bit international character set
machines, the NCF model supports a logical defined by ISO 10646. See also ASCII.
three-tier implementation in which the software
on the middle and third tier are on the same box. user-defined data type (UDT) . See distinct
type.
thread A separate flow of control within a
program. user-defined function (UDF). A function
defined to DB2 using the CREATE FUNCTION
threadsafe. Characteristic of code that allows statement that can be referenced thereafter in
multithreading both by providing private storage SQL statements. A user-defined function can be
areas for each thread, and by properly serializing either an external function or a sourced function.
shared (global) storage areas. Contrast with built-in function.
timestamp. A seven-part value that consists of a URL See Uniform Resource Locator.
date and time expressed in years, months, days,
hours, minutes, seconds, and microseconds. V
trace. A DB2 facility that provides the ability to variable (1) An identifier that represents a data
monitor and collect DB2 monitoring, auditing, item whose value can be changed while the
performance, accounting, statistics, and program is running. The values of a variable are
serviceability (global) data. restricted to a certain data type. (2)A data
transaction (1) In a CICS program, an event element that specifies a value that can be
that queries or modifies a database that resides changed. A COBOL elementary data item is an
on a CICS server. (2) In the Persistence Builder, example of a variable. Contrast with constant.
a representation of a path of code execution. (3) virtual machine A software or hardware
The code activity necessary to manipulate a implementation of a central processing unit
persistent object. For example, a bank application (CPU) that manages the resources of a machine
might have a transaction that updates a company and can run compiled code. See Java Virtual
account. Machine .
transient This Java keyword specifies that a visual bean In the Visual Composition Editor, a
field is not included in the serial representation of bean that is visible to the end user in the
an object. See serialization . graphical user interface.

381
Visual Composition Editor In VisualAge for Workbench In VisualAge for Java, the main
Java, the tool you can use to create graphical window from which you can manage the
user interfaces from prefabricated beans, and to workspace, create and modify code, and open
define relationships (called connections) between browsers and other tools.
beans. The Visual Composition Editor is a page
workspace The work area that contains the
in the class browser.
Java code that you are developing and the class
visual servlet A servlet that is designed to be libraries on which your code depends. Program
built using the VisualAge for Java Visual elements must be added to the workspace from
Composition Editor. the repository before they can be modified.
VisualAge for Java, Enterprise Edition An wrapper Code that provides an interface for
edition of VisualAge for Java that is designed for one program to access the functionality of
building enterprise Java applications, and has all another program.
of the Professional Edition features plus support
WWW See World Wide Web.
for developers working in large teams, developing
high-performance or heterogeneous applications,
X
or needing to connect Java programs to existing
enterprise systems. X/Open. An independent, worldwide open systems
organization that is supported by most of the
VisualAge for Java, Entry Edition An edition
of VisualAge for Java suitable for learning and world's largest information systems suppliers, user
building small projects of 500 classes or less. It is organizations, and software companies. X/Open's
available as a no-charge download from goal is to increase the portability of applications by
VisualAge for Java and VisualAge Developer combining existing and emerging standards.
Domain Web sites.
100% Pure Java Sun Microsystems initiative to
VisualAge for Java, Professional Edition A certify that applications and applets are purely
complete Java development environment, Java-written.
including easy access to JDBC-enabled
databases for building Java applications.

W
WebSphere WebSphere is the cornerstone of
IBM's overall Web strategy, offering customers a
comprehensive solution to build, deploy and
manage e-business Web sites. The product line
provides companies with an open,
standards-based, Web server deployment
platform and Web site development and
management tools to help accelerate the process
of moving to e-business.
world readable files A permission level on
Web servers specifying that files can be read by
any user.
World Wide Web A network of servers that
contain programs and files. Many of the files
contain hypertext links to other documents
available through the network.

382 DB2 Java Stored Procedures: Learning by Example


Abbreviations and acronyms

ACEE access control CFRM coupling facility


environment resource management

AER application execution CLI call level interface


region CLP command line
AIX Advanced Interactive processor
eXecutive from IBM CPU central processing unit
APAR authorized program CSA common storage area
analysis report
DASD direct access storage
APF authorized program device
facility (MVS)
DB2 PM DB2 performance
API application program monitor
interface
DBAT database access
APPC advanced thread
program-to-program
communication DBCTL database control
subsystem
AR application requester
DBD database descriptor
ARM automatic restart
manager DBID database identifier

AS application server DBRM database request


module
ASCII American National
Standard Code for DCL data control language
Information DDCS distributed database
Interchange connection services
BLOB binary large objects DDF distributed data facility
CCSID coded character set DDL data definition
identifier language
CCA client configuration DLL dynamic load library
assistant manipulation language
CFCC coupling facility control DML data manipulation
code language
CGI common gateway DNS domain name server
interface DRA database resource
CTT created temporary table adapter
CEC central electronics DRDA distributed relational
complex database architecture
CD compact disk DTT declared temporary
tables
CF coupling facility

© Copyright IBM Corp. 2000 383


EA extended addressability ISPF interactive system
productivity facility
EBCDIC extended binary coded
decimal interchange ISV independent software
code vendor
ECS enhanced catalog I/O input/output
sharing
ITSO International Technical
ECSA extended common Support Organization
storage area
IVP installation verification
EDM environment descriptor process
management
JDBC Java Database
ERP enterprise resource Connectivity
planning
JFS journaled file systems
ESA Enterprise Systems
JVM Java Virtual Machine
Architecture
KB kilobyte (1,024 bytes)
EXCI external CICS interface
LPAR logically partitioned
FDT functional track directory
mode
FTP File Transfer Program
LOB large object
GB gigabyte (1,073,741,824
LPL logical page list
bytes)
LRSN log record sequence
GBP group buffer pool
number
GRS global resource
LVM logical volume manager
serialization
MB megabyte (1,048,576
GUI graphical user interface
bytes)
HPJ high performance Java
MQ message and queueing
or the high performance
(IBM software)
Java compiler
MQA message queue agent
IBM International Business
Machines Corporation MQI message queue
interface
ICF integrated catalog facility
OBD object descriptor in DBD
ICF integrated coupling
facility ODBC Open Data Base
Connectivity
ICMF internal coupling
migration facility OS/390 Operating System/390
IFCID instrumentation facility PAV parallel access volume
component identifier PDS partioned data set
IFI instrumentation facility PSID pageset identifier
interface
PSP preventive service
IRLM internal resource lock planning
manager

384 DB2 Java Stored Procedures: Learning by Example


PTF program temporary fix
PUNC possibly uncommitted
QMF Query Management
Facility
RACF Resource Access
Control Facility
RBA relative byte address
RID record identifier
RRS resource recovery
services
RRSAF resource recovery
services attach facility
RS read stability
RR repeatable read
SDK software developers kit
SMIT System Management
Interface Tool
SNA systems network
architecture
SP stored procedure
SRB system resource block
STC started task
TCB task control block
WLM workload manager

385
386 DB2 Java Stored Procedures: Learning by Example
Index
EBCDIC 162
USS 162
Symbols COLLID 123, 126, 131, 168
"CALL" is not a valid database alias name 115
COMMENT ON 197
.class files 149
COMMENT ON PROCEDURE 269
.jar file 150
COMMIT ON RETURN 262, 274
.java file 149
CONNECT statement 187, 193
.profile 59, 63, 64, 72, 80, 81, 170
savepoint 209
DB2SQLJPROPERTIES 71
connection pooling
.ser files 149
DDF 202
CREATE PROCEDURE 123, 181, 257
A schema 269
AIX CREATE TRIGGER 226
JDBC program preparation 144 CURRENT PATH 181, 234, 237, 238, 239, 240
SQLJ program preparation 149 schema 236
ALLOCATE CURSOR 193, 194 CURRENT SERVER 192
ALTER INDEX 183 CURRENT SQLID 233
ALTER PROCEDURE 182 customize 119
ALTER TABLESPACE 183
ASSOCIATE LOCATORS 193
authorization D
data propagation
client application 174
identity columns 229
hopping 197
data set passwords 181
Java stored procedures 120
Data sharing 73
JDBC client 174
data sharing
authorization checking 121
identity columns 230
DB2
B data set passwords 181
BEGIN ATOMIC 226 JDBC programs 7
Bind package 89
DBPROTOCOL option 193 schema 233
PATH option 181, 240 shared read-only data 181
SQLJ programs 8
type 1 indexe 181
C
CALL statement 171 type 2 indexes 181
Cannot call a schema-qualified stored procedure DB2 Connect 106
118 DB2 package 119, 167
CATMAINT 111 DB2 plan 167
catmaint 183 DB2 Stored Procedure Builder 105
class files 133 DB2 utilities
Class Not Found at runtime 106 identity columns 218
Class.forName 162 db2jdbc.cursors 71
CLASSPATH 60, 61, 65, 70, 80, 81, 143 db2profc 9, 79, 130, 133, 150, 160, 167
COBOL 23, 172 db2profile 80, 81
Code translation 162 DB2SQLJATTACHTYPE 72
ASCII 162 DB2SQLJDBRMLIB 73
DB2SQLJJDBCPROGRAM 72

© Copyright IBM Corp. 2000 387


DB2SQLJPLANNAME 72, 167 SQLJ classes 76
DB2SQLJPROPERTIES 61, 64, 71, 167, 170 Unable to load HPJ module during HPJ com-
DB2SQLJSSID 72 pile 76
DBPROTOCOL Java
bind option 193 Class Not Found at runtime 106
DBRM 119, 133, 167 JAR files - removing, refreshing 146
DDF JNI panic during db2profc 118
connection pooling 202 Method Not Found at runtime 107
DRDA enhancements 197 Path or file name "Java" not found 79
MODE(SUSPEND) 203 SQL20201N 114
debugging Unable to find user class 76
SPB 104 Unable to find user method 77
stored procedures 103 Other
writing to a text file 104 Cannot call a schema-qualified stored proce-
DESCRIBE CURSOR 193, 194 dure 118
DESCRIBE PROCEDURE 193 other
DISPLAY PROCEDURE command 280 CEE5207E 77
DRDA 187 DSNL065I 285
DDF enhancements 197 DSNL066I 285
hopping 195 DSNL067I 285
Loop back 195 DSNL068 285
OPTIMIZE FOR n ROWS 198 DSNL069I 285
query block size 198 DSNL070I 286
savepoint 209 DSNL071I 286
SNA connections 188 DSNL072 286
stored procedures 243 DSNL073I 286
TCP/IP connections 188 ICH408I 77
Three-part name 189 SQLCODE
DROP PROCEDURE 151 +585 239
DYNAMICRULES 120, 121 -104 107
DYNAMICRULES(DEFINEBIND) -113 108, 111
JDBC 121 -151 218
DYNAMICRULES(INVOKERUN) -204 110
JDBC 122 -390 111
-426 255
-440 108, 270, 272
E -471 77, 117
Enterprise Toolkit for OS/390 4, 58
-487 264
ENVAR 71
-577 264
error message
-579 264
SQLCODE
-585 239
-965 77
-586 240
error messages
-713 239
DB2 RC
-728 188
00E79107 76, 77
-729 274
00E79108 77
-751 264
HPJ
-805 191
HPJ3115(S) 76, 106
-818 115
Out of storage -- HPJ compile JDBC and
-950 111

388 DB2 Java Stored Procedures: Learning by Example


-965 78, 116 I
SQL10013N The specified library could not identity columns 210, 211
be loaded 113 altering 215
SQL20201N JAR name is invalid during copying tables 216
sqlj.install_jar 114 data definition 211
SQL4301N Java interpreter start-up 112 data manipulation 217
SQL4304N 116 data propagation 229
SQLSTATE data sharing 230
01625 239 DB2 family 230
42602 108, 111 DB2 utilities 218
42705 111 Indexing 222
42732 239 properties 220
42808 218 retrieving values 222
42815 239 ROWID columns 228
42907 240 IDENTITY_VAL_LOCAL 224, 225
51021 116 INCREMENT BY 229
55023 117 installVAJDLLs 68
executable-centric Iterator
migration 159, 161 SQLJ 100
external savepoint 209

J
F JAR file 146, 147, 148, 150, 151, 153, 154, 155
Fallback JAR routines
Version 6 to Version 5 184 sqlj.install_jar 146, 155
sqlj.remove_jar 146
sqlj.replace_jar 155
G
GENERATED ALWAYS 217 Java
getConnection method 170 classes 4
global transactions CLASSPATH 4
savepoint 210 JAR file 4, 88
methods 4
package 4, 86, 91, 93, 95, 96
H Java Development Kit 4
HOME path 61, 73, 77 Java method 86
Home path 74 Java package
Hopping statement 124, 131
authorization 197 Java stored procedures
DRDA and pivate protocol 195 case sensitive 92
Loop back 195 data sharing 73
host variables 181 DB2 portability 24
HPJ 58, 62, 68, 70, 74, 93, 96 deployment 157
base libraries 60 execution
dynamic load library 70 OS/390 163
JDBC/SQLJ drivers 57 UNIX 163
HPJ3115(S) message received during HPJ compile Windows NT 163
106 LOBs 90
HPJ3TBY 76 migrating between environments on S/390 157
naming 83

389
output parameters 90 location name 170
parameters 90
preparation 119
system setup 76
M
Method Not Found at runtime 107
OS/390 57
migration
UNIX 80
executable-centric 159
Windows NT 78
source-centric 158
Java stored procedures, compiled 57
MODE(SUSPEND)
JAVA_HOME 65, 80, 81
Command syntax 204
javac
DDF 203
command 149
JAVAENV data set 57, 60, 62, 63, 69
contents 70 N
JDBC 7, 23, 120, 172 nested stored procedures 274
client COMMIT ON RETURN 274
call stored procedure 173 three-part name 275
create SQL string 172 NT
input parameters 173 JDBC program preparation 144
output parameters 173 SQLJ program preparation 149
client applications 167 Null handling
client authorization 174 JDBC
client coding 170 inserting 99
cursors file 71 JDBC stored procedures 97
dynamic load libraries 70 null values 97
DYNAMICRULES(DEFINEBIND) 121
DYNAMICRULES(INVOKEBIND) 122
O
insenting a null 99 ODBC 19
migration 160 OPTIMIZE FOR n ROWS 197
program preparation 122 OS/390 High Performance Java Compiler 5
OS/390 124 OS/390 UNIX System Services 4, 143
serialized profile 61
stored procedures 119
null handling 97 P
JDBC DBRM PATH
DSNJDBC1 76 bind option 181, 240
DSNJDBC2 76 PATH system variable 79
DSNJDBC3 76 PDSE 62, 66, 124, 133
DSNJDBC4 76 porting stored procedutes
JDBC driver 11 UNIX/NT and S/390 161
JDK 57, 78, 79, 80, 123 prepareCall 173
JNI panic during db2profc 118 printStackTrace 102
JSPDEBUG 67, 104 private protocol
JVM 3, 5, 119 hopping 195
SNA connections 188
program preparation
L JDBC 122
LABEL ON 197 SQLJ 129
LD_LIBRARY_PATH 65, 69, 70, 80, 81
LIBPATH 60, 65, 69, 70, 80, 81

390 DB2 Java Stored Procedures: Learning by Example


Q DRDA 188
Query_oi_summ 34 private protocol 188
source-centric
migration 158, 161
R SPB 105
RACF 66, 329, 330, 335
SQL string 172
PERMIT command 335
preparation 173
profiles 335
SQL10013N 113
RDEFINE command 335
SQL4301N 112
RACF user IDs
SQL4304N 116
stored procedures 335
SQLJ 8, 23, 120, 174
RELEASE SAVEPOINT 208
client application 100
ResultSet
client applications 167
SQLJ 100
client coding 174
ROLLBACK TO SAVEPOINT 209
command 132
ROWID columns
dynamic load libraries 70
identity columns 228
Iterators 100
RRS 57, 58, 59, 66
migration 160
program preparation
S OS/390 129
sample application 19 ResultSets 100
components 21 serialized profile 149
naming conventions 22 stored procedures 119, 160
package names 22 authorization 120
savepoint 208 error handling 102
DRDA access 209 inserting a null 100
global transactions 210 receiving a null 100
roll back 209 SQLJ properties 57, 60, 61, 70, 71, 72
stored procedures 210 sqlj.install_jar 145, 146, 148, 151, 153, 155, 161
triggers 210 sqlj.remove_jar 146, 151, 153, 155
UDFs 210 sqlj.replace_jar 148, 155
UNIQUE option 208 SQLJ/JDBC base libraries 60
schema 125 SQLJPLAN 167, 170
characteristics 234 -START DATABASE 183
CURRENT PATH 236 START WITH 229
DB2 support 233 -STOP DATABASE 183
explicit specification 234 stored procedure 12
implicit specification 235 Stored Procedure Builder 164
SET CURRENT PATH 237 stored procedures
SYSFUN 237 authorization 258, 275
SYSIBM 237 calling with a null value 97
SYSPROC 237 COMMIT_ON_RETURN 254
Serialized profiles directory 61 CONNECT statement 246, 248, 249 , 258
SET CONNECTION 192, 193 CONNECT TYPE 1 248, 249
SET CURRENT PATH 240 CONNECT TYPE 2 248
SET CURRENT SQLID 121 debugging 103
setNull 97 DLI support 255
shared read-only dat 181 DML 258
SNA connections LOBs 259

391
nested 274 compatibility mode 338, 345
parameters 97, 262 enable stored procedure support 331
privileges 268 goal mode 339, 345
result sets 251, 252, 253 Java stored procedures 66
savepoint 210 JAVAENV data set 67
SQL CALL 246 RACF 335
time line characteristics 247 recommendations 344
triggers 259 service definition 342
UDFs 258 service policy 342
UDTs 259
usage of schemas 258, 268
SYSCAT.PROCEDURES 182
SYSIBM.SYSCOLDIST 183
SYSIBM.SYSCOLDISTSTATS 183
SYSIBM.SYSJARCONTENTS 145, 150
SYSIBM.SYSPARMS 181, 182, 257 , 267, 281
SYSIBM.SYSPROCEDURES 96, 123, 125, 181,
182, 250, 251, 257, 267, 270, 281, 335
SYSIBM.SYSROUTINES 96, 181, 182, 257, 267,
281
SYSIBM.SYSSEQUENCES 221
SYSIBM.SYSSEQUENCESDEP 221

T
TCP/IP connections
DRDA 188
Three-part name
DRDA 189
Package requirements 191
trigger
savepoint 210
type 1 indexes 181
type 2 indexes 181

U
UNIQUE OPTION
savepoint 208
UNIX Systems Services 57

V
VisuaAge for Java Enterprise Edition 58
VisualAge for Java 4, 8
Enterprise Edition for OS/390 119

W
wasNull 99
WLM 58, 59, 66, 163

392 DB2 Java Stored Procedures: Learning by Example


IBM Redbooks review
Your feedback is valued by the Redbook authors. In particular we are interested in situations where a
Redbook "made the difference" in a task or problem you encountered. Using one of the following
methods, please review the Redbook, addressing value, subject matter, structure, depth and
quality as appropriate.
• Use the online Contact us review redbook form found at ibm.com/redbooks
• Fax this form to: USA International Access Code + 1 914 432 8264
• Send your comments in an Internet note to redbook@us.ibm.com

Document Number SG24-5945-00


Redbook Title DB2 Java Stored Procedures: Learning by Example

Review

What other subjects would you


like to see IBM Redbooks
address?

Please rate your overall O Very Good O Good O Average O Poor


satisfaction:

Please identify yourself as O Customer O Business Partner O Solution Developer


belonging to one of the O IBM, Lotus or Tivoli Employee
following groups: O None of the above

Your email address:


The data you provide here may
be used to provide you with O Please do not use the information collected here for future
information from IBM or our marketing or promotional contacts or other communications beyond
business partners about our the scope of this transaction.
products, services or activities.

Questions about IBM’s privacy The following link explains how we protect your personal information.
policy? ibm.com/privacy/yourprivacy/

© Copyright IBM Corp. 2000 393


250 <-> 459 pages
0.475”<->0.875”
(0.5” spine)
DB2 Java Stored Procedures: Learning by Example
®

DB2 Java Stored Procedures


Learning by Example

Implementation Stored procedures can provide major benefits in the areas of


guide for DB2 Java application performance, code re-use, security, and integrity.
INTERNATIONAL
stored procedures The DB2 Family of products has offered support for stored TECHNICAL
procedures for some time, with each release offering SUPPORT
DB2 Java stored significant enhancements over the last. ORGANIZATION
procedures across
In the meantime, Java’s inherent portability and openness,
platforms
combined with the availability of skilled programming
resource, has made it an increasingly attractive choice as the BUILDING TECHNICAL
Reference guide for central plank in the e-business strategy of many INFORMATION BASED ON
network computing PRACTICAL EXPERIENCE
organizations.
enhancements in
DB2 UDB for Until recently, DB2 did not support stored procedures written IBM Redbooks are developed by
OS/390 V6 in Java, so the advantages of the two technologies could not the IBM International Technical
be combined. The latest releases of DB2 have changed all Support Organization. Experts
from IBM, Customers and
that, opening up new possibilities for secure, highly portable
Partners from around the world
application development. create timely technical
information based on realistic
This IBM Redbook aims to give the reader an in-depth scenarios. Specific
understanding of the techniques and issues associated with recommendations are provided
to help you implement IT
the development of DB2 stored procedures written in SQLJ
solutions more effectively in
and JDBC. The extensive collection of sample code presented your environment.
in this book and included on the accompanying CD-ROM was
designed to run against DB2 UDB Server across the OS/390,
Windows, and UNIX platforms.
For more information:
ibm.com/redbooks

SG24-5945-00 ISBN 0738418773

You might also like